PKCS Pad: public API to do PKCS padding

PKCS padding adds length of padding as repeated padding byte.
Use the new function in all places.
This commit is contained in:
Sean Parkinson
2025-02-25 13:03:01 +10:00
parent a85641574d
commit f204ac8363
4 changed files with 69 additions and 45 deletions

View File

@@ -9210,26 +9210,6 @@ int ToTraditionalEnc(byte* input, word32 sz, const char* password,
#ifdef HAVE_PKCS12 #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 #ifdef WOLFSSL_ASN_TEMPLATE
/* ASN.1 template for PKCS #8 encrypted key with PBES1 parameters. /* ASN.1 template for PKCS #8 encrypted key with PBES1 parameters.
* PKCS #8: RFC 5958, 3 - EncryptedPrivateKeyInfo * PKCS #8: RFC 5958, 3 - EncryptedPrivateKeyInfo
@@ -9339,7 +9319,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
/* calculate size */ /* calculate size */
/* size of constructed string at end */ /* 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 = ASN_TAG_SZ;
totalSz += SetLength(sz, seq); totalSz += SetLength(sz, seq);
totalSz += sz; totalSz += sz;
@@ -9435,7 +9415,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0;
/* get pad size and verify buffer room */ /* 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) { if (sz + inOutIdx > *outSz) {
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); 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 */ /* copy input to output buffer and pad end */
XMEMCPY(out + inOutIdx, input, inputSz); 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 #ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) { if (cbcIv == NULL) {
@@ -9520,7 +9500,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
salt, saltSz); salt, saltSz);
SetASN_Int16Bit(&dataASN[P8ENCPBES1ASN_IDX_ENCALGO_PBEPARAM_ITER], SetASN_Int16Bit(&dataASN[P8ENCPBES1ASN_IDX_ENCALGO_PBEPARAM_ITER],
(word16)itt); (word16)itt);
pkcs8Sz = (word32)Pkcs8Pad(NULL, (int)inputSz, blockSz); pkcs8Sz = wc_PkcsPad(NULL, inputSz, (word32)blockSz);
SetASN_Buffer(&dataASN[P8ENCPBES1ASN_IDX_ENCDATA], NULL, pkcs8Sz); SetASN_Buffer(&dataASN[P8ENCPBES1ASN_IDX_ENCDATA], NULL, pkcs8Sz);
/* Calculate size of encoding. */ /* Calculate size of encoding. */
@@ -9558,7 +9538,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
byte* pkcs8 = byte* pkcs8 =
(byte*)dataASN[P8ENCPBES1ASN_IDX_ENCDATA].data.buffer.data; (byte*)dataASN[P8ENCPBES1ASN_IDX_ENCDATA].data.buffer.data;
XMEMCPY(pkcs8, input, inputSz); XMEMCPY(pkcs8, input, inputSz);
Pkcs8Pad(pkcs8, (int)inputSz, blockSz); (void)wc_PkcsPad(pkcs8, inputSz, (word32)blockSz);
/* Encrypt PKCS#8 key inline. */ /* Encrypt PKCS#8 key inline. */
ret = wc_CryptKey(password, passwordSz, salt, (int)saltSz, itt, id, 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 /* HAVE_PKCS12 */
#endif /* NO_PWDBASED */ #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 #ifndef NO_RSA
#ifdef WOLFSSL_ASN_TEMPLATE #ifdef WOLFSSL_ASN_TEMPLATE
/* ASN.1 template for an RSA public key. /* ASN.1 template for an RSA public key.

View File

@@ -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 */ /* return size of padded data, padded to blockSz chunks, or negative on error */
int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
{ {
word32 padSz;
if (blockSz == 0) if (blockSz == 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
padSz = blockSz - (inputSz % blockSz); return (int)(blockSz - (inputSz % blockSz));
return (int)padSz;
} }
@@ -8722,28 +8718,16 @@ int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
word32 blockSz) word32 blockSz)
{ {
int ret;
word32 i, padSz;
if (in == NULL || inSz == 0 || if (in == NULL || inSz == 0 ||
out == NULL || outSz == 0) out == NULL || outSz == 0 || blockSz == 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
ret = wc_PKCS7_GetPadSize(inSz, blockSz); if (outSz < wc_PkcsPad(NULL, inSz, blockSz))
if (ret < 0)
return ret;
padSz = (word32)ret;
if (outSz < (inSz + padSz))
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
XMEMCPY(out, in, inSz); XMEMCPY(out, in, inSz);
for (i = 0; i < padSz; i++) { return (int)wc_PkcsPad(out, inSz, blockSz);
out[inSz + i] = (byte)padSz;
}
return (int)(inSz + padSz);
} }

View File

@@ -3065,6 +3065,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t asn_test(void)
struct tm timearg; struct tm timearg;
time_t now; time_t now;
#endif #endif
int i;
unsigned char buf[16];
WOLFSSL_ENTER("asn_test"); WOLFSSL_ENTER("asn_test");
ret = wc_GetDateInfo(dateBuf, (int)sizeof(dateBuf), &datePart, &format, 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); return WC_TEST_RET_ENC_EC(ret);
#endif /* !NO_ASN_TIME */ #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; return 0;
} }
#endif /* !NO_ASN */ #endif /* !NO_ASN */

View File

@@ -729,6 +729,8 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer);
word32 outputSz, byte *cipherIno, int type); word32 outputSz, byte *cipherIno, int type);
#endif #endif
WOLFSSL_API word32 wc_PkcsPad(byte* buf, word32 sz, word32 blockSz);
#ifndef NO_RSA #ifndef NO_RSA
WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx,
word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz);