X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=crypto%2Frsa%2Frsa_pmeth.c;h=bd0870b48dc019133755debe4d7d58bfa95daeb6;hb=70b0b977f73cd70e17538af3095d18e0cf59132e;hp=b128d736f73272a40d8c0e2608ae1c4c53c190a0;hpb=14f051a0ae3d752c50f419d3583e85fdf4c5bfc9;p=openssl.git diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index b128d736f7..bd0870b48d 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -1,61 +1,14 @@ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006. - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * 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 above 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 acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +#include "internal/constant_time_locl.h" + #include #include "internal/cryptlib.h" #include @@ -74,6 +27,7 @@ typedef struct { /* Key gen parameters */ int nbits; BIGNUM *pub_exp; + int primes; /* Keygen callback info */ int gentmp[2]; /* RSA padding mode */ @@ -84,6 +38,8 @@ typedef struct { const EVP_MD *mgf1md; /* PSS salt length */ int saltlen; + /* Minimum salt length or -1 if no PSS parameter restriction */ + int min_saltlen; /* Temp buffer */ unsigned char *tbuf; /* OAEP label */ @@ -91,15 +47,24 @@ typedef struct { size_t oaep_labellen; } RSA_PKEY_CTX; +/* True if PSS parameters are restricted */ +#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1) + static int pkey_rsa_init(EVP_PKEY_CTX *ctx) { - RSA_PKEY_CTX *rctx; - rctx = OPENSSL_zalloc(sizeof(*rctx)); + RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx)); + if (rctx == NULL) return 0; - rctx->nbits = 1024; - rctx->pad_mode = RSA_PKCS1_PADDING; - rctx->saltlen = -2; + rctx->nbits = 2048; + rctx->primes = RSA_DEFAULT_PRIME_NUM; + if (pkey_ctx_is_pss(ctx)) + rctx->pad_mode = RSA_PKCS1_PSS_PADDING; + else + rctx->pad_mode = RSA_PKCS1_PADDING; + /* Maximum for sign, auto for verify */ + rctx->saltlen = RSA_PSS_SALTLEN_AUTO; + rctx->min_saltlen = -1; ctx->data = rctx; ctx->keygen_info = rctx->gentmp; ctx->keygen_info_count = 2; @@ -107,9 +72,10 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx) return 1; } -static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) { RSA_PKEY_CTX *dctx, *sctx; + if (!pkey_rsa_init(dst)) return 0; sctx = src->data; @@ -123,6 +89,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) dctx->pad_mode = sctx->pad_mode; dctx->md = sctx->md; dctx->mgf1md = sctx->mgf1md; + dctx->saltlen = sctx->saltlen; if (sctx->oaep_label) { OPENSSL_free(dctx->oaep_label); dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen); @@ -135,11 +102,12 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) { - if (ctx->tbuf) + if (ctx->tbuf != NULL) return 1; - ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey)); - if (ctx->tbuf == NULL) + if ((ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey))) == NULL) { + RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE); return 0; + } return 1; } @@ -208,11 +176,13 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, return -1; ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf, sig, rsa, RSA_NO_PADDING); - } else + } else { return -1; - } else + } + } else { ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa, rctx->pad_mode); + } if (ret < 0) return ret; *siglen = ret; @@ -256,11 +226,13 @@ static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx, if (ret <= 0) return 0; ret = sltmp; - } else + } else { return -1; - } else + } + } else { ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa, rctx->pad_mode); + } if (ret < 0) return ret; *routlen = ret; @@ -274,10 +246,15 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, RSA_PKEY_CTX *rctx = ctx->data; RSA *rsa = ctx->pkey->pkey.rsa; size_t rslen; + if (rctx->md) { if (rctx->pad_mode == RSA_PKCS1_PADDING) return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa); + if (tbslen != (size_t)EVP_MD_size(rctx->md)) { + RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } if (rctx->pad_mode == RSA_X931_PADDING) { if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0) return 0; @@ -295,8 +272,9 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, if (ret <= 0) return 0; return 1; - } else + } else { return -1; + } } else { if (!setup_tbuf(rctx, ctx)) return -1; @@ -319,6 +297,7 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, { int ret; RSA_PKEY_CTX *rctx = ctx->data; + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { int klen = RSA_size(ctx->pkey->pkey.rsa); if (!setup_tbuf(rctx, ctx)) @@ -331,9 +310,10 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, return -1; ret = RSA_public_encrypt(klen, rctx->tbuf, out, ctx->pkey->pkey.rsa, RSA_NO_PADDING); - } else + } else { ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa, rctx->pad_mode); + } if (ret < 0) return ret; *outlen = ret; @@ -346,35 +326,32 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, { int ret; RSA_PKEY_CTX *rctx = ctx->data; + if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { - int i; if (!setup_tbuf(rctx, ctx)) return -1; ret = RSA_private_decrypt(inlen, in, rctx->tbuf, ctx->pkey->pkey.rsa, RSA_NO_PADDING); if (ret <= 0) return ret; - for (i = 0; i < ret; i++) { - if (rctx->tbuf[i]) - break; - } - ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf + i, - ret - i, ret, + ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf, + ret, ret, rctx->oaep_label, rctx->oaep_labellen, rctx->md, rctx->mgf1md); - } else + } else { ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa, rctx->pad_mode); - if (ret < 0) - return ret; - *outlen = ret; - return 1; + } + *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret); + ret = constant_time_select_int(constant_time_msb(ret), ret, 1); + return ret; } static int check_padding_md(const EVP_MD *md, int padding) { int mdnid; + if (!md) return 1; @@ -404,6 +381,10 @@ static int check_padding_md(const EVP_MD *md, int padding) case NID_md4: case NID_mdc2: case NID_ripemd160: + case NID_sha3_224: + case NID_sha3_256: + case NID_sha3_384: + case NID_sha3_512: return 1; default: @@ -419,6 +400,7 @@ static int check_padding_md(const EVP_MD *md, int padding) static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { RSA_PKEY_CTX *rctx = ctx->data; + switch (type) { case EVP_PKEY_CTRL_RSA_PADDING: if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) { @@ -430,6 +412,8 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) goto bad_pad; if (!rctx->md) rctx->md = EVP_sha1(); + } else if (pkey_ctx_is_pss(ctx)) { + goto bad_pad; } if (p1 == RSA_PKCS1_OAEP_PADDING) { if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT)) @@ -455,17 +439,30 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN); return -2; } - if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) + if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { *(int *)p2 = rctx->saltlen; - else { - if (p1 < -2) + } else { + if (p1 < RSA_PSS_SALTLEN_MAX) return -2; + if (rsa_pss_restricted(rctx)) { + if (p1 == RSA_PSS_SALTLEN_AUTO + && ctx->operation == EVP_PKEY_OP_VERIFY) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN); + return -2; + } + if ((p1 == RSA_PSS_SALTLEN_DIGEST + && rctx->min_saltlen > EVP_MD_size(rctx->md)) + || (p1 >= 0 && p1 < rctx->min_saltlen)) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + } rctx->saltlen = p1; } return 1; case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: - if (p1 < 512) { + if (p1 < RSA_MIN_MODULUS_BITS) { RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL); return -2; } @@ -473,12 +470,22 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return 1; case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: - if (!p2) + if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE); return -2; + } BN_free(rctx->pub_exp); rctx->pub_exp = p2; return 1; + case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES: + if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) { + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID); + return -2; + } + rctx->primes = p1; + return 1; + case EVP_PKEY_CTRL_RSA_OAEP_MD: case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) { @@ -494,6 +501,12 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_MD: if (!check_padding_md(p2, rctx->pad_mode)) return 0; + if (rsa_pss_restricted(rctx)) { + if (EVP_MD_type(rctx->md) == EVP_MD_type(p2)) + return 1; + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED); + return 0; + } rctx->md = p2; return 1; @@ -513,8 +526,15 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) *(const EVP_MD **)p2 = rctx->mgf1md; else *(const EVP_MD **)p2 = rctx->md; - } else + } else { + if (rsa_pss_restricted(rctx)) { + if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2)) + return 1; + RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED); + return 0; + } rctx->mgf1md = p2; + } return 1; case EVP_PKEY_CTRL_RSA_OAEP_LABEL: @@ -541,16 +561,21 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return rctx->oaep_labellen; case EVP_PKEY_CTRL_DIGESTINIT: + case EVP_PKEY_CTRL_PKCS7_SIGN: +#ifndef OPENSSL_NO_CMS + case EVP_PKEY_CTRL_CMS_SIGN: +#endif + return 1; + 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_DECRYPT: case EVP_PKEY_CTRL_CMS_ENCRYPT: - case EVP_PKEY_CTRL_CMS_SIGN: - return 1; #endif + if (!pkey_ctx_is_pss(ctx)) + return 1; + /* fall through */ case EVP_PKEY_CTRL_PEER_KEY: RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -565,27 +590,28 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { - if (!value) { + if (value == NULL) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (strcmp(type, "rsa_padding_mode") == 0) { int pm; - if (strcmp(value, "pkcs1") == 0) + + if (strcmp(value, "pkcs1") == 0) { pm = RSA_PKCS1_PADDING; - else if (strcmp(value, "sslv23") == 0) + } else if (strcmp(value, "sslv23") == 0) { pm = RSA_SSLV23_PADDING; - else if (strcmp(value, "none") == 0) + } else if (strcmp(value, "none") == 0) { pm = RSA_NO_PADDING; - else if (strcmp(value, "oeap") == 0) + } else if (strcmp(value, "oeap") == 0) { pm = RSA_PKCS1_OAEP_PADDING; - else if (strcmp(value, "oaep") == 0) + } else if (strcmp(value, "oaep") == 0) { pm = RSA_PKCS1_OAEP_PADDING; - else if (strcmp(value, "x931") == 0) + } else if (strcmp(value, "x931") == 0) { pm = RSA_X931_PADDING; - else if (strcmp(value, "pss") == 0) + } else if (strcmp(value, "pss") == 0) { pm = RSA_PKCS1_PSS_PADDING; - else { + } else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } @@ -594,18 +620,27 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, if (strcmp(type, "rsa_pss_saltlen") == 0) { int saltlen; - saltlen = atoi(value); + + if (!strcmp(value, "digest")) + saltlen = RSA_PSS_SALTLEN_DIGEST; + else if (!strcmp(value, "max")) + saltlen = RSA_PSS_SALTLEN_MAX; + else if (!strcmp(value, "auto")) + saltlen = RSA_PSS_SALTLEN_AUTO; + else + saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (strcmp(type, "rsa_keygen_bits") == 0) { - int nbits; - nbits = atoi(value); + int nbits = atoi(value); + return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (strcmp(type, "rsa_keygen_pubexp") == 0) { int ret; + BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; @@ -615,27 +650,43 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, return ret; } - if (strcmp(type, "rsa_mgf1_md") == 0) { - const EVP_MD *md; - if ((md = EVP_get_digestbyname(value)) == NULL) { - RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); - return 0; - } - return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md); + if (strcmp(type, "rsa_keygen_primes") == 0) { + int nprimes = atoi(value); + + return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes); } - if (strcmp(type, "rsa_oaep_md") == 0) { - const EVP_MD *md; - if ((md = EVP_get_digestbyname(value)) == NULL) { - RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); - return 0; + if (strcmp(type, "rsa_mgf1_md") == 0) + return EVP_PKEY_CTX_md(ctx, + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_MGF1_MD, value); + + if (pkey_ctx_is_pss(ctx)) { + + if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_MGF1_MD, value); + + if (strcmp(type, "rsa_pss_keygen_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_MD, value); + + if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) { + int saltlen = atoi(value); + + return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen); } - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md); } + + if (strcmp(type, "rsa_oaep_md") == 0) + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_OAEP_MD, value); + if (strcmp(type, "rsa_oaep_label") == 0) { unsigned char *lab; long lablen; int ret; + lab = OPENSSL_hexstr2buf(value, &lablen); if (!lab) return 0; @@ -648,12 +699,30 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, return -2; } +/* Set PSS parameters when generating a key, if necessary */ +static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx) +{ + RSA_PKEY_CTX *rctx = ctx->data; + + if (!pkey_ctx_is_pss(ctx)) + return 1; + /* If all parameters are default values don't set pss */ + if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2) + return 1; + rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md, + rctx->saltlen == -2 ? 0 : rctx->saltlen); + if (rsa->pss == NULL) + return 0; + return 1; +} + static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { RSA *rsa = NULL; RSA_PKEY_CTX *rctx = ctx->data; BN_GENCB *pcb; int ret; + if (rctx->pub_exp == NULL) { rctx->pub_exp = BN_new(); if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4)) @@ -669,12 +738,18 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) return 0; } evp_pkey_set_cb_translate(pcb, ctx); - } else + } else { pcb = NULL; - ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb); + } + ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes, + rctx->pub_exp, pcb); BN_GENCB_free(pcb); + if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) { + RSA_free(rsa); + return 0; + } if (ret > 0) - EVP_PKEY_assign_RSA(pkey, rsa); + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa); else RSA_free(rsa); return ret; @@ -714,3 +789,74 @@ const EVP_PKEY_METHOD rsa_pkey_meth = { pkey_rsa_ctrl, pkey_rsa_ctrl_str }; + +/* + * Called for PSS sign or verify initialisation: checks PSS parameter + * sanity and sets any restrictions on key usage. + */ + +static int pkey_pss_init(EVP_PKEY_CTX *ctx) +{ + RSA *rsa; + RSA_PKEY_CTX *rctx = ctx->data; + const EVP_MD *md; + const EVP_MD *mgf1md; + int min_saltlen, max_saltlen; + + /* Should never happen */ + if (!pkey_ctx_is_pss(ctx)) + return 0; + rsa = ctx->pkey->pkey.rsa; + /* If no restrictions just return */ + if (rsa->pss == NULL) + return 1; + /* Get and check parameters */ + if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen)) + return 0; + + /* See if minimum salt length exceeds maximum possible */ + max_saltlen = RSA_size(rsa) - EVP_MD_size(md); + if ((RSA_bits(rsa) & 0x7) == 1) + max_saltlen--; + if (min_saltlen > max_saltlen) { + RSAerr(RSA_F_PKEY_PSS_INIT, RSA_R_INVALID_SALT_LENGTH); + return 0; + } + + rctx->min_saltlen = min_saltlen; + + /* + * Set PSS restrictions as defaults: we can then block any attempt to + * use invalid values in pkey_rsa_ctrl + */ + + rctx->md = md; + rctx->mgf1md = mgf1md; + rctx->saltlen = min_saltlen; + + return 1; +} + +const EVP_PKEY_METHOD rsa_pss_pkey_meth = { + EVP_PKEY_RSA_PSS, + EVP_PKEY_FLAG_AUTOARGLEN, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + + 0, 0, + + 0, + pkey_rsa_keygen, + + pkey_pss_init, + pkey_rsa_sign, + + pkey_pss_init, + pkey_rsa_verify, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + pkey_rsa_ctrl, + pkey_rsa_ctrl_str +};