Merge pull request #1386 from JacobBarthelmeh/RSA

add WC_RSA_NO_PADDING macro and WC_RSA_NO_PAD enum
pull/1379/head^2
David Garske 2018-02-22 13:34:20 -08:00 committed by GitHub
commit 6500c40015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 354 additions and 8 deletions

View File

@ -871,6 +871,23 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
break;
#endif
#ifdef WC_RSA_NO_PADDING
case WC_RSA_NO_PAD:
WOLFSSL_MSG("wolfSSL Using NO padding");
/* In the case of no padding being used check that input is exactly
* the RSA key length */
if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
WOLFSSL_MSG("Bad input size");
ret = RSA_PAD_E;
}
else {
XMEMCPY(pkcsBlock, input, inputLen);
ret = 0;
}
break;
#endif
default:
WOLFSSL_MSG("Unknown RSA Pad Type");
ret = RSA_PAD_E;
@ -1099,7 +1116,10 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
return outputLen;
}
/* helper function to direct unpadding */
/* helper function to direct unpadding
*
* bits is the key modulus size in bits
*/
static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
byte padValue, int padType, enum wc_HashType hType,
int mgf, byte* optLabel, word32 labelLen, int saltLen,
@ -1129,6 +1149,25 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
break;
#endif
#ifdef WC_RSA_NO_PADDING
case WC_RSA_NO_PAD:
WOLFSSL_MSG("wolfSSL Using NO un-padding");
/* In the case of no padding being used check that input is exactly
* the RSA key length */
if (bits <= 0 || pkcsBlockLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
WOLFSSL_MSG("Bad input size");
ret = RSA_PAD_E;
}
else {
if (out != NULL) {
*out = pkcsBlock;
}
ret = pkcsBlockLen;
}
break;
#endif /* WC_RSA_NO_PADDING */
default:
WOLFSSL_MSG("Unknown RSA UnPad Type");
ret = RSA_PAD_E;
@ -1470,6 +1509,103 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out,
}
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */
#ifdef WC_RSA_NO_PADDING
/* Function that does the RSA operation directly with no padding.
*
* in buffer to do operation on
* inLen length of input buffer
* out buffer to hold results
* outSz gets set to size of result buffer. Should be passed in as length
* of out buffer. If the pointer "out" is null then outSz gets set to
* the expected buffer size needed and LENGTH_ONLY_E gets returned.
* key RSA key to use for encrypt/decrypt
* type if using private or public key {RSA_PUBLIC_ENCRYPT,
* RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT}
* rng wolfSSL RNG to use if needed
*
* returns size of result on success
*/
int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
RsaKey* key, int type, WC_RNG* rng)
{
int ret;
if (in == NULL || outSz == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
/* sanity check on type of RSA operation */
switch (type) {
case RSA_PUBLIC_ENCRYPT:
case RSA_PUBLIC_DECRYPT:
case RSA_PRIVATE_ENCRYPT:
case RSA_PRIVATE_DECRYPT:
break;
default:
WOLFSSL_MSG("Bad RSA type");
return BAD_FUNC_ARG;
}
if ((ret = wc_RsaEncryptSize(key)) < 0) {
return BAD_FUNC_ARG;
}
if (inLen != (word32)ret) {
WOLFSSL_MSG("Bad input length. Should be RSA key size");
return BAD_FUNC_ARG;
}
if (out == NULL) {
*outSz = inLen;
return LENGTH_ONLY_E;
}
switch (key->state) {
case RSA_STATE_NONE:
case RSA_STATE_ENCRYPT_PAD:
case RSA_STATE_ENCRYPT_EXPTMOD:
case RSA_STATE_DECRYPT_EXPTMOD:
case RSA_STATE_DECRYPT_UNPAD:
key->state = (type == RSA_PRIVATE_ENCRYPT ||
type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD:
RSA_STATE_DECRYPT_EXPTMOD;
key->dataLen = *outSz;
ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng);
if (ret >= 0 || ret == WC_PENDING_E) {
key->state = (type == RSA_PRIVATE_ENCRYPT ||
type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES:
RSA_STATE_DECRYPT_RES;
}
if (ret < 0) {
break;
}
FALL_THROUGH;
case RSA_STATE_ENCRYPT_RES:
case RSA_STATE_DECRYPT_RES:
ret = key->dataLen;
break;
default:
ret = BAD_STATE_E;
}
/* if async pending then skip cleanup*/
if (ret == WC_PENDING_E) {
return ret;
}
key->state = RSA_STATE_NONE;
wc_RsaCleanup(key);
return ret;
}
#endif /* WC_RSA_NO_PADDING */
int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
word32* outLen, int type, RsaKey* key, WC_RNG* rng)
{
@ -1517,8 +1653,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD or
WC_RSA_PSS_PAD
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
WC_RSA_NO_PAD or WC_RSA_PSS_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
@ -1548,6 +1684,11 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
}
if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) {
#ifdef WC_RSA_NO_PADDING
/* In the case that no padding is used the input length can and should
* be the same size as the RSA key. */
if (pad_type != WC_RSA_NO_PAD)
#endif
return RSA_BUFFER_E;
}
@ -1630,8 +1771,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD
WC_RSA_PSS_PAD
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
WC_RSA_NO_PAD, WC_RSA_PSS_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
@ -1777,7 +1918,7 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
}
#ifndef WC_NO_RSA_OAEP
#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng, int type,
enum wc_HashType hash, int mgf, byte* label,
@ -1829,7 +1970,7 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
}
#ifndef WC_NO_RSA_OAEP
#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, int type,
enum wc_HashType hash, int mgf, byte* label,
@ -1843,7 +1984,7 @@ int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label,
labelSz, 0, rng);
}
#endif /* WC_NO_RSA_OAEP */
#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */
int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)

View File

@ -250,6 +250,7 @@ int gmac_test(void);
int aesccm_test(void);
int aeskeywrap_test(void);
int camellia_test(void);
int rsa_no_pad_test(void);
int rsa_test(void);
int dh_test(void);
int dsa_test(void);
@ -737,6 +738,12 @@ int wolfcrypt_test(void* args)
#endif
#ifndef NO_RSA
#ifdef WC_RSA_NO_PADDING
if ( (ret = rsa_no_pad_test()) != 0)
return err_sys("RSA NOPAD test failed!\n", ret);
else
printf( "RSA NOPAD test passed!\n");
#endif
if ( (ret = rsa_test()) != 0)
return err_sys("RSA test failed!\n", ret);
else
@ -8626,6 +8633,201 @@ exit_rsa_pss:
}
#endif
#ifdef WC_RSA_NO_PADDING
int rsa_no_pad_test(void)
{
WC_RNG rng;
RsaKey key;
byte* tmp = NULL;
size_t bytes;
int ret;
word32 inLen = 0;
word32 idx = 0;
word32 outSz = RSA_TEST_BYTES;
word32 plainSz = RSA_TEST_BYTES;
#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) \
&& !defined(NO_FILESYSTEM)
FILE *file;
#endif
DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT);
DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT);
/* initialize stack structures */
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(&key, 0, sizeof(key));
#ifdef USE_CERT_BUFFERS_1024
bytes = (size_t)sizeof_client_key_der_1024;
if (bytes < (size_t)sizeof_client_cert_der_1024)
bytes = (size_t)sizeof_client_cert_der_1024;
#elif defined(USE_CERT_BUFFERS_2048)
bytes = (size_t)sizeof_client_key_der_2048;
if (bytes < (size_t)sizeof_client_cert_der_2048)
bytes = (size_t)sizeof_client_cert_der_2048;
#else
bytes = FOURK_BUF;
#endif
tmp = (byte*)XMALLOC(bytes, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL
#ifdef WOLFSSL_ASYNC_CRYPT
|| out == NULL || plain == NULL
#endif
) {
return -500;
}
#ifdef USE_CERT_BUFFERS_1024
XMEMCPY(tmp, client_key_der_1024, (size_t)sizeof_client_key_der_1024);
#elif defined(USE_CERT_BUFFERS_2048)
XMEMCPY(tmp, client_key_der_2048, (size_t)sizeof_client_key_der_2048);
#elif !defined(NO_FILESYSTEM)
file = fopen(clientKey, "rb");
if (!file) {
err_sys("can't open ./certs/client-key.der, "
"Please run from wolfSSL home dir", -40);
ERROR_OUT(-501, exit_rsa_nopadding);
}
bytes = fread(tmp, 1, FOURK_BUF, file);
fclose(file);
#else
/* No key to use. */
ERROR_OUT(-502, exit_rsa_nopadding);
#endif /* USE_CERT_BUFFERS */
ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId);
if (ret != 0) {
ERROR_OUT(-503, exit_rsa_nopadding);
}
ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);
if (ret != 0) {
ERROR_OUT(-504, exit_rsa_nopadding);
}
/* after loading in key use tmp as the test buffer */
#ifndef HAVE_FIPS
ret = wc_InitRng_ex(&rng, HEAP_HINT, devId);
#else
ret = wc_InitRng(&rng);
#endif
if (ret != 0) {
ERROR_OUT(-505, exit_rsa_nopadding);
}
inLen = wc_RsaEncryptSize(&key);
XMEMSET(tmp, 7, inLen);
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaDirect(tmp, inLen, out, &outSz, &key,
RSA_PRIVATE_ENCRYPT, &rng);
}
} while (ret == WC_PENDING_E);
if (ret <= 0) {
ERROR_OUT(-506, exit_rsa_nopadding);
}
/* encrypted result should not be the same as input */
if (XMEMCMP(out, tmp, inLen) == 0) {
ERROR_OUT(-507, exit_rsa_nopadding);
}
/* decrypt with public key and compare result */
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key,
RSA_PUBLIC_DECRYPT, &rng);
}
} while (ret == WC_PENDING_E);
if (ret <= 0) {
ERROR_OUT(-508, exit_rsa_nopadding);
}
if (XMEMCMP(plain, tmp, inLen) != 0) {
ERROR_OUT(-509, exit_rsa_nopadding);
}
#ifdef WC_RSA_BLINDING
ret = wc_RsaSetRNG(&key, &rng);
if (ret < 0) {
ERROR_OUT(-510, exit_rsa_nopadding);
}
#endif
/* test encrypt and decrypt using WC_RSA_NO_PAD */
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaPublicEncrypt_ex(tmp, inLen, out, (int)outSz, &key, &rng,
WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0);
}
} while (ret == WC_PENDING_E);
if (ret < 0) {
ERROR_OUT(-511, exit_rsa_nopadding);
}
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaPrivateDecrypt_ex(out, outSz, plain, (int)plainSz, &key,
WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0);
}
} while (ret == WC_PENDING_E);
if (ret < 0) {
ERROR_OUT(-512, exit_rsa_nopadding);
}
if (XMEMCMP(plain, tmp, inLen) != 0) {
ERROR_OUT(-513, exit_rsa_nopadding);
}
/* test some bad arguments */
ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key, -1,
&rng);
if (ret != BAD_FUNC_ARG) {
ERROR_OUT(-514, exit_rsa_nopadding);
}
ret = wc_RsaDirect(out, outSz, plain, &plainSz, NULL, RSA_PUBLIC_DECRYPT,
&rng);
if (ret != BAD_FUNC_ARG) {
ERROR_OUT(-515, exit_rsa_nopadding);
}
ret = wc_RsaDirect(out, outSz, NULL, &plainSz, &key, RSA_PUBLIC_DECRYPT,
&rng);
if (ret != LENGTH_ONLY_E || plainSz != inLen) {
ERROR_OUT(-516, exit_rsa_nopadding);
}
ret = wc_RsaDirect(out, outSz - 10, plain, &plainSz, &key,
RSA_PUBLIC_DECRYPT, &rng);
if (ret != BAD_FUNC_ARG) {
ERROR_OUT(-517, exit_rsa_nopadding);
}
/* if making it to this point of code without hitting an ERROR_OUT then
* all tests have passed */
ret = 0;
exit_rsa_nopadding:
wc_FreeRsaKey(&key);
wc_FreeRng(&rng);
return ret;
}
#endif /* WC_RSA_NO_PADDING */
int rsa_test(void)
{
int ret;

View File

@ -217,6 +217,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
#define WC_RSA_PKCSV15_PAD 0
#define WC_RSA_OAEP_PAD 1
#define WC_RSA_PSS_PAD 2
#define WC_RSA_NO_PAD 3
WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng, int type,
@ -227,6 +228,8 @@ WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen,
byte** out, RsaKey* key, int type, enum wc_HashType hash,
int mgf, byte* label, word32 lableSz);
WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
RsaKey* key, int type, WC_RNG* rng);
#endif /* HAVE_FIPS*/
WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
word32*);