/* Decrypt one block using CBC. */ static krb5_error_code cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { int ret = 0, olen = BLOCK_SIZE; unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE]; EVP_CIPHER_CTX *ctx; struct iov_cursor cursor; ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return ENOMEM; ret = EVP_DecryptInit_ex(ctx, map_mode(key->keyblock.length), NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL); if (ret == 0) { EVP_CIPHER_CTX_free(ctx); return KRB5_CRYPTO_INTERNAL; } k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); k5_iov_cursor_get(&cursor, iblock); EVP_CIPHER_CTX_set_padding(ctx,0); ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE); if (ret == 1) k5_iov_cursor_put(&cursor, oblock); EVP_CIPHER_CTX_free(ctx); zap(iblock, BLOCK_SIZE); zap(oblock, BLOCK_SIZE); return (ret == 1) ? 0 : KRB5_CRYPTO_INTERNAL; }
/* * k5_des3_encrypt: Encrypt data buffer using 3DES. * * @key DES key (with odd parity) * @ivec Initialization Vector * @data Input/Output buffer (in-place encryption, block-by-block) * @num_data Number of blocks * * Returns 0 on success, krb5_error_code on error */ static krb5_error_code k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { int ret; Des3 des3; unsigned char iv[DES_BLOCK_SIZE]; unsigned char iblock[DES_BLOCK_SIZE]; unsigned char oblock[DES_BLOCK_SIZE]; //struct iov_block_state input_pos, output_pos; struct iov_cursor cursor; krb5_boolean empty; ret = validate(key, ivec, data, num_data, &empty); if (ret != 0 || empty) return ret; memset(iv, 0, sizeof(iv)); /* Check if IV exists and is the correct size */ if (ivec && ivec->data) { if (ivec->length != sizeof(iv)) return KRB5_CRYPTO_INTERNAL; memcpy(iv, ivec->data, ivec->length); } Des3_SetKey(&des3, key->keyblock.contents, iv, DES_ENCRYPTION); k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE); for (;;) { if (!k5_iov_cursor_get(&cursor, iblock)) break; Des3_CbcEncrypt(&des3, oblock, iblock, DES_BLOCK_SIZE); k5_iov_cursor_put(&cursor, oblock); } if (ivec != NULL) memcpy(ivec->data, oblock, DES_BLOCK_SIZE); zap(iv, sizeof(iv)); zap(iblock, sizeof(iblock)); zap(oblock, sizeof(oblock)); return 0; }
static krb5_error_code cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, size_t dlen) { int ret = 0; size_t size = 0; unsigned char *oblock = NULL; unsigned char *dbuf = NULL; unsigned char iv_cts[IV_CTS_BUF_SIZE]; struct iov_cursor cursor; AES_KEY deck; memset(iv_cts,0,sizeof(iv_cts)); if (ivec && ivec->data) { if (ivec->length != sizeof(iv_cts)) return KRB5_CRYPTO_INTERNAL; memcpy(iv_cts, ivec->data,ivec->length); } oblock = OPENSSL_malloc(dlen); if (!oblock) return ENOMEM; dbuf = OPENSSL_malloc(dlen); if (!dbuf) { OPENSSL_free(oblock); return ENOMEM; } AES_set_decrypt_key(key->keyblock.contents, NUM_BITS * key->keyblock.length, &deck); 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 k5_iov_cursor_put(&cursor, oblock); if (!ret && ivec && ivec->data) memcpy(ivec->data, iv_cts, sizeof(iv_cts)); zap(oblock, dlen); zap(dbuf, dlen); OPENSSL_free(oblock); OPENSSL_free(dbuf); return ret; }