Merge pull request #246 from JacobBarthelmeh/OAEP

RSA OAEP padding
This commit is contained in:
toddouska
2016-01-15 11:34:37 -08:00
4 changed files with 778 additions and 7 deletions

View File

@ -175,7 +175,7 @@ int wc_InitRsaKey(RsaKey* key, void* heap)
key->n.dp = key->e.dp = 0; /* public alloc parts */
key->d.dp = key->p.dp = 0; /* private alloc parts */
key->q.dp = key->dP.dp = 0;
key->q.dp = key->dP.dp = 0;
key->u.dp = key->dQ.dp = 0;
#else
mp_init(&key->n);
@ -218,6 +218,293 @@ int wc_FreeRsaKey(RsaKey* key)
return 0;
}
#ifndef WC_NO_RSA_OAEP
/* Uses MGF1 standard as a mask generation function
hType: hash type used
seed: seed to use for generating mask
seedSz: size of seed buffer
out: mask output after generation
outSz: size of output buffer
*/
static int wc_MGF1(int hType, byte* seed, word32 seedSz,
byte* out, word32 outSz)
{
byte* tmp;
/* needs to be large enough for seed size plus counter(4) */
byte tmpA[WC_MAX_DIGEST_SIZE + 4];
byte tmpF; /* 1 if dynamic memory needs freed */
word32 tmpSz;
int hLen;
int ret;
word32 counter;
word32 idx;
hLen = wc_HashGetDigestSize(hType);
counter = 0;
idx = 0;
/* check error return of wc_HashGetDigestSize */
if (hLen < 0) {
return hLen;
}
/* if tmp is not large enough than use some dynamic memory */
if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) {
/* find largest amount of memory needed which will be the max of
* hLen and (seedSz + 4) since tmp is used to store the hash digest */
tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen;
tmp = (byte*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
tmpF = 1; /* make sure to free memory when done */
}
else {
/* use array on the stack */
tmpSz = sizeof(tmpA);
tmp = tmpA;
tmpF = 0; /* no need to free memory at end */
}
do {
int i = 0;
XMEMCPY(tmp, seed, seedSz);
/* counter to byte array appended to tmp */
tmp[seedSz] = (counter >> 24) & 0xFF;
tmp[seedSz + 1] = (counter >> 16) & 0xFF;
tmp[seedSz + 2] = (counter >> 8) & 0xFF;
tmp[seedSz + 3] = (counter) & 0xFF;
/* hash and append to existing output */
if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) {
/* check for if dynamic memory was needed, then free */
if (tmpF) {
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
return ret;
}
for (i = 0; i < hLen && idx < outSz; i++) {
out[idx++] = tmp[i];
}
counter++;
}
while (idx < outSz);
/* check for if dynamic memory was needed, then free */
if (tmpF) {
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
return 0;
}
/* helper function to direct which mask generation function is used
switeched on type input
*/
static int wc_MGF(int type, byte* seed, word32 seedSz,
byte* out, word32 outSz)
{
int ret;
switch(type) {
#ifndef NO_SHA
case WC_MGF1SHA1:
ret = wc_MGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz);
break;
#endif
#ifndef NO_SHA256
case WC_MGF1SHA256:
ret = wc_MGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz);
break;
#endif
#ifdef WOLFSSL_SHA512
#ifdef WOLFSSL_SHA384
case WC_MGF1SHA384:
ret = wc_MGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz);
break;
#endif
case WC_MGF1SHA512:
ret = wc_MGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz);
break;
#endif
default:
WOLFSSL_MSG("Unknown MGF function: check build options");
ret = BAD_FUNC_ARG;
}
/* in case of default avoid unused warrning */
(void)seed;
(void)seedSz;
(void)out;
(void)outSz;
return ret;
}
static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock,
word32 pkcsBlockLen, byte padValue, WC_RNG* rng,
int hType, int mgf, byte* optLabel, word32 labelLen)
{
int ret;
int hLen;
int psLen;
int i;
word32 idx;
byte* dbMask;
#ifdef WOLFSSL_SMALL_STACK
byte* lHash = NULL;
byte* seed = NULL;
#else
/* must be large enough to contain largest hash */
byte lHash[WC_MAX_DIGEST_SIZE];
byte seed[ WC_MAX_DIGEST_SIZE];
#endif
/* can use with no lable but catch if no lable provided while having
length > 0 */
if (optLabel == NULL && labelLen > 0) {
return BUFFER_E;
}
/* limit of label is the same as limit of hash function which is massive */
hLen = wc_HashGetDigestSize(hType);
if (hLen < 0) {
return hLen;
}
#ifdef WOLFSSL_SMALL_STACK
lHash = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (lHash == NULL) {
return MEMORY_E;
}
seed = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (seed == NULL) {
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#else
/* hLen should never be larger than lHash since size is max digest size,
but check before blindly calling wc_Hash */
if ((word32)hLen > sizeof(lHash)) {
WOLFSSL_MSG("OAEP lHash to small for digest!!");
return MEMORY_E;
}
#endif
if ((ret = wc_Hash(hType, optLabel, labelLen,
lHash, hLen)) != 0) {
WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small");
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
/* handles check of location for idx as well as psLen */
if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BAD_FUNC_ARG;
}
/* concatinate lHash || PS || 0x01 || msg */
idx = pkcsBlockLen - 1 - inputLen;
psLen = pkcsBlockLen - inputLen - 2 * hLen - 2;
if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BUFFER_E;
}
XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen);
pkcsBlock[idx--] = 0x01; /* PS and M seperator */
while (psLen > 0 && idx > 0) {
pkcsBlock[idx--] = 0x00;
psLen--;
}
idx = idx - hLen + 1;
XMEMCPY(pkcsBlock + idx, lHash, hLen);
/* generate random seed */
if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
/* create maskedDB from dbMask */
dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, NULL, DYNAMIC_TYPE_RSA);
if (dbMask == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
ret = wc_MGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1);
if (ret != 0) {
XFREE(dbMask, NULL, DYNAMIC_TYPE_RSA);
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
i = 0;
idx = hLen + 1;
while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) {
pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx];
idx++;
}
XFREE(dbMask, NULL, DYNAMIC_TYPE_RSA);
/* create maskedSeed from seedMask */
idx = 0;
pkcsBlock[idx++] = 0x00;
/* create seedMask inline */
if ((ret = wc_MGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1,
pkcsBlock + 1, hLen)) != 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
/* xor created seedMask with seed to make maskedSeed */
i = 0;
while (idx < (word32)(hLen + 1) && i < hLen) {
pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++];
idx++;
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
(void)padValue;
return 0;
}
#endif /* WC_NO_RSA_OAEP */
static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
word32 pkcsBlockLen, byte padValue, WC_RNG* rng)
{
@ -251,6 +538,124 @@ static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
}
#ifndef WC_NO_RSA_OAEP
/* helper function to direct which padding is used */
static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType,
int hType, int mgf, byte* optLabel, word32 labelLen)
{
int ret;
switch (padType)
{
case WC_RSA_PKCSV15_PAD:
WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");
ret = wc_RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen,
padValue, rng);
break;
case WC_RSA_OAEP_PAD:
WOLFSSL_MSG("wolfSSL Using RSA OAEP padding");
ret = wc_RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen,
padValue, rng, hType, mgf, optLabel, labelLen);
break;
default:
WOLFSSL_MSG("Unknown RSA Pad Type");
ret = RSA_PAD_E;
}
/* silence warrning if not used with padding scheme */
(void)padType;
(void)hType;
(void)mgf;
(void)optLabel;
(void)labelLen;
return ret;
}
/* UnPad plaintext, set start to *output, return length of plaintext,
* < 0 on error */
static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen,
byte **output, int hType, int mgf, byte* optLabel, word32 labelLen)
{
int hLen;
int ret;
byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */
byte* tmp;
word32 idx;
hLen = wc_HashGetDigestSize(hType);
if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) {
return BAD_FUNC_ARG;
}
tmp = XMALLOC(pkcsBlockLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
XMEMSET(tmp, 0, pkcsBlockLen);
/* find seedMask value */
if ((ret = wc_MGF(mgf, (byte*)(pkcsBlock + (hLen + 1)),
pkcsBlockLen - hLen - 1, tmp, hLen)) != 0) {
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
/* xor seedMask value with maskedSeed to get seed value */
for (idx = 0; idx < (word32)hLen; idx++) {
tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx];
}
/* get dbMask value */
if ((ret = wc_MGF(mgf, tmp, hLen, tmp + hLen,
pkcsBlockLen - hLen - 1)) != 0) {
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
/* get DB vaule by doing maskedDB xor dbMask */
for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) {
pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen];
}
/* done with use of tmp buffer */
XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
/* advance idx to index of PS and msg seperator */
idx = hLen + 2 + hLen;
while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;}
/* create hash of label for comparision with hash sent */
if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) {
return ret;
}
/* say no to chosen ciphertext attack.
Comparision of lHash, Y, and seperator value needs to all happen in
constant time.
Attackers should not be able to get error condition from the timing of
these checks.
*/
ret = 0;
ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen);
ret += pkcsBlock[idx++] ^ 0x01; /* seperator value is 0x01 */
ret += pkcsBlock[0] ^ 0x00; /* Y, the first value, should be 0 */
if (ret != 0) {
return BAD_PADDING_E;
}
/* adjust pointer to correct location in array and return size of M */
*output = (byte*)(pkcsBlock + idx);
return pkcsBlockLen - idx;
}
#endif /* WC_NO_RSA_OAEP */
/* UnPad plaintext, set start to *output, return length of plaintext,
* < 0 on error */
static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
@ -294,6 +699,44 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
}
#ifndef WC_NO_RSA_OAEP
/* helper function to direct unpadding */
static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
byte padValue, int padType, int hType, int mgf,
byte* optLabel, word32 labelLen)
{
int ret;
switch (padType)
{
case WC_RSA_PKCSV15_PAD:
WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");
ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue);
break;
case WC_RSA_OAEP_PAD:
WOLFSSL_MSG("wolfSSL Using RSA OAEP padding");
ret = wc_RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out,
hType, mgf, optLabel, labelLen);
break;
default:
WOLFSSL_MSG("Unknown RSA Pad Type");
ret = RSA_PAD_E;
}
/* silence warrning if not used with padding scheme */
(void)padType;
(void)hType;
(void)mgf;
(void)optLabel;
(void)labelLen;
return ret;
}
#endif /* WC_NO_RSA_OAEP */
static int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
word32* outLen, int type, RsaKey* key)
{
@ -419,6 +862,51 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
}
#ifndef WC_NO_RSA_OAEP
/* Gives the option of chossing padding type
in : input to be encrypted
inLen: length of input buffer
out: encrypted output
outLen: length of encrypted output buffer
key : wolfSSL initialised RSA key struct
rng : wolfSSL initialized random number struct
type : type of padding to use ie WC_RSA_OAEP_PAD
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
mgf : type of mask generation function to use
label : optional label
labelSz : size of optional label buffer */
int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng,
int type, int hash, int mgf, byte* label, word32 labelSz)
{
int sz, ret;
#ifdef HAVE_CAVIUM
if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key);
#endif
sz = mp_unsigned_bin_size(&key->n);
if (sz > (int)outLen)
return RSA_BUFFER_E;
if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
return RSA_BUFFER_E;
ret = wc_RsaPad_ex(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng,
type, hash, mgf, label, labelSz);
if (ret != 0)
return ret;
if ((ret = wc_RsaFunction(out, sz, out, &outLen,
RSA_PUBLIC_ENCRYPT, key)) < 0)
sz = ret;
return sz;
}
#endif /* WC_NO_RSA_OAEP */
int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
{
int ret;
@ -436,11 +924,57 @@ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
< 0) {
return ret;
}
return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
}
#ifndef WC_NO_RSA_OAEP
/* Gives the option of chossing padding type
in : input to be decrypted
inLen: length of input buffer
out: pointer to place of decrypted message
key : wolfSSL initialised RSA key struct
type : type of padding to use ie WC_RSA_OAEP_PAD
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
mgf : type of mask generation function to use
label : optional label
labelSz : size of optional label buffer */
int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out,
RsaKey* key, int type, int hash, int mgf, byte* label, word32 labelSz)
{
int ret;
/* sanity check on arguments */
if (in == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
/* check if given a label size but not given a label buffer */
if (label == NULL && labelSz > 0) {
return BAD_FUNC_ARG;
}
#ifdef HAVE_CAVIUM
if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) {
ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key);
if (ret > 0)
*out = in;
return ret;
}
#endif
if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
< 0) {
return ret;
}
return wc_RsaUnPad_ex(in, inLen, out, RSA_BLOCK_TYPE_2, type, hash, mgf,
label, labelSz);
}
#endif /* WC_NO_RSA_OAEP */
int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
RsaKey* key)
{
@ -476,6 +1010,65 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
}
#ifndef WC_NO_RSA_OAEP
/* Gives the option of chossing padding type
in : input to be decrypted
inLen: length of input buffer
out: decrypted message
outLen: length of decrypted message in bytes
key : wolfSSL initialised RSA key struct
type : type of padding to use ie WC_RSA_OAEP_PAD
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
mgf : type of mask generation function to use
label : optional label
labelSz : size of optional label buffer */
int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen,
RsaKey* key, int type, int hash, int mgf, byte* label, word32 labelSz)
{
int plainLen;
byte* tmp;
byte* pad = 0;
/* sanity check on arguments */
if (out == NULL || in == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
/* check if given a label size but not given a label buffer */
if (label == NULL && labelSz > 0) {
return BAD_FUNC_ARG;
}
#ifdef HAVE_CAVIUM
if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key);
#endif
tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
if (tmp == NULL) {
return MEMORY_E;
}
XMEMCPY(tmp, in, inLen);
if ( (plainLen = wc_RsaPrivateDecryptInline_ex(tmp, inLen, &pad, key,
type, hash, mgf, label, labelSz) ) < 0) {
XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
return plainLen;
}
if (plainLen > (int)outLen || pad == NULL)
plainLen = BAD_FUNC_ARG;
else
XMEMCPY(out, pad, plainLen);
ForceZero(tmp, inLen);
XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
return plainLen;
}
#endif /* WC_NO_RSA_OAEP */
/* for Rsa Verify */
int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
{
@ -494,7 +1087,7 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
< 0) {
return ret;
}
return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
}
@ -560,7 +1153,7 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
if ((ret = wc_RsaFunction(out, sz, out, &outLen,
RSA_PRIVATE_ENCRYPT,key)) < 0)
sz = ret;
return sz;
}
@ -729,7 +1322,7 @@ int wc_RsaInitCavium(RsaKey* rsa, int devId)
rsa->devId = devId;
rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC;
return 0;
}
@ -771,7 +1364,7 @@ static int InitCaviumRsaKey(RsaKey* key, void* heap)
key->c_dP_Sz = 0;
key->c_dQ_Sz = 0;
key->c_uSz = 0;
return 0;
}

View File

@ -3886,7 +3886,6 @@ int certext_test(void)
}
#endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */
int rsa_test(void)
{
byte* tmp;
@ -3981,6 +3980,142 @@ int rsa_test(void)
free(tmp);
return -48;
}
#ifndef WC_NO_RSA_OAEP
/* OAEP padding testing */
#if !defined(HAVE_FAST_RSA) && !defined(HAVE_FIPS)
#ifndef NO_SHA
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0);
if (ret < 0) {
free(tmp);
return -143;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0);
if (ret < 0) {
free(tmp);
return -144;
}
if (XMEMCMP(plain, in, inLen)) {
free(tmp);
return -145;
}
#endif /* NO_SHA */
#ifndef NO_SHA256
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0);
if (ret < 0) {
free(tmp);
return -243;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0);
if (ret < 0) {
free(tmp);
return -244;
}
if (XMEMCMP(plain, in, inLen)) {
free(tmp);
return -245;
}
/* check fails if not using the same optional label */
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0);
if (ret < 0) {
free(tmp);
return -246;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in));
if (ret > 0) { /* in this case decrypt should fail */
free(tmp);
return -247;
}
/* check using optional label with encrypt/decrypt */
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in));
if (ret < 0) {
free(tmp);
return -248;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in));
if (ret < 0) {
free(tmp);
return -249;
}
if (XMEMCMP(plain, in, inLen)) {
free(tmp);
return -250;
}
#ifndef NO_SHA
/* check fail using missmatch hash algorithms */
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, sizeof(in));
if (ret < 0) {
free(tmp);
return -251;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in));
if (ret > 0) { /* should fail */
free(tmp);
return -252;
}
#endif /* NO_SHA*/
#endif /* NO_SHA256 */
#ifdef WOLFSSL_SHA512
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0);
if (ret < 0) {
free(tmp);
return -343;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0);
if (ret < 0) {
free(tmp);
return -344;
}
if (XMEMCMP(plain, in, inLen)) {
free(tmp);
return -345;
}
#endif /* NO_SHA */
/* check using pkcsv15 padding with _ex API */
XMEMSET(plain, 0, sizeof(plain));
ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng,
WC_RSA_PKCSV15_PAD, 0, 0, NULL, 0);
if (ret < 0) {
free(tmp);
return -443;
}
ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key,
WC_RSA_PKCSV15_PAD, 0, 0, NULL, 0);
if (ret < 0) {
free(tmp);
return -444;
}
if (XMEMCMP(plain, in, inLen)) {
free(tmp);
return -445;
}
#endif /* !HAVE_FAST_RSA && !HAVE_FIPS */
#endif /* WC_NO_RSA_OAEP */
#if defined(WOLFSSL_MDK_ARM)
#define sizeof(s) strlen((char *)(s))
#endif

View File

@ -54,6 +54,22 @@ enum wc_HashType {
#endif /* WOLFSSL_SHA512 */
};
/* Find largest possible digest size
Note if this gets up to the size of 80 or over check smallstack build */
#if defined(WOLFSSL_SHA512)
#define WC_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
#elif defined(WOLFSSL_SHA384)
#define WC_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE
#elif !defined(NO_SHA256)
#define WC_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
#elif !defined(NO_SHA)
#define WC_MAX_DIGEST_SIZE SHA_DIGEST_SIZE
#elif !defined(NO_MD5)
#define WC_MAX_DIGEST_SIZE MD5_DIGEST_SIZE
#else
#define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */
#endif
WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type);
WOLFSSL_API int wc_Hash(enum wc_HashType hash_type,
const byte* data, word32 data_len,

View File

@ -42,6 +42,9 @@
#include <wolfssl/wolfcrypt/random.h>
#endif /* HAVE_FIPS */
/* header file needed for OAEP padding */
#include <wolfssl/wolfcrypt/hash.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -105,6 +108,30 @@ WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
#ifdef WOLFSSL_KEY_GEN
WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen);
#endif
/*
choice of padding added after fips, so not avialable when using fips RSA
*/
/* Mask Generation Function Identifiers */
#define WC_MGF1SHA1 26
#define WC_MGF1SHA256 1
#define WC_MGF1SHA384 2
#define WC_MGF1SHA512 3
/* Padding types */
#define WC_RSA_PKCSV15_PAD 0
#define WC_RSA_OAEP_PAD 1
WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng,
int type, int hash, int mgf, byte* label, word32 lableSz);
WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
byte* out, word32 outLen, RsaKey* key,
int type, int hash, int mgf, byte* label, word32 lableSz);
WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen,
byte** out, RsaKey* key,
int type, int hash, int mgf, byte* label, word32 lableSz);
#endif /* HAVE_FIPS*/
WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
word32*);