summaryrefslogtreecommitdiff
path: root/usr/src/lib/pkcs11/pkcs11_softtoken/common
diff options
context:
space:
mode:
authorJason King <jason.king@joyent.com>2019-08-21 14:05:59 +0000
committerJason King <jason.king@joyent.com>2020-01-21 10:42:28 -0600
commit2f9f8a9bcff03868ad346b312981e5d198aafd63 (patch)
treeebba65a4015a338f6e2dab50847586d2c4d256b4 /usr/src/lib/pkcs11/pkcs11_softtoken/common
parent709d065fa472580d0fd685caa2fe31c61c2fa25c (diff)
downloadillumos-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.c94
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;