@@ -3209,6 +3209,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
32093209 if (!WP11_Session_IsOpInitialized (session , WP11_INIT_AES_GCM_DEC ))
32103210 return CKR_OPERATION_NOT_INITIALIZED ;
32113211
3212+ if (ulEncryptedDataLen < (CK_ULONG )WP11_AesGcm_GetTagBits (session ) / 8 )
3213+ return CKR_ENCRYPTED_DATA_LEN_RANGE ;
32123214 decDataLen = (word32 )ulEncryptedDataLen -
32133215 WP11_AesGcm_GetTagBits (session ) / 8 ;
32143216 if (pData == NULL ) {
@@ -3230,6 +3232,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
32303232 if (!WP11_Session_IsOpInitialized (session , WP11_INIT_AES_CCM_DEC ))
32313233 return CKR_OPERATION_NOT_INITIALIZED ;
32323234
3235+ if (ulEncryptedDataLen < (CK_ULONG )WP11_AesCcm_GetMacLen (session ))
3236+ return CKR_ENCRYPTED_DATA_LEN_RANGE ;
32333237 decDataLen = (word32 )ulEncryptedDataLen -
32343238 WP11_AesCcm_GetMacLen (session );
32353239 if (pData == NULL ) {
@@ -3294,9 +3298,10 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
32943298 if (!WP11_Session_IsOpInitialized (session , WP11_INIT_AES_KEYWRAP_DEC ))
32953299 return CKR_OPERATION_NOT_INITIALIZED ;
32963300
3297- /* AES Key Wrap unwrapping reduces the size by 8 bytes (the
3298- * integrity check value). If using padding then its even smaller
3299- * but we can't know the final size without decrypting first. */
3301+ /* AES Key Wrap ciphertext is at least two semiblocks: one data
3302+ * semiblock plus the 8-byte integrity check value. */
3303+ if (ulEncryptedDataLen < 2 * KEYWRAP_BLOCK_SIZE )
3304+ return CKR_ENCRYPTED_DATA_LEN_RANGE ;
33003305 decDataLen = (word32 )(ulEncryptedDataLen - KEYWRAP_BLOCK_SIZE );
33013306 if (pData == NULL ) {
33023307 * pulDataLen = decDataLen ;
@@ -3312,12 +3317,31 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
33123317 if (mechanism == CKM_AES_KEY_WRAP_PAD ) {
33133318 int i ;
33143319 byte padValue = pData [decDataLen - 1 ];
3315- if (padValue > KEYWRAP_BLOCK_SIZE || padValue > decDataLen )
3316- return CKR_ENCRYPTED_DATA_LEN_RANGE ;
3317- for (i = 0 ; i < padValue ; i ++ ) {
3318- if (pData [decDataLen - 1 - i ] != padValue )
3319- return CKR_ENCRYPTED_DATA_INVALID ;
3320+ unsigned int badPad = 0 ;
3321+ unsigned int inPad ;
3322+
3323+ /* Constant-time range check: padValue must be 1..KEYWRAP_BLOCK_SIZE
3324+ * and must not exceed decDataLen. */
3325+ badPad |= ((unsigned int )padValue - 1 ) >> 31 ;
3326+ badPad |= ((unsigned int )KEYWRAP_BLOCK_SIZE -
3327+ (unsigned int )padValue ) >> 31 ;
3328+ badPad |= ((unsigned int )decDataLen -
3329+ (unsigned int )padValue ) >> 31 ;
3330+
3331+ /* Constant-time padding byte verification.
3332+ * Always iterate KEYWRAP_BLOCK_SIZE times to avoid leaking
3333+ * padValue through iteration count. */
3334+ for (i = 0 ; i < KEYWRAP_BLOCK_SIZE ; i ++ ) {
3335+ /* Full mask: all-ones when i < padValue, else 0 */
3336+ inPad = 0 - (((unsigned int )i -
3337+ (unsigned int )padValue ) >> 31 );
3338+ badPad |= inPad &
3339+ ((unsigned int )pData [decDataLen - 1 - i ] ^
3340+ (unsigned int )padValue );
33203341 }
3342+
3343+ if (badPad != 0 )
3344+ return CKR_ENCRYPTED_DATA_INVALID ;
33213345 decDataLen -= padValue ;
33223346 }
33233347 * pulDataLen = decDataLen ;
@@ -3623,6 +3647,9 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
36233647 if (!WP11_Session_IsOpInitialized (session , WP11_INIT_AES_GCM_DEC ))
36243648 return CKR_OPERATION_NOT_INITIALIZED ;
36253649
3650+ if (WP11_AesGcm_EncDataLen (session ) <
3651+ WP11_AesGcm_GetTagBits (session ) / 8 )
3652+ return CKR_ENCRYPTED_DATA_LEN_RANGE ;
36263653 decPartLen = WP11_AesGcm_EncDataLen (session ) -
36273654 WP11_AesGcm_GetTagBits (session ) / 8 ;
36283655 if (pLastPart == NULL ) {
0 commit comments