void krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, const mit_des_key_schedule schedule, mit_des_cblock ivec) { 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); /* 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; /* Decompose this block and xor it with the previous ciphertext. */ GET_HALF_BLOCK(temp, ptr); left ^= temp; GET_HALF_BLOCK(temp, ptr); right ^= temp; /* 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); krb5int_c_iov_put_block_nocopy(data, num_data, storage, MIT_DES_BLOCK_LENGTH, &output_pos, block); } if (ivec != NULL && block != NULL) { ptr = ivec; PUT_HALF_BLOCK(left, ptr); PUT_HALF_BLOCK(right, ptr); } }
unsigned long mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, unsigned long length, const mit_des_key_schedule schedule, const krb5_octet *ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp; const unsigned char *ip; unsigned char *op; register DES_INT32 len; /* * Initialize left and right with the contents of the initial * vector. */ ip = ivec; GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); /* * Suitably initialized, now work the length down 8 bytes * at a time. */ ip = in; len = length; while (len > 0) { /* * Get more input, xor it in. If the length is * greater than or equal to 8 this is straight * forward. Otherwise we have to fart around. */ if (len >= 8) { unsigned DES_INT32 temp; GET_HALF_BLOCK(temp, ip); left ^= temp; GET_HALF_BLOCK(temp, ip); right ^= temp; len -= 8; } else { /* * Oh, shoot. We need to pad the * end with zeroes. Work backwards * to do this. */ ip += (int) len; switch(len) { case 7: right ^= (*(--ip) & FF_UINT32) << 8; case 6: right ^= (*(--ip) & FF_UINT32) << 16; case 5: right ^= (*(--ip) & FF_UINT32) << 24; case 4: left ^= *(--ip) & FF_UINT32; case 3: left ^= (*(--ip) & FF_UINT32) << 8; case 2: left ^= (*(--ip) & FF_UINT32) << 16; case 1: left ^= (*(--ip) & FF_UINT32) << 24; break; } len = 0; } /* * Encrypt what we have */ kp = (const unsigned DES_INT32 *)schedule; DES_DO_ENCRYPT(left, right, kp); } /* * Done. Left and right have the checksum. Put it into * the output. */ op = out; PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); /* * Return right. I'll bet the MIT code returns this * inconsistantly (with the low order byte of the checksum * not always in the low order byte of the DES_INT32). We won't. */ return right & 0xFFFFFFFFUL; }
void krb5int_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, unsigned long length, const mit_des_key_schedule schedule, const mit_des_cblock ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp; const unsigned char *ip; unsigned char *op; /* * 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; GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); /* * Suitably initialized, now work the length down 8 bytes * at a time. */ ip = *in; op = *out; while (length > 0) { /* * Get more input, xor it in. If the length is * greater than or equal to 8 this is straight * forward. Otherwise we have to fart around. */ if (length >= 8) { unsigned DES_INT32 temp; GET_HALF_BLOCK(temp, ip); left ^= temp; GET_HALF_BLOCK(temp, ip); right ^= temp; length -= 8; } else { /* * Oh, shoot. We need to pad the * end with zeroes. Work backwards * to do this. */ ip += (int) length; switch(length) { case 7: right ^= (*(--ip) & FF_UINT32) << 8; case 6: right ^= (*(--ip) & FF_UINT32) << 16; case 5: right ^= (*(--ip) & FF_UINT32) << 24; case 4: left ^= *(--ip) & FF_UINT32; case 3: left ^= (*(--ip) & FF_UINT32) << 8; case 2: left ^= (*(--ip) & FF_UINT32) << 16; case 1: left ^= (*(--ip) & FF_UINT32) << 24; break; } length = 0; } /* * Encrypt what we have */ DES_DO_ENCRYPT(left, right, kp); /* * Copy the results out */ PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); } }
void krb5int_des_cbc_decrypt(const mit_des_cblock *in, mit_des_cblock *out, unsigned long length, const mit_des_key_schedule schedule, const mit_des_cblock ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp; const unsigned char *ip; unsigned char *op; unsigned DES_INT32 ocipherl, ocipherr; unsigned DES_INT32 cipherl, cipherr; /* * Get key pointer here. This won't need to be reinitialized */ kp = (const unsigned DES_INT32 *)schedule; /* * Decrypting is harder than encrypting because of * the necessity of remembering a lot more things. * Should think about this a little more... */ if (length <= 0) return; /* * Prime the old cipher with ivec. */ ip = ivec; GET_HALF_BLOCK(ocipherl, ip); GET_HALF_BLOCK(ocipherr, ip); /* * Now do this in earnest until we run out of length. */ ip = *in; op = *out; for (;;) { /* check done inside loop */ /* * Read a block from the input into left and * right. Save this cipher block for later. */ GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); cipherl = left; cipherr = right; /* * Decrypt this. */ DES_DO_DECRYPT(left, right, kp); /* * Xor with the old cipher to get plain * text. Output 8 or less bytes of this. */ left ^= ocipherl; right ^= ocipherr; if (length > 8) { length -= 8; PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); /* * Save current cipher block here */ ocipherl = cipherl; ocipherr = cipherr; } else { /* * Trouble here. Start at end of output, * work backwards. */ op += (int) length; switch(length) { case 8: *(--op) = (unsigned char) (right & 0xff); case 7: *(--op) = (unsigned char) ((right >> 8) & 0xff); case 6: *(--op) = (unsigned char) ((right >> 16) & 0xff); case 5: *(--op) = (unsigned char) ((right >> 24) & 0xff); case 4: *(--op) = (unsigned char) (left & 0xff); case 3: *(--op) = (unsigned char) ((left >> 8) & 0xff); case 2: *(--op) = (unsigned char) ((left >> 16) & 0xff); case 1: *(--op) = (unsigned char) ((left >> 24) & 0xff); break; } break; /* we're done */ } } }
void krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data, unsigned long num_data, const mit_des_key_schedule ks1, const mit_des_key_schedule ks2, const mit_des_key_schedule ks3, mit_des_cblock ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp1, *kp2, *kp3; const unsigned char *ip; unsigned char *op; struct iov_block_state input_pos, output_pos; unsigned char iblock[MIT_DES_BLOCK_LENGTH]; unsigned char oblock[MIT_DES_BLOCK_LENGTH]; IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); /* * Get key pointer here. This won't need to be reinitialized */ kp1 = (const unsigned DES_INT32 *)ks1; kp2 = (const unsigned DES_INT32 *)ks2; kp3 = (const unsigned DES_INT32 *)ks3; /* * Initialize left and right with the contents of the initial * vector. */ if (ivec != NULL) ip = ivec; else ip = mit_des_zeroblock; GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); /* * Suitably initialized, now work the length down 8 bytes * at a time. */ for (;;) { unsigned DES_INT32 temp; ip = iblock; op = oblock; if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) break; if (input_pos.iov_pos == num_data) break; GET_HALF_BLOCK(temp, ip); left ^= temp; GET_HALF_BLOCK(temp, ip); right ^= temp; /* * Encrypt what we have */ DES_DO_ENCRYPT(left, right, kp1); DES_DO_DECRYPT(left, right, kp2); DES_DO_ENCRYPT(left, right, kp3); /* * Copy the results out */ PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); } if (ivec != NULL) memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); }
void krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data, unsigned long num_data, const mit_des_key_schedule ks1, const mit_des_key_schedule ks2, const mit_des_key_schedule ks3, mit_des_cblock ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp1, *kp2, *kp3; const unsigned char *ip; unsigned DES_INT32 ocipherl, ocipherr; unsigned DES_INT32 cipherl, cipherr; unsigned char *op; struct iov_block_state input_pos, output_pos; unsigned char iblock[MIT_DES_BLOCK_LENGTH]; unsigned char oblock[MIT_DES_BLOCK_LENGTH]; IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); /* * Get key pointer here. This won't need to be reinitialized */ kp1 = (const unsigned DES_INT32 *)ks1; kp2 = (const unsigned DES_INT32 *)ks2; kp3 = (const unsigned DES_INT32 *)ks3; /* * Decrypting is harder than encrypting because of * the necessity of remembering a lot more things. * Should think about this a little more... */ if (num_data == 0) return; /* * Prime the old cipher with ivec. */ if (ivec != NULL) ip = ivec; else ip = mit_des_zeroblock; GET_HALF_BLOCK(ocipherl, ip); GET_HALF_BLOCK(ocipherr, ip); /* * Now do this in earnest until we run out of length. */ for (;;) { /* * Read a block from the input into left and * right. Save this cipher block for later. */ if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) break; if (input_pos.iov_pos == num_data) break; ip = iblock; op = oblock; GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); cipherl = left; cipherr = right; /* * Decrypt this. */ DES_DO_DECRYPT(left, right, kp3); DES_DO_ENCRYPT(left, right, kp2); DES_DO_DECRYPT(left, right, kp1); /* * Xor with the old cipher to get plain * text. Output 8 or less bytes of this. */ left ^= ocipherl; right ^= ocipherr; PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); /* * Save current cipher block here */ ocipherl = cipherl; ocipherr = cipherr; krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); } if (ivec != NULL) { op = ivec; PUT_HALF_BLOCK(ocipherl,op); PUT_HALF_BLOCK(ocipherr, op); } }
void krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, const mit_des_key_schedule schedule, mit_des_cblock ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp; 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); /* Get key pointer here. This won't need to be reinitialized. */ kp = (const unsigned DES_INT32 *)schedule; /* * Decrypting is harder than encrypting because of * the necessity of remembering a lot more things. * Should think about this a little more... */ /* 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; /* Split this block into left and right. */ GET_HALF_BLOCK(left, ptr); GET_HALF_BLOCK(right, ptr); cipherl = left; cipherr = right; /* Decrypt and xor with the old cipher to get plain text. */ DES_DO_DECRYPT(left, right, kp); left ^= ocipherl; right ^= ocipherr; /* Store the encrypted halves back into block. */ ptr = block; PUT_HALF_BLOCK(left, ptr); PUT_HALF_BLOCK(right, ptr); /* 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); } if (ivec != NULL && block != NULL) { ptr = ivec; PUT_HALF_BLOCK(ocipherl, ptr); PUT_HALF_BLOCK(ocipherr, ptr); } }