diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8507503d3..5ea84f340 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9210,26 +9210,6 @@ int ToTraditionalEnc(byte* input, word32 sz, const char* password, #ifdef HAVE_PKCS12 -#define PKCS8_MIN_BLOCK_SIZE 8 -static int Pkcs8Pad(byte* buf, int sz, int blockSz) -{ - int padSz; - - /* calculate pad size */ - padSz = blockSz - (sz & (blockSz - 1)); - - /* pad with padSz value */ - if (buf) { - int i; - for (i = 0; i < padSz; i++) { - buf[sz+i] = (byte)(padSz & 0xFF); - } - } - - /* return adjusted length */ - return sz + padSz; -} - #ifdef WOLFSSL_ASN_TEMPLATE /* ASN.1 template for PKCS #8 encrypted key with PBES1 parameters. * PKCS #8: RFC 5958, 3 - EncryptedPrivateKeyInfo @@ -9339,7 +9319,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, /* calculate size */ /* size of constructed string at end */ - sz = (word32)Pkcs8Pad(NULL, (int)inputSz, blockSz); + sz = wc_PkcsPad(NULL, inputSz, (word32)blockSz); totalSz = ASN_TAG_SZ; totalSz += SetLength(sz, seq); totalSz += sz; @@ -9435,7 +9415,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; /* get pad size and verify buffer room */ - sz = (word32)Pkcs8Pad(NULL, (int)inputSz, blockSz); + sz = wc_PkcsPad(NULL, inputSz, (word32)blockSz); if (sz + inOutIdx > *outSz) { #ifdef WOLFSSL_SMALL_STACK XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -9446,7 +9426,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, /* copy input to output buffer and pad end */ XMEMCPY(out + inOutIdx, input, inputSz); - sz = (word32)Pkcs8Pad(out + inOutIdx, (int)inputSz, blockSz); + sz = wc_PkcsPad(out + inOutIdx, inputSz, (word32)blockSz); #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { @@ -9520,7 +9500,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, salt, saltSz); SetASN_Int16Bit(&dataASN[P8ENCPBES1ASN_IDX_ENCALGO_PBEPARAM_ITER], (word16)itt); - pkcs8Sz = (word32)Pkcs8Pad(NULL, (int)inputSz, blockSz); + pkcs8Sz = wc_PkcsPad(NULL, inputSz, (word32)blockSz); SetASN_Buffer(&dataASN[P8ENCPBES1ASN_IDX_ENCDATA], NULL, pkcs8Sz); /* Calculate size of encoding. */ @@ -9558,7 +9538,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, byte* pkcs8 = (byte*)dataASN[P8ENCPBES1ASN_IDX_ENCDATA].data.buffer.data; XMEMCPY(pkcs8, input, inputSz); - Pkcs8Pad(pkcs8, (int)inputSz, blockSz); + (void)wc_PkcsPad(pkcs8, inputSz, (word32)blockSz); /* Encrypt PKCS#8 key inline. */ ret = wc_CryptKey(password, passwordSz, salt, (int)saltSz, itt, id, @@ -9578,6 +9558,36 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, #endif /* HAVE_PKCS12 */ #endif /* NO_PWDBASED */ +/* Block padding used for PKCS#5, PKCS#7, PKCS#8 and PKCS#12. + * + * The length of padding is the value of each padding byte. + * + * When buf is NULL, the padded size is returned. + * + * @param [in, out] buf Buffer of data to be padded. May be NULL. + * @param [in] sz Size of data in bytes. + * @param [in] blockSz Size of block, in bytes, which buffer size must be + * a multiple of. Assumed to be less than 256 and + * a power of 2. + * @return Size of padded buffer in bytes. + */ +word32 wc_PkcsPad(byte* buf, word32 sz, word32 blockSz) +{ + /* Calculate number of padding bytes. */ + word32 padSz = blockSz - (sz & (blockSz - 1)); + + /* Pad with padSz byte. */ + if (buf != NULL) { + word32 i; + for (i = 0; i < padSz; i++) { + buf[sz+i] = (byte)(padSz & 0xFF); + } + } + + /* Return padded buffer size in bytes. */ + return sz + padSz; +} + #ifndef NO_RSA #ifdef WOLFSSL_ASN_TEMPLATE /* ASN.1 template for an RSA public key. diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index dc6736f44..5050a3331 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8706,14 +8706,10 @@ int wc_PKCS7_SetContentType(wc_PKCS7* pkcs7, byte* contentType, word32 sz) /* return size of padded data, padded to blockSz chunks, or negative on error */ int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) { - word32 padSz; - if (blockSz == 0) return BAD_FUNC_ARG; - padSz = blockSz - (inputSz % blockSz); - - return (int)padSz; + return (int)(blockSz - (inputSz % blockSz)); } @@ -8722,28 +8718,16 @@ int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, word32 blockSz) { - int ret; - word32 i, padSz; - if (in == NULL || inSz == 0 || - out == NULL || outSz == 0) + out == NULL || outSz == 0 || blockSz == 0) return BAD_FUNC_ARG; - ret = wc_PKCS7_GetPadSize(inSz, blockSz); - if (ret < 0) - return ret; - padSz = (word32)ret; - - if (outSz < (inSz + padSz)) + if (outSz < wc_PkcsPad(NULL, inSz, blockSz)) return BAD_FUNC_ARG; XMEMCPY(out, in, inSz); - for (i = 0; i < padSz; i++) { - out[inSz + i] = (byte)padSz; - } - - return (int)(inSz + padSz); + return (int)wc_PkcsPad(out, inSz, blockSz); } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index faebc8ecd..1e5bdfcba 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -3065,6 +3065,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t asn_test(void) struct tm timearg; time_t now; #endif + int i; + unsigned char buf[16]; + WOLFSSL_ENTER("asn_test"); ret = wc_GetDateInfo(dateBuf, (int)sizeof(dateBuf), &datePart, &format, @@ -3093,6 +3096,31 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t asn_test(void) return WC_TEST_RET_ENC_EC(ret); #endif /* !NO_ASN_TIME */ + /* Test that only calculating the length works. */ + for (i = 16; i < 32; i++) { + ret = wc_PkcsPad(NULL, i, 16); + if (ret != i + (16 - (i % 16))) + return WC_TEST_RET_ENC_I(i); + } + + /* Test that adding padding works. */ + XMEMSET(buf, 0xa5, sizeof(buf)); + for (i = 15; i >= 0; i--) { + int j; + ret = wc_PkcsPad(buf, i, 16); + if (ret != 16) + return WC_TEST_RET_ENC_I(i); + /* Check padded buffer. */ + for (j = 0; j < 16; j++) { + /* Check buffer bytes haven't been modified. */ + if ((j < i) && (buf[j] != 0xa5)) + return WC_TEST_RET_ENC_I(i); + /* Check padding bytes are correct. */ + if (j >= i && (buf[j] != (16 - i))) + return WC_TEST_RET_ENC_I(i); + } + } + return 0; } #endif /* !NO_ASN */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 9e7a8558a..db4f272a8 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -729,6 +729,8 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); word32 outputSz, byte *cipherIno, int type); #endif +WOLFSSL_API word32 wc_PkcsPad(byte* buf, word32 sz, word32 blockSz); + #ifndef NO_RSA WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz);