aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2008-12-01 16:41:52 +0000
committerSam Hartman <hartmans@mit.edu>2008-12-01 16:41:52 +0000
commit79c765842d07d9d51dcf84ad91e76c4a8db53a68 (patch)
treed4851de59fc91f28aae11043c7c2439917888841
parent6088ea4708fbc5a2c25c80f522c2c77502f14460 (diff)
downloadkrb5-79c765842d07d9d51dcf84ad91e76c4a8db53a68.zip
krb5-79c765842d07d9d51dcf84ad91e76c4a8db53a68.tar.gz
krb5-79c765842d07d9d51dcf84ad91e76c4a8db53a68.tar.bz2
Initial implementation of krb5int_aes_decrypt_iov()
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mskrb-integ-crypto-iov@21217 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/crypto/enc_provider/aes.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/lib/crypto/enc_provider/aes.c b/src/lib/crypto/enc_provider/aes.c
index b0967be..517ac00 100644
--- a/src/lib/crypto/enc_provider/aes.c
+++ b/src/lib/crypto/enc_provider/aes.c
@@ -359,10 +359,90 @@ krb5int_aes_encrypt_iov(const krb5_keyblock *key,
static krb5_error_code
krb5int_aes_decrypt_iov(const krb5_keyblock *key,
- const krb5_data *state,
+ const krb5_data *ivec,
krb5_crypto_iov *data,
size_t num_data)
{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+ size_t input_length, i;
+
+ CHECK_SIZES;
+
+ if (aes_dec_key(key->contents, key->length, &ctx) != aes_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;
+ }
+
+ nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ if (nblocks == 1) {
+ /* XXX Used for DK function, probably will be never used with IOV API,
+ * so it's safe to make some arbitrary restrictions here */
+ assert(num_data == 1);
+ assert(data[0].flags == KRB5_CRYPTO_TYPE_HEADER);
+ assert(data[0].data.length == BLOCK_SIZE);
+
+ dec(data[0].data.data, data[0].data.data, &ctx);
+ } else {
+ char blockN2[BLOCK_SIZE]; /* second last */
+ char blockN1[BLOCK_SIZE]; /* last block */
+ size_t input_iov_pos = 0, input_block_pos = 0;
+ size_t output_iov_pos = 0, output_block_pos = 0;
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ char blockN[BLOCK_SIZE];
+
+ iov_get_block(blockN, data, num_data, &input_iov_pos, &input_block_pos);
+ dec(tmp2, blockN, &ctx);
+ xorblock(tmp2, tmp);
+ iov_put_block(data, num_data, tmp2, &output_iov_pos, &output_block_pos);
+ memcpy(tmp, blockN, BLOCK_SIZE);
+ }
+
+ /* Do last two blocks, the second of which (next-to-last block
+ of plaintext) may be incomplete. */
+
+ /* First, get the last two encrypted blocks */
+ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */
+ iov_get_block(blockN2, data, num_data, &input_iov_pos, &input_block_pos);
+ iov_get_block(blockN1, data, num_data, &input_iov_pos, &input_block_pos);
+
+ /* Decrypt second last block */
+ dec(tmp2, blockN2, &ctx);
+ /* Set tmp3 to last ciphertext block (already padded) */
+ memcpy(tmp3, blockN1, BLOCK_SIZE);
+ /* Set tmp2 to last (possibly partial) plaintext block, and
+ save it. */
+ xorblock(tmp2, tmp3);
+ memcpy(blockN1, tmp2, BLOCK_SIZE);
+ /* Maybe keep the trailing part, and copy in the last
+ ciphertext block. */
+ memcpy(tmp2, tmp3, BLOCK_SIZE);
+ dec(tmp3, tmp2, &ctx);
+ xorblock(tmp3, tmp);
+ /* Copy out ivec first before we clobber blockN2 with plaintext */
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN2, BLOCK_SIZE);
+ memcpy(blockN2, tmp3, BLOCK_SIZE);
+
+ /* Put the last two blocks back into the ivec, in reverse order */
+ iov_put_block(data, num_data, blockN1, &output_iov_pos, &output_block_pos);
+ iov_put_block(data, num_data, blockN2, &output_iov_pos, &output_block_pos);
+ }
+
+ return 0;
}
static krb5_error_code