X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frsa%2Frsa_pmeth.c;h=e899fbd6053dee8353e8a334fae22a3beab63c2c;hp=8c8e0e86e47df70f68e6f83c79675ed0b9edd40c;hb=45c236ad1f1c881281017941a0e7126735a190e8;hpb=7f572e958b13041056f377a62d3219633cfb1e8a diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 8c8e0e86e4..e899fbd605 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -1,62 +1,20 @@ -/* crypto/rsa/rsa_pmeth.c */ /* - * 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-2020 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 */ +/* + * RSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include "internal/constant_time.h" + #include #include "internal/cryptlib.h" #include @@ -65,11 +23,10 @@ #include #include #include -#ifndef OPENSSL_NO_CMS -# include -#endif -#include "internal/evp_int.h" -#include "rsa_locl.h" +#include +#include "crypto/evp.h" +#include "crypto/rsa.h" +#include "rsa_local.h" /* RSA pkey context structure */ @@ -77,6 +34,7 @@ typedef struct { /* Key gen parameters */ int nbits; BIGNUM *pub_exp; + int primes; /* Keygen callback info */ int gentmp[2]; /* RSA padding mode */ @@ -87,6 +45,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 */ @@ -94,15 +54,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; @@ -110,9 +79,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; @@ -126,9 +96,10 @@ 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 = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen); + dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen); if (!dctx->oaep_label) return 0; dctx->oaep_labellen = sctx->oaep_labellen; @@ -138,11 +109,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(RSA_size(pk->pkey->pkey.rsa))) == NULL) { + RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE); return 0; + } return 1; } @@ -175,14 +147,14 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, unsigned int sltmp; if (rctx->pad_mode != RSA_PKCS1_PADDING) return -1; - ret = RSA_sign_ASN1_OCTET_STRING(NID_mdc2, + ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, rsa); if (ret <= 0) return ret; ret = sltmp; } else if (rctx->pad_mode == RSA_X931_PADDING) { - if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) { + if ((size_t)RSA_size(rsa) < tbslen + 1) { RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL); return -1; } @@ -211,11 +183,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; @@ -259,11 +233,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; @@ -277,10 +253,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; @@ -298,8 +279,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; @@ -322,6 +304,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)) @@ -334,9 +317,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; @@ -349,35 +333,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; @@ -401,12 +382,18 @@ static int check_padding_md(const EVP_MD *md, int padding) case NID_sha256: case NID_sha384: case NID_sha512: + case NID_sha512_224: + case NID_sha512_256: case NID_md5: case NID_md5_sha1: case NID_md2: 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: @@ -422,6 +409,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)) { @@ -433,6 +421,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)) @@ -458,17 +448,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; } @@ -476,12 +479,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) { @@ -497,6 +510,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; @@ -516,8 +535,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: @@ -544,16 +570,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); @@ -568,27 +599,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; } @@ -597,18 +629,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; @@ -618,28 +659,44 @@ 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 = string_to_hex(value, &lablen); + + lab = OPENSSL_hexstr2buf(value, &lablen); if (!lab) return 0; ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen); @@ -651,12 +708,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)) @@ -672,18 +747,24 @@ 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; } -const EVP_PKEY_METHOD rsa_pkey_meth = { +static const EVP_PKEY_METHOD rsa_pkey_meth = { EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN, pkey_rsa_init, @@ -717,3 +798,84 @@ const EVP_PKEY_METHOD rsa_pkey_meth = { pkey_rsa_ctrl, pkey_rsa_ctrl_str }; + +const EVP_PKEY_METHOD *rsa_pkey_method(void) +{ + return &rsa_pkey_meth; +} + +/* + * 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; +} + +static 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 +}; + +const EVP_PKEY_METHOD *rsa_pss_pkey_method(void) +{ + return &rsa_pss_pkey_meth; +}