mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
Merge pull request #1757 from dgarske/pkcs8_pad
Fix to resolve padding issue with PKCS 8 encryption.
This commit is contained in:
@ -2523,10 +2523,11 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
|
||||
|
||||
/* Check To see if PKCS version algo is supported, set id if it is return 0
|
||||
< 0 on error */
|
||||
static int CheckAlgo(int first, int second, int* id, int* version)
|
||||
static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz)
|
||||
{
|
||||
*id = ALGO_ID_E;
|
||||
*version = PKCS5; /* default */
|
||||
if (blockSz) *blockSz = 8; /* default */
|
||||
|
||||
if (first == 1) {
|
||||
switch (second) {
|
||||
@ -2541,6 +2542,7 @@ static int CheckAlgo(int first, int second, int* id, int* version)
|
||||
case PBE_SHA1_DES3:
|
||||
*id = PBE_SHA1_DES3;
|
||||
*version = PKCS12v1;
|
||||
if (blockSz) *blockSz = DES_BLOCK_SIZE;
|
||||
return 0;
|
||||
#endif
|
||||
#endif /* !NO_SHA */
|
||||
@ -2562,11 +2564,13 @@ static int CheckAlgo(int first, int second, int* id, int* version)
|
||||
#ifndef NO_MD5
|
||||
case 3: /* see RFC 2898 for ids */
|
||||
*id = PBE_MD5_DES;
|
||||
if (blockSz) *blockSz = DES_BLOCK_SIZE;
|
||||
return 0;
|
||||
#endif
|
||||
#ifndef NO_SHA
|
||||
case 10:
|
||||
*id = PBE_SHA1_DES;
|
||||
if (blockSz) *blockSz = DES_BLOCK_SIZE;
|
||||
return 0;
|
||||
#endif
|
||||
#endif /* !NO_DES3 */
|
||||
@ -2579,21 +2583,25 @@ static int CheckAlgo(int first, int second, int* id, int* version)
|
||||
|
||||
/* Check To see if PKCS v2 algo is supported, set id if it is return 0
|
||||
< 0 on error */
|
||||
static int CheckAlgoV2(int oid, int* id)
|
||||
static int CheckAlgoV2(int oid, int* id, int* blockSz)
|
||||
{
|
||||
if (blockSz) *blockSz = 8; /* default */
|
||||
(void)id; /* not used if AES and DES3 disabled */
|
||||
switch (oid) {
|
||||
#if !defined(NO_DES3) && !defined(NO_SHA)
|
||||
case DESb:
|
||||
*id = PBE_SHA1_DES;
|
||||
if (blockSz) *blockSz = DES_BLOCK_SIZE;
|
||||
return 0;
|
||||
case DES3b:
|
||||
*id = PBE_SHA1_DES3;
|
||||
if (blockSz) *blockSz = DES_BLOCK_SIZE;
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_256
|
||||
case AES256CBCb:
|
||||
*id = PBE_AES256_CBC;
|
||||
if (blockSz) *blockSz = AES_BLOCK_SIZE;
|
||||
return 0;
|
||||
#endif
|
||||
default:
|
||||
@ -2683,6 +2691,24 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PKCS8_MIN_BLOCK_SIZE 8
|
||||
static int Pkcs8Pad(byte* buf, int sz, int blockSz)
|
||||
{
|
||||
int i, padSz;
|
||||
|
||||
/* calculate pad size */
|
||||
padSz = blockSz - (sz & (blockSz - 1));
|
||||
|
||||
/* pad with padSz value */
|
||||
if (buf) {
|
||||
for (i = 0; i < padSz; i++) {
|
||||
buf[sz+i] = (byte)(padSz & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* return adjusted length */
|
||||
return sz + padSz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used when creating PKCS12 shrouded key bags
|
||||
@ -2706,6 +2732,7 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
|
||||
word32 totalSz = 0;
|
||||
int version, id;
|
||||
int ret;
|
||||
int blockSz = 0;
|
||||
|
||||
const byte* curveOID = NULL;
|
||||
word32 oidSz = 0;
|
||||
@ -2725,7 +2752,7 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
|
||||
|
||||
|
||||
inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */
|
||||
if (CheckAlgo(vPKCS, vAlgo, &id, &version) < 0) {
|
||||
if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) {
|
||||
WOLFSSL_MSG("Bad/Unsupported algorithm ID");
|
||||
return ASN_INPUT_E; /* Algo ID error */
|
||||
}
|
||||
@ -2825,7 +2852,8 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
|
||||
return LENGTH_ONLY_E;
|
||||
}
|
||||
|
||||
tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
/* reserve buffer for crypto and make sure it supports full blocks */
|
||||
tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tmp == NULL) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
if (saltTmp != NULL)
|
||||
@ -2846,6 +2874,9 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
|
||||
}
|
||||
tmpSz = ret;
|
||||
|
||||
/* adjust size to pad */
|
||||
tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz);
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (cbcIv == NULL) {
|
||||
@ -2889,7 +2920,7 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
|
||||
XMEMCPY(out + inOutIdx, tmp, tmpSz);
|
||||
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
/* set total size at begining */
|
||||
/* set total size at beginning */
|
||||
sz = SetSequence(totalSz, out);
|
||||
XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz);
|
||||
|
||||
@ -2928,7 +2959,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
|
||||
first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
|
||||
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
|
||||
|
||||
if (CheckAlgo(first, second, &id, &version) < 0) {
|
||||
if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
|
||||
ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */
|
||||
}
|
||||
|
||||
@ -3002,7 +3033,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
|
||||
ERROR_OUT(ASN_PARSE_E, exit_tte);
|
||||
}
|
||||
|
||||
if (CheckAlgoV2(oid, &id) < 0) {
|
||||
if (CheckAlgoV2(oid, &id, NULL) < 0) {
|
||||
ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */
|
||||
}
|
||||
|
||||
@ -3071,7 +3102,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
word32 totalSz = 0;
|
||||
word32 seqSz;
|
||||
int ret;
|
||||
int version, id;
|
||||
int version, id, blockSz = 0;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
byte* saltTmp = NULL;
|
||||
byte* cbcIv = NULL;
|
||||
@ -3084,7 +3115,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
|
||||
WOLFSSL_ENTER("EncryptContent()");
|
||||
|
||||
if (CheckAlgo(vPKCS, vAlgo, &id, &version) < 0)
|
||||
if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
|
||||
return ASN_INPUT_E; /* Algo ID error */
|
||||
|
||||
if (version == PKCS5v2) {
|
||||
@ -3107,7 +3138,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
case PBE_SHA1_DES:
|
||||
case PBE_SHA1_DES3:
|
||||
/* set to block size of 8 for DES operations. This rounds up
|
||||
* to the nearset multiple of 8 */
|
||||
* to the nearest multiple of 8 */
|
||||
sz &= 0xfffffff8;
|
||||
sz += 8;
|
||||
break;
|
||||
@ -3131,9 +3162,15 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
}
|
||||
|
||||
/* add 2 for tags */
|
||||
*outSz = sz + MAX_ALGO_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ +
|
||||
totalSz = sz + MAX_ALGO_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ +
|
||||
MAX_LENGTH_SZ + MAX_LENGTH_SZ + MAX_SHORT_SZ + 2;
|
||||
|
||||
/* adjust size to pad */
|
||||
totalSz = Pkcs8Pad(NULL, totalSz, blockSz);
|
||||
|
||||
/* return result */
|
||||
*outSz = totalSz;
|
||||
|
||||
return LENGTH_ONLY_E;
|
||||
}
|
||||
|
||||
@ -3178,7 +3215,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
XMEMCPY(out + tmpIdx, salt, saltSz);
|
||||
tmpIdx += saltSz;
|
||||
|
||||
/* place itteration setting in buffer */
|
||||
/* place iteration setting in buffer */
|
||||
ret = SetShortInt(out, &tmpIdx, itt, *outSz);
|
||||
if (ret < 0) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
@ -3202,8 +3239,26 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inOutIdx + 1 + MAX_LENGTH_SZ + inputSz > *outSz)
|
||||
return BUFFER_E;
|
||||
|
||||
out[inOutIdx++] = ASN_LONG_LENGTH; totalSz++;
|
||||
sz = SetLength(inputSz, out + inOutIdx);
|
||||
inOutIdx += sz; totalSz += sz;
|
||||
|
||||
/* get pad size and verify buffer room */
|
||||
sz = Pkcs8Pad(NULL, inputSz, blockSz);
|
||||
if (sz + inOutIdx > *outSz)
|
||||
return BUFFER_E;
|
||||
|
||||
/* copy input to output buffer and pad end */
|
||||
XMEMCPY(out + inOutIdx, input, inputSz);
|
||||
sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz);
|
||||
totalSz += sz;
|
||||
|
||||
/* encrypt */
|
||||
if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
|
||||
input, inputSz, version, cbcIv, 1)) < 0) {
|
||||
out + inOutIdx, sz, version, cbcIv, 1)) < 0) {
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
@ -3217,15 +3272,6 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
|
||||
XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
if (inOutIdx + 1 + MAX_LENGTH_SZ + inputSz > *outSz)
|
||||
return BUFFER_E;
|
||||
|
||||
out[inOutIdx++] = ASN_LONG_LENGTH; totalSz++;
|
||||
sz = SetLength(inputSz, out + inOutIdx);
|
||||
inOutIdx += sz; totalSz += sz;
|
||||
XMEMCPY(out + inOutIdx, input, inputSz);
|
||||
totalSz += inputSz;
|
||||
|
||||
return totalSz;
|
||||
}
|
||||
|
||||
@ -3262,7 +3308,7 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz)
|
||||
first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
|
||||
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
|
||||
|
||||
if (CheckAlgo(first, second, &id, &version) < 0) {
|
||||
if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
|
||||
ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
|
||||
}
|
||||
|
||||
@ -3336,7 +3382,7 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz)
|
||||
ERROR_OUT(ASN_PARSE_E, exit_dc);
|
||||
}
|
||||
|
||||
if (CheckAlgoV2(oid, &id) < 0) {
|
||||
if (CheckAlgoV2(oid, &id, NULL) < 0) {
|
||||
ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user