#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#include <wolfssl/internal.h>
#ifndef WC_NO_RNG
#include <wolfssl/wolfcrypt/random.h>
#endif
#if !defined(WOLFSSL_PK_RSA_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning pk_rsa.c does not need to be compiled separately from ssl.c
#endif
#else
#ifndef NO_RSA
#include <wolfssl/wolfcrypt/rsa.h>
#endif
#ifndef NO_RSA
#if defined(OPENSSL_EXTRA)
WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
{
WOLFSSL_RSA_METHOD* meth = NULL;
int name_len = 0;
int err;
if (name == NULL)
return NULL;
meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
DYNAMIC_TYPE_OPENSSL);
if (meth == NULL)
return NULL;
XMEMSET(meth, 0, sizeof(*meth));
meth->flags = flags;
meth->dynamic = 1;
name_len = (int)XSTRLEN(name);
meth->name = (char*)XMALLOC((size_t)(name_len + 1), NULL,
DYNAMIC_TYPE_OPENSSL);
err = (meth->name == NULL);
if (!err) {
XMEMCPY(meth->name, name, (size_t)(name_len + 1));
}
if (err) {
XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
meth = NULL;
}
return meth;
}
const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void)
{
static const WOLFSSL_RSA_METHOD wolfssl_rsa_meth = {
0,
(char*)"wolfSSL RSA",
0
};
return &wolfssl_rsa_meth;
}
void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth)
{
if ((meth != NULL) && meth->dynamic) {
XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
#ifndef NO_WOLFSSL_STUB
int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *meth, void* p)
{
WOLFSSL_STUB("RSA_METHOD is not implemented.");
(void)meth;
(void)p;
return 1;
}
#endif
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
{
int doFree = 1;
WOLFSSL_ENTER("wolfSSL_RSA_free");
if (rsa == NULL) {
doFree = 0;
}
if (doFree) {
int err;
wolfSSL_RefDec(&rsa->ref, &doFree, &err);
#ifndef WOLFSSL_REFCNT_ERROR_RETURN
(void)err;
#endif
}
if (doFree) {
void* heap = rsa->heap;
wolfSSL_RefFree(&rsa->ref);
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
wolfSSL_CRYPTO_cleanup_ex_data(&rsa->ex_data);
#endif
if (rsa->internal != NULL) {
#if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
if (rsa->ownRng) {
WC_RNG* rng = ((RsaKey*)(rsa->internal))->rng;
if ((rng != NULL) && (rng != wolfssl_get_global_rng())) {
wc_FreeRng(rng);
XFREE(rng, heap, DYNAMIC_TYPE_RNG);
}
}
#endif
wc_FreeRsaKey((RsaKey*)rsa->internal);
XFREE(rsa->internal, heap, DYNAMIC_TYPE_RSA);
}
wolfSSL_BN_clear_free(rsa->iqmp);
wolfSSL_BN_clear_free(rsa->dmq1);
wolfSSL_BN_clear_free(rsa->dmp1);
wolfSSL_BN_clear_free(rsa->q);
wolfSSL_BN_clear_free(rsa->p);
wolfSSL_BN_clear_free(rsa->d);
wolfSSL_BN_free(rsa->e);
wolfSSL_BN_free(rsa->n);
#if defined(OPENSSL_EXTRA)
if (rsa->meth) {
wolfSSL_RSA_meth_free((WOLFSSL_RSA_METHOD*)rsa->meth);
}
#endif
ForceZero(rsa, sizeof(*rsa));
XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
(void)heap;
}
}
WOLFSSL_RSA* wolfSSL_RSA_new_ex(void* heap, int devId)
{
WOLFSSL_RSA* rsa = NULL;
RsaKey* key = NULL;
int err = 0;
int rsaKeyInited = 0;
WOLFSSL_ENTER("wolfSSL_RSA_new");
key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
if (key == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc RsaKey failure");
err = 1;
}
if (!err) {
rsa = (WOLFSSL_RSA*)XMALLOC(sizeof(WOLFSSL_RSA), heap,
DYNAMIC_TYPE_RSA);
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
err = 1;
}
}
if (!err) {
XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
rsa->heap = heap;
#ifdef OPENSSL_EXTRA
rsa->meth = wolfSSL_RSA_get_default_method();
#endif
wolfSSL_RefInit(&rsa->ref, &err);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
}
if (!err) {
#endif
if (wc_InitRsaKey_ex(key, heap, devId) != 0) {
WOLFSSL_ERROR_MSG("InitRsaKey WOLFSSL_RSA failure");
err = 1;
}
else {
rsaKeyInited = 1;
}
}
#if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
if (!err) {
WC_RNG* rng;
rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
if ((rng != NULL) && (wc_InitRng_ex(rng, heap, devId) != 0)) {
WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
XFREE(rng, heap, DYNAMIC_TYPE_RNG);
rng = NULL;
}
rsa->ownRng = 1;
if (rng == NULL) {
rng = wolfssl_get_global_rng();
rsa->ownRng = 0;
}
if (rng == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
err = 1;
}
else {
(void)wc_RsaSetRNG(key, rng);
}
}
#endif
if (!err) {
rsa->internal = key;
rsa->inSet = 0;
}
if (err) {
if (rsaKeyInited) {
wc_FreeRsaKey(key);
}
XFREE(key, heap, DYNAMIC_TYPE_RSA);
XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
rsa = NULL;
}
return rsa;
}
WOLFSSL_RSA* wolfSSL_RSA_new(void)
{
return wolfSSL_RSA_new_ex(NULL, INVALID_DEVID);
}
int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
{
int err = 0;
if (rsa != NULL) {
wolfSSL_RefInc(&rsa->ref, &err);
}
return !err;
}
#endif
#ifdef OPENSSL_EXTRA
#if defined(WOLFSSL_KEY_GEN)
WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa)
{
WOLFSSL_RSA* ret = NULL;
int derSz = 0;
byte* derBuf = NULL;
int err;
WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup");
err = (rsa == NULL);
if (!err) {
ret = wolfSSL_RSA_new();
if (ret == NULL) {
WOLFSSL_ERROR_MSG("Error creating a new WOLFSSL_RSA structure");
err = 1;
}
}
if (!err) {
if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
err = 1;
}
}
if (!err) {
if (wolfSSL_RSA_LoadDer_ex(ret, derBuf, derSz,
WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_LoadDer_ex failed");
err = 1;
}
}
XFREE(derBuf, rsa ? rsa->heap : NULL, DYNAMIC_TYPE_ASN1);
if (err) {
wolfSSL_RSA_free(ret);
ret = NULL;
}
return ret;
}
#endif
static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
void* heap);
WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **out,
const unsigned char **derBuf, long derSz)
{
WOLFSSL_RSA *rsa = NULL;
int err = 0;
WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
if (derBuf == NULL) {
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
WOLFSSL_ERROR_MSG("RSA_new failed");
err = 1;
}
if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
err = 1;
}
if ((!err) && (out != NULL)) {
*out = rsa;
*derBuf += wolfssl_der_length(*derBuf, (int)derSz);
}
if (err) {
wolfSSL_RSA_free(rsa);
rsa = NULL;
}
return rsa;
}
WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **out,
const unsigned char **derBuf, long derSz)
{
WOLFSSL_RSA *rsa = NULL;
int err = 0;
WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
if (derBuf == NULL) {
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
WOLFSSL_ERROR_MSG("RSA_new failed");
err = 1;
}
if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
WOLFSSL_RSA_LOAD_PRIVATE) != 1)) {
WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
err = 1;
}
if ((!err) && (out != NULL)) {
*out = rsa;
*derBuf += wolfssl_der_length(*derBuf, (int)derSz);
}
if (err) {
wolfSSL_RSA_free(rsa);
rsa = NULL;
}
return rsa;
}
int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
{
int ret;
WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Bad Function Arguments");
ret = BAD_FUNC_ARG;
}
else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 0, NULL)) < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
ret = 0;
}
return ret;
}
int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, unsigned char **pp)
{
int ret;
WOLFSSL_ENTER("wolfSSL_i2d_RSAPublicKey");
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Bad Function Arguments");
ret = BAD_FUNC_ARG;
}
else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 1, NULL)) < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
ret = 0;
}
return ret;
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
|| defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
#if defined(WOLFSSL_KEY_GEN) && !defined(NO_BIO)
static int wolfssl_read_der_bio(WOLFSSL_BIO* bio, unsigned char** out)
{
int err = 0;
unsigned char seq[MAX_SEQ_SZ];
unsigned char* der = NULL;
int derLen = 0;
if (wolfSSL_BIO_read(bio, seq, sizeof(seq)) != sizeof(seq)) {
WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() of sequence failure");
err = 1;
}
if ((!err) && ((derLen = wolfssl_der_length(seq, sizeof(seq))) <= 0)) {
WOLFSSL_ERROR_MSG("DER SEQUENCE decode failed");
err = 1;
}
if ((!err) && ((der = (unsigned char*)XMALLOC((size_t)derLen, bio->heap,
DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {
WOLFSSL_ERROR_MSG("Malloc failure");
err = 1;
}
if ((!err) && (derLen <= (int)sizeof(seq))) {
XMEMCPY(der, seq, derLen);
}
else if (!err) {
int len = derLen - (int)sizeof(seq);
XMEMCPY(der, seq, sizeof(seq));
if (wolfSSL_BIO_read(bio, der + sizeof(seq), len) != len) {
WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() failure");
err = 1;
}
}
if (!err) {
*out = der;
}
if (err) {
XFREE(der, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
derLen = 0;
}
return derLen;
}
WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
{
WOLFSSL_RSA* key = NULL;
unsigned char* der = NULL;
int derLen = 0;
int err;
WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio");
err = (bio == NULL);
if ((!err) && ((derLen = wolfssl_read_der_bio(bio, &der)) == 0)) {
err = 1;
}
if (!err) {
const unsigned char* cder = der;
key = wolfSSL_d2i_RSAPrivateKey(NULL, &cder, derLen);
err = (key == NULL);
}
if ((!err) && (out != NULL)) {
*out = key;
}
if (err) {
wolfSSL_RSA_free(key);
key = NULL;
}
XFREE(der, bio ? bio->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER);
return key;
}
#endif
#endif
#ifdef OPENSSL_EXTRA
int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
void* heap)
{
byte* p = NULL;
int ret;
if (outBuf != NULL) {
p = *outBuf;
}
ret = wolfSSL_RSA_To_Der_ex(rsa, outBuf, publicKey, heap);
if ((ret > 0) && (p != NULL)) {
*outBuf = p;
}
return ret;
}
static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
void* heap)
{
int ret = 1;
int derSz = 0;
byte* derBuf = NULL;
WOLFSSL_ENTER("wolfSSL_RSA_To_Der");
(void)heap;
if ((rsa == NULL) || ((publicKey != 0) && (publicKey != 1))) {
WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG);
ret = BAD_FUNC_ARG;
}
if ((ret == 1) && (!rsa->inSet)) {
ret = SetRsaInternal(rsa);
}
if ((ret == 1) && publicKey && (mp_iszero(&((RsaKey*)rsa->internal)->n) ||
mp_iszero(&((RsaKey*)rsa->internal)->e))) {
ret = BAD_FUNC_ARG;
}
if (ret == 1) {
if (publicKey) {
derSz = wc_RsaPublicKeyDerSize((RsaKey*)rsa->internal, 1);
if (derSz < 0) {
WOLFSSL_ERROR_MSG("wc_RsaPublicKeyDerSize failed");
ret = derSz;
}
}
else {
derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0);
if (derSz < 0) {
WOLFSSL_ERROR_MSG("wc_RsaKeyToDer failed");
ret = derSz;
}
}
}
if ((ret == 1) && (outBuf != NULL)) {
derBuf = *outBuf;
if (derBuf == NULL) {
derBuf = (byte*)XMALLOC((size_t)derSz, heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (derBuf == NULL) {
WOLFSSL_ERROR_MSG("Memory allocation failed");
ret = MEMORY_ERROR;
}
}
}
if ((ret == 1) && (outBuf != NULL)) {
if (publicKey > 0) {
derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf,
(word32)derSz);
}
else {
derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf,
(word32)derSz);
}
if (derSz < 0) {
WOLFSSL_ERROR_MSG("RSA key encoding failed");
ret = derSz;
}
else if ((*outBuf) != NULL) {
derBuf = NULL;
*outBuf += derSz;
}
else {
*outBuf = derBuf;
}
}
if (ret == 1) {
ret = derSz;
}
if ((outBuf != NULL) && (*outBuf != derBuf)) {
XFREE(derBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret);
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
int derSz)
{
return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
}
int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
int derSz, int opt)
{
int ret = 1;
int res;
word32 idx = 0;
word32 algId;
WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
if ((rsa == NULL) || (rsa->internal == NULL) || (derBuf == NULL) ||
(derSz <= 0)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
rsa->pkcs8HeaderSz = 0;
res = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz,
&algId);
if (res >= 0) {
WOLFSSL_MSG("Found PKCS8 header");
rsa->pkcs8HeaderSz = (word16)idx;
}
else if (res != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
WOLFSSL_ERROR_MSG("Unexpected error with trying to remove PKCS#8 "
"header");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
res = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
(word32)derSz);
}
else {
res = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
(word32)derSz);
}
if (res < 0) {
if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
WOLFSSL_ERROR_MSG("RsaPrivateKeyDecode failed");
}
else {
WOLFSSL_ERROR_MSG("RsaPublicKeyDecode failed");
}
WOLFSSL_ERROR_VERBOSE(res);
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
if (SetRsaExternal(rsa) != 1) {
ret = WOLFSSL_FATAL_ERROR;
}
else {
rsa->inSet = 1;
}
}
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
#if !defined(NO_BIO) || !defined(NO_FILESYSTEM)
static WOLFSSL_RSA* wolfssl_rsa_d2i(WOLFSSL_RSA** rsa, const unsigned char* in,
long inSz, int opt)
{
WOLFSSL_RSA* ret = NULL;
if ((rsa != NULL) && (*rsa != NULL)) {
ret = *rsa;
}
else {
ret = wolfSSL_RSA_new();
}
if ((ret != NULL) && (wolfSSL_RSA_LoadDer_ex(ret, in, (int)inSz, opt)
!= 1)) {
if ((rsa == NULL) || (ret != *rsa)) {
wolfSSL_RSA_free(ret);
}
ret = NULL;
}
if ((rsa != NULL) && (*rsa == NULL)) {
*rsa = ret;
}
return ret;
}
#endif
#endif
#ifdef OPENSSL_EXTRA
#ifndef NO_BIO
#if defined(WOLFSSL_KEY_GEN)
int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa)
{
int ret = 1;
int derSz = 0;
byte* derBuf = NULL;
WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY");
if ((bio == NULL) || (rsa == NULL)) {
WOLFSSL_ERROR_MSG("Bad Function Arguments");
return 0;
}
if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, bio->heap)) < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
ret = 0;
}
if (derBuf == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
ret = 0;
}
if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
PUBLICKEY_TYPE) != 1)) {
ret = 0;
}
XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif
#endif
#if defined(WOLFSSL_KEY_GEN)
#ifndef NO_FILESYSTEM
static int wolfssl_pem_write_rsa_public_key(XFILE fp, WOLFSSL_RSA* rsa,
int type)
{
int ret = 1;
int derSz;
byte* derBuf = NULL;
if ((fp == XBADFILE) || (rsa == NULL)) {
WOLFSSL_ERROR_MSG("Bad Function Arguments");
return 0;
}
if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
ret = 0;
}
if (derBuf == NULL) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
ret = 0;
}
if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, type,
rsa->heap) != 1)) {
ret = 0;
}
XFREE(derBuf, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA* rsa)
{
return wolfssl_pem_write_rsa_public_key(fp, rsa, PUBLICKEY_TYPE);
}
int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA* rsa)
{
return wolfssl_pem_write_rsa_public_key(fp, rsa, RSA_PUBLICKEY_TYPE);
}
#endif
#endif
#ifndef NO_BIO
WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,
WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
{
WOLFSSL_RSA* rsa = NULL;
DerBuffer* der = NULL;
int keyFormat = 0;
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY");
if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE,
&keyFormat, &der) >= 0)) {
rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
WOLFSSL_RSA_LOAD_PUBLIC);
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
}
}
FreeDer(&der);
if ((out != NULL) && (rsa != NULL)) {
*out = rsa;
}
return rsa;
}
WOLFSSL_RSA *wolfSSL_d2i_RSA_PUBKEY_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
{
char* data = NULL;
int dataSz = 0;
int memAlloced = 0;
WOLFSSL_RSA* rsa = NULL;
WOLFSSL_ENTER("wolfSSL_d2i_RSA_PUBKEY_bio");
if (bio == NULL)
return NULL;
if (wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
if (memAlloced)
XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return NULL;
}
rsa = wolfssl_rsa_d2i(out, (const unsigned char*)data, dataSz,
WOLFSSL_RSA_LOAD_PUBLIC);
if (memAlloced)
XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return rsa;
}
#endif
#ifndef NO_FILESYSTEM
WOLFSSL_RSA *wolfSSL_PEM_read_RSA_PUBKEY(XFILE fp,
WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
{
WOLFSSL_RSA* rsa = NULL;
DerBuffer* der = NULL;
int keyFormat = 0;
WOLFSSL_ENTER("wolfSSL_PEM_read_RSA_PUBKEY");
if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PUBLICKEY_TYPE,
&keyFormat, &der) >= 0)) {
rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
WOLFSSL_RSA_LOAD_PUBLIC);
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
}
}
FreeDer(&der);
if ((out != NULL) && (rsa != NULL)) {
*out = rsa;
}
return rsa;
}
WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa,
wc_pem_password_cb* cb, void* pass)
{
return wolfSSL_PEM_read_RSA_PUBKEY(fp, rsa, cb, pass);
}
#endif
#if defined(WOLFSSL_KEY_GEN) && \
(defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
int wolfSSL_PEM_write_mem_RSAPrivateKey(WOLFSSL_RSA* rsa,
const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
unsigned char **pem, int *pLen)
{
int ret = 1;
byte* derBuf = NULL;
int derSz = 0;
WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
if ((pem == NULL) || (pLen == NULL) || (rsa == NULL) ||
(rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = 0;
}
if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = 0;
}
if ((ret == 1) && ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0,
rsa->heap)) < 0)) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
ret = 0;
}
if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
passwdSz, PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
ret = 0;
}
return ret;
}
#ifndef NO_BIO
int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
wc_pem_password_cb* cb, void* arg)
{
int ret = 1;
byte* pem = NULL;
int pLen = 0;
(void)cb;
(void)arg;
WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
if ((bio == NULL) || (rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = 0;
}
if (ret == 1) {
ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, len,
&pem, &pLen);
if (ret != 1) {
WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
}
}
if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) <= 0)) {
WOLFSSL_ERROR_MSG("RSA private key BIO write failed");
ret = 0;
}
XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
return ret;
}
#endif
#ifndef NO_FILESYSTEM
int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
wc_pem_password_cb *cb, void *arg)
{
int ret = 1;
byte* pem = NULL;
int pLen = 0;
(void)cb;
(void)arg;
WOLFSSL_ENTER("wolfSSL_PEM_write_RSAPrivateKey");
if ((fp == XBADFILE) || (rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = 0;
}
if (ret == 1) {
ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, passwdSz,
&pem, &pLen);
if (ret != 1) {
WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
}
}
if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) {
WOLFSSL_ERROR_MSG("RSA private key file write failed");
ret = 0;
}
XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
return ret;
}
#endif
#endif
#ifndef NO_BIO
WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
WOLFSSL_RSA** out, wc_pem_password_cb* cb, void* pass)
{
WOLFSSL_RSA* rsa = NULL;
DerBuffer* der = NULL;
int keyFormat = 0;
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSAPrivateKey");
if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE,
&keyFormat, &der) >= 0)) {
rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
WOLFSSL_RSA_LOAD_PRIVATE);
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
}
}
FreeDer(&der);
if ((out != NULL) && (rsa != NULL)) {
*out = rsa;
}
return rsa;
}
#endif
#ifndef NO_FILESYSTEM
WOLFSSL_RSA* wolfSSL_PEM_read_RSAPrivateKey(XFILE fp, WOLFSSL_RSA** out,
wc_pem_password_cb* cb, void* pass)
{
WOLFSSL_RSA* rsa = NULL;
DerBuffer* der = NULL;
int keyFormat = 0;
WOLFSSL_ENTER("wolfSSL_PEM_read_RSAPrivateKey");
if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PRIVATEKEY_TYPE,
&keyFormat, &der) >= 0)) {
rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
WOLFSSL_RSA_LOAD_PRIVATE);
if (rsa == NULL) {
WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
}
}
FreeDer(&der);
if ((out != NULL) && (rsa != NULL)) {
*out = rsa;
}
return rsa;
}
#endif
#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
!defined(NO_STDIO_FILESYSTEM)
int wolfSSL_RSA_print_fp(XFILE fp, WOLFSSL_RSA* rsa, int indent)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_RSA_print_fp");
if ((fp == XBADFILE) || (rsa == NULL)) {
ret = 0;
}
if ((ret == 1) && (!rsa->exSet)) {
ret = SetRsaExternal(rsa);
}
if ((ret == 1) && (rsa->n != NULL)) {
int keySize = wolfSSL_BN_num_bits(rsa->n);
if (keySize == 0) {
ret = 0;
}
else {
if (XFPRINTF(fp, "%*s", indent, "") < 0)
ret = 0;
else if (XFPRINTF(fp, "RSA Private-Key: (%d bit, 2 primes)\n",
keySize) < 0)
ret = 0;
}
}
if ((ret == 1) && (rsa->n != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "modulus", rsa->n);
}
if ((ret == 1) && (rsa->d != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "privateExponent", rsa->d);
}
if ((ret == 1) && (rsa->p != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "prime1", rsa->p);
}
if ((ret == 1) && (rsa->q != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "prime2", rsa->q);
}
if ((ret == 1) && (rsa->dmp1 != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "exponent1", rsa->dmp1);
}
if ((ret == 1) && (rsa->dmq1 != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "exponent2", rsa->dmq1);
}
if ((ret == 1) && (rsa->iqmp != NULL)) {
ret = pk_bn_field_print_fp(fp, indent, "coefficient", rsa->iqmp);
}
WOLFSSL_LEAVE("wolfSSL_RSA_print_fp", ret);
return ret;
}
#endif
#if defined(XSNPRINTF) && !defined(NO_BIO)
#define RSA_PRINT_MAX_HEADER_LINE PRINT_NUM_MAX_INDENT
int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent)
{
int ret = 1;
int sz = 0;
RsaKey* key = NULL;
char line[RSA_PRINT_MAX_HEADER_LINE];
int i = 0;
mp_int *num = NULL;
const char *name[] = {
"Modulus:", "Exponent:", "PrivateExponent:", "Prime1:", "Prime2:",
"Exponent1:", "Exponent2:", "Coefficient:"
};
WOLFSSL_ENTER("wolfSSL_RSA_print");
if ((bio == NULL) || (rsa == NULL) || (indent > PRINT_NUM_MAX_INDENT)) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
key = (RsaKey*)rsa->internal;
sz = wolfSSL_RSA_bits(rsa);
if (sz <= 0) {
WOLFSSL_ERROR_MSG("Error getting RSA key size");
ret = 0;
}
}
if (ret == 1) {
ret = wolfssl_print_indent(bio, line, sizeof(line), indent);
}
if (ret == 1) {
int len = XSNPRINTF(line, sizeof(line), "\nRSA %s: (%d bit)\n",
(!mp_iszero(&key->d)) ? "Private-Key" : "Public-Key", sz);
if (len >= (int)sizeof(line)) {
WOLFSSL_ERROR_MSG("Buffer overflow while formatting key preamble");
ret = 0;
}
else {
if (wolfSSL_BIO_write(bio, line, len) <= 0) {
ret = 0;
}
}
}
for (i = 0; (ret == 1) && (i < RSA_INTS); i++) {
switch (i) {
case 0:
num = &key->n;
break;
case 1:
num = &key->e;
break;
case 2:
num = &key->d;
break;
case 3:
num = &key->p;
break;
case 4:
num = &key->q;
break;
case 5:
num = &key->dP;
break;
case 6:
num = &key->dQ;
break;
case 7:
num = &key->u;
break;
default:
WOLFSSL_ERROR_MSG("Bad index value");
}
if (i == 1) {
ret = wolfssl_print_value(bio, num, name[i], indent);
}
else if (!mp_iszero(num)) {
ret = wolfssl_print_number(bio, num, name[i], indent);
}
}
return ret;
}
#endif
#endif
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
int SetRsaExternal(WOLFSSL_RSA* rsa)
{
int ret = 1;
WOLFSSL_ENTER("SetRsaExternal");
if ((rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("rsa key NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
RsaKey* key = (RsaKey*)rsa->internal;
ret = wolfssl_bn_set_value(&rsa->n, &key->n);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa n error");
}
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->e, &key->e);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa e error");
}
}
if (key->type == RSA_PRIVATE) {
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->d, &key->d);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa d error");
}
}
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->p, &key->p);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa p error");
}
}
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->q, &key->q);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa q error");
}
}
#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \
!defined(RSA_LOW_MEM)
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->dmp1, &key->dP);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa dP error");
}
}
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->dmq1, &key->dQ);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa dq error");
}
}
if (ret == 1) {
ret = wolfssl_bn_set_value(&rsa->iqmp, &key->u);
if (ret != 1) {
WOLFSSL_ERROR_MSG("rsa u error");
}
}
#endif
#else
WOLFSSL_ERROR_MSG("rsa private key not compiled in ");
ret = 0;
#endif
}
}
if (ret == 1) {
rsa->exSet = 1;
}
else {
ret = 0;
}
return ret;
}
#endif
#ifdef OPENSSL_EXTRA
int SetRsaInternal(WOLFSSL_RSA* rsa)
{
int ret = 1;
WOLFSSL_ENTER("SetRsaInternal");
if ((rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("rsa key NULL error");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
RsaKey* key = (RsaKey*)rsa->internal;
if ((rsa->n != NULL) && (wolfssl_bn_get_value(rsa->n, &key->n) != 1)) {
WOLFSSL_ERROR_MSG("rsa n key error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (rsa->e != NULL) &&
(wolfssl_bn_get_value(rsa->e, &key->e) != 1)) {
WOLFSSL_ERROR_MSG("rsa e key error");
ret = WOLFSSL_FATAL_ERROR;
}
key->type = RSA_PUBLIC;
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
if ((ret == 1) && (rsa->d != NULL)) {
if (wolfssl_bn_get_value(rsa->d, &key->d) != 1) {
WOLFSSL_ERROR_MSG("rsa d key error");
ret = WOLFSSL_FATAL_ERROR;
}
else {
key->type = RSA_PRIVATE;
}
}
if ((ret == 1) && (rsa->p != NULL) &&
(wolfssl_bn_get_value(rsa->p, &key->p) != 1)) {
WOLFSSL_ERROR_MSG("rsa p key error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (rsa->q != NULL) &&
(wolfssl_bn_get_value(rsa->q, &key->q) != 1)) {
WOLFSSL_ERROR_MSG("rsa q key error");
ret = WOLFSSL_FATAL_ERROR;
}
#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
if ((ret == 1) && (rsa->dmp1 != NULL) &&
(wolfssl_bn_get_value(rsa->dmp1, &key->dP) != 1)) {
WOLFSSL_ERROR_MSG("rsa dP key error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (rsa->dmq1 != NULL) &&
(wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) {
WOLFSSL_ERROR_MSG("rsa dQ key error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (rsa->iqmp != NULL) &&
(wolfssl_bn_get_value(rsa->iqmp, &key->u) != 1)) {
WOLFSSL_ERROR_MSG("rsa u key error");
ret = WOLFSSL_FATAL_ERROR;
}
#endif
#endif
if (ret == 1) {
rsa->inSet = 1;
}
}
return ret;
}
int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth)
{
if (rsa != NULL) {
rsa->meth = meth;
rsa->flags = meth->flags;
}
return 1;
}
const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa)
{
return (rsa != NULL) ? rsa->meth : NULL;
}
int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_RSA_size");
if (rsa != NULL) {
if (rsa->inSet || (SetRsaInternal((WOLFSSL_RSA*)rsa) == 1)) {
ret = wc_RsaEncryptSize((RsaKey*)rsa->internal);
}
}
return ret;
}
int wolfSSL_RSA_bits(const WOLFSSL_RSA* rsa)
{
int ret = 0;
WOLFSSL_ENTER("wolfSSL_RSA_bits");
if (rsa != NULL) {
ret = wolfSSL_BN_num_bits(rsa->n);
}
return ret;
}
void wolfSSL_RSA_get0_crt_params(const WOLFSSL_RSA *rsa,
const WOLFSSL_BIGNUM **dmp1, const WOLFSSL_BIGNUM **dmq1,
const WOLFSSL_BIGNUM **iqmp)
{
WOLFSSL_ENTER("wolfSSL_RSA_get0_crt_params");
if (dmp1 != NULL) {
*dmp1 = (rsa != NULL) ? rsa->dmp1 : NULL;
}
if (dmq1 != NULL) {
*dmq1 = (rsa != NULL) ? rsa->dmq1 : NULL;
}
if (iqmp != NULL) {
*iqmp = (rsa != NULL) ? rsa->iqmp : NULL;
}
}
int wolfSSL_RSA_set0_crt_params(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *dmp1,
WOLFSSL_BIGNUM *dmq1, WOLFSSL_BIGNUM *iqmp)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_RSA_set0_crt_params");
if ((rsa == NULL) || ((rsa->dmp1 == NULL) && (dmp1 == NULL)) ||
((rsa->dmq1 == NULL) && (dmq1 == NULL)) ||
((rsa->iqmp == NULL) && (iqmp == NULL))) {
WOLFSSL_ERROR_MSG("Bad parameters");
ret = 0;
}
if (ret == 1) {
if (dmp1 != NULL) {
wolfSSL_BN_clear_free(rsa->dmp1);
rsa->dmp1 = dmp1;
}
if (dmq1 != NULL) {
wolfSSL_BN_clear_free(rsa->dmq1);
rsa->dmq1 = dmq1;
}
if (iqmp != NULL) {
wolfSSL_BN_clear_free(rsa->iqmp);
rsa->iqmp = iqmp;
}
if (SetRsaInternal(rsa) != 1) {
if (dmp1 != NULL) {
rsa->dmp1 = NULL;
}
if (dmq1 != NULL) {
rsa->dmq1 = NULL;
}
if (iqmp != NULL) {
rsa->iqmp = NULL;
}
ret = 0;
}
}
return ret;
}
void wolfSSL_RSA_get0_factors(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **p,
const WOLFSSL_BIGNUM **q)
{
WOLFSSL_ENTER("wolfSSL_RSA_get0_factors");
if (p != NULL) {
*p = (rsa != NULL) ? rsa->p : NULL;
}
if (q != NULL) {
*q = (rsa != NULL) ? rsa->q : NULL;
}
}
int wolfSSL_RSA_set0_factors(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *p,
WOLFSSL_BIGNUM *q)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_RSA_set0_factors");
if (rsa == NULL || ((rsa->p == NULL) && (p == NULL)) ||
((rsa->q == NULL) && (q == NULL))) {
WOLFSSL_ERROR_MSG("Bad parameters");
ret = 0;
}
if (ret == 1) {
if (p != NULL) {
wolfSSL_BN_clear_free(rsa->p);
rsa->p = p;
}
if (q != NULL) {
wolfSSL_BN_clear_free(rsa->q);
rsa->q = q;
}
if (SetRsaInternal(rsa) != 1) {
if (p != NULL) {
rsa->p = NULL;
}
if (q != NULL) {
rsa->q = NULL;
}
ret = 0;
}
}
return ret;
}
void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **n,
const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d)
{
WOLFSSL_ENTER("wolfSSL_RSA_get0_key");
if (n != NULL) {
*n = (rsa != NULL) ? rsa->n : NULL;
}
if (e != NULL) {
*e = (rsa != NULL) ? rsa->e : NULL;
}
if (d != NULL) {
*d = (rsa != NULL) ? rsa->d : NULL;
}
}
int wolfSSL_RSA_set0_key(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
WOLFSSL_BIGNUM *d)
{
int ret = 1;
if ((rsa == NULL) || ((rsa->n == NULL) && (n == NULL)) ||
((rsa->e == NULL) && (e == NULL))) {
ret = 0;
}
if (ret == 1) {
if (n != NULL) {
wolfSSL_BN_free(rsa->n);
rsa->n = n;
}
if (e != NULL) {
wolfSSL_BN_free(rsa->e);
rsa->e = e;
}
if (d != NULL) {
wolfSSL_BN_clear_free(rsa->d);
rsa->d = d;
}
if (SetRsaInternal(rsa) != 1) {
if (n != NULL) {
rsa->n = NULL;
}
if (e != NULL) {
rsa->e = NULL;
}
if (d != NULL) {
rsa->d = NULL;
}
ret = 0;
}
}
return ret;
}
int wolfSSL_RSA_flags(const WOLFSSL_RSA *rsa)
{
int ret = 0;
if (rsa != NULL) {
ret = rsa->flags;
}
return ret;
}
void wolfSSL_RSA_set_flags(WOLFSSL_RSA *rsa, int flags)
{
if (rsa != NULL) {
rsa->flags |= flags;
}
}
void wolfSSL_RSA_clear_flags(WOLFSSL_RSA *rsa, int flags)
{
if (rsa != NULL) {
rsa->flags &= ~flags;
}
}
int wolfSSL_RSA_test_flags(const WOLFSSL_RSA *rsa, int flags)
{
return (rsa != NULL) ? (rsa->flags & flags) : 0;
}
void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx)
{
WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data");
#ifdef HAVE_EX_DATA
return (rsa == NULL) ? NULL :
wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx);
#else
(void)rsa;
(void)idx;
return NULL;
#endif
}
int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
{
WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data");
#ifdef HAVE_EX_DATA
return (rsa == NULL) ? 0 :
wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data);
#else
(void)rsa;
(void)idx;
(void)data;
return 0;
#endif
}
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
int wolfSSL_RSA_set_ex_data_with_cleanup(WOLFSSL_RSA *rsa, int idx, void *data,
wolfSSL_ex_data_cleanup_routine_t freeCb)
{
WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data_with_cleanup");
return (rsa == NULL) ? 0 :
wolfSSL_CRYPTO_set_ex_data_with_cleanup(&rsa->ex_data, idx, data,
freeCb);
}
#endif
#ifdef WOLFSSL_RSA_KEY_CHECK
int wolfSSL_RSA_check_key(const WOLFSSL_RSA* rsa)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_RSA_check_key");
if ((rsa == NULL) || (rsa->internal == NULL)) {
ret = 0;
}
if ((ret == 1) && (wc_CheckRsaKey((RsaKey*)rsa->internal) != 0)) {
ret = 0;
}
WOLFSSL_LEAVE("wolfSSL_RSA_check_key", ret);
return ret;
}
#endif
WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA* rsa, WC_RNG** tmpRng, int* initTmpRng)
{
WC_RNG* rng = NULL;
int err = 0;
if ((rsa == NULL) || (initTmpRng == NULL)) {
err = 1;
}
if (!err) {
*initTmpRng = 0;
#if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
rng = ((RsaKey*)rsa->internal)->rng;
#endif
}
if ((!err) && (rng == NULL) && (tmpRng != NULL)) {
rng = wolfssl_make_rng(*tmpRng, initTmpRng);
if ((rng != NULL) && *initTmpRng) {
*tmpRng = rng;
}
}
return rng;
}
static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
WOLFSSL_BIGNUM* e, void* cb)
{
#ifdef WOLFSSL_KEY_GEN
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
WC_RNG* tmpRng = NULL;
#else
WC_RNG _tmpRng[1];
WC_RNG* tmpRng = _tmpRng;
#endif
int initTmpRng = 0;
WC_RNG* rng = NULL;
long en = 0;
#endif
(void)cb;
WOLFSSL_ENTER("wolfssl_rsa_generate_key_native");
#ifdef WOLFSSL_KEY_GEN
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
ret = MEMORY_E;
}
if ((ret == 0) && ((en = (long)wolfSSL_BN_get_word(e)) <= 0)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_MakeRsaKey((RsaKey*)rsa->internal, bits, en, rng);
if (ret != MP_OKAY) {
WOLFSSL_ERROR_MSG("wc_MakeRsaKey failed");
}
}
if (ret == 0) {
ret = SetRsaExternal(rsa);
if (ret == 1) {
rsa->inSet = 1;
ret = 0;
}
else {
ret = MEMORY_E;
}
}
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
return ret;
#else
WOLFSSL_ERROR_MSG("No Key Gen built in");
(void)rsa;
(void)e;
(void)bits;
return NOT_COMPILED_IN;
#endif
}
WOLFSSL_RSA* wolfSSL_RSA_generate_key(int bits, unsigned long e,
void(*cb)(int, int, void*), void* data)
{
WOLFSSL_RSA* rsa = NULL;
WOLFSSL_BIGNUM* bn = NULL;
int err = 0;
WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
(void)cb;
(void)data;
if (bits < 0) {
WOLFSSL_ERROR_MSG("Bad argument: bits was less than 0");
err = 1;
}
if ((!err) && ((bn = wolfSSL_BN_new()) == NULL)) {
WOLFSSL_ERROR_MSG("Error creating big number");
err = 1;
}
if ((!err) && (wolfSSL_BN_set_word(bn, e) != 1)) {
WOLFSSL_ERROR_MSG("Error using e value");
err = 1;
}
if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
WOLFSSL_ERROR_MSG("memory error");
err = 1;
}
while (!err) {
int ret;
ret = wolfssl_rsa_generate_key_native(rsa, bits, bn, NULL);
#ifdef HAVE_FIPS
if (ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
continue;
}
#endif
if (ret != WOLFSSL_ERROR_NONE) {
err = 1;
}
break;
}
if (err) {
wolfSSL_RSA_free(rsa);
rsa = NULL;
}
wolfSSL_BN_free(bn);
return rsa;
}
int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
void* cb)
{
int ret = 1;
if ((rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("bad arguments");
ret = 0;
}
else {
for (;;) {
int gen_ret = wolfssl_rsa_generate_key_native(rsa, bits, e, cb);
#ifdef HAVE_FIPS
if (gen_ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
continue;
}
#endif
if (gen_ret != WOLFSSL_ERROR_NONE) {
ret = 0;
}
break;
}
}
return ret;
}
#endif
#ifdef WC_RSA_PSS
#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen)
{
switch (saltLen) {
case WC_RSA_PSS_SALTLEN_DIGEST:
saltLen = hashLen;
break;
case WC_RSA_PSS_SALTLEN_MAX_SIGN:
case WC_RSA_PSS_SALTLEN_MAX:
#ifdef WOLFSSL_PSS_LONG_SALT
saltLen = emLen - hashLen - 2;
#else
saltLen = hashLen;
(void)emLen;
#endif
break;
default:
break;
}
if (saltLen < 0) {
WOLFSSL_ERROR_MSG("invalid saltLen");
saltLen = -3;
}
return saltLen;
}
#endif
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
int wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, unsigned char *em,
const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
const WOLFSSL_EVP_MD *mgf1Hash, int saltLen)
{
int ret = 1;
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
int hashLen = 0;
int emLen = 0;
int mgf = 0;
int initTmpRng = 0;
WC_RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
WC_RNG* tmpRng = NULL;
#else
WC_RNG _tmpRng[1];
WC_RNG* tmpRng = _tmpRng;
#endif
WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS");
if ((rsa == NULL) || (em == NULL) || (mHash == NULL) || (hashAlg == NULL)) {
ret = 0;
}
if (mgf1Hash == NULL)
mgf1Hash = hashAlg;
if (ret == 1) {
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
ret = 0;
}
}
if ((ret == 1) && (!rsa->exSet)) {
ret = SetRsaExternal(rsa);
}
if (ret == 1) {
hashType = EvpMd2MacType(hashAlg);
if (hashType > WC_HASH_TYPE_MAX) {
WOLFSSL_ERROR_MSG("EvpMd2MacType error");
ret = 0;
}
}
if (ret == 1) {
mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash));
if (mgf == WC_MGF1NONE) {
WOLFSSL_ERROR_MSG("wc_hash2mgf error");
ret = 0;
}
}
if (ret == 1) {
hashLen = wolfSSL_EVP_MD_size(hashAlg);
if (hashLen < 0) {
WOLFSSL_ERROR_MSG("wolfSSL_EVP_MD_size error");
ret = 0;
}
}
if (ret == 1) {
emLen = wolfSSL_RSA_size(rsa);
if (emLen <= 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
ret = 0;
}
}
if (ret == 1) {
saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
}
if (ret == 1) {
if (wc_RsaPad_ex(mHash, (word32)hashLen, em, (word32)emLen,
RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0,
saltLen, wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) {
WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
ret = 0;
}
}
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
return ret;
}
int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg, int saltLen)
{
return wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(rsa, em, mHash, hashAlg, NULL,
saltLen);
}
int wolfSSL_RSA_verify_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa,
const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
const WOLFSSL_EVP_MD *mgf1Hash, const unsigned char *em, int saltLen)
{
int ret = 1;
int hashLen = 0;
int mgf = 0;
int emLen = 0;
int mPrimeLen = 0;
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
byte *mPrime = NULL;
byte *buf = NULL;
WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS");
if ((rsa == NULL) || (mHash == NULL) || (hashAlg == NULL) || (em == NULL)) {
ret = 0;
}
if (mgf1Hash == NULL)
mgf1Hash = hashAlg;
if ((ret == 1) && (!rsa->exSet)) {
ret = SetRsaExternal(rsa);
}
if (ret == 1) {
hashLen = wolfSSL_EVP_MD_size(hashAlg);
if (hashLen < 0) {
ret = 0;
}
}
if (ret == 1) {
emLen = wolfSSL_RSA_size(rsa);
if (emLen <= 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
ret = 0;
}
}
if (ret == 1) {
saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
}
if (ret == 1) {
hashType = EvpMd2MacType(hashAlg);
if (hashType > WC_HASH_TYPE_MAX) {
WOLFSSL_ERROR_MSG("EvpMd2MacType error");
ret = 0;
}
}
if (ret == 1) {
if ((mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash))) == WC_MGF1NONE) {
WOLFSSL_ERROR_MSG("wc_hash2mgf error");
ret = 0;
}
}
if (ret == 1) {
buf = (byte*)XMALLOC((size_t)emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL) {
WOLFSSL_ERROR_MSG("malloc error");
ret = 0;
}
}
if (ret == 1) {
XMEMCPY(buf, em, (size_t)emLen);
mPrimeLen = wc_RsaUnPad_ex(buf, (word32)emLen, &mPrime,
RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0, saltLen,
wolfSSL_BN_num_bits(rsa->n), NULL);
if (mPrimeLen < 0) {
WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
ret = 0;
}
}
if (ret == 1) {
if (wc_RsaPSS_CheckPadding_ex(mHash, (word32)hashLen, mPrime,
(word32)mPrimeLen, hashType, saltLen,
wolfSSL_BN_num_bits(rsa->n)) != MP_OKAY) {
WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
ret = 0;
}
}
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
const WOLFSSL_EVP_MD *hashAlg,
const unsigned char *em, int saltLen)
{
return wolfSSL_RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, hashAlg, NULL, em,
saltLen);
}
#endif
#endif
#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
#define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT
#else
#define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER
#endif
#else
#define DEF_PSS_SALT_LEN 0
#endif
#if defined(OPENSSL_EXTRA)
static int wolfssl_rsa_sig_encode(int hashAlg, const unsigned char* hash,
unsigned int hLen, unsigned char* enc, unsigned int* encLen, int padding)
{
int ret = 1;
int hType = WC_HASH_TYPE_NONE;
if ((hash == NULL) || (enc == NULL) || (encLen == NULL)) {
ret = 0;
}
if ((ret == 1) && (hashAlg != WC_NID_undef) &&
(padding == WC_RSA_PKCS1_PADDING)) {
hType = (int)nid2oid(hashAlg, oidHashType);
if (hType == -1) {
ret = 0;
}
}
if ((ret == 1) && (padding == WC_RSA_PKCS1_PADDING)) {
word32 encSz = wc_EncodeSignature(enc, hash, hLen, hType);
if (encSz == 0) {
WOLFSSL_ERROR_MSG("Bad Encode Signature");
ret = 0;
}
else {
*encLen = (unsigned int)encSz;
}
}
if ((ret == 1) && (padding != WC_RSA_PKCS1_PADDING)) {
XMEMCPY(enc, hash, hLen);
*encLen = hLen;
}
return ret;
}
int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen,
unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA* rsa)
{
if (sigLen != NULL) {
*sigLen = RSA_MAX_SIZE / CHAR_BIT;
}
return wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
sigLen, rsa, 1, WC_RSA_PKCS1_PADDING);
}
int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
WOLFSSL_RSA* rsa, int flag)
{
int ret = 0;
if ((flag == 0) || (flag == 1)) {
if (sigLen != NULL) {
*sigLen = RSA_MAX_SIZE / CHAR_BIT;
}
ret = wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
sigLen, rsa, flag, WC_RSA_PKCS1_PADDING);
}
return ret;
}
int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
WOLFSSL_RSA* rsa, int flag, int padding)
{
return wolfSSL_RSA_sign_mgf(hashAlg, hash, hLen, sigRet, sigLen, rsa, flag,
padding, hashAlg, DEF_PSS_SALT_LEN);
}
int wolfSSL_RSA_sign_mgf(int hashAlg, const unsigned char* hash,
unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
WOLFSSL_RSA* rsa, int flag, int padding, int mgf1Hash, int saltLen)
{
int ret = 1;
word32 outLen = 0;
int signSz = 0;
WC_RNG* rng = NULL;
int initTmpRng = 0;
#ifdef WOLFSSL_SMALL_STACK
WC_RNG* tmpRng = NULL;
byte* encodedSig = NULL;
#else
WC_RNG _tmpRng[1];
WC_RNG* tmpRng = _tmpRng;
byte encodedSig[MAX_ENCODED_SIG_SZ];
#endif
unsigned int encSz = 0;
WOLFSSL_ENTER("wolfSSL_RSA_sign_mgf");
if (flag == 0) {
return wolfssl_rsa_sig_encode(hashAlg, hash, hLen, sigRet, sigLen,
padding);
}
if ((hash == NULL) || (sigRet == NULL) || sigLen == NULL || rsa == NULL) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = 0;
}
if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = 0;
}
if (ret == 1) {
outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
ret = 0;
}
else if (outLen > *sigLen) {
WOLFSSL_ERROR_MSG("Output buffer too small");
ret = 0;
}
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 1) {
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_SIGNATURE);
if (encodedSig == NULL) {
ret = 0;
}
}
#endif
if (ret == 1) {
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
ret = 0;
}
}
if ((ret == 1) && (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig,
&encSz, padding) == 0)) {
WOLFSSL_ERROR_MSG("Bad Encode Signature");
ret = 0;
}
if (ret == 1) {
switch (padding) {
#if defined(WC_RSA_NO_PADDING) || defined(WC_RSA_DIRECT)
case WC_RSA_NO_PAD:
if ((signSz = wc_RsaDirect(encodedSig, encSz, sigRet, &outLen,
(RsaKey*)rsa->internal, RSA_PRIVATE_ENCRYPT, rng)) <= 0) {
WOLFSSL_ERROR_MSG("Bad RSA Sign no pad");
ret = 0;
}
break;
#endif
#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
case WC_RSA_PKCS1_PSS_PADDING:
{
RsaKey* key = (RsaKey*)rsa->internal;
enum wc_HashType mgf1, hType;
hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
if (mgf1Hash == WC_NID_undef)
mgf1Hash = hashAlg;
mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
wolfSSL_RSA_size(rsa));
if ((signSz = wc_RsaPSS_Sign_ex(encodedSig, encSz, sigRet, outLen,
hType, wc_hash2mgf(mgf1), saltLen, key, rng)) <= 0) {
WOLFSSL_ERROR_MSG("Bad RSA PSS Sign");
ret = 0;
}
break;
}
#endif
#ifndef WC_NO_RSA_OAEP
case WC_RSA_PKCS1_OAEP_PADDING:
WOLFSSL_ERROR_MSG("RSA_PKCS1_OAEP_PADDING not supported for "
"signing");
ret = 0;
break;
#endif
case WC_RSA_PKCS1_PADDING:
{
if ((signSz = wc_RsaSSL_Sign(encodedSig, encSz, sigRet, outLen,
(RsaKey*)rsa->internal, rng)) <= 0) {
WOLFSSL_ERROR_MSG("Bad PKCS1 RSA Sign");
ret = 0;
}
break;
}
default:
WOLFSSL_ERROR_MSG("Unsupported padding");
(void)mgf1Hash;
(void)saltLen;
ret = 0;
break;
}
}
if (ret == 1) {
*sigLen = (unsigned int)signSz;
}
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
WOLFSSL_LEAVE("wolfSSL_RSA_sign_mgf", ret);
return ret;
}
int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
WOLFSSL_RSA* rsa)
{
return wolfSSL_RSA_verify_ex(hashAlg, hash, hLen, sig, sigLen, rsa,
WC_RSA_PKCS1_PADDING);
}
int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
WOLFSSL_RSA* rsa, int padding)
{
return wolfSSL_RSA_verify_mgf(hashAlg, hash, hLen, sig, sigLen, rsa,
padding, hashAlg, DEF_PSS_SALT_LEN);
}
int wolfSSL_RSA_verify_mgf(int hashAlg, const unsigned char* hash,
unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
WOLFSSL_RSA* rsa, int padding, int mgf1Hash, int saltLen)
{
int ret = 1;
#ifdef WOLFSSL_SMALL_STACK
unsigned char* encodedSig = NULL;
#else
unsigned char encodedSig[MAX_ENCODED_SIG_SZ];
#endif
unsigned char* sigDec = NULL;
unsigned int len = MAX_ENCODED_SIG_SZ;
int verLen = 0;
#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && !defined(HAVE_SELFTEST)
enum wc_HashType hType = WC_HASH_TYPE_NONE;
#endif
WOLFSSL_ENTER("wolfSSL_RSA_verify_mgf");
if ((hash == NULL) || (sig == NULL) || (rsa == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = 0;
}
if (ret == 1) {
sigDec = (unsigned char *)XMALLOC(sigLen, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (sigDec == NULL) {
WOLFSSL_ERROR_MSG("Memory allocation failure");
ret = 0;
}
}
if (ret == 1 && padding == WC_RSA_PKCS1_PSS_PADDING) {
#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
RsaKey* key = (RsaKey*)rsa->internal;
enum wc_HashType mgf1;
hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
if (mgf1Hash == WC_NID_undef)
mgf1Hash = hashAlg;
mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
wolfSSL_RSA_size(rsa));
verLen = wc_RsaPSS_Verify_ex((byte*)sig, sigLen, sigDec, sigLen,
hType, wc_hash2mgf(mgf1), saltLen, key);
if (verLen > 0) {
if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen,
hType, saltLen, mp_count_bits(&key->n)) != 0) {
WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
ret = WOLFSSL_FAILURE;
}
else {
XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return WOLFSSL_SUCCESS;
}
}
else {
WOLFSSL_ERROR_MSG("wc_RsaPSS_Verify_ex failed!");
ret = WOLFSSL_FAILURE;
}
#else
(void)mgf1Hash;
(void)saltLen;
WOLFSSL_ERROR_MSG("RSA PSS not compiled in!");
ret = WOLFSSL_FAILURE;
#endif
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 1) {
encodedSig = (unsigned char *)XMALLOC(len, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) {
WOLFSSL_ERROR_MSG("Memory allocation failure");
ret = 0;
}
}
#endif
if (ret == 1) {
if (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig, &len,
padding) <= 0) {
WOLFSSL_ERROR_MSG("Message Digest Error");
ret = 0;
}
}
if (ret == 1) {
#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && \
!defined(HAVE_SELFTEST)
hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
if ((verLen = wc_RsaSSL_Verify_ex2(sig, sigLen, (unsigned char *)sigDec,
sigLen, (RsaKey*)rsa->internal, padding, hType)) <= 0) {
WOLFSSL_ERROR_MSG("RSA Decrypt error");
ret = 0;
}
#else
verLen = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
(RsaKey*)rsa->internal);
if (verLen < 0) {
ret = 0;
}
#endif
}
if (ret == 1) {
if (((int)len != verLen) ||
(XMEMCMP(encodedSig, sigDec, (size_t)verLen) != 0)) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_verify_ex failed");
ret = 0;
}
}
WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
WOLFSSL_LEAVE("wolfSSL_RSA_verify_mgf", ret);
return ret;
}
int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
unsigned char* to, WOLFSSL_RSA* rsa, int padding)
{
int ret = 0;
int initTmpRng = 0;
WC_RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
WC_RNG* tmpRng = NULL;
#else
WC_RNG _tmpRng[1];
WC_RNG* tmpRng = _tmpRng;
#endif
#if !defined(HAVE_FIPS)
int mgf = WC_MGF1NONE;
enum wc_HashType hash = WC_HASH_TYPE_NONE;
int pad_type = WC_RSA_NO_PAD;
#endif
int outLen = 0;
WOLFSSL_ENTER("wolfSSL_RSA_public_encrypt");
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
switch (padding) {
case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
case WC_RSA_PKCS1_OAEP_PADDING:
pad_type = WC_RSA_OAEP_PAD;
hash = WC_HASH_TYPE_SHA;
mgf = WC_MGF1SHA1;
break;
case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
default:
WOLFSSL_ERROR_MSG("RSA_public_encrypt doesn't support padding "
"scheme");
ret = WOLFSSL_FATAL_ERROR;
}
#else
if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
"FIPS");
ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
ret = wc_RsaPublicEncrypt_ex(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal, rng, pad_type, hash, mgf, NULL, 0);
#else
ret = wc_RsaPublicEncrypt(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal, rng);
#endif
}
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
if (ret <= 0) {
ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_public_encrypt", ret);
return ret;
}
int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
unsigned char* to, WOLFSSL_RSA* rsa, int padding)
{
int ret = 0;
#if !defined(HAVE_FIPS)
int mgf = WC_MGF1NONE;
enum wc_HashType hash = WC_HASH_TYPE_NONE;
int pad_type = WC_RSA_NO_PAD;
#endif
int outLen = 0;
WOLFSSL_ENTER("wolfSSL_RSA_private_decrypt");
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
switch (padding) {
case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
case WC_RSA_PKCS1_OAEP_PADDING:
pad_type = WC_RSA_OAEP_PAD;
hash = WC_HASH_TYPE_SHA;
mgf = WC_MGF1SHA1;
break;
case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
default:
WOLFSSL_ERROR_MSG("RSA_private_decrypt unsupported padding");
ret = WOLFSSL_FATAL_ERROR;
}
#else
if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
"FIPS");
ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
ret = wc_RsaPrivateDecrypt_ex(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal, pad_type, hash, mgf, NULL, 0);
#else
ret = wc_RsaPrivateDecrypt(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal);
#endif
}
if (ret <= 0) {
ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_private_decrypt", ret);
return ret;
}
int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
unsigned char* to, WOLFSSL_RSA* rsa, int padding)
{
int ret = 0;
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
int pad_type = WC_RSA_NO_PAD;
#endif
int outLen = 0;
WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
switch (padding) {
case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
default:
WOLFSSL_ERROR_MSG("RSA_public_decrypt unsupported padding");
ret = WOLFSSL_FATAL_ERROR;
}
#else
if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_decrypt pad type not supported in "
"FIPS");
ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
ret = wc_RsaSSL_Verify_ex(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal, pad_type);
#else
ret = wc_RsaSSL_Verify(from, (word32)len, to, (word32)outLen,
(RsaKey*)rsa->internal);
#endif
}
if (ret <= 0) {
ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_public_decrypt", ret);
return ret;
}
int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
unsigned char* to, WOLFSSL_RSA* rsa, int padding)
{
int ret = 0;
int initTmpRng = 0;
WC_RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
WC_RNG* tmpRng = NULL;
#else
WC_RNG _tmpRng[1];
WC_RNG* tmpRng = _tmpRng;
#endif
WOLFSSL_ENTER("wolfSSL_RSA_private_encrypt");
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
switch (padding) {
case WC_RSA_PKCS1_PADDING:
#ifdef WC_RSA_NO_PADDING
case WC_RSA_NO_PAD:
#endif
break;
default:
WOLFSSL_ERROR_MSG("RSA_private_encrypt unsupported padding");
ret = WOLFSSL_FATAL_ERROR;
}
}
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
if (padding == WC_RSA_PKCS1_PADDING) {
ret = wc_RsaSSL_Sign(from, (word32)len, to,
(word32)wolfSSL_RSA_size(rsa), (RsaKey*)rsa->internal, rng);
}
#ifdef WC_RSA_NO_PADDING
else if (padding == WC_RSA_NO_PAD) {
word32 outLen = (word32)wolfSSL_RSA_size(rsa);
ret = wc_RsaFunction(from, (word32)len, to, &outLen,
RSA_PRIVATE_ENCRYPT, (RsaKey*)rsa->internal, rng);
if (ret == 0)
ret = (int)outLen;
}
#endif
}
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
if (ret <= 0) {
ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", ret);
return ret;
}
int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
{
int ret = 1;
int err;
mp_int* t = NULL;
WC_DECLARE_VAR(tmp, mp_int, 1, 0);
WOLFSSL_ENTER("wolfSSL_RsaGenAdd");
if ((rsa == NULL) || (rsa->p == NULL) || (rsa->q == NULL) ||
(rsa->d == NULL) || (rsa->dmp1 == NULL) || (rsa->dmq1 == NULL)) {
WOLFSSL_ERROR_MSG("rsa no init error");
ret = WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 1) {
tmp = (mp_int *)XMALLOC(sizeof(*tmp), rsa->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
WOLFSSL_ERROR_MSG("Memory allocation failure");
ret = WOLFSSL_FATAL_ERROR;
}
}
#endif
if (ret == 1) {
if (mp_init(tmp) != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_init error");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
t = tmp;
err = mp_sub_d((mp_int*)rsa->p->internal, 1, tmp);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_sub_d error");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
err = mp_mod((mp_int*)rsa->d->internal, tmp,
(mp_int*)rsa->dmp1->internal);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_mod error");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
err = mp_sub_d((mp_int*)rsa->q->internal, 1, tmp);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_sub_d error");
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
err = mp_mod((mp_int*)rsa->d->internal, tmp,
(mp_int*)rsa->dmq1->internal);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_mod error");
ret = WOLFSSL_FATAL_ERROR;
}
}
mp_forcezero(t);
#ifdef WOLFSSL_SMALL_STACK
if (rsa != NULL) {
XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
return ret;
}
#ifndef NO_WOLFSSL_STUB
int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bnCtx)
{
WOLFSSL_STUB("RSA_blinding_on");
WOLFSSL_ENTER("wolfSSL_RSA_blinding_on");
(void)rsa;
(void)bnCtx;
return 1;
}
#endif
#endif
#endif
#endif