diff options
author | Jason King <jason.king@joyent.com> | 2019-08-21 14:05:59 +0000 |
---|---|---|
committer | Jason King <jason.king@joyent.com> | 2020-01-21 10:42:28 -0600 |
commit | 2f9f8a9bcff03868ad346b312981e5d198aafd63 (patch) | |
tree | ebba65a4015a338f6e2dab50847586d2c4d256b4 /usr/src/lib/pkcs11/pkcs11_softtoken/common | |
parent | 709d065fa472580d0fd685caa2fe31c61c2fa25c (diff) | |
download | illumos-gate-2f9f8a9bcff03868ad346b312981e5d198aafd63.tar.gz |
11966 CTR mode tries to be both a stream and block cipher and fails at both
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src/lib/pkcs11/pkcs11_softtoken/common')
-rw-r--r-- | usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c index 61a807cff7..fb8dc6d448 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c @@ -226,7 +226,7 @@ soft_aes_init_ctx(aes_ctx_t *aes_ctx, CK_MECHANISM_PTR mech_p, CK_AES_CTR_PARAMS *pp = (CK_AES_CTR_PARAMS *)mech_p->pParameter; rc = ctr_init_ctx((ctr_ctx_t *)aes_ctx, pp->ulCounterBits, - pp->cb, aes_copy_block); + pp->cb, aes_encrypt_block, aes_copy_block); break; } case CKM_AES_CCM: { @@ -811,38 +811,53 @@ soft_aes_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pData, }; CK_MECHANISM_TYPE mech = session_p->encrypt.mech.mechanism; CK_RV rv = CKR_OK; - size_t out_len = aes_ctx->ac_remainder_len + ulDataLen; + size_t out_len; int rc; + /* + * If pData is NULL, we should have zero bytes to process, and + * the aes_encrypt_contiguous_blocks() call will be an effective no-op. + */ + IMPLY(pData == NULL, ulDataLen == 0); + /* Check size of the output buffer */ - if (aes_ctx->ac_flags & CMAC_MODE) { + switch (mech) { + case CKM_AES_CMAC: /* * The underlying CMAC implementation handles the storing of * extra bytes and does not output any data until *_final, * so do not bother looking at the size of the output * buffer at this time. */ - if (pData == NULL) { - *pulEncryptedDataLen = 0; - return (CKR_OK); - } - } else { + out_len = 0; + break; + case CKM_AES_CTR: + /* + * CTR mode is a stream cipher, so we always output exactly as + * much ciphertext as input plaintext + */ + out_len = ulDataLen; + break; + default: + out_len = aes_ctx->ac_remainder_len + ulDataLen; + /* * The number of complete blocks we can encrypt right now. * The underlying implementation will buffer any remaining data * until the next *_update call. */ out_len &= ~(AES_BLOCK_LEN - 1); + break; + } - if (pEncryptedData == NULL) { - *pulEncryptedDataLen = out_len; - return (CKR_OK); - } + if (pEncryptedData == NULL) { + *pulEncryptedDataLen = out_len; + return (CKR_OK); + } - if (*pulEncryptedDataLen < out_len) { - *pulEncryptedDataLen = out_len; - return (CKR_BUFFER_TOO_SMALL); - } + if (*pulEncryptedDataLen < out_len) { + *pulEncryptedDataLen = out_len; + return (CKR_BUFFER_TOO_SMALL); } rc = aes_encrypt_contiguous_blocks(aes_ctx, (char *)pData, ulDataLen, @@ -859,15 +874,6 @@ soft_aes_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pData, return (CKR_FUNCTION_FAILED); } - /* - * Since AES counter mode is a stream cipher, we call ctr_mode_final() - * to pick up any remaining bytes. It is an internal function that - * does not destroy the context like *normal* final routines. - */ - if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) { - rc = ctr_mode_final((ctr_ctx_t *)aes_ctx, &out, - aes_encrypt_block); - } rv = crypto2pkcs11_error_number(rc); return (rv); @@ -1060,6 +1066,13 @@ soft_aes_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData, out_len &= ~(AES_BLOCK_LEN - 1); } break; + case CKM_AES_CTR: + /* + * CKM_AES_CTR is a stream cipher, so we always output + * exactly as much output plaintext as input ciphertext + */ + out_len = in_len; + break; default: out_len = aes_ctx->ac_remainder_len + in_len; out_len &= ~(AES_BLOCK_LEN - 1); @@ -1108,14 +1121,6 @@ soft_aes_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData, *pulDataLen = out.cd_offset; switch (mech) { - case CKM_AES_CTR: - if (aes_ctx->ac_remainder_len == 0) { - break; - } - rc = ctr_mode_final((ctr_ctx_t *)aes_ctx, &out, - aes_encrypt_block); - rv = crypto2pkcs11_error_number(rc); - break; case CKM_AES_CBC_PAD: if (buffer_block == NULL) { break; @@ -1170,7 +1175,11 @@ soft_aes_encrypt_final(soft_session_t *session_p, out_len = AES_BLOCK_LEN; break; case CKM_AES_CTR: - out_len = aes_ctx->ac_remainder_len; + /* + * Since CKM_AES_CTR is a stream cipher, we never buffer any + * input, so we always have 0 remaining bytes of output. + */ + out_len = 0; break; case CKM_AES_CCM: out_len = aes_ctx->ac_remainder_len + @@ -1219,12 +1228,11 @@ soft_aes_encrypt_final(soft_session_t *session_p, break; } case CKM_AES_CTR: - if (aes_ctx->ac_remainder_len == 0) { - break; - } - - rc = ctr_mode_final((ctr_ctx_t *)aes_ctx, &data, - aes_encrypt_block); + /* + * Since CKM_AES_CTR is a stream cipher, we never + * buffer any data, and thus have no remaining data + * to output at the end + */ break; case CKM_AES_CCM: rc = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, &data, @@ -1361,7 +1369,11 @@ soft_aes_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart, out_len = aes_ctx->ac_remainder_len; break; case CKM_AES_CTR: - out_len = aes_ctx->ac_remainder_len; + /* + * Since CKM_AES_CTR is a stream cipher, we never have + * any remaining bytes to output. + */ + out_len = 0; break; case CKM_AES_CCM: out_len = aes_ctx->ac_data_len; |