summaryrefslogtreecommitdiffstats
path: root/src/lib/crypto
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-05-06 00:43:27 -0400
committerGreg Hudson <ghudson@mit.edu>2013-05-24 14:15:03 -0400
commit3b142e5746e7db1939a9cf8095faecfed6222054 (patch)
treeef9496f0e47a52e58a88b7f0aac8e3cc77fcf797 /src/lib/crypto
parent48c9a082940373b82d4b8e3c338e9eb9d0d3c3f2 (diff)
downloadkrb5-3b142e5746e7db1939a9cf8095faecfed6222054.tar.gz
krb5-3b142e5746e7db1939a9cf8095faecfed6222054.tar.xz
krb5-3b142e5746e7db1939a9cf8095faecfed6222054.zip
Simplify crypto IOV helpers
Expand the concept of an IOV block state into a cursor which remembers the IOV set being iterated over, the block size, and both input and output positions. Eliminate the no-copy inline block getter for now, but provide helpers to grab contiguous chains of blocks from a cursor. Also provide an inline helper to sum the total length of an iov chain.
Diffstat (limited to 'src/lib/crypto')
-rw-r--r--src/lib/crypto/builtin/des/d3_aead.c88
-rw-r--r--src/lib/crypto/builtin/des/f_aead.c118
-rw-r--r--src/lib/crypto/builtin/enc_provider/aes.c83
-rw-r--r--src/lib/crypto/builtin/enc_provider/camellia.c97
-rw-r--r--src/lib/crypto/builtin/enc_provider/des.c13
-rw-r--r--src/lib/crypto/builtin/enc_provider/des3.c11
-rw-r--r--src/lib/crypto/krb/aead.c86
-rw-r--r--src/lib/crypto/krb/cmac.c18
-rw-r--r--src/lib/crypto/krb/crypto_int.h260
-rw-r--r--src/lib/crypto/krb/enc_old.c10
-rw-r--r--src/lib/crypto/nss/enc_provider/enc_gen.c93
-rw-r--r--src/lib/crypto/openssl/enc_provider/aes.c77
-rw-r--r--src/lib/crypto/openssl/enc_provider/camellia.c93
-rw-r--r--src/lib/crypto/openssl/enc_provider/des.c54
-rw-r--r--src/lib/crypto/openssl/enc_provider/des3.c42
15 files changed, 375 insertions, 768 deletions
diff --git a/src/lib/crypto/builtin/des/d3_aead.c b/src/lib/crypto/builtin/des/d3_aead.c
index af34fe9b1e..bddf75a474 100644
--- a/src/lib/crypto/builtin/des/d3_aead.c
+++ b/src/lib/crypto/builtin/des/d3_aead.c
@@ -36,11 +36,8 @@ krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
unsigned DES_INT32 left, right;
const unsigned DES_INT32 *kp1, *kp2, *kp3;
const unsigned char *ip;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
+ struct iov_cursor cursor;
+ unsigned char block[MIT_DES_BLOCK_LENGTH];
/* Get key pointers here. These won't need to be reinitialized. */
kp1 = (const unsigned DES_INT32 *)ks1;
@@ -49,41 +46,28 @@ krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
/* Initialize left and right with the contents of the initial vector. */
ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
- GET_HALF_BLOCK(left, ip);
- GET_HALF_BLOCK(right, ip);
-
- /* Work the length down 8 bytes at a time. */
- for (;;) {
- unsigned DES_INT32 temp;
-
- if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
- data, num_data, &input_pos, &ptr))
- break;
- block = ptr;
+ left = load_32_be(ip);
+ right = load_32_be(ip + 4);
- /* Decompose this block and xor it with the previous ciphertext. */
- GET_HALF_BLOCK(temp, ptr);
- left ^= temp;
- GET_HALF_BLOCK(temp, ptr);
- right ^= temp;
+ k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+ while (k5_iov_cursor_get(&cursor, block)) {
+ /* xor this block with the previous ciphertext. */
+ left ^= load_32_be(block);
+ right ^= load_32_be(block + 4);
/* Encrypt what we have and store it back into block. */
DES_DO_ENCRYPT(left, right, kp1);
DES_DO_DECRYPT(left, right, kp2);
DES_DO_ENCRYPT(left, right, kp3);
- ptr = block;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ store_32_be(left, block);
+ store_32_be(right, block + 4);
- krb5int_c_iov_put_block_nocopy(data, num_data, storage,
- MIT_DES_BLOCK_LENGTH, &output_pos,
- block);
+ k5_iov_cursor_put(&cursor, block);
}
- if (ivec != NULL && block != NULL) {
- ptr = ivec;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ if (ivec != NULL) {
+ store_32_be(left, ivec);
+ store_32_be(right, ivec + 4);
}
}
@@ -99,11 +83,8 @@ krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
const unsigned char *ip;
unsigned DES_INT32 ocipherl, ocipherr;
unsigned DES_INT32 cipherl, cipherr;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
+ struct iov_cursor cursor;
+ unsigned char block[MIT_DES_BLOCK_LENGTH];
/* Get key pointers here. These won't need to be reinitialized. */
kp1 = (const unsigned DES_INT32 *)ks1;
@@ -118,21 +99,14 @@ krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
/* Prime the old cipher with ivec.*/
ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
- GET_HALF_BLOCK(ocipherl, ip);
- GET_HALF_BLOCK(ocipherr, ip);
-
- /* Work the length down 8 bytes at a time. */
- for (;;) {
- if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
- data, num_data, &input_pos, &ptr))
- break;
- block = ptr;
+ ocipherl = load_32_be(ip);
+ ocipherr = load_32_be(ip + 4);
+ k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+ while (k5_iov_cursor_get(&cursor, block)) {
/* Split this block into left and right. */
- GET_HALF_BLOCK(left, ptr);
- GET_HALF_BLOCK(right, ptr);
- cipherl = left;
- cipherr = right;
+ cipherl = left = load_32_be(block);
+ cipherr = right = load_32_be(block + 4);
/* Decrypt and xor with the old cipher to get plain text. */
DES_DO_DECRYPT(left, right, kp3);
@@ -142,22 +116,18 @@ krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
right ^= ocipherr;
/* Store the encrypted halves back into block. */
- ptr = block;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ store_32_be(left, block);
+ store_32_be(right, block + 4);
/* Save current cipher block halves. */
ocipherl = cipherl;
ocipherr = cipherr;
- krb5int_c_iov_put_block_nocopy(data, num_data, storage,
- MIT_DES_BLOCK_LENGTH, &output_pos,
- block);
+ k5_iov_cursor_put(&cursor, block);
}
- if (ivec != NULL && block != NULL) {
- ptr = ivec;
- PUT_HALF_BLOCK(ocipherl, ptr);
- PUT_HALF_BLOCK(ocipherr, ptr);
+ if (ivec != NULL) {
+ store_32_be(ocipherl, ivec);
+ store_32_be(ocipherr, ivec + 4);
}
}
diff --git a/src/lib/crypto/builtin/des/f_aead.c b/src/lib/crypto/builtin/des/f_aead.c
index 5d80286269..71b8dff4d4 100644
--- a/src/lib/crypto/builtin/des/f_aead.c
+++ b/src/lib/crypto/builtin/des/f_aead.c
@@ -36,50 +36,34 @@ krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
unsigned DES_INT32 left, right;
const unsigned DES_INT32 *kp;
const unsigned char *ip;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
+ struct iov_cursor cursor;
+ unsigned char block[MIT_DES_BLOCK_LENGTH];
/* Get key pointer here. This won't need to be reinitialized. */
kp = (const unsigned DES_INT32 *)schedule;
/* Initialize left and right with the contents of the initial vector. */
ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
- GET_HALF_BLOCK(left, ip);
- GET_HALF_BLOCK(right, ip);
-
- /* Work the length down 8 bytes at a time. */
- for (;;) {
- unsigned DES_INT32 temp;
-
- if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
- data, num_data, &input_pos, &ptr))
- break;
- block = ptr;
+ left = load_32_be(ip);
+ right = load_32_be(ip + 4);
+ k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+ while (k5_iov_cursor_get(&cursor, block)) {
/* Decompose this block and xor it with the previous ciphertext. */
- GET_HALF_BLOCK(temp, ptr);
- left ^= temp;
- GET_HALF_BLOCK(temp, ptr);
- right ^= temp;
+ left ^= load_32_be(block);
+ right ^= load_32_be(block + 4);
/* Encrypt what we have and put back into block. */
DES_DO_ENCRYPT(left, right, kp);
- ptr = block;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ store_32_be(left, block);
+ store_32_be(right, block + 4);
- krb5int_c_iov_put_block_nocopy(data, num_data, storage,
- MIT_DES_BLOCK_LENGTH, &output_pos,
- block);
+ k5_iov_cursor_put(&cursor, block);
}
- if (ivec != NULL && block != NULL) {
- ptr = ivec;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ if (ivec != NULL) {
+ store_32_be(left, ivec);
+ store_32_be(right, ivec + 4);
}
}
@@ -93,11 +77,8 @@ krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
const unsigned char *ip;
unsigned DES_INT32 ocipherl, ocipherr;
unsigned DES_INT32 cipherl, cipherr;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MIT_DES_BLOCK_LENGTH], *block = NULL, *ptr;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
+ struct iov_cursor cursor;
+ unsigned char block[MIT_DES_BLOCK_LENGTH];
/* Get key pointer here. This won't need to be reinitialized. */
kp = (const unsigned DES_INT32 *)schedule;
@@ -110,21 +91,14 @@ krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
/* Prime the old cipher with ivec. */
ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
- GET_HALF_BLOCK(ocipherl, ip);
- GET_HALF_BLOCK(ocipherr, ip);
-
- /* Work the length down 8 bytes at a time. */
- for (;;) {
- if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
- data, num_data, &input_pos, &ptr))
- break;
- block = ptr;
+ ocipherl = load_32_be(ip);
+ ocipherr = load_32_be(ip + 4);
+ k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE);
+ while (k5_iov_cursor_get(&cursor, block)) {
/* Split this block into left and right. */
- GET_HALF_BLOCK(left, ptr);
- GET_HALF_BLOCK(right, ptr);
- cipherl = left;
- cipherr = right;
+ cipherl = left = load_32_be(block);
+ cipherr = right = load_32_be(block + 4);
/* Decrypt and xor with the old cipher to get plain text. */
DES_DO_DECRYPT(left, right, kp);
@@ -132,23 +106,19 @@ krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
right ^= ocipherr;
/* Store the encrypted halves back into block. */
- ptr = block;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ store_32_be(left, block);
+ store_32_be(right, block + 4);
/* Save current cipher block halves. */
ocipherl = cipherl;
ocipherr = cipherr;
- krb5int_c_iov_put_block_nocopy(data, num_data, storage,
- MIT_DES_BLOCK_LENGTH, &output_pos,
- block);
+ k5_iov_cursor_put(&cursor, block);
}
- if (ivec != NULL && block != NULL) {
- ptr = ivec;
- PUT_HALF_BLOCK(ocipherl, ptr);
- PUT_HALF_BLOCK(ocipherr, ptr);
+ if (ivec != NULL) {
+ store_32_be(ocipherl, ivec);
+ store_32_be(ocipherr, ivec + 4);
}
}
@@ -160,42 +130,30 @@ krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
unsigned DES_INT32 left, right;
const unsigned DES_INT32 *kp;
const unsigned char *ip;
- struct iov_block_state input_pos;
- unsigned char storage[MIT_DES_BLOCK_LENGTH], *ptr;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- input_pos.include_sign_only = 1;
+ struct iov_cursor cursor;
+ unsigned char block[MIT_DES_BLOCK_LENGTH];
/* Get key pointer here. This won't need to be reinitialized. */
kp = (const unsigned DES_INT32 *)schedule;
/* Initialize left and right with the contents of the initial vector. */
ip = (ivec != NULL) ? ivec : mit_des_zeroblock;
- GET_HALF_BLOCK(left, ip);
- GET_HALF_BLOCK(right, ip);
-
- /* Work the length down 8 bytes at a time. */
- for (;;) {
- unsigned DES_INT32 temp;
-
- if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
- data, num_data, &input_pos, &ptr))
- break;
+ left = load_32_be(ip);
+ right = load_32_be(ip + 4);
+ k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE);
+ while (k5_iov_cursor_get(&cursor, block)) {
/* Decompose this block and xor it with the previous ciphertext. */
- GET_HALF_BLOCK(temp, ptr);
- left ^= temp;
- GET_HALF_BLOCK(temp, ptr);
- right ^= temp;
+ left ^= load_32_be(block);
+ right ^= load_32_be(block + 4);
/* Encrypt what we have. */
DES_DO_ENCRYPT(left, right, kp);
}
/* Output the final ciphertext block. */
- ptr = out;
- PUT_HALF_BLOCK(left, ptr);
- PUT_HALF_BLOCK(right, ptr);
+ store_32_be(left, out);
+ store_32_be(right, out + 4);
}
#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO)
diff --git a/src/lib/crypto/builtin/enc_provider/aes.c b/src/lib/crypto/builtin/enc_provider/aes.c
index b46680a9e0..280119a2cc 100644
--- a/src/lib/crypto/builtin/enc_provider/aes.c
+++ b/src/lib/crypto/builtin/enc_provider/aes.c
@@ -85,9 +85,8 @@ krb5int_aes_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;
+ size_t input_length, nblocks, blockno;
+ struct iov_cursor cursor;
if (key->cache == NULL) {
key->cache = malloc(sizeof(struct aes_key_info_cache));
@@ -106,34 +105,25 @@ krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
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);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
- krb5int_c_iov_get_block(tmp, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_get(&cursor, tmp);
enc(tmp2, tmp, &CACHE(key)->enc_ctx);
- krb5int_c_iov_put_block(data, num_data, tmp2, BLOCK_SIZE, &output_pos);
+ k5_iov_cursor_put(&cursor, tmp2);
} 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;
+ unsigned char block[BLOCK_SIZE];
- krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
- data, num_data, &input_pos, &block);
+ k5_iov_cursor_get(&cursor, 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);
+ k5_iov_cursor_put(&cursor, block);
/* Set up for next block. */
memcpy(tmp, block, BLOCK_SIZE);
@@ -143,11 +133,8 @@ krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
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);
+ k5_iov_cursor_get(&cursor, blockN2);
+ k5_iov_cursor_get(&cursor, blockN1);
/* Encrypt second last block */
xorblock(tmp, blockN2);
@@ -161,10 +148,8 @@ krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
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);
+ k5_iov_cursor_put(&cursor, blockN1);
+ k5_iov_cursor_put(&cursor, blockN2);
if (ivec != NULL)
memcpy(ivec->data, blockN1, BLOCK_SIZE);
@@ -178,10 +163,8 @@ krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
size_t num_data)
{
unsigned char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
- int nblocks = 0, blockno;
- unsigned int i;
- size_t input_length;
- struct iov_block_state input_pos, output_pos;
+ size_t input_length, nblocks, blockno;
+ struct iov_cursor cursor;
CHECK_SIZES;
@@ -202,47 +185,35 @@ krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
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);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
- krb5int_c_iov_get_block(tmp, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_get(&cursor, tmp);
dec(tmp2, tmp, &CACHE(key)->dec_ctx);
- krb5int_c_iov_put_block(data, num_data, tmp2, BLOCK_SIZE, &output_pos);
+ k5_iov_cursor_put(&cursor, tmp2);
} 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;
+ unsigned char block[BLOCK_SIZE];
- krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
- data, num_data, &input_pos, &block);
+ k5_iov_cursor_get(&cursor, block);
memcpy(tmp2, block, BLOCK_SIZE);
dec(block, block, &CACHE(key)->dec_ctx);
xorblock(block, tmp);
memcpy(tmp, tmp2, BLOCK_SIZE);
- krb5int_c_iov_put_block_nocopy(data, num_data, blockN, BLOCK_SIZE,
- &output_pos, block);
+ k5_iov_cursor_put(&cursor, block);
}
/* 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 */
- 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);
+ k5_iov_cursor_get(&cursor, blockN2);
+ k5_iov_cursor_get(&cursor, blockN1);
if (ivec != NULL)
memcpy(ivec->data, blockN2, BLOCK_SIZE);
@@ -263,10 +234,8 @@ krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
memcpy(blockN1, tmp3, BLOCK_SIZE);
/* Put the last two blocks back into the iovec */
- 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);
+ k5_iov_cursor_put(&cursor, blockN1);
+ k5_iov_cursor_put(&cursor, blockN2);
}
return 0;
diff --git a/src/lib/crypto/builtin/enc_provider/camellia.c b/src/lib/crypto/builtin/enc_provider/camellia.c
index 7a0fbd96ef..efba629ebe 100644
--- a/src/lib/crypto/builtin/enc_provider/camellia.c
+++ b/src/lib/crypto/builtin/enc_provider/camellia.c
@@ -82,9 +82,8 @@ 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;
+ size_t input_length, nblocks, blockno;
+ struct iov_cursor cursor;
if (key->cache == NULL) {
key->cache = malloc(sizeof(struct camellia_key_info_cache));
@@ -102,34 +101,25 @@ krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec,
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);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
- krb5int_c_iov_get_block(tmp, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_get(&cursor, tmp);
enc(tmp2, tmp, &CACHE(key)->enc_ctx);
- krb5int_c_iov_put_block(data, num_data, tmp2, BLOCK_SIZE, &output_pos);
+ k5_iov_cursor_put(&cursor, tmp2);
} 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;
+ unsigned char block[BLOCK_SIZE];
- krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
- data, num_data, &input_pos, &block);
+ k5_iov_cursor_get(&cursor, 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);
+ k5_iov_cursor_put(&cursor, block);
/* Set up for next block. */
memcpy(tmp, block, BLOCK_SIZE);
@@ -139,11 +129,8 @@ krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec,
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);
+ k5_iov_cursor_get(&cursor, blockN2);
+ k5_iov_cursor_get(&cursor, blockN1);
/* Encrypt second last block */
xorblock(tmp, blockN2);
@@ -157,10 +144,8 @@ krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec,
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);
+ k5_iov_cursor_put(&cursor, blockN1);
+ k5_iov_cursor_put(&cursor, blockN2);
if (ivec != NULL)
memcpy(ivec->data, blockN1, BLOCK_SIZE);
@@ -174,10 +159,8 @@ krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec,
krb5_crypto_iov *data, size_t num_data)
{
unsigned char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
- int nblocks = 0, blockno;
- unsigned int i;
- size_t input_length;
- struct iov_block_state input_pos, output_pos;
+ size_t input_length, nblocks, blockno;
+ struct iov_cursor cursor;
if (key->cache == NULL) {
key->cache = malloc(sizeof(struct camellia_key_info_cache));
@@ -196,47 +179,35 @@ krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec,
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);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
- krb5int_c_iov_get_block(tmp, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_get(&cursor, tmp);
dec(tmp2, tmp, &CACHE(key)->dec_ctx);
- krb5int_c_iov_put_block(data, num_data, tmp2, BLOCK_SIZE, &output_pos);
+ k5_iov_cursor_put(&cursor, tmp2);
} 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;
+ unsigned char block[BLOCK_SIZE];
- krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
- data, num_data, &input_pos, &block);
+ k5_iov_cursor_get(&cursor, block);
memcpy(tmp2, block, BLOCK_SIZE);
dec(block, block, &CACHE(key)->dec_ctx);
xorblock(block, tmp);
memcpy(tmp, tmp2, BLOCK_SIZE);
- krb5int_c_iov_put_block_nocopy(data, num_data, blockN, BLOCK_SIZE,
- &output_pos, block);
+ k5_iov_cursor_put(&cursor, block);
}
/* 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 */
- 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);
+ k5_iov_cursor_get(&cursor, blockN2);
+ k5_iov_cursor_get(&cursor, blockN1);
if (ivec != NULL)
memcpy(ivec->data, blockN2, BLOCK_SIZE);
@@ -257,10 +228,8 @@ krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec,
memcpy(blockN1, tmp3, BLOCK_SIZE);
/* Put the last two blocks back into the iovec */
- 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);
+ k5_iov_cursor_put(&cursor, blockN1);
+ k5_iov_cursor_put(&cursor, blockN2);
}
return 0;
@@ -272,8 +241,8 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
krb5_data *output)
{
camellia_ctx ctx;
- unsigned char blockY[BLOCK_SIZE];
- struct iov_block_state iov_state;
+ unsigned char blockY[BLOCK_SIZE], blockB[BLOCK_SIZE];
+ struct iov_cursor cursor;
if (output->length < BLOCK_SIZE)
return KRB5_BAD_MSIZE;
@@ -287,14 +256,8 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
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;
-
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, blockB)) {
xorblock(blockB, blockY);
if (camellia_enc_blk(blockB, blockY, &ctx) != camellia_good)
abort();
diff --git a/src/lib/crypto/builtin/enc_provider/des.c b/src/lib/crypto/builtin/enc_provider/des.c
index 72a3ffc3b7..30b8229f8c 100644
--- a/src/lib/crypto/builtin/enc_provider/des.c
+++ b/src/lib/crypto/builtin/enc_provider/des.c
@@ -33,18 +33,11 @@ validate_and_schedule(krb5_key key, const krb5_data *ivec,
const krb5_crypto_iov *data, size_t num_data,
mit_des_key_schedule schedule)
{
- size_t i, input_length;
-
- for (i = 0, input_length = 0; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
-
- if (ENCRYPT_IOV(iov))
- input_length += iov->data.length;
- }
-
if (key->keyblock.length != 8)
return KRB5_BAD_KEYSIZE;
- if (input_length % 8 != 0 || (ivec != NULL && ivec->length != 8))
+ if (iov_total_length(data, num_data, FALSE) % 8 != 0)
+ return KRB5_BAD_MSIZE;
+ if (ivec != NULL && ivec->length != 8)
return KRB5_BAD_MSIZE;
switch (mit_des_key_sched(key->keyblock.contents, schedule)) {
diff --git a/src/lib/crypto/builtin/enc_provider/des3.c b/src/lib/crypto/builtin/enc_provider/des3.c
index 793db5e563..9b82442236 100644
--- a/src/lib/crypto/builtin/enc_provider/des3.c
+++ b/src/lib/crypto/builtin/enc_provider/des3.c
@@ -33,18 +33,9 @@ validate_and_schedule(krb5_key key, const krb5_data *ivec,
const krb5_crypto_iov *data, size_t num_data,
mit_des3_key_schedule *schedule)
{
- size_t i, input_length;
-
- for (i = 0, input_length = 0; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
-
- if (ENCRYPT_IOV(iov))
- input_length += iov->data.length;
- }
-
if (key->keyblock.length != 24)
return(KRB5_BAD_KEYSIZE);
- if ((input_length%8) != 0)
+ if (iov_total_length(data, num_data, FALSE) % 8 != 0)
return(KRB5_BAD_MSIZE);
if (ivec && (ivec->length != 8))
return(KRB5_BAD_MSIZE);
diff --git a/src/lib/crypto/krb/aead.c b/src/lib/crypto/krb/aead.c
index 7bfed4b1e0..935125d9d0 100644
--- a/src/lib/crypto/krb/aead.c
+++ b/src/lib/crypto/krb/aead.c
@@ -135,3 +135,89 @@ krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length)
else
return padding - (data_length % padding);
}
+
+/* Return the next iov (starting from ind) which cursor should process, or
+ * cursor->iov_count if there are none remaining. */
+static size_t
+next_iov_to_process(struct iov_cursor *cursor, size_t ind)
+{
+ krb5_crypto_iov *iov;
+
+ for (; ind < cursor->iov_count; ind++) {
+ iov = &cursor->iov[ind];
+ if (cursor->signing ? SIGN_IOV(iov) : ENCRYPT_IOV(iov))
+ break;
+ }
+ return ind;
+}
+
+void
+k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov,
+ size_t count, size_t block_size, krb5_boolean signing)
+{
+ cursor->iov = iov;
+ cursor->iov_count = count;
+ cursor->block_size = block_size;
+ cursor->signing = signing;
+ cursor->in_iov = next_iov_to_process(cursor, 0);
+ cursor->out_iov = cursor->in_iov;
+ cursor->in_pos = cursor->out_pos = 0;
+}
+
+/* Fetch one block from cursor's input position. */
+krb5_boolean
+k5_iov_cursor_get(struct iov_cursor *cursor, unsigned char *block)
+{
+ size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size;
+ const krb5_crypto_iov *iov;
+
+ remain = cursor->block_size;
+ while (remain > 0 && cursor->in_iov < cursor->iov_count) {
+ iov = &cursor->iov[cursor->in_iov];
+
+ nbytes = iov->data.length - cursor->in_pos;
+ if (nbytes > remain)
+ nbytes = remain;
+
+ memcpy(block + bsz - remain, iov->data.data + cursor->in_pos, nbytes);
+ cursor->in_pos += nbytes;
+ remain -= nbytes;
+
+ if (cursor->in_pos == iov->data.length) {
+ cursor->in_iov = next_iov_to_process(cursor, cursor->in_iov + 1);
+ cursor->in_pos = 0;
+ }
+ }
+
+ if (remain == bsz)
+ return FALSE;
+ if (remain > 0)
+ memset(block + bsz - remain, 0, remain);
+ return TRUE;
+}
+
+/* Write a block to a cursor's output position. */
+void
+k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block)
+{
+ size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size;
+ const krb5_crypto_iov *iov;
+
+ remain = cursor->block_size;
+ while (remain > 0 && cursor->out_iov < cursor->iov_count) {
+ iov = &cursor->iov[cursor->out_iov];
+
+ nbytes = iov->data.length - cursor->out_pos;
+ if (nbytes > remain)
+ nbytes = remain;
+
+ memcpy(iov->data.data + cursor->out_pos, block + bsz - remain, nbytes);
+ cursor->out_pos += nbytes;
+ remain -= nbytes;
+
+ if (cursor->out_pos == iov->data.length) {
+ cursor->out_iov = next_iov_to_process(cursor, cursor->out_iov + 1);
+ cursor->out_pos = 0;
+ }
+ }
+}
diff --git a/src/lib/crypto/krb/cmac.c b/src/lib/crypto/krb/cmac.c
index 2e220c5d56..066b534d1b 100644
--- a/src/lib/crypto/krb/cmac.c
+++ b/src/lib/crypto/krb/cmac.c
@@ -145,8 +145,8 @@ krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
unsigned char input[BLOCK_SIZE];
unsigned int n, i, flag;
krb5_error_code ret;
- struct iov_block_state iov_state;
- unsigned int length;
+ struct iov_cursor cursor;
+ size_t length;
krb5_crypto_iov iov[1];
krb5_data d;
@@ -155,12 +155,7 @@ krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
if (enc->block_size != BLOCK_SIZE)
return KRB5_BAD_MSIZE;
- for (i = 0, length = 0; i < num_data; i++) {
- const krb5_crypto_iov *piov = &data[i];
-
- if (SIGN_IOV(piov))
- length += piov->data.length;
- }
+ length = iov_total_length(data, num_data, TRUE);
/* Step 1. */
ret = generate_subkey(enc, key, K1, K2);
@@ -186,10 +181,9 @@ krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
d = make_data(Y, BLOCK_SIZE);
/* Step 6 (all but last block). */
- IOV_BLOCK_STATE_INIT(&iov_state);
- iov_state.include_sign_only = 1;
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, TRUE);
for (i = 0; i < n - 1; i++) {
- krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state);
+ k5_iov_cursor_get(&cursor, input);
ret = enc->cbc_mac(key, iov, 1, &d, &d);
if (ret != 0)
@@ -197,7 +191,7 @@ krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
}
/* Step 4. */
- krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state);
+ k5_iov_cursor_get(&cursor, input);
if (flag) {
/* last block is complete block */
xor_128(input, K1, M_last);
diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
index 01090d0068..c2c6344bc8 100644
--- a/src/lib/crypto/krb/crypto_int.h
+++ b/src/lib/crypto/krb/crypto_int.h
@@ -381,20 +381,17 @@ void krb5int_default_free_state(krb5_data *state);
#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \
(_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY )
-struct iov_block_state {
- size_t iov_pos; /* index into iov array */
- size_t data_pos; /* index into iov contents */
- unsigned int ignore_header : 1; /* have/should we process HEADER */
- unsigned int include_sign_only : 1; /* should we process SIGN_ONLY blocks */
- unsigned int pad_to_boundary : 1; /* should we zero fill blocks until next buffer */
+struct iov_cursor {
+ const krb5_crypto_iov *iov; /* iov array we are iterating over */
+ size_t iov_count; /* size of iov array */
+ size_t block_size; /* size of blocks we will be obtaining */
+ krb5_boolean signing; /* should we process SIGN_ONLY blocks */
+ size_t in_iov; /* read index into iov array */
+ size_t in_pos; /* read index into iov contents */
+ size_t out_iov; /* write index into iov array */
+ size_t out_pos; /* write index into iov contents */
};
-#define IOV_BLOCK_STATE_INIT(_state) ((_state)->iov_pos = \
- (_state)->data_pos = \
- (_state)->ignore_header = \
- (_state)->include_sign_only = \
- (_state)->pad_to_boundary = 0)
-
krb5_crypto_iov *krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data,
krb5_cryptotype type);
@@ -408,6 +405,14 @@ krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp,
unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp,
size_t data_length);
+void k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov,
+ size_t count, size_t block_size, krb5_boolean signing);
+
+krb5_boolean k5_iov_cursor_get(struct iov_cursor *cursor,
+ unsigned char *block);
+
+void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block);
+
/*** Crypto module declarations ***/
/* Modules must implement the following enc_providers and hash_providers: */
@@ -580,225 +585,50 @@ encrypt_block(const struct krb5_enc_provider *enc, krb5_key key,
return enc->encrypt(key, 0, &iov, 1);
}
-/* Decide whether to process an IOV block. */
-static inline int
-process_block_p(const krb5_crypto_iov *data, size_t num_data,
- struct iov_block_state *iov_state, size_t i)
-{
- const krb5_crypto_iov *iov = &data[i];
- int process_block;
-
- switch (iov->flags) {
- case KRB5_CRYPTO_TYPE_SIGN_ONLY:
- process_block = iov_state->include_sign_only;
- break;
- case KRB5_CRYPTO_TYPE_PADDING:
- process_block = (iov_state->pad_to_boundary == 0);
- break;
- case KRB5_CRYPTO_TYPE_HEADER:
- process_block = (iov_state->ignore_header == 0);
- break;
- case KRB5_CRYPTO_TYPE_DATA:
- process_block = 1;
- break;
- default:
- process_block = 0;
- break;
- }
-
- return process_block;
-}
-
-/*
- * Returns TRUE if, having reached the end of the current buffer,
- * we should pad the rest of the block with zeros.
- */
-static inline int
-pad_to_boundary_p(const krb5_crypto_iov *data,
- size_t num_data,
- struct iov_block_state *iov_state,
- size_t i,
- size_t j)
-{
- /* If the pad_to_boundary flag is unset, return FALSE */
- if (iov_state->pad_to_boundary == 0)
- return 0;
-
- /* If we haven't got any data, we need to get some */
- if (j == 0)
- return 0;
-
- /* No boundary between adjacent buffers marked for processing */
- if (data[iov_state->iov_pos].flags == data[i].flags)
- return 0;
-
- return 1;
-}
-
-/*
- * Retrieve a block from the IOV. If p is non-NULL and the next block is
- * completely contained within the current buffer, then *p will contain an
- * alias into the buffer; otherwise, a copy will be made into storage.
- *
- * After calling this function, encrypt the returned block and then call
- * krb5int_c_iov_put_block_nocopy() (with a separate output cursor). If
- * p was non-NULL on the call to get_block(), then pass that pointer in.
- */
-static inline krb5_boolean
-krb5int_c_iov_get_block_nocopy(unsigned char *storage,
- size_t block_size,
- const krb5_crypto_iov *data,
- size_t num_data,
- struct iov_block_state *iov_state,
- unsigned char **p)
+/* Return the total length of the to-be-signed or to-be-encrypted buffers in an
+ * iov chain. */
+static inline size_t
+iov_total_length(const krb5_crypto_iov *data, size_t num_data,
+ krb5_boolean signing)
{
- size_t i, j = 0;
-
- if (p != NULL)
- *p = storage;
-
- for (i = iov_state->iov_pos; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
- size_t nbytes;
-
- if (!process_block_p(data, num_data, iov_state, i))
- continue;
-
- if (pad_to_boundary_p(data, num_data, iov_state, i, j))
- break;
-
- iov_state->iov_pos = i;
-
- nbytes = iov->data.length - iov_state->data_pos;
- if (nbytes > block_size - j)
- nbytes = block_size - j;
-
- /*
- * If we can return a pointer into a complete block, then do so.
- */
- if (p != NULL && j == 0 && nbytes == block_size) {
- *p = (unsigned char *)iov->data.data + iov_state->data_pos;
- } else {
- memcpy(storage + j, iov->data.data + iov_state->data_pos, nbytes);
- }
+ size_t i, total = 0;
- iov_state->data_pos += nbytes;
- j += nbytes;
-
- assert(j <= block_size);
-
- if (j == block_size)
- break;
-
- assert(iov_state->data_pos == iov->data.length);
-
- iov_state->data_pos = 0;
+ for (i = 0; i < num_data; i++) {
+ if (signing ? SIGN_IOV(&data[i]) : ENCRYPT_IOV(&data[i]))
+ total += data[i].data.length;
}
-
- iov_state->iov_pos = i;
-
- if (j == 0)
- return FALSE;
- else if (j != block_size)
- memset(storage + j, 0, block_size - j);
-
- return TRUE;
+ return total;
}
/*
- * Store a block retrieved with krb5int_c_iov_get_block_no_copy if
- * necessary, and advance the output cursor.
+ * Return the number of contiguous blocks available within the current input
+ * IOV of the cursor c, so that the caller can do in-place encryption.
+ * Do not call if c might be exhausted.
*/
-static inline krb5_boolean
-krb5int_c_iov_put_block_nocopy(const krb5_crypto_iov *data,
- size_t num_data,
- unsigned char *storage,
- size_t block_size,
- struct iov_block_state *iov_state,
- unsigned char *p)
+static inline size_t
+iov_cursor_contig_blocks(struct iov_cursor *c)
{
- size_t i, j = 0;
-
- assert(p != NULL);
-
- for (i = iov_state->iov_pos; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
- size_t nbytes;
-
- if (!process_block_p(data, num_data, iov_state, i))
- continue;
-
- if (pad_to_boundary_p(data, num_data, iov_state, i, j))
- break;
-
- iov_state->iov_pos = i;
-
- nbytes = iov->data.length - iov_state->data_pos;
- if (nbytes > block_size - j)
- nbytes = block_size - j;
-
- /*
- * If we had previously returned a pointer into a complete block,
- * then no action is required.
- */
- if (p == storage) {
- memcpy(iov->data.data + iov_state->data_pos, storage + j, nbytes);
- } else {
- /* Ensure correctly paired with a call to get_block_nocopy(). */
- assert(j == 0);
- assert(nbytes == 0 || nbytes == block_size);
- }
-
- iov_state->data_pos += nbytes;
- j += nbytes;
-
- assert(j <= block_size);
-
- if (j == block_size)
- break;
-
- assert(iov_state->data_pos == iov->data.length);
-
- iov_state->data_pos = 0;
- }
-
- iov_state->iov_pos = i;
-
-#ifdef DEBUG_IOV
- dump_block("put_block", i, j, p, block_size);
-#endif
-
- return (iov_state->iov_pos < num_data);
+ return (c->iov[c->in_iov].data.length - c->in_pos) / c->block_size;
}
-/*
- * A wrapper for krb5int_c_iov_get_block_nocopy() that always makes
- * a copy.
- */
-static inline krb5_boolean
-krb5int_c_iov_get_block(unsigned char *block,
- size_t block_size,
- const krb5_crypto_iov *data,
- size_t num_data,
- struct iov_block_state *iov_state)
+/* Return the current input pointer within the cursor c. Do not call if c
+ * might be exhausted. */
+static inline unsigned char *
+iov_cursor_ptr(struct iov_cursor *c)
{
- return krb5int_c_iov_get_block_nocopy(block, block_size, data, num_data,
- iov_state, NULL);
+ return (unsigned char *)&c->iov[c->in_iov].data.data[c->in_pos];
}
/*
- * A wrapper for krb5int_c_iov_put_block_nocopy() that always copies
- * the block.
+ * Advance the input and output pointers of c by nblocks blocks. nblocks must
+ * not be greater than the return value of iov_cursor_contig_blocks, and the
+ * input and output positions must be identical.
*/
-static inline krb5_boolean
-krb5int_c_iov_put_block(const krb5_crypto_iov *data,
- size_t num_data,
- unsigned char *block,
- size_t block_size,
- struct iov_block_state *iov_state)
+static inline void
+iov_cursor_advance(struct iov_cursor *c, size_t nblocks)
{
- return krb5int_c_iov_put_block_nocopy(data, num_data, block, block_size,
- iov_state, block);
+ c->in_pos += nblocks * c->block_size;
+ c->out_pos += nblocks * c->block_size;
}
#endif /* CRYPTO_INT_H */
diff --git a/src/lib/crypto/krb/enc_old.c b/src/lib/crypto/krb/enc_old.c
index b44a3994f0..a40f709425 100644
--- a/src/lib/crypto/krb/enc_old.c
+++ b/src/lib/crypto/krb/enc_old.c
@@ -130,17 +130,9 @@ krb5int_old_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
krb5_crypto_iov *header, *trailer;
krb5_data checksum, crcivec = empty_data();
char *saved_checksum = NULL;
- size_t i;
- unsigned int cipherlen = 0;
/* Check that the input data is correctly padded. */
- for (i = 0; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
-
- if (ENCRYPT_IOV(iov))
- cipherlen += iov->data.length;
- }
- if (cipherlen % enc->block_size != 0)
+ if (iov_total_length(data, num_data, FALSE) % enc->block_size != 0)
return KRB5_BAD_MSIZE;
header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
diff --git a/src/lib/crypto/nss/enc_provider/enc_gen.c b/src/lib/crypto/nss/enc_provider/enc_gen.c
index dea22f8466..7022a78eed 100644
--- a/src/lib/crypto/nss/enc_provider/enc_gen.c
+++ b/src/lib/crypto/nss/enc_provider/enc_gen.c
@@ -172,35 +172,25 @@ k5_nss_gen_block_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
PK11Context *ctx = NULL;
SECStatus rv;
SECItem *param = NULL;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MAX_BLOCK_SIZE];
+ struct iov_cursor cursor;
+ unsigned char block[MAX_BLOCK_SIZE];
unsigned char iv0[MAX_BLOCK_SIZE];
- unsigned char *ptr = NULL,*lastptr = NULL;
+ unsigned char *lastptr = NULL;
SECItem iv;
size_t blocksize;
int length = 0;
int lastblock = -1;
int currentblock;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
blocksize = PK11_GetBlockSize(mech, NULL);
- assert(blocksize <= sizeof(storage));
+ assert(blocksize <= sizeof(block));
if (ivec && ivec->data) {
iv.data = (unsigned char *)ivec->data;
iv.len = ivec->length;
if (operation == CKA_DECRYPT) {
- int i, inputlength;
-
/* Count the blocks so we know which block is last. */
- for (i = 0, inputlength = 0; i < (int)num_data; i++) {
- krb5_crypto_iov *iov = &data[i];
-
- if (ENCRYPT_IOV(iov))
- inputlength += iov->data.length;
- }
+ int inputlength = iov_total_length(data, num_data, FALSE);
lastblock = (inputlength/blocksize) -1;
}
} else {
@@ -216,26 +206,25 @@ k5_nss_gen_block_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
goto done;
}
+ k5_iov_cursor_init(&cursor, data, num_data, blocksize, FALSE);
for (currentblock = 0;;currentblock++) {
- if (!krb5int_c_iov_get_block_nocopy(storage, blocksize, data, num_data,
- &input_pos, &ptr))
+ if (!k5_iov_cursor_get(&cursor, block))
break;
lastptr = NULL;
/* only set if we are decrypting */
if (lastblock == currentblock)
- memcpy(ivec->data, ptr, blocksize);
+ memcpy(ivec->data, block, blocksize);
- rv = PK11_CipherOp(ctx, ptr, &length, blocksize, ptr, blocksize);
+ rv = PK11_CipherOp(ctx, block, &length, blocksize, block, blocksize);
if (rv != SECSuccess) {
ret = k5_nss_map_last_error();
break;
}
- lastptr = ptr;
- krb5int_c_iov_put_block_nocopy(data, num_data, storage, blocksize,
- &output_pos, ptr);
+ lastptr = block;
+ k5_iov_cursor_put(&cursor, block);
}
if (lastptr && ivec && ivec->data && operation == CKA_ENCRYPT) {
@@ -349,26 +338,22 @@ k5_nss_gen_cts_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
PK11Context *ctx = NULL;
SECStatus rv;
SECItem *param = NULL;
- struct iov_block_state input_pos, output_pos;
- unsigned char storage[MAX_BLOCK_SIZE];
+ struct iov_cursor cursor;
+ unsigned char block[MAX_BLOCK_SIZE];
unsigned char recover1[MAX_BLOCK_SIZE];
unsigned char recover2[MAX_BLOCK_SIZE];
unsigned char block1[MAX_BLOCK_SIZE];
unsigned char block2[MAX_BLOCK_SIZE];
unsigned char iv0[MAX_BLOCK_SIZE];
- unsigned char *ptr = NULL;
SECItem iv;
size_t blocksize;
size_t bulk_length, remainder;
size_t input_length, lastblock;
size_t length;
- int i, len;
-
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
+ int len;
blocksize = PK11_GetBlockSize(mech, NULL);
- assert(blocksize <= sizeof(storage));
+ assert(blocksize <= sizeof(block));
if (ivec) {
iv.data = (unsigned char *)ivec->data;
@@ -380,12 +365,7 @@ k5_nss_gen_cts_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
}
param = PK11_ParamFromIV(mech, &iv);
- for (i = 0, input_length = 0; i < (int)num_data; i++) {
- krb5_crypto_iov *iov = &data[i];
-
- if (ENCRYPT_IOV(iov))
- input_length += iov->data.length;
- }
+ input_length = iov_total_length(data, num_data, FALSE);
/* Must be at least a block or we fail. */
if (input_length < blocksize) {
ret = EINVAL;
@@ -429,48 +409,44 @@ k5_nss_gen_cts_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
}
}
}
+ k5_iov_cursor_init(&cursor, data, num_data, blocksize, FALSE);
for (length = 0; length < lastblock; length += blocksize) {
- if (!krb5int_c_iov_get_block_nocopy(storage, blocksize, data, num_data,
- &input_pos, &ptr))
+ if (!k5_iov_cursor_get(&cursor, block))
break;
- rv = PK11_CipherOp(ctx, ptr, &len, blocksize, ptr, blocksize);
+ rv = PK11_CipherOp(ctx, block, &len, blocksize, block, blocksize);
if (rv != SECSuccess) {
ret = k5_nss_map_last_error();
break;
}
- krb5int_c_iov_put_block_nocopy(data, num_data, storage, blocksize,
- &output_pos, ptr);
+ k5_iov_cursor_put(&cursor, block);
}
if (remainder) {
if (operation == CKA_DECRYPT) {
if (bulk_length > blocksize) {
/* we need to save cn-2 */
- if (!krb5int_c_iov_get_block_nocopy(storage, blocksize, data,
- num_data, &input_pos,
- &ptr))
+ if (!k5_iov_cursor_get(&cursor, block))
goto done; /* shouldn't happen */
/* save cn-2 */
- memcpy(recover1, ptr, blocksize);
- memcpy(recover2, ptr, blocksize);
+ memcpy(recover1, block, blocksize);
+ memcpy(recover2, block, blocksize);
/* now process it as normal */
- rv = PK11_CipherOp(ctx, ptr, &len, blocksize, ptr, blocksize);
+ rv = PK11_CipherOp(ctx, block, &len, blocksize, block,
+ blocksize);
if (rv != SECSuccess) {
ret = k5_nss_map_last_error();
goto done;
}
- krb5int_c_iov_put_block_nocopy(data, num_data, storage,
- blocksize, &output_pos, ptr);
+ k5_iov_cursor_put(&cursor, block);
}
}
/* fetch the last 2 blocks */
- memset(block1, 0, blocksize); /* last block, could be partial */
- krb5int_c_iov_get_block(block2, blocksize, data, num_data, &input_pos);
- krb5int_c_iov_get_block(block1, remainder, data, num_data, &input_pos);
+ k5_iov_cursor_get(&cursor, block2);
+ k5_iov_cursor_get(&cursor, block1);
if (operation == CKA_DECRYPT) {
/* recover1 and recover2 are xor values to recover the true
* underlying data of the last 2 decrypts. This keeps us from
@@ -518,8 +494,8 @@ k5_nss_gen_cts_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
memcpy(ivec->data, block1, blocksize);
}
}
- krb5int_c_iov_put_block(data,num_data, block1, blocksize, &output_pos);
- krb5int_c_iov_put_block(data,num_data, block2, remainder, &output_pos);
+ k5_iov_cursor_put(&cursor, block1);
+ k5_iov_cursor_put(&cursor, block2);
}
done:
@@ -541,7 +517,7 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
PK11Context *ctx = NULL;
SECStatus rv;
SECItem *param = NULL;
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
unsigned char block[MAX_BLOCK_SIZE], *lastblock;
unsigned char iv0[MAX_BLOCK_SIZE];
SECItem iv;
@@ -549,9 +525,6 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
int length = 0;
int currentblock;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
blocksize = PK11_GetBlockSize(mech, NULL);
assert(blocksize <= sizeof(block));
if (output->length < blocksize)
@@ -574,9 +547,9 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
}
lastblock = iv.data;
+ k5_iov_cursor_init(&cursor, data, num_data, blocksize, FALSE);
for (currentblock = 0;;currentblock++) {
- if (!krb5int_c_iov_get_block(block, blocksize, data, num_data,
- &input_pos))
+ if (!k5_iov_cursor_get(&cursor, block))
break;
rv = PK11_CipherOp(ctx, block, &length, blocksize, block, blocksize);
if (rv != SECSuccess) {
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
index ced93f7426..8afa1a7579 100644
--- a/src/lib/crypto/openssl/enc_provider/aes.c
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
@@ -66,7 +66,7 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
int ret, olen = BLOCK_SIZE;
unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
EVP_CIPHER_CTX ciph_ctx;
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
@@ -74,15 +74,12 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret == 0)
return KRB5_CRYPTO_INTERNAL;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
- krb5int_c_iov_get_block(iblock, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
- if (ret == 1) {
- krb5int_c_iov_put_block(data, num_data, oblock, BLOCK_SIZE,
- &output_pos);
- }
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
zap(iblock, BLOCK_SIZE);
@@ -98,7 +95,7 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
int ret = 0, olen = BLOCK_SIZE;
unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
EVP_CIPHER_CTX ciph_ctx;
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
@@ -106,15 +103,12 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret == 0)
return KRB5_CRYPTO_INTERNAL;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
- krb5int_c_iov_get_block(iblock, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
- if (ret == 1) {
- krb5int_c_iov_put_block(data, num_data, oblock, BLOCK_SIZE,
- &output_pos);
- }
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
zap(iblock, BLOCK_SIZE);
@@ -130,7 +124,7 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
size_t size = 0;
unsigned char *oblock = NULL, *dbuf = NULL;
unsigned char iv_cts[IV_CTS_BUF_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
AES_KEY enck;
memset(iv_cts,0,sizeof(iv_cts));
@@ -150,22 +144,18 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
return ENOMEM;
}
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
- krb5int_c_iov_get_block(dbuf, dlen, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+ k5_iov_cursor_get(&cursor, dbuf);
AES_set_encrypt_key(key->keyblock.contents,
NUM_BITS * key->keyblock.length, &enck);
size = CRYPTO_cts128_encrypt((unsigned char *)dbuf, oblock, dlen, &enck,
iv_cts, (cbc128_f)AES_cbc_encrypt);
- if (size <= 0) {
+ if (size <= 0)
ret = KRB5_CRYPTO_INTERNAL;
- } else {
- krb5int_c_iov_put_block(data, num_data,
- oblock, dlen, &output_pos);
- }
+ else
+ k5_iov_cursor_put(&cursor, oblock);
if (!ret && ivec && ivec->data)
memcpy(ivec->data, iv_cts, sizeof(iv_cts));
@@ -187,7 +177,7 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
unsigned char *oblock = NULL;
unsigned char *dbuf = NULL;
unsigned char iv_cts[IV_CTS_BUF_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
AES_KEY deck;
memset(iv_cts,0,sizeof(iv_cts));
@@ -197,9 +187,6 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
memcpy(iv_cts, ivec->data,ivec->length);
}
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
oblock = OPENSSL_malloc(dlen);
if (!oblock)
return ENOMEM;
@@ -212,16 +199,16 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
AES_set_decrypt_key(key->keyblock.contents,
NUM_BITS * key->keyblock.length, &deck);
- krb5int_c_iov_get_block(dbuf, dlen, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+ k5_iov_cursor_get(&cursor, dbuf);
size = CRYPTO_cts128_decrypt((unsigned char *)dbuf, oblock,
dlen, &deck,
iv_cts, (cbc128_f)AES_cbc_encrypt);
if (size <= 0)
ret = KRB5_CRYPTO_INTERNAL;
- else {
- krb5int_c_iov_put_block(data, num_data, oblock, dlen, &output_pos);
- }
+ else
+ k5_iov_cursor_put(&cursor, oblock);
if (!ret && ivec && ivec->data)
memcpy(ivec->data, iv_cts, sizeof(iv_cts));
@@ -239,16 +226,9 @@ krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec,
krb5_crypto_iov *data, size_t num_data)
{
int ret = 0;
- int nblocks = 0;
- size_t input_length, i;
-
- 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;
- }
+ size_t input_length, nblocks;
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
if (input_length != BLOCK_SIZE)
@@ -266,16 +246,9 @@ krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec,
krb5_crypto_iov *data, size_t num_data)
{
int ret = 0;
- int nblocks = 0;
- size_t input_length, i;
-
- 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;
- }
+ size_t input_length, nblocks;
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
if (input_length != BLOCK_SIZE)
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index 2173db6a86..3ac3fd999b 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -90,7 +90,7 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
int ret, olen = BLOCK_SIZE;
unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
EVP_CIPHER_CTX ciph_ctx;
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
@@ -98,15 +98,12 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret == 0)
return KRB5_CRYPTO_INTERNAL;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
- krb5int_c_iov_get_block(iblock, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
- if (ret == 1) {
- krb5int_c_iov_put_block(data, num_data, oblock, BLOCK_SIZE,
- &output_pos);
- }
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
zap(iblock, BLOCK_SIZE);
@@ -122,7 +119,7 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
int ret = 0, olen = BLOCK_SIZE;
unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
EVP_CIPHER_CTX ciph_ctx;
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
@@ -130,15 +127,12 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret == 0)
return KRB5_CRYPTO_INTERNAL;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
- krb5int_c_iov_get_block(iblock, BLOCK_SIZE, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
- if (ret == 1) {
- krb5int_c_iov_put_block(data, num_data, oblock, BLOCK_SIZE,
- &output_pos);
- }
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
zap(iblock, BLOCK_SIZE);
@@ -154,7 +148,7 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
size_t size = 0;
unsigned char *oblock = NULL, *dbuf = NULL;
unsigned char iv_cts[IV_CTS_BUF_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
CAMELLIA_KEY enck;
memset(iv_cts,0,sizeof(iv_cts));
@@ -174,22 +168,18 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
return ENOMEM;
}
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
- krb5int_c_iov_get_block(dbuf, dlen, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+ k5_iov_cursor_get(&cursor, dbuf);
Camellia_set_key(key->keyblock.contents, NUM_BITS * key->keyblock.length,
&enck);
size = CRYPTO_cts128_encrypt((unsigned char *)dbuf, oblock, dlen, &enck,
iv_cts, (cbc128_f)Camellia_cbc_encrypt);
- if (size <= 0) {
+ if (size <= 0)
ret = KRB5_CRYPTO_INTERNAL;
- } else {
- krb5int_c_iov_put_block(data, num_data,
- oblock, dlen, &output_pos);
- }
+ else
+ k5_iov_cursor_put(&cursor, oblock);
if (!ret && ivec && ivec->data)
memcpy(ivec->data, iv_cts, sizeof(iv_cts));
@@ -211,7 +201,7 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
unsigned char *oblock = NULL;
unsigned char *dbuf = NULL;
unsigned char iv_cts[IV_CTS_BUF_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
CAMELLIA_KEY deck;
memset(iv_cts,0,sizeof(iv_cts));
@@ -221,9 +211,6 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
memcpy(iv_cts, ivec->data,ivec->length);
}
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
oblock = OPENSSL_malloc(dlen);
if (!oblock)
return ENOMEM;
@@ -236,16 +223,16 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
Camellia_set_key(key->keyblock.contents, NUM_BITS * key->keyblock.length,
&deck);
- krb5int_c_iov_get_block(dbuf, dlen, data, num_data, &input_pos);
+ k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE);
+ k5_iov_cursor_get(&cursor, dbuf);
size = CRYPTO_cts128_decrypt((unsigned char *)dbuf, oblock,
dlen, &deck,
iv_cts, (cbc128_f)Camellia_cbc_encrypt);
if (size <= 0)
ret = KRB5_CRYPTO_INTERNAL;
- else {
- krb5int_c_iov_put_block(data, num_data, oblock, dlen, &output_pos);
- }
+ else
+ k5_iov_cursor_put(&cursor, oblock);
if (!ret && ivec && ivec->data)
memcpy(ivec->data, iv_cts, sizeof(iv_cts));
@@ -263,16 +250,9 @@ krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec,
krb5_crypto_iov *data, size_t num_data)
{
int ret = 0;
- int nblocks = 0;
- size_t input_length, i;
-
- 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;
- }
+ size_t input_length, nblocks;
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
if (input_length != BLOCK_SIZE)
@@ -290,16 +270,9 @@ krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec,
krb5_crypto_iov *data, size_t num_data)
{
int ret = 0;
- int nblocks = 0;
- size_t input_length, i;
-
- 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;
- }
+ size_t input_length, nblocks;
+ input_length = iov_total_length(data, num_data, FALSE);
nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (nblocks == 1) {
if (input_length != BLOCK_SIZE)
@@ -318,8 +291,8 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
krb5_data *output)
{
CAMELLIA_KEY enck;
- unsigned char blockY[CAMELLIA_BLOCK_SIZE];
- struct iov_block_state iov_state;
+ unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
+ struct iov_cursor cursor;
if (output->length < CAMELLIA_BLOCK_SIZE)
return KRB5_BAD_MSIZE;
@@ -332,17 +305,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
else
memset(blockY, 0, CAMELLIA_BLOCK_SIZE);
- IOV_BLOCK_STATE_INIT(&iov_state);
-
- for (;;) {
- unsigned char blockB[CAMELLIA_BLOCK_SIZE];
-
- if (!krb5int_c_iov_get_block(blockB, CAMELLIA_BLOCK_SIZE, data,
- num_data, &iov_state))
- break;
-
+ k5_iov_cursor_init(&cursor, data, num_data, CAMELLIA_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, blockB)) {
xorblock(blockB, blockY);
-
Camellia_ecb_encrypt(blockB, blockY, &enck, 1);
}
diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
index 644e26633e..1db5ef0f41 100644
--- a/src/lib/crypto/openssl/enc_provider/des.c
+++ b/src/lib/crypto/openssl/enc_provider/des.c
@@ -62,13 +62,7 @@ static krb5_error_code
validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
size_t num_data, krb5_boolean *empty)
{
- size_t i, input_length;
-
- for (i = 0, input_length = 0; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
- if (ENCRYPT_IOV(iov))
- input_length += iov->data.length;
- }
+ size_t input_length = iov_total_length(data, num_data, FALSE);
if (key->keyblock.length != DES_KEY_SIZE)
return(KRB5_BAD_KEYSIZE);
@@ -87,13 +81,10 @@ k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
{
int ret, olen = DES_BLOCK_SIZE;
unsigned char iblock[DES_BLOCK_SIZE], oblock[DES_BLOCK_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX ciph_ctx;
krb5_boolean empty;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
ret = validate(key, ivec, data, num_data, &empty);
if (ret != 0 || empty)
return ret;
@@ -107,19 +98,13 @@ k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
- for (;;) {
-
- if (!krb5int_c_iov_get_block(iblock, DES_BLOCK_SIZE, data,
- num_data, &input_pos))
- break;
-
+ k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen,
(unsigned char *)iblock, DES_BLOCK_SIZE);
if (!ret)
break;
-
- krb5int_c_iov_put_block(data, num_data, oblock, DES_BLOCK_SIZE,
- &output_pos);
+ k5_iov_cursor_put(&cursor, oblock);
}
if (ivec != NULL)
@@ -141,13 +126,10 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
{
int ret, olen = DES_BLOCK_SIZE;
unsigned char iblock[DES_BLOCK_SIZE], oblock[DES_BLOCK_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX ciph_ctx;
krb5_boolean empty;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
ret = validate(key, ivec, data, num_data, &empty);
if (ret != 0 || empty)
return ret;
@@ -162,18 +144,13 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
- for (;;) {
-
- if (!krb5int_c_iov_get_block(iblock, DES_BLOCK_SIZE,
- data, num_data, &input_pos))
- break;
-
+ k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen,
iblock, DES_BLOCK_SIZE);
- if (!ret) break;
-
- krb5int_c_iov_put_block(data, num_data, oblock,
- DES_BLOCK_SIZE, &output_pos);
+ if (!ret)
+ break;
+ k5_iov_cursor_put(&cursor, oblock);
}
if (ivec != NULL)
@@ -194,7 +171,7 @@ k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
const krb5_data *ivec, krb5_data *output)
{
int ret;
- struct iov_block_state iov_state;
+ struct iov_cursor cursor;
DES_cblock blockY, blockB;
DES_key_schedule sched;
krb5_boolean empty;
@@ -214,11 +191,8 @@ k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
else
memset(blockY, 0, DES_BLOCK_SIZE);
- IOV_BLOCK_STATE_INIT(&iov_state);
- for (;;) {
- if (!krb5int_c_iov_get_block(blockB, DES_BLOCK_SIZE, data, num_data,
- &iov_state))
- break;
+ k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, blockB)) {
store_64_n(load_64_n(blockB) ^ load_64_n(blockY), blockB);
DES_ecb_encrypt(&blockB, &blockY, &sched, 1);
}
diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
index ca843f9f5e..d531f1036c 100644
--- a/src/lib/crypto/openssl/enc_provider/des3.c
+++ b/src/lib/crypto/openssl/enc_provider/des3.c
@@ -61,13 +61,7 @@ static krb5_error_code
validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data,
size_t num_data, krb5_boolean *empty)
{
- size_t i, input_length;
-
- for (i = 0, input_length = 0; i < num_data; i++) {
- const krb5_crypto_iov *iov = &data[i];
- if (ENCRYPT_IOV(iov))
- input_length += iov->data.length;
- }
+ size_t input_length = iov_total_length(data, num_data, FALSE);
if (key->keyblock.length != DES3_KEY_SIZE)
return(KRB5_BAD_KEYSIZE);
@@ -86,7 +80,7 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
{
int ret, olen = DES3_BLOCK_SIZE;
unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX ciph_ctx;
krb5_boolean empty;
@@ -94,9 +88,6 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret != 0 || empty)
return ret;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
@@ -107,19 +98,13 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
- for (;;) {
-
- if (!krb5int_c_iov_get_block(iblock, DES3_BLOCK_SIZE,
- data, num_data, &input_pos))
- break;
-
+ k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen,
(unsigned char *)iblock, DES3_BLOCK_SIZE);
if (!ret)
break;
-
- krb5int_c_iov_put_block(data, num_data,
- oblock, DES3_BLOCK_SIZE, &output_pos);
+ k5_iov_cursor_put(&cursor, oblock);
}
if (ivec != NULL)
@@ -141,7 +126,7 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
{
int ret, olen = DES3_BLOCK_SIZE;
unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
- struct iov_block_state input_pos, output_pos;
+ struct iov_cursor cursor;
EVP_CIPHER_CTX ciph_ctx;
krb5_boolean empty;
@@ -149,9 +134,6 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
if (ret != 0 || empty)
return ret;
- IOV_BLOCK_STATE_INIT(&input_pos);
- IOV_BLOCK_STATE_INIT(&output_pos);
-
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
@@ -162,19 +144,13 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
- for (;;) {
-
- if (!krb5int_c_iov_get_block(iblock, DES3_BLOCK_SIZE,
- data, num_data, &input_pos))
- break;
-
+ k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen,
(unsigned char *)iblock, DES3_BLOCK_SIZE);
if (!ret)
break;
-
- krb5int_c_iov_put_block(data, num_data, oblock, DES3_BLOCK_SIZE,
- &output_pos);
+ k5_iov_cursor_put(&cursor, oblock);
}
if (ivec != NULL)