static void init () { int i, j, r; srand(42); for (i = 0; i < 16; i++) key[i] = 0xff & rand(); memset(test_case, 0, sizeof(test_case)); for (i = 0; i < NTESTS; i++) for (j = 0; j < test_case_len[i]; j++) { test_case[i].input[j] = 0xff & rand(); } r = camellia_enc_key (key, sizeof(key), &ctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); r = camellia_dec_key (key, sizeof(key), &dctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); }
static void fips_test () { static const unsigned char fipskey[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, }; static const unsigned char input[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, }; static const unsigned char expected[16] = { 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 }; unsigned char output[16]; unsigned char tmp[16]; camellia_ctx fipsctx; int r; printf ("FIPS test:\nkey:"); hexdump (fipskey, 16); printf ("\ninput:"); hexdump (input, 16); r = camellia_enc_key (fipskey, sizeof(fipskey), &fipsctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); r = camellia_enc_blk (input, output, &fipsctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); printf ("\noutput:"); hexdump (output, 16); printf ("\n"); if (memcmp(expected, output, 16)) fprintf(stderr, "wrong results!!!\n"), exit (1); r = camellia_dec_key (fipskey, sizeof(fipskey), &fipsctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); r = camellia_dec_blk (output, tmp, &fipsctx); if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); if (memcmp(input, tmp, 16)) fprintf(stderr, "decryption failed!!\n"), exit(1); printf ("ok.\n\n"); }
krb5_error_code krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data, const krb5_data *iv, krb5_data *output) { camellia_ctx ctx; unsigned char blockY[BLOCK_SIZE]; struct iov_block_state iov_state; if (output->length < BLOCK_SIZE) return KRB5_BAD_MSIZE; if (camellia_enc_key(key->keyblock.contents, key->keyblock.length, &ctx) != camellia_good) abort(); if (iv != NULL) memcpy(blockY, iv->data, BLOCK_SIZE); else memset(blockY, 0, BLOCK_SIZE); IOV_BLOCK_STATE_INIT(&iov_state); for (;;) { unsigned char blockB[BLOCK_SIZE]; if (!krb5int_c_iov_get_block(blockB, BLOCK_SIZE, data, num_data, &iov_state)) break; xorblock(blockB, blockY); if (camellia_enc_blk(blockB, blockY, &ctx) != camellia_good) abort(); } output->length = BLOCK_SIZE; memcpy(output->data, blockY, BLOCK_SIZE); return 0; }
static krb5_error_code krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { unsigned char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE]; int nblocks = 0, blockno; size_t input_length, i; struct iov_block_state input_pos, output_pos; if (key->cache == NULL) { key->cache = malloc(sizeof(struct camellia_key_info_cache)); if (key->cache == NULL) return ENOMEM; CACHE(key)->enc_ctx.keybitlen = CACHE(key)->dec_ctx.keybitlen = 0; } if (CACHE(key)->enc_ctx.keybitlen == 0) { if (camellia_enc_key(key->keyblock.contents, key->keyblock.length, &CACHE(key)->enc_ctx) != camellia_good) abort(); } if (ivec != NULL) memcpy(tmp, ivec->data, BLOCK_SIZE); else memset(tmp, 0, BLOCK_SIZE); for (i = 0, input_length = 0; i < num_data; i++) { krb5_crypto_iov *iov = &data[i]; if (ENCRYPT_IOV(iov)) input_length += iov->data.length; } IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; if (nblocks == 1) { krb5int_c_iov_get_block(tmp, BLOCK_SIZE, data, num_data, &input_pos); enc(tmp2, tmp, &CACHE(key)->enc_ctx); krb5int_c_iov_put_block(data, num_data, tmp2, BLOCK_SIZE, &output_pos); } else if (nblocks > 1) { unsigned char blockN2[BLOCK_SIZE]; /* second last */ unsigned char blockN1[BLOCK_SIZE]; /* last block */ for (blockno = 0; blockno < nblocks - 2; blockno++) { unsigned char blockN[BLOCK_SIZE], *block; krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE, data, num_data, &input_pos, &block); xorblock(tmp, block); enc(block, tmp, &CACHE(key)->enc_ctx); krb5int_c_iov_put_block_nocopy(data, num_data, blockN, BLOCK_SIZE, &output_pos, block); /* Set up for next block. */ memcpy(tmp, block, BLOCK_SIZE); } /* Do final CTS step for last two blocks (the second of which may or may not be incomplete). */ /* First, get the last two blocks */ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */ krb5int_c_iov_get_block(blockN2, BLOCK_SIZE, data, num_data, &input_pos); krb5int_c_iov_get_block(blockN1, BLOCK_SIZE, data, num_data, &input_pos); /* Encrypt second last block */ xorblock(tmp, blockN2); enc(tmp2, tmp, &CACHE(key)->enc_ctx); memcpy(blockN2, tmp2, BLOCK_SIZE); /* blockN2 now contains first block */ memcpy(tmp, tmp2, BLOCK_SIZE); /* Encrypt last block */ xorblock(tmp, blockN1); enc(tmp2, tmp, &CACHE(key)->enc_ctx); memcpy(blockN1, tmp2, BLOCK_SIZE); /* Put the last two blocks back into the iovec (reverse order) */ krb5int_c_iov_put_block(data, num_data, blockN1, BLOCK_SIZE, &output_pos); krb5int_c_iov_put_block(data, num_data, blockN2, BLOCK_SIZE, &output_pos); if (ivec != NULL) memcpy(ivec->data, blockN1, BLOCK_SIZE); } return 0; }