summaryrefslogtreecommitdiffstats
path: root/lib/libcrypto/rsa
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libcrypto/rsa')
-rw-r--r--lib/libcrypto/rsa/rsa_ameth.c351
-rw-r--r--lib/libcrypto/rsa/rsa_crpt.c257
-rw-r--r--lib/libcrypto/rsa/rsa_pmeth.c154
-rw-r--r--lib/libcrypto/rsa/rsa_pss.c81
4 files changed, 805 insertions, 38 deletions
diff --git a/lib/libcrypto/rsa/rsa_ameth.c b/lib/libcrypto/rsa/rsa_ameth.c
index 8c3209885ea..2460910ab27 100644
--- a/lib/libcrypto/rsa/rsa_ameth.c
+++ b/lib/libcrypto/rsa/rsa_ameth.c
@@ -265,6 +265,147 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
}
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+ X509_ALGOR **pmaskHash)
+ {
+ const unsigned char *p;
+ int plen;
+ RSA_PSS_PARAMS *pss;
+
+ *pmaskHash = NULL;
+
+ if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE)
+ return NULL;
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+
+ if (!pss)
+ return NULL;
+
+ if (pss->maskGenAlgorithm)
+ {
+ ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
+ if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
+ && param->type == V_ASN1_SEQUENCE)
+ {
+ p = param->value.sequence->data;
+ plen = param->value.sequence->length;
+ *pmaskHash = d2i_X509_ALGOR(NULL, &p, plen);
+ }
+ }
+
+ return pss;
+ }
+
+static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
+ X509_ALGOR *maskHash, int indent)
+ {
+ int rv = 0;
+ if (!pss)
+ {
+ if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0)
+ return 0;
+ return 1;
+ }
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
+ goto err;
+
+ if (pss->hashAlgorithm)
+ {
+ if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "sha1 (default)") <= 0)
+ goto err;
+
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+
+ if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
+ goto err;
+ if (pss->maskGenAlgorithm)
+ {
+ if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0)
+ goto err;
+ if (BIO_puts(bp, " with ") <= 0)
+ goto err;
+ if (maskHash)
+ {
+ if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "INVALID") <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Salt Length: ") <= 0)
+ goto err;
+ if (pss->saltLength)
+ {
+ if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "20 (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128))
+ goto err;
+ if (BIO_puts(bp, "Trailer Field: ") <= 0)
+ goto err;
+ if (pss->trailerField)
+ {
+ if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
+ goto err;
+ }
+ else if (BIO_puts(bp, "0xbc (default)") <= 0)
+ goto err;
+ BIO_puts(bp, "\n");
+
+ rv = 1;
+
+ err:
+ return rv;
+
+ }
+
+static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
+ const ASN1_STRING *sig,
+ int indent, ASN1_PCTX *pctx)
+ {
+ if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss)
+ {
+ int rv;
+ RSA_PSS_PARAMS *pss;
+ X509_ALGOR *maskHash;
+ pss = rsa_pss_decode(sigalg, &maskHash);
+ rv = rsa_pss_param_print(bp, pss, maskHash, indent);
+ if (pss)
+ RSA_PSS_PARAMS_free(pss);
+ if (maskHash)
+ X509_ALGOR_free(maskHash);
+ if (!rv)
+ return 0;
+ }
+ else if (!sig && BIO_puts(bp, "\n") <= 0)
+ return 0;
+ if (sig)
+ return X509_signature_dump(bp, sig, indent);
+ return 1;
+ }
static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
@@ -310,6 +451,211 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
}
+/* Customised RSA item verification routine. This is called
+ * when a signature is encountered requiring special handling. We
+ * currently only handle PSS.
+ */
+
+
+static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
+ EVP_PKEY *pkey)
+ {
+ int rv = -1;
+ int saltlen;
+ const EVP_MD *mgf1md = NULL, *md = NULL;
+ RSA_PSS_PARAMS *pss;
+ X509_ALGOR *maskHash;
+ EVP_PKEY_CTX *pkctx;
+ /* Sanity check: make sure it is PSS */
+ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+ return -1;
+ }
+ /* Decode PSS parameters */
+ pss = rsa_pss_decode(sigalg, &maskHash);
+
+ if (pss == NULL)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+ /* Check mask and lookup mask hash algorithm */
+ if (pss->maskGenAlgorithm)
+ {
+ if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_ALGORITHM);
+ goto err;
+ }
+ if (!maskHash)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_PARAMETER);
+ goto err;
+ }
+ mgf1md = EVP_get_digestbyobj(maskHash->algorithm);
+ if (mgf1md == NULL)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_MASK_DIGEST);
+ goto err;
+ }
+ }
+ else
+ mgf1md = EVP_sha1();
+
+ if (pss->hashAlgorithm)
+ {
+ md = EVP_get_digestbyobj(pss->hashAlgorithm->algorithm);
+ if (md == NULL)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST);
+ goto err;
+ }
+ }
+ else
+ md = EVP_sha1();
+
+ if (pss->saltLength)
+ {
+ saltlen = ASN1_INTEGER_get(pss->saltLength);
+
+ /* Could perform more salt length sanity checks but the main
+ * RSA routines will trap other invalid values anyway.
+ */
+ if (saltlen < 0)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_SALT_LENGTH);
+ goto err;
+ }
+ }
+ else
+ saltlen = 20;
+
+ /* low-level routines support only trailer field 0xbc (value 1)
+ * and PKCS#1 says we should reject any other value anyway.
+ */
+ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1)
+ {
+ RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER);
+ goto err;
+ }
+
+ /* We have all parameters now set up context */
+
+ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
+ goto err;
+
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
+ goto err;
+ /* Carry on */
+ rv = 2;
+
+ err:
+ RSA_PSS_PARAMS_free(pss);
+ if (maskHash)
+ X509_ALGOR_free(maskHash);
+ return rv;
+ }
+
+static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *alg1, X509_ALGOR *alg2,
+ ASN1_BIT_STRING *sig)
+ {
+ int pad_mode;
+ EVP_PKEY_CTX *pkctx = ctx->pctx;
+ if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
+ return 0;
+ if (pad_mode == RSA_PKCS1_PADDING)
+ return 2;
+ if (pad_mode == RSA_PKCS1_PSS_PADDING)
+ {
+ const EVP_MD *sigmd, *mgf1md;
+ RSA_PSS_PARAMS *pss = NULL;
+ X509_ALGOR *mgf1alg = NULL;
+ ASN1_STRING *os1 = NULL, *os2 = NULL;
+ EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
+ int saltlen, rv = 0;
+ sigmd = EVP_MD_CTX_md(ctx);
+ if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
+ goto err;
+ if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
+ goto err;
+ if (saltlen == -1)
+ saltlen = EVP_MD_size(sigmd);
+ else if (saltlen == -2)
+ {
+ saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+ if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
+ saltlen--;
+ }
+ pss = RSA_PSS_PARAMS_new();
+ if (!pss)
+ goto err;
+ if (saltlen != 20)
+ {
+ pss->saltLength = ASN1_INTEGER_new();
+ if (!pss->saltLength)
+ goto err;
+ if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
+ goto err;
+ }
+ if (EVP_MD_type(sigmd) != NID_sha1)
+ {
+ pss->hashAlgorithm = X509_ALGOR_new();
+ if (!pss->hashAlgorithm)
+ goto err;
+ X509_ALGOR_set_md(pss->hashAlgorithm, sigmd);
+ }
+ if (EVP_MD_type(mgf1md) != NID_sha1)
+ {
+ ASN1_STRING *stmp = NULL;
+ /* need to embed algorithm ID inside another */
+ mgf1alg = X509_ALGOR_new();
+ X509_ALGOR_set_md(mgf1alg, mgf1md);
+ if (!ASN1_item_pack(mgf1alg, ASN1_ITEM_rptr(X509_ALGOR),
+ &stmp))
+ goto err;
+ pss->maskGenAlgorithm = X509_ALGOR_new();
+ if (!pss->maskGenAlgorithm)
+ goto err;
+ X509_ALGOR_set0(pss->maskGenAlgorithm,
+ OBJ_nid2obj(NID_mgf1),
+ V_ASN1_SEQUENCE, stmp);
+ }
+ /* Finally create string with pss parameter encoding. */
+ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os1))
+ goto err;
+ if (alg2)
+ {
+ os2 = ASN1_STRING_dup(os1);
+ if (!os2)
+ goto err;
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss),
+ V_ASN1_SEQUENCE, os2);
+ }
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss),
+ V_ASN1_SEQUENCE, os1);
+ os1 = os2 = NULL;
+ rv = 3;
+ err:
+ if (mgf1alg)
+ X509_ALGOR_free(mgf1alg);
+ if (pss)
+ RSA_PSS_PARAMS_free(pss);
+ if (os1)
+ ASN1_STRING_free(os1);
+ return rv;
+
+ }
+ return 2;
+ }
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
{
@@ -335,10 +681,13 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
0,0,0,0,0,0,
+ rsa_sig_print,
int_rsa_free,
rsa_pkey_ctrl,
old_rsa_priv_decode,
- old_rsa_priv_encode
+ old_rsa_priv_encode,
+ rsa_item_verify,
+ rsa_item_sign
},
{
diff --git a/lib/libcrypto/rsa/rsa_crpt.c b/lib/libcrypto/rsa/rsa_crpt.c
new file mode 100644
index 00000000000..d3e44785dcf
--- /dev/null
+++ b/lib/libcrypto/rsa/rsa_crpt.c
@@ -0,0 +1,257 @@
+/* crypto/rsa/rsa_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/lhash.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+
+int RSA_size(const RSA *r)
+ {
+ return(BN_num_bytes(r->n));
+ }
+
+int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
+ && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+ {
+ RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_NON_FIPS_RSA_METHOD);
+ return -1;
+ }
+#endif
+ return(rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding));
+ }
+
+int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
+ && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+ {
+ RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_NON_FIPS_RSA_METHOD);
+ return -1;
+ }
+#endif
+ return(rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding));
+ }
+
+int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
+ && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+ {
+ RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_NON_FIPS_RSA_METHOD);
+ return -1;
+ }
+#endif
+ return(rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding));
+ }
+
+int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
+ && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
+ {
+ RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_NON_FIPS_RSA_METHOD);
+ return -1;
+ }
+#endif
+ return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding));
+ }
+
+int RSA_flags(const RSA *r)
+ {
+ return((r == NULL)?0:r->meth->flags);
+ }
+
+void RSA_blinding_off(RSA *rsa)
+ {
+ if (rsa->blinding != NULL)
+ {
+ BN_BLINDING_free(rsa->blinding);
+ rsa->blinding=NULL;
+ }
+ rsa->flags &= ~RSA_FLAG_BLINDING;
+ rsa->flags |= RSA_FLAG_NO_BLINDING;
+ }
+
+int RSA_blinding_on(RSA *rsa, BN_CTX *ctx)
+ {
+ int ret=0;
+
+ if (rsa->blinding != NULL)
+ RSA_blinding_off(rsa);
+
+ rsa->blinding = RSA_setup_blinding(rsa, ctx);
+ if (rsa->blinding == NULL)
+ goto err;
+
+ rsa->flags |= RSA_FLAG_BLINDING;
+ rsa->flags &= ~RSA_FLAG_NO_BLINDING;
+ ret=1;
+err:
+ return(ret);
+ }
+
+static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
+ const BIGNUM *q, BN_CTX *ctx)
+{
+ BIGNUM *ret = NULL, *r0, *r1, *r2;
+
+ if (d == NULL || p == NULL || q == NULL)
+ return NULL;
+
+ BN_CTX_start(ctx);
+ r0 = BN_CTX_get(ctx);
+ r1 = BN_CTX_get(ctx);
+ r2 = BN_CTX_get(ctx);
+ if (r2 == NULL)
+ goto err;
+
+ if (!BN_sub(r1, p, BN_value_one())) goto err;
+ if (!BN_sub(r2, q, BN_value_one())) goto err;
+ if (!BN_mul(r0, r1, r2, ctx)) goto err;
+
+ ret = BN_mod_inverse(NULL, d, r0, ctx);
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
+{
+ BIGNUM local_n;
+ BIGNUM *e,*n;
+ BN_CTX *ctx;
+ BN_BLINDING *ret = NULL;
+
+ if (in_ctx == NULL)
+ {
+ if ((ctx = BN_CTX_new()) == NULL) return 0;
+ }
+ else
+ ctx = in_ctx;
+
+ BN_CTX_start(ctx);
+ e = BN_CTX_get(ctx);
+ if (e == NULL)
+ {
+ RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (rsa->e == NULL)
+ {
+ e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
+ if (e == NULL)
+ {
+ RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
+ goto err;
+ }
+ }
+ else
+ e = rsa->e;
+
+
+ if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
+ {
+ /* if PRNG is not properly seeded, resort to secret
+ * exponent as unpredictable seed */
+ RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0);
+ }
+
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ /* Set BN_FLG_CONSTTIME flag */
+ n = &local_n;
+ BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
+ }
+ else
+ n = rsa->n;
+
+ ret = BN_BLINDING_create_param(NULL, e, n, ctx,
+ rsa->meth->bn_mod_exp, rsa->_method_mod_n);
+ if (ret == NULL)
+ {
+ RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
+ goto err;
+ }
+ CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
+err:
+ BN_CTX_end(ctx);
+ if (in_ctx == NULL)
+ BN_CTX_free(ctx);
+ if(rsa->e == NULL)
+ BN_free(e);
+
+ return ret;
+}
diff --git a/lib/libcrypto/rsa/rsa_pmeth.c b/lib/libcrypto/rsa/rsa_pmeth.c
index c6892ecd09c..5b2ecf56adc 100644
--- a/lib/libcrypto/rsa/rsa_pmeth.c
+++ b/lib/libcrypto/rsa/rsa_pmeth.c
@@ -63,6 +63,12 @@
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
+#ifndef OPENSSL_NO_CMS
+#include <openssl/cms.h>
+#endif
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
#include "evp_locl.h"
#include "rsa_locl.h"
@@ -79,6 +85,8 @@ typedef struct
int pad_mode;
/* message digest */
const EVP_MD *md;
+ /* message digest for MGF1 */
+ const EVP_MD *mgf1md;
/* PSS/OAEP salt length */
int saltlen;
/* Temp buffer */
@@ -95,6 +103,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
rctx->pub_exp = NULL;
rctx->pad_mode = RSA_PKCS1_PADDING;
rctx->md = NULL;
+ rctx->mgf1md = NULL;
rctx->tbuf = NULL;
rctx->saltlen = -2;
@@ -147,6 +156,31 @@ static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
OPENSSL_free(rctx);
}
}
+#ifdef OPENSSL_FIPS
+/* FIP checker. Return value indicates status of context parameters:
+ * 1 : redirect to FIPS.
+ * 0 : don't redirect to FIPS.
+ * -1 : illegal operation in FIPS mode.
+ */
+
+static int pkey_fips_check_ctx(EVP_PKEY_CTX *ctx)
+ {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ int rv = -1;
+ if (!FIPS_mode())
+ return 0;
+ if (rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
+ rv = 0;
+ if (!(rsa->meth->flags & RSA_FLAG_FIPS_METHOD) && rv)
+ return -1;
+ if (rctx->md && !(rctx->md->flags & EVP_MD_FLAG_FIPS))
+ return rv;
+ if (rctx->mgf1md && !(rctx->mgf1md->flags & EVP_MD_FLAG_FIPS))
+ return rv;
+ return 1;
+ }
+#endif
static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
@@ -155,6 +189,15 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
RSA_PKEY_CTX *rctx = ctx->data;
RSA *rsa = ctx->pkey->pkey.rsa;
+#ifdef OPENSSL_FIPS
+ ret = pkey_fips_check_ctx(ctx);
+ if (ret < 0)
+ {
+ RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+ return -1;
+ }
+#endif
+
if (rctx->md)
{
if (tbslen != (size_t)EVP_MD_size(rctx->md))
@@ -163,7 +206,36 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
RSA_R_INVALID_DIGEST_LENGTH);
return -1;
}
- if (rctx->pad_mode == RSA_X931_PADDING)
+#ifdef OPENSSL_FIPS
+ if (ret > 0)
+ {
+ unsigned int slen;
+ ret = FIPS_rsa_sign_digest(rsa, tbs, tbslen, rctx->md,
+ rctx->pad_mode,
+ rctx->saltlen,
+ rctx->mgf1md,
+ sig, &slen);
+ if (ret > 0)
+ *siglen = slen;
+ else
+ *siglen = 0;
+ return ret;
+ }
+#endif
+
+ if (EVP_MD_type(rctx->md) == NID_mdc2)
+ {
+ unsigned int sltmp;
+ if (rctx->pad_mode != RSA_PKCS1_PADDING)
+ return -1;
+ ret = RSA_sign_ASN1_OCTET_STRING(NID_mdc2,
+ tbs, tbslen, sig, &sltmp, rsa);
+
+ if (ret <= 0)
+ return ret;
+ ret = sltmp;
+ }
+ else if (rctx->pad_mode == RSA_X931_PADDING)
{
if (!setup_tbuf(rctx, ctx))
return -1;
@@ -186,8 +258,10 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
{
if (!setup_tbuf(rctx, ctx))
return -1;
- if (!RSA_padding_add_PKCS1_PSS(rsa, rctx->tbuf, tbs,
- rctx->md, rctx->saltlen))
+ if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
+ rctx->tbuf, tbs,
+ rctx->md, rctx->mgf1md,
+ rctx->saltlen))
return -1;
ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
sig, rsa, RSA_NO_PADDING);
@@ -269,8 +343,30 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
RSA_PKEY_CTX *rctx = ctx->data;
RSA *rsa = ctx->pkey->pkey.rsa;
size_t rslen;
+#ifdef OPENSSL_FIPS
+ int rv;
+ rv = pkey_fips_check_ctx(ctx);
+ if (rv < 0)
+ {
+ RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE);
+ return -1;
+ }
+#endif
if (rctx->md)
{
+#ifdef OPENSSL_FIPS
+ if (rv > 0)
+ {
+ return FIPS_rsa_verify_digest(rsa,
+ tbs, tbslen,
+ rctx->md,
+ rctx->pad_mode,
+ rctx->saltlen,
+ rctx->mgf1md,
+ sig, siglen);
+
+ }
+#endif
if (rctx->pad_mode == RSA_PKCS1_PADDING)
return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
sig, siglen, rsa);
@@ -289,7 +385,8 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
rsa, RSA_NO_PADDING);
if (ret <= 0)
return 0;
- ret = RSA_verify_PKCS1_PSS(rsa, tbs, rctx->md,
+ ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
+ rctx->md, rctx->mgf1md,
rctx->tbuf, rctx->saltlen);
if (ret <= 0)
return 0;
@@ -403,15 +500,25 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return -2;
+ case EVP_PKEY_CTRL_GET_RSA_PADDING:
+ *(int *)p2 = rctx->pad_mode;
+ return 1;
+
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
- if (p1 < -2)
- return -2;
+ case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
{
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
- rctx->saltlen = p1;
+ if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
+ *(int *)p2 = rctx->saltlen;
+ else
+ {
+ if (p1 < -2)
+ return -2;
+ rctx->saltlen = p1;
+ }
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
@@ -435,16 +542,45 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
rctx->md = p2;
return 1;
+ case EVP_PKEY_CTRL_RSA_MGF1_MD:
+ case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
+ if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING)
+ {
+ RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
+ return -2;
+ }
+ if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD)
+ {
+ if (rctx->mgf1md)
+ *(const EVP_MD **)p2 = rctx->mgf1md;
+ else
+ *(const EVP_MD **)p2 = rctx->md;
+ }
+ else
+ rctx->mgf1md = p2;
+ return 1;
+
case EVP_PKEY_CTRL_DIGESTINIT:
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
+ return 1;
#ifndef OPENSSL_NO_CMS
- case EVP_PKEY_CTRL_CMS_ENCRYPT:
case EVP_PKEY_CTRL_CMS_DECRYPT:
+ {
+ X509_ALGOR *alg = NULL;
+ ASN1_OBJECT *encalg = NULL;
+ if (p2)
+ CMS_RecipientInfo_ktri_get0_algs(p2, NULL, NULL, &alg);
+ if (alg)
+ X509_ALGOR_get0(&encalg, NULL, NULL, alg);
+ if (encalg && OBJ_obj2nid(encalg) == NID_rsaesOaep)
+ rctx->pad_mode = RSA_PKCS1_OAEP_PADDING;
+ }
+ case EVP_PKEY_CTRL_CMS_ENCRYPT:
case EVP_PKEY_CTRL_CMS_SIGN:
-#endif
return 1;
+#endif
case EVP_PKEY_CTRL_PEER_KEY:
RSAerr(RSA_F_PKEY_RSA_CTRL,
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
diff --git a/lib/libcrypto/rsa/rsa_pss.c b/lib/libcrypto/rsa/rsa_pss.c
index ac211e2ffe0..5f9f533d0ce 100644
--- a/lib/libcrypto/rsa/rsa_pss.c
+++ b/lib/libcrypto/rsa/rsa_pss.c
@@ -73,6 +73,13 @@ static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
const EVP_MD *Hash, const unsigned char *EM, int sLen)
{
+ return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
+ }
+
+int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+ const unsigned char *EM, int sLen)
+ {
int i;
int ret = 0;
int hLen, maskedDBLen, MSBits, emLen;
@@ -80,6 +87,10 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
unsigned char *DB = NULL;
EVP_MD_CTX ctx;
unsigned char H_[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX_init(&ctx);
+
+ if (mgf1Hash == NULL)
+ mgf1Hash = Hash;
hLen = EVP_MD_size(Hash);
if (hLen < 0)
@@ -94,7 +105,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
else if (sLen == -2) sLen = -2;
else if (sLen < -2)
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
goto err;
}
@@ -102,7 +113,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
emLen = RSA_size(rsa);
if (EM[0] & (0xFF << MSBits))
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_FIRST_OCTET_INVALID);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID);
goto err;
}
if (MSBits == 0)
@@ -112,12 +123,12 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
}
if (emLen < (hLen + sLen + 2)) /* sLen can be small negative */
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_DATA_TOO_LARGE);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
goto err;
}
if (EM[emLen - 1] != 0xbc)
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_LAST_OCTET_INVALID);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID);
goto err;
}
maskedDBLen = emLen - hLen - 1;
@@ -125,10 +136,10 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
DB = OPENSSL_malloc(maskedDBLen);
if (!DB)
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, ERR_R_MALLOC_FAILURE);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, Hash) < 0)
+ if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
goto err;
for (i = 0; i < maskedDBLen; i++)
DB[i] ^= EM[i];
@@ -137,25 +148,28 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
for (i = 0; DB[i] == 0 && i < (maskedDBLen-1); i++) ;
if (DB[i++] != 0x1)
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_RECOVERY_FAILED);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED);
goto err;
}
if (sLen >= 0 && (maskedDBLen - i) != sLen)
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
goto err;
}
- EVP_MD_CTX_init(&ctx);
- EVP_DigestInit_ex(&ctx, Hash, NULL);
- EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
- EVP_DigestUpdate(&ctx, mHash, hLen);
+ if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
+ || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
+ || !EVP_DigestUpdate(&ctx, mHash, hLen))
+ goto err;
if (maskedDBLen - i)
- EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i);
- EVP_DigestFinal(&ctx, H_, NULL);
- EVP_MD_CTX_cleanup(&ctx);
+ {
+ if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i))
+ goto err;
+ }
+ if (!EVP_DigestFinal_ex(&ctx, H_, NULL))
+ goto err;
if (memcmp(H_, H, hLen))
{
- RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_BAD_SIGNATURE);
+ RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE);
ret = 0;
}
else
@@ -164,6 +178,7 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
err:
if (DB)
OPENSSL_free(DB);
+ EVP_MD_CTX_cleanup(&ctx);
return ret;
@@ -173,12 +188,22 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
const unsigned char *mHash,
const EVP_MD *Hash, int sLen)
{
+ return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
+ }
+
+int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
+ const unsigned char *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen)
+ {
int i;
int ret = 0;
int hLen, maskedDBLen, MSBits, emLen;
unsigned char *H, *salt = NULL, *p;
EVP_MD_CTX ctx;
+ if (mgf1Hash == NULL)
+ mgf1Hash = Hash;
+
hLen = EVP_MD_size(Hash);
if (hLen < 0)
goto err;
@@ -192,7 +217,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
else if (sLen == -2) sLen = -2;
else if (sLen < -2)
{
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
goto err;
}
@@ -209,8 +234,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
}
else if (emLen < (hLen + sLen + 2))
{
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
- RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
goto err;
}
if (sLen > 0)
@@ -218,8 +242,7 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
salt = OPENSSL_malloc(sLen);
if (!salt)
{
- RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
- ERR_R_MALLOC_FAILURE);
+ RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,ERR_R_MALLOC_FAILURE);
goto err;
}
if (RAND_bytes(salt, sLen) <= 0)
@@ -228,16 +251,18 @@ int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
maskedDBLen = emLen - hLen - 1;
H = EM + maskedDBLen;
EVP_MD_CTX_init(&ctx);
- EVP_DigestInit_ex(&ctx, Hash, NULL);
- EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
- EVP_DigestUpdate(&ctx, mHash, hLen);
- if (sLen)
- EVP_DigestUpdate(&ctx, salt, sLen);
- EVP_DigestFinal(&ctx, H, NULL);
+ if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
+ || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
+ || !EVP_DigestUpdate(&ctx, mHash, hLen))
+ goto err;
+ if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen))
+ goto err;
+ if (!EVP_DigestFinal_ex(&ctx, H, NULL))
+ goto err;
EVP_MD_CTX_cleanup(&ctx);
/* Generate dbMask in place then perform XOR on it */
- if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, Hash))
+ if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
goto err;
p = EM;