diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 34ecc96d7..836943638 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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 */ }