📄 seal.c
字号:
return err_status_ok;}/* * The macro seal_initialize(...) implements the 'initialize' * function from the SEAL specification. Note that this function * has nothing to do with the 'init' function of cipher.h * * This macro is internal to the implementation and should * never be called externally * * note that l is the number of rounds, and that each time that this * macro is used, l is a multiple of 64 */#define seal_initialize(R, T, index, l , A, B, C, D, n1, n2, n3, n4) { \ \ /* set A,B,C,D registers from the R-table */ \ A = index ^ R[4 * (l >> 6)]; \ B = ROT8(index) ^ R[4 * (l >> 6) + 1]; \ C = ROT16(index) ^ R[4 * (l >> 6) + 2]; \ D = ROT24(index) ^ R[4 * (l >> 6) + 3]; \ \ /* pass one */ \ P = A & 0x7fc; B += T[P/4]; A = ROT9(A); \ P = B & 0x7fc; C += T[P/4]; B = ROT9(B); \ P = C & 0x7fc; D += T[P/4]; C = ROT9(C); \ P = D & 0x7fc; A += T[P/4]; D = ROT9(D); \ \ /* pass two */ \ P = A & 0x7fc; B += T[P/4]; A = ROT9(A); \ P = B & 0x7fc; C += T[P/4]; B = ROT9(B); \ P = C & 0x7fc; D += T[P/4]; C = ROT9(C); \ P = D & 0x7fc; A += T[P/4]; D = ROT9(D); \ \ /* set state registers */ \ n1 = D; \ n2 = B; \ n3 = A; \ n4 = C; \ \ P = A & 0x7fc; B += T[P/4]; A = ROT9(A); \ P = B & 0x7fc; C += T[P/4]; B = ROT9(B); \ P = C & 0x7fc; D += T[P/4]; C = ROT9(C); \ P = D & 0x7fc; A += T[P/4]; D = ROT9(D); \ \}err_status_tseal_set_segment(seal_ctx_t *ctx, xtd_seq_num_t idx) { /* set index from idx */ ctx->index = (idx.roc << 16) | idx.seq; /* initialize counters to zero */ ctx->bytes_in_buffer = 0; ctx->l = 0;#if PRINT_DEBUG printf("setting segment index to: %x\n", ctx->index);#endif return err_status_ok;}/* * seal_round(ctx, s, output) generates 16 octets of keystream and * exors that into the data at *output * * seal_ctx_t *ctx is the seal context * uint32_t *s_ptr is a pointer into the S-table * uint32_t *output is a pointer to the output * */#define seal_round(A, B, C, D, P, Q, s_ptr) { \ P = A & 0x7fc; B += T[P/4]; A = ROT9(A); B ^= A; \ Q = B & 0x7fc; C ^= T[Q/4]; B = ROT9(B); C += B; \ P = (P+C) & 0x7fc; D += T[P/4]; C = ROT9(C); D ^= C; \ Q = (Q+D) & 0x7fc; A ^= T[Q/4]; D = ROT9(D); A += D; \ P = (P+A) & 0x7fc; B ^= T[P/4]; A = ROT9(A); \ Q = (Q+B) & 0x7fc; C += T[Q/4]; B = ROT9(B); \ P = (P+C) & 0x7fc; D ^= T[P/4]; C = ROT9(C); \ Q = (Q+D) & 0x7fc; A += T[Q/4]; D = ROT9(D); \}err_status_tseal_encrypt(seal_ctx_t *c, unsigned char *buf, int bytes_to_encr) { uint32_t P, Q; uint32_t *buf32; const uint32_t *T = c->T; uint32_t *S = c->S + ((c->l & 63) * 4); v128_t state; int i; /* * check that there's enough segment left * * there have been l rounds (16 octets each) encrypted so far, with * a maximum of 2^16 bytes per index */ if ((c->l * 16) + bytes_to_encr > 0x10000) return err_status_terminus; if (bytes_to_encr <= c->bytes_in_buffer) { /* deal with odd case of small bytes_to_encr */ for (i = (16 - c->bytes_in_buffer); i < (16 - c->bytes_in_buffer + bytes_to_encr); i++) *buf++ ^= c->keystream.octet[i]; c->bytes_in_buffer -= bytes_to_encr; /* return now to avoid the main loop */ return err_status_ok; } else { /* encrypt bytes until the remaining data is 16-byte aligned */ for (i=(16 - c->bytes_in_buffer); i < 16; i++) *buf++ ^= c->keystream.octet[i]; bytes_to_encr -= c->bytes_in_buffer; c->bytes_in_buffer = 0; } /* copy state into registers */ state.v32[0] = c->state[0]; state.v32[1] = c->state[1]; state.v32[2] = c->state[2]; state.v32[3] = c->state[3]; /* * now loop over entire 16-octet blocks of keystream, running * the seal round function once per block * * every 64 rounds, we pause to re-initialize the cipher state * using the segment_init function * */ buf32 = (uint32_t *)buf; for (i=0; i < (bytes_to_encr/16); i++) { /* every 64 rounds, re-run the initialize function */ if (!(c->l & 63)) { seal_initialize(c->R, T, c->index, c->l, state.v32[3], state.v32[0], state.v32[1], state.v32[2], c->n1, c->n2, c->n3, c->n4); S = c->S; } /* apply the round function to the state */ seal_round(state.v32[3], state.v32[0], state.v32[1], state.v32[2], P, Q, S); /* exor the state into the output buffer */ *buf32++ ^= bswap_32(state.v32[0] + *S++); *buf32++ ^= bswap_32(state.v32[1] ^ *S++); *buf32++ ^= bswap_32(state.v32[2] + *S++); *buf32++ ^= bswap_32(state.v32[3] ^ *S++); /* update state, depending on the parity of the round number */ if (c->l++ & 1) { state.v32[3] += c->n3; state.v32[0] += c->n4; state.v32[1] ^= c->n3; state.v32[2] ^= c->n4; } else { state.v32[3] += c->n1; state.v32[0] += c->n2; state.v32[1] ^= c->n1; state.v32[2] ^= c->n2; } } buf = (octet_t *)buf32; /* if there is a tail end of the data, process it */ if ((bytes_to_encr & 0xf) != 0) { /* fill buffer with new keystream */ /* every 64 rounds, re-run the initialize function */ if (!(c->l & 63)) { seal_initialize(c->R, T, c->index, c->l, state.v32[3], state.v32[0], state.v32[1], state.v32[2], c->n1, c->n2, c->n3, c->n4); S = c->S; } /* apply the round function to the state */ seal_round(state.v32[3], state.v32[0], state.v32[1], state.v32[2], P, Q, S); c->keystream.v32[0] = bswap_32(state.v32[0] + *S++); c->keystream.v32[1] = bswap_32(state.v32[1] ^ *S++); c->keystream.v32[2] = bswap_32(state.v32[2] + *S++); c->keystream.v32[3] = bswap_32(state.v32[3] ^ *S++); /* munge 'n' values into the state */ if (c->l++ & 1) { state.v32[3] += c->n3; state.v32[0] += c->n4; state.v32[1] ^= c->n3; state.v32[2] ^= c->n4; } else { state.v32[3] += c->n1; state.v32[0] += c->n2; state.v32[1] ^= c->n1; state.v32[2] ^= c->n2; } /* exor as much keystream as needed into the output */ for (i=0; i < (bytes_to_encr & 0xf); i++) *buf++ ^= c->keystream.octet[i]; /* reset the keystream buffer size to right value */ c->bytes_in_buffer = 16 - i; } else { /* no tail, so just reset the keystream buffer size to zero */ c->bytes_in_buffer = 0; } /* set cipher state */ c->state[0] = state.v32[0]; c->state[1] = state.v32[1]; c->state[2] = state.v32[2]; c->state[3] = state.v32[3]; return err_status_ok;}/* * seal_test_case is a test vector set for correctness checking */octet_t seal_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};octet_t seal_test_case_0_ciphertext[32] = { 0x37, 0xa0, 0x05, 0x95, 0x9b, 0x84, 0xc4, 0x9c, 0xa4, 0xbe, 0x1e, 0x05, 0x06, 0x73, 0x53, 0x0f, 0x5f, 0xb0, 0x97, 0xfd, 0xf6, 0xa1, 0x3f, 0xbd, 0x6c, 0x2c, 0xde, 0xcd, 0x81, 0xfd, 0xee, 0x7c};octet_t seal_test_case_0_key[20] = { 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0};cipher_test_case_t seal_test_case_0 = { 20, /* octets in key */ seal_test_case_0_key, /* key */ 0, /* octets in salt */ NULL, /* salt */ { 0x0135, 0x77af }, /* packet index */ 32, /* octets in plaintext */ seal_test_case_0_plaintext, /* plaintext */ seal_test_case_0_ciphertext, /* ciphertext */ NULL /* pointer to next testcase */};charseal_description[] = "SEAL 3.0";cipher_type_t seal = { (cipher_alloc_func_t) seal_alloc, (cipher_dealloc_func_t) seal_dealloc, (cipher_init_func_t) seal_init, (cipher_set_segment_func_t) seal_set_segment, (cipher_encrypt_func_t) seal_encrypt, (char *) seal_description, (int) 0, (cipher_test_case_t *) &seal_test_case_0};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -