diff options
author | Richard Levitte <levitte@openssl.org> | 2019-12-01 15:01:50 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-02-22 01:07:15 +0100 |
commit | 6f4b7663150e2ee264836dbc5b338bd979828312 (patch) | |
tree | 52d0a120512bb8ea123150e2ffccd0841008cbc2 | |
parent | e8d0819d52b2741fcb4ddb79ced4d824c3056918 (diff) | |
download | openssl-new-6f4b7663150e2ee264836dbc5b338bd979828312.tar.gz |
PROV: add RSA signature implementation
This includes legacy PSS controls to params conversion, and an attempt
to generalise the parameter names when they are suitable for more than
one operation.
Also added crypto/rsa/rsa_aid.c, containing proper AlgorithmIdentifiers
for known RSA+hash function combinations.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/10557)
-rw-r--r-- | crypto/err/openssl.txt | 11 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 118 | ||||
-rw-r--r-- | crypto/rsa/build.info | 2 | ||||
-rw-r--r-- | crypto/rsa/rsa_aid.c | 98 | ||||
-rw-r--r-- | crypto/rsa/rsa_lib.c | 113 | ||||
-rw-r--r-- | crypto/rsa/rsa_local.h | 4 | ||||
-rw-r--r-- | crypto/rsa/rsa_pmeth.c | 1 | ||||
-rw-r--r-- | crypto/rsa/rsa_sign.c | 40 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_CTX_ctrl.pod | 59 | ||||
-rw-r--r-- | include/crypto/rsa.h | 8 | ||||
-rw-r--r-- | include/openssl/core_names.h | 26 | ||||
-rw-r--r-- | include/openssl/rsa.h | 10 | ||||
-rw-r--r-- | providers/common/include/prov/providercommonerr.h | 10 | ||||
-rw-r--r-- | providers/common/provider_err.c | 19 | ||||
-rw-r--r-- | providers/defltprov.c | 1 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 1 | ||||
-rw-r--r-- | providers/implementations/signature/build.info | 3 | ||||
-rw-r--r-- | providers/implementations/signature/rsa.c | 1113 | ||||
-rw-r--r-- | util/libcrypto.num | 2 |
19 files changed, 1517 insertions, 122 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index e6a45ac03a..47a20e828f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2752,6 +2752,7 @@ PROP_R_PARSE_FAILED:108:parse failed PROP_R_STRING_TOO_LONG:109:string too long PROP_R_TRAILING_CHARACTERS:110:trailing characters PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed +PROV_R_ALGORITHM_MISMATCH:173:algorithm mismatch PROV_R_BAD_DECRYPT:100:bad decrypt PROV_R_BAD_ENCODING:141:bad encoding PROV_R_BAD_LENGTH:142:bad length @@ -2759,17 +2760,21 @@ PROV_R_BAD_TLS_CLIENT_VERSION:161:bad tls client version PROV_R_BN_ERROR:160:bn error PROV_R_BOTH_MODE_AND_MODE_INT:127:both mode and mode int PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed +PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed PROV_R_FAILED_DURING_DERIVATION:164:failed during derivation PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter +PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ + illegal or unsupported padding mode PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length PROV_R_INVALID_AAD:108:invalid aad PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length PROV_R_INVALID_DATA:115:invalid data PROV_R_INVALID_DIGEST:122:invalid digest +PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count PROV_R_INVALID_IVLEN:116:invalid ivlen PROV_R_INVALID_IV_LENGTH:109:invalid iv length @@ -2778,12 +2783,17 @@ PROV_R_INVALID_KEYLEN:117:invalid keylen PROV_R_INVALID_KEY_LEN:124:invalid key len PROV_R_INVALID_KEY_LENGTH:105:invalid key length PROV_R_INVALID_MAC:151:invalid mac +PROV_R_INVALID_MGF1_MD:167:invalid mgf1 md PROV_R_INVALID_MODE:125:invalid mode PROV_R_INVALID_MODE_INT:126:invalid mode int +PROV_R_INVALID_PADDING_MODE:168:invalid padding mode +PROV_R_INVALID_PSS_SALTLEN:169:invalid pss saltlen PROV_R_INVALID_SALT_LENGTH:112:invalid salt length PROV_R_INVALID_SEED_LENGTH:154:invalid seed length PROV_R_INVALID_TAG:110:invalid tag PROV_R_INVALID_TAGLEN:118:invalid taglen +PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest +PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small PROV_R_MISSING_CEK_ALG:144:missing cek alg PROV_R_MISSING_CIPHER:155:missing cipher PROV_R_MISSING_CONSTANT:156:missing constant @@ -2801,6 +2811,7 @@ PROV_R_NOT_SUPPORTED:136:not supported PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length PROV_R_NO_KEY_SET:114:no key set PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small +PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small PROV_R_READ_KEY:159:read key PROV_R_TAG_NOTSET:119:tag notset PROV_R_TAG_NOT_NEEDED:120:tag not needed diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 6be796fafc..cb64b95bf6 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -786,69 +786,73 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, # ifndef OPENSSL_NO_EC if (keytype == EVP_PKEY_EC) { switch (cmd) { - case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: - if (p1 == -2) { - return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx); - } else if (p1 < -1 || p1 > 1) { - /* Uses the same return values as EVP_PKEY_CTX_ctrl */ - return -2; - } else { - return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1); - } - case EVP_PKEY_CTRL_EC_KDF_TYPE: - if (p1 == -2) { - return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx); - } else { - return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1); - } - case EVP_PKEY_CTRL_GET_EC_KDF_MD: - return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2); - case EVP_PKEY_CTRL_EC_KDF_MD: - return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2); - case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: - return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2); - case EVP_PKEY_CTRL_EC_KDF_OUTLEN: - return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1); - case EVP_PKEY_CTRL_GET_EC_KDF_UKM: - return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2); - case EVP_PKEY_CTRL_EC_KDF_UKM: - return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1); + case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: + if (p1 == -2) { + return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx); + } else if (p1 < -1 || p1 > 1) { + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } else { + return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1); + } + case EVP_PKEY_CTRL_EC_KDF_TYPE: + if (p1 == -2) { + return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx); + } else { + return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1); + } + case EVP_PKEY_CTRL_GET_EC_KDF_MD: + return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_MD: + return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2); + case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: + return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_OUTLEN: + return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1); + case EVP_PKEY_CTRL_GET_EC_KDF_UKM: + return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_UKM: + return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1); } } # endif if (keytype == -1) { switch (cmd) { - case EVP_PKEY_CTRL_MD: - return EVP_PKEY_CTX_set_signature_md(ctx, p2); - case EVP_PKEY_CTRL_GET_MD: - return EVP_PKEY_CTX_get_signature_md(ctx, p2); - case EVP_PKEY_CTRL_RSA_PADDING: - return EVP_PKEY_CTX_set_rsa_padding(ctx, p1); - case EVP_PKEY_CTRL_GET_RSA_PADDING: - return EVP_PKEY_CTX_get_rsa_padding(ctx, p2); - case EVP_PKEY_CTRL_RSA_OAEP_MD: - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: - return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_RSA_MGF1_MD: - return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: - return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); - case EVP_PKEY_CTRL_RSA_OAEP_LABEL: - return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1); - case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: - return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); - case EVP_PKEY_CTRL_PKCS7_ENCRYPT: - case EVP_PKEY_CTRL_PKCS7_DECRYPT: + case EVP_PKEY_CTRL_MD: + return EVP_PKEY_CTX_set_signature_md(ctx, p2); + case EVP_PKEY_CTRL_GET_MD: + return EVP_PKEY_CTX_get_signature_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_PADDING: + return EVP_PKEY_CTX_set_rsa_padding(ctx, p1); + case EVP_PKEY_CTRL_GET_RSA_PADDING: + return EVP_PKEY_CTX_get_rsa_padding(ctx, p2); + case EVP_PKEY_CTRL_RSA_OAEP_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: + return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_MGF1_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: + return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1); + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); + case EVP_PKEY_CTRL_RSA_PSS_SALTLEN: + return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1); + case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN: + return EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, p2); + case EVP_PKEY_CTRL_PKCS7_ENCRYPT: + case EVP_PKEY_CTRL_PKCS7_DECRYPT: # ifndef OPENSSL_NO_CMS - case EVP_PKEY_CTRL_CMS_DECRYPT: - case EVP_PKEY_CTRL_CMS_ENCRYPT: + case EVP_PKEY_CTRL_CMS_DECRYPT: + case EVP_PKEY_CTRL_CMS_ENCRYPT: # endif - if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) - return 1; - ERR_raise(ERR_LIB_EVP, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; + if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return 1; + ERR_raise(ERR_LIB_EVP, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } } return 0; @@ -918,6 +922,8 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, name = OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST; else if (strcmp(name, "rsa_oaep_label") == 0) name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL; + else if (strcmp(name, "rsa_pss_saltlen") == 0) + name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN; # ifndef OPENSSL_NO_DH else if (strcmp(name, "dh_pad") == 0) name = OSSL_EXCHANGE_PARAM_PAD; diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info index 274f376979..ddb4e6fc5a 100644 --- a/crypto/rsa/build.info +++ b/crypto/rsa/build.info @@ -1,6 +1,6 @@ LIBS=../../libcrypto -$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_pk1.c \ +$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_aid.c rsa_pk1.c \ rsa_none.c rsa_oaep.c rsa_chk.c rsa_pss.c rsa_x931.c rsa_crpt.c \ rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c diff --git a/crypto/rsa/rsa_aid.c b/crypto/rsa/rsa_aid.c new file mode 100644 index 0000000000..4b4d3a62f1 --- /dev/null +++ b/crypto/rsa/rsa_aid.c @@ -0,0 +1,98 @@ +/* + * Copyright 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 + */ + +#include <stdlib.h> + +#include <openssl/objects.h> +#include "crypto/rsa.h" + +#define ASN1_SEQUENCE 0x30 +#define ASN1_OID 0x06 + +/* + * -- RFC 2313 + * pkcs-1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1) 1 + * } + */ + +/* + * -- RFC 3279 + * md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } + * md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } + * sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } + */ +#define ENCODE_ALGORITHMIDENTIFIER_PKCS1(name, n) \ + static const unsigned char algorithmidentifier_##name##_der[] = { \ + ASN1_SEQUENCE, 0x0b, \ + ASN1_OID, 0x09, 1 * 40 + 2, 134, 72, 134, 247, 13, 1, 1, n \ +} +#ifndef FIPS_MODE +ENCODE_ALGORITHMIDENTIFIER_PKCS1(md2, 2); +ENCODE_ALGORITHMIDENTIFIER_PKCS1(md5, 4); +#endif +ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha1, 5); + +/* + * -- RFC 4055 + * sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 } + * sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } + * sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } + * sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } + */ +ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha224, 14); +ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha256, 11); +ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha384, 12); +ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha512, 13); + +/* + * -- https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration + * + * sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 } + * + * id-rsassa-pkcs1-v1_5-with-sha3-224 ::= { sigAlgs 13 } + * id-rsassa-pkcs1-v1_5-with-sha3-256 ::= { sigAlgs 14 } + * id-rsassa-pkcs1-v1_5-with-sha3-384 ::= { sigAlgs 15 } + * id-rsassa-pkcs1-v1_5-with-sha3-512 ::= { sigAlgs 16 } + */ +#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n) \ + static const unsigned char algorithmidentifier_##name##_der[] = { \ + ASN1_SEQUENCE, 0x0c, \ + ASN1_OID, 0x0a, 1 * 40 + 2, 16, 134, 72, 1, 101, 3, 4, 3, n \ +} +ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 13); +ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 14); +ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 15); +ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 16); + +#define MD_CASE(name) \ + case NID_##name: \ + *len = sizeof(algorithmidentifier_##name##_der); \ + return algorithmidentifier_##name##_der + +const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len) +{ + switch (md_nid) { +#ifndef FIPS_MODE + MD_CASE(md2); + MD_CASE(md5); +#endif + MD_CASE(sha1); + MD_CASE(sha224); + MD_CASE(sha256); + MD_CASE(sha384); + MD_CASE(sha512); + MD_CASE(sha3_224); + MD_CASE(sha3_256); + MD_CASE(sha3_384); + MD_CASE(sha3_512); + default: + return NULL; + } +} diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index c43c9fdd48..39d7f5f54a 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -817,12 +817,14 @@ int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode) return -1; /* TODO(3.0): Remove this eventually when no more legacy */ - if (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - || ctx->op.ciph.ciphprovctx == NULL) + if ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + || ctx->op.ciph.ciphprovctx == NULL) + && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + || ctx->op.sig.sigprovctx == NULL)) return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_RSA_PADDING, pad_mode, NULL); - *p++ = OSSL_PARAM_construct_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, &pad_mode); + *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, &pad_mode); *p++ = OSSL_PARAM_construct_end(); return EVP_PKEY_CTX_set_params(ctx, pad_params); @@ -845,12 +847,14 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode) return -1; /* TODO(3.0): Remove this eventually when no more legacy */ - if (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - || ctx->op.ciph.ciphprovctx == NULL) + if ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + || ctx->op.ciph.ciphprovctx == NULL) + && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + || ctx->op.sig.sigprovctx == NULL)) return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, pad_mode); - *p++ = OSSL_PARAM_construct_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, pad_mode); + *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, pad_mode); *p++ = OSSL_PARAM_construct_end(); if (!EVP_PKEY_CTX_get_params(ctx, pad_params)) @@ -1026,20 +1030,20 @@ int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname, && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) return -1; - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_DIGEST, /* - * Cast away the const. This is read - * only so should be safe + * Cast away the const. This is + * read only so should be safe */ (char *)mdname, 0); if (mdprops != NULL) { - *p++ = OSSL_PARAM_construct_utf8_string( - OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, - /* - * Cast away the const. This is read - * only so should be safe - */ - (char *)mdprops, 0); + *p++ = + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_PROPERTIES, + /* + * Cast away the const. This is + * read only so should be safe + */ + (char *)mdprops, 0); } *p++ = OSSL_PARAM_construct_end(); @@ -1065,7 +1069,7 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name, && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) return -1; - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_DIGEST, name, namelen); *p++ = OSSL_PARAM_construct_end(); @@ -1133,12 +1137,12 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen) (void *)label); *p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, - /* - * Cast away the const. This is read - * only so should be safe - */ - (void *)label, - (size_t)llen); + /* + * Cast away the const. This is + * read only so should be safe + */ + (void *)label, + (size_t)llen); *p++ = OSSL_PARAM_construct_end(); if (!EVP_PKEY_CTX_set_params(ctx, rsa_params)) @@ -1183,4 +1187,67 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label) return (int)labellen; } + +int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen) +{ + OSSL_PARAM pad_params[2], *p = pad_params; + + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA or RSA-PSS return error */ + if (ctx->pmeth != NULL + && ctx->pmeth->pkey_id != EVP_PKEY_RSA + && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + || ctx->op.sig.sigprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_RSA_PSS_SALTLEN, + saltlen, NULL); + + *p++ = + OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, &saltlen); + *p++ = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, pad_params); +} + +int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen) +{ + OSSL_PARAM pad_params[2], *p = pad_params; + + if (ctx == NULL || saltlen == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* If key type not RSA or RSA-PSS return error */ + if (ctx->pmeth != NULL + && ctx->pmeth->pkey_id != EVP_PKEY_RSA + && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) + return -1; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + || ctx->op.sig.sigprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, -1, + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, + 0, saltlen); + + *p++ = + OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, saltlen); + *p++ = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_get_params(ctx, pad_params)) + return 0; + + return 1; + +} #endif diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h index e15c1ae3d5..11d7635c35 100644 --- a/crypto/rsa/rsa_local.h +++ b/crypto/rsa/rsa_local.h @@ -122,10 +122,6 @@ struct rsa_meth_st { BIGNUM *e, BN_GENCB *cb); }; -extern int int_rsa_verify(int dtype, const unsigned char *m, - unsigned int m_len, unsigned char *rm, - size_t *prm_len, const unsigned char *sigbuf, - size_t siglen, RSA *rsa); /* Macros to test if a pkey or ctx is for a PSS key */ #define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS) #define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 174271874a..7a298d5d93 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -25,6 +25,7 @@ #include <openssl/x509v3.h> #include <openssl/cms.h> #include "crypto/evp.h" +#include "crypto/rsa.h" #include "rsa_local.h" /* RSA pkey context structure */ diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 31b8ed11fa..e9c4c55398 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -23,13 +23,20 @@ #ifndef OPENSSL_NO_MD2 # include <openssl/md2.h> /* uses MD2_DIGEST_LENGTH */ #endif +#ifndef OPENSSL_NO_MD4 +# include <openssl/md4.h> /* uses MD4_DIGEST_LENGTH */ +#endif #ifndef OPENSSL_NO_MD5 # include <openssl/md5.h> /* uses MD5_DIGEST_LENGTH */ #endif #ifndef OPENSSL_NO_MDC2 # include <openssl/mdc2.h> /* uses MDC2_DIGEST_LENGTH */ #endif +#ifndef OPENSSL_NO_RMD160 +# include <openssl/ripemd.h> /* uses RIPEMD160_DIGEST_LENGTH */ +#endif #include <openssl/sha.h> /* uses SHA???_DIGEST_LENGTH */ +#include "crypto/rsa.h" #include "rsa_local.h" /* @@ -76,7 +83,7 @@ static const unsigned char digestinfo_##name##_der[] = { \ ASN1_OCTET_STRING, sz \ }; -/* MD2 and MD5 OIDs are of the form: (1 2 840 113549 2 |n|) */ +/* MD2, MD4 and MD5 OIDs are of the form: (1 2 840 113549 2 |n|) */ #define ENCODE_DIGESTINFO_MD(name, n, sz) \ static const unsigned char digestinfo_##name##_der[] = { \ ASN1_SEQUENCE, 0x10 + sz, \ @@ -90,6 +97,9 @@ static const unsigned char digestinfo_##name##_der[] = { \ # ifndef OPENSSL_NO_MD2 ENCODE_DIGESTINFO_MD(md2, 0x02, MD2_DIGEST_LENGTH) # endif +# ifndef OPENSSL_NO_MD4 +ENCODE_DIGESTINFO_MD(md4, 0x03, MD4_DIGEST_LENGTH) +# endif # ifndef OPENSSL_NO_MD5 ENCODE_DIGESTINFO_MD(md5, 0x05, MD5_DIGEST_LENGTH) # endif @@ -103,6 +113,18 @@ static const unsigned char digestinfo_mdc2_der[] = { ASN1_OCTET_STRING, MDC2_DIGEST_LENGTH }; # endif +# ifndef OPENSSL_NO_RMD160 +/* RIPEMD160 (1 3 36 3 3 1 2) */ +static const unsigned char digestinfo_ripemd160_der[] = { + ASN1_SEQUENCE, 0x0c + RIPEMD160_DIGEST_LENGTH, + ASN1_SEQUENCE, 0x08, + ASN1_OID, 0x04, 1 * 40 + 3, 36, 3, 3, 1, 2, + ASN1_NULL, 0x00, + ASN1_OCTET_STRING, RIPEMD160_DIGEST_LENGTH +}; +# endif +#endif /* FIPS_MODE */ + /* SHA-1 (1 3 14 3 2 26) */ static const unsigned char digestinfo_sha1_der[] = { ASN1_SEQUENCE, 0x0d + SHA_DIGEST_LENGTH, @@ -112,8 +134,6 @@ static const unsigned char digestinfo_sha1_der[] = { ASN1_OCTET_STRING, SHA_DIGEST_LENGTH }; -#endif /* FIPS_MODE */ - ENCODE_DIGESTINFO_SHA(sha256, 0x01, SHA256_DIGEST_LENGTH) ENCODE_DIGESTINFO_SHA(sha384, 0x02, SHA384_DIGEST_LENGTH) ENCODE_DIGESTINFO_SHA(sha512, 0x03, SHA512_DIGEST_LENGTH) @@ -130,9 +150,9 @@ ENCODE_DIGESTINFO_SHA(sha3_512, 0x0a, SHA512_DIGEST_LENGTH) *len = sizeof(digestinfo_##name##_der); \ return digestinfo_##name##_der; -static const unsigned char *digestinfo_encoding(int nid, size_t *len) +const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len) { - switch (nid) { + switch (md_nid) { #ifndef FIPS_MODE # ifndef OPENSSL_NO_MDC2 MD_CASE(mdc2) @@ -140,11 +160,17 @@ static const unsigned char *digestinfo_encoding(int nid, size_t *len) # ifndef OPENSSL_NO_MD2 MD_CASE(md2) # endif +# ifndef OPENSSL_NO_MD4 + MD_CASE(md4) +# endif # ifndef OPENSSL_NO_MD5 MD_CASE(md5) # endif - MD_CASE(sha1) +# ifndef OPENSSL_NO_RMD160 + MD_CASE(ripemd160) +# endif #endif /* FIPS_MODE */ + MD_CASE(sha1) MD_CASE(sha224) MD_CASE(sha256) MD_CASE(sha384) @@ -183,7 +209,7 @@ static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } - di_prefix = digestinfo_encoding(type, &di_prefix_len); + di_prefix = rsa_digestinfo_encoding(type, &di_prefix_len); if (di_prefix == NULL) { RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index 8334cfc110..08b6f69925 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -94,8 +94,8 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad); int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad); - int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len); - int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *len); + int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen); + int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits); int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp); int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes); @@ -211,8 +211,8 @@ B<optype> is a mask indicating which operations the control can be applied to. The control command is indicated in B<cmd> and any additional arguments in B<p1> and B<p2>. -For B<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, B<p1> is the length of the MAC key, -and B<p2> is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC. +For I<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, I<p1> is the length of the MAC key, +and I<p2> is the MAC key. This is used by Poly1305, SipHash, HMAC and CMAC. Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will instead call one of the algorithm specific macros below. @@ -272,20 +272,36 @@ buffer is expected to be the algorithm identifier byte. The EVP_PKEY_CTX_get_rsa_padding() function gets the RSA padding mode for B<ctx>. -The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro sets the RSA PSS salt length to -B<len>. As its name implies it is only supported for PSS padding. Three special -values are supported: B<RSA_PSS_SALTLEN_DIGEST> sets the salt length to the -digest length, B<RSA_PSS_SALTLEN_MAX> sets the salt length to the maximum -permissible value. When verifying B<RSA_PSS_SALTLEN_AUTO> causes the salt length -to be automatically determined based on the B<PSS> block structure. If this -macro is not called maximum salt length is used when signing and auto detection -when verifying is used by default. +The EVP_PKEY_CTX_set_rsa_pss_saltlen() function sets the RSA PSS salt +length to I<saltlen>. As its name implies it is only supported for PSS +padding. If this function is not called then the maximum salt length +is used when signing and auto detection when verifying. Three special +values are supported: -The EVP_PKEY_CTX_get_rsa_pss_saltlen() macro gets the RSA PSS salt length -for B<ctx>. The padding mode must have been set to B<RSA_PKCS1_PSS_PADDING>. +=over 4 + +=item B<RSA_PSS_SALTLEN_DIGEST> + +sets the salt length to the digest length. + +=item B<RSA_PSS_SALTLEN_MAX> + +sets the salt length to the maximum permissible value. + +=item B<RSA_PSS_SALTLEN_AUTO> + +causes the salt length to be automatically determined based on the +B<PSS> block structure when verifying. When signing, it has the same +meaning as B<RSA_PSS_SALTLEN_MAX>. + +=back + +The EVP_PKEY_CTX_get_rsa_pss_saltlen() function gets the RSA PSS salt length +for B<ctx>. The padding mode must already have been set to +B<RSA_PKCS1_PSS_PADDING>. The EVP_PKEY_CTX_set_rsa_keygen_bits() macro sets the RSA key length for -RSA key generation to B<bits>. If not specified 1024 bits is used. +RSA key generation to I<bits>. If not specified 2048 bits is used. The EVP_PKEY_CTX_set_rsa_keygen_pubexp() macro sets the public exponent value for RSA key generation to B<pubexp>. Currently it should be an odd integer. The @@ -374,12 +390,12 @@ negotiated protocol version. Otherwise it should be left unset. =head2 DSA parameters The EVP_PKEY_CTX_set_dsa_paramgen_bits() macro sets the number of bits used -for DSA parameter generation to B<nbits>. If not specified, 1024 is used. +for DSA parameter generation to I<nbits>. If not specified, 2048 is used. The EVP_PKEY_CTX_set_dsa_paramgen_q_bits() macro sets the number of bits in the -subprime parameter B<q> for DSA parameter generation to B<qbits>. If not -specified, 160 is used. If a digest function is specified below, this parameter -is ignored and instead, the number of bits in B<q> matches the size of the +subprime parameter I<q> for DSA parameter generation to I<qbits>. If not +specified, 224 is used. If a digest function is specified below, this parameter +is ignored and instead, the number of bits in I<q> matches the size of the digest. The EVP_PKEY_CTX_set_dsa_paramgen_md() macro sets the digest function used for @@ -598,8 +614,9 @@ EVP_PKEY_CTX_set_dh_pad(), EVP_PKEY_CTX_set_rsa_padding(), EVP_PKEY_CTX_get_rsa_padding(), EVP_PKEY_CTX_get_rsa_mgf1_md(), EVP_PKEY_CTX_set_rsa_mgf1_md(), EVP_PKEY_CTX_set_rsa_oaep_md(), EVP_PKEY_CTX_get_rsa_oaep_md(), EVP_PKEY_CTX_set0_rsa_oaep_label(), -EVP_PKEY_CTX_get0_rsa_oaep_label() were macros in OpenSSL 1.1.1 and below. From -OpenSSL 3.0 they are functions. +EVP_PKEY_CTX_get0_rsa_oaep_label(), EVP_PKEY_CTX_set_rsa_pss_saltlen(), +EVP_PKEY_CTX_get_rsa_pss_saltlen(), were macros in OpenSSL 1.1.1 and below. +From OpenSSL 3.0 they are functions. EVP_PKEY_CTX_get_rsa_oaep_md_name(), EVP_PKEY_CTX_get_rsa_mgf1_md_name(), EVP_PKEY_CTX_set_rsa_mgf1_md_name() and EVP_PKEY_CTX_set_rsa_oaep_md_name() were diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h index 97fd0f7aad..51ac0148af 100644 --- a/include/crypto/rsa.h +++ b/include/crypto/rsa.h @@ -29,4 +29,12 @@ int rsa_validate_public(const RSA *key); int rsa_validate_private(const RSA *key); int rsa_validate_pairwise(const RSA *key); +int int_rsa_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *rm, + size_t *prm_len, const unsigned char *sigbuf, + size_t siglen, RSA *rsa); + +const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len); +const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len); + #endif diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index b2befd8bb5..5e3a13a34b 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -88,11 +88,16 @@ extern "C" { /* Known DIGEST names (not a complete list) */ #define OSSL_DIGEST_NAME_MD5 "MD5" +#define OSSL_DIGEST_NAME_MD5_SHA1 "MD5-SHA1" #define OSSL_DIGEST_NAME_SHA1 "SHA1" #define OSSL_DIGEST_NAME_SHA2_224 "SHA2-224" #define OSSL_DIGEST_NAME_SHA2_256 "SHA2-256" #define OSSL_DIGEST_NAME_SHA2_384 "SHA2-384" #define OSSL_DIGEST_NAME_SHA2_512 "SHA2-512" +#define OSSL_DIGEST_NAME_MD2 "MD2" +#define OSSL_DIGEST_NAME_MD4 "MD4" +#define OSSL_DIGEST_NAME_MDC2 "MDC2" +#define OSSL_DIGEST_NAME_RIPEMD160 "RIPEMD160" #define OSSL_DIGEST_NAME_SHA3_224 "SHA3-224" #define OSSL_DIGEST_NAME_SHA3_256 "SHA3-256" #define OSSL_DIGEST_NAME_SHA3_384 "SHA3-384" @@ -171,6 +176,14 @@ extern "C" { #define OSSL_PKEY_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES #define OSSL_PKEY_PARAM_DEFAULT_DIGEST "default-digest" /* utf8 string */ #define OSSL_PKEY_PARAM_MANDATORY_DIGEST "mandatory-digest" /* utf8 string */ +#define OSSL_PKEY_PARAM_PAD_MODE "pad-mode" +#define OSSL_PKEY_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST +#define OSSL_PKEY_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES +#define OSSL_PKEY_PARAM_DIGEST_SIZE "digest-size" +#define OSSL_PKEY_PARAM_MGF1_DIGEST "mgf1-digest" +#define OSSL_PKEY_PARAM_MGF1_PROPERTIES "mgf1-properties" + +/* Diffie-Hellman/DSA public/private key */ #define OSSL_PKEY_PARAM_PUB_KEY "pub" #define OSSL_PKEY_PARAM_PRIV_KEY "priv" @@ -234,15 +247,22 @@ extern "C" { /* Signature parameters */ #define OSSL_SIGNATURE_PARAM_ALGORITHM_ID "algorithm-id" +#define OSSL_SIGNATURE_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE #define OSSL_SIGNATURE_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST #define OSSL_SIGNATURE_PARAM_PROPERTIES OSSL_PKEY_PARAM_PROPERTIES +#define OSSL_SIGNATURE_PARAM_PSS_SALTLEN "pss-saltlen" +#define OSSL_SIGNATURE_PARAM_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST +#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \ + OSSL_PKEY_PARAM_MGF1_PROPERTIES /* Asym cipher parameters */ -#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE "pad-mode" +#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE +#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST \ + OSSL_PKEY_PARAM_MGF1_DIGEST +#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS \ + OSSL_PKEY_PARAM_MGF1_PROPERTIES #define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST OSSL_ALG_PARAM_DIGEST #define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS "digest-props" -#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST "mgf1-digest" -#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS "mgf1-digest-props" #define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL "oaep-label" #define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN "oaep-label-len" #define OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION "tls-client-version" diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 12ee01192e..1f0687df24 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -108,9 +108,9 @@ extern "C" { int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode); int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode); -# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \ - RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ - EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) +int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen); +int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen); + /* Salt length matches digest */ # define RSA_PSS_SALTLEN_DIGEST -1 /* Verify only: auto detect salt length */ @@ -124,10 +124,6 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode); EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) -# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \ - RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ - EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen) - # define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \ RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL) diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index 6586d65626..19ecab1f0f 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -50,6 +50,7 @@ int ERR_load_PROV_strings(void); * PROV reason codes. */ # define PROV_R_AES_KEY_SETUP_FAILED 101 +# define PROV_R_ALGORITHM_MISMATCH 173 # define PROV_R_BAD_DECRYPT 100 # define PROV_R_BAD_ENCODING 141 # define PROV_R_BAD_LENGTH 142 @@ -57,17 +58,20 @@ int ERR_load_PROV_strings(void); # define PROV_R_BN_ERROR 160 # define PROV_R_BOTH_MODE_AND_MODE_INT 127 # define PROV_R_CIPHER_OPERATION_FAILED 102 +# define PROV_R_DIGEST_NOT_ALLOWED 174 # define PROV_R_FAILED_DURING_DERIVATION 164 # define PROV_R_FAILED_TO_DECRYPT 162 # define PROV_R_FAILED_TO_GENERATE_KEY 121 # define PROV_R_FAILED_TO_GET_PARAMETER 103 # define PROV_R_FAILED_TO_SET_PARAMETER 104 +# define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165 # define PROV_R_INAVLID_UKM_LENGTH 146 # define PROV_R_INVALID_AAD 108 # define PROV_R_INVALID_CONSTANT_LENGTH 157 # define PROV_R_INVALID_CUSTOM_LENGTH 111 # define PROV_R_INVALID_DATA 115 # define PROV_R_INVALID_DIGEST 122 +# define PROV_R_INVALID_DIGEST_LENGTH 166 # define PROV_R_INVALID_ITERATION_COUNT 123 # define PROV_R_INVALID_IVLEN 116 # define PROV_R_INVALID_IV_LENGTH 109 @@ -76,12 +80,17 @@ int ERR_load_PROV_strings(void); # define PROV_R_INVALID_KEY_LEN 124 # define PROV_R_INVALID_KEY_LENGTH 105 # define PROV_R_INVALID_MAC 151 +# define PROV_R_INVALID_MGF1_MD 167 # define PROV_R_INVALID_MODE 125 # define PROV_R_INVALID_MODE_INT 126 +# define PROV_R_INVALID_PADDING_MODE 168 +# define PROV_R_INVALID_PSS_SALTLEN 169 # define PROV_R_INVALID_SALT_LENGTH 112 # define PROV_R_INVALID_SEED_LENGTH 154 # define PROV_R_INVALID_TAG 110 # define PROV_R_INVALID_TAGLEN 118 +# define PROV_R_INVALID_X931_DIGEST 170 +# define PROV_R_KEY_SIZE_TOO_SMALL 171 # define PROV_R_MISSING_CEK_ALG 144 # define PROV_R_MISSING_CIPHER 155 # define PROV_R_MISSING_CONSTANT 156 @@ -99,6 +108,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113 # define PROV_R_NO_KEY_SET 114 # define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106 +# define PROV_R_PSS_SALTLEN_TOO_SMALL 172 # define PROV_R_READ_KEY 159 # define PROV_R_TAG_NOTSET 119 # define PROV_R_TAG_NOT_NEEDED 120 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 792697c810..f73f82351f 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -16,6 +16,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED), "aes key setup failed"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ALGORITHM_MISMATCH), + "algorithm mismatch"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"}, @@ -26,6 +28,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "both mode and mode int"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED), "cipher operation failed"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED), + "digest not allowed"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_DURING_DERIVATION), "failed during derivation"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_DECRYPT), "failed to decrypt"}, @@ -35,6 +39,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "failed to get parameter"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER), "failed to set parameter"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), + "illegal or unsupported padding mode"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INAVLID_UKM_LENGTH), "inavlid ukm length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"}, @@ -44,6 +50,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "invalid custom length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH), + "invalid digest length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT), "invalid iteration count"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"}, @@ -54,14 +62,23 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH), "invalid key length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MGF1_MD), "invalid mgf1 md"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PADDING_MODE), + "invalid padding mode"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PSS_SALTLEN), + "invalid pss saltlen"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH), "invalid salt length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SEED_LENGTH), "invalid seed length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST), + "invalid x931 digest"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL), + "key size too small"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONSTANT), "missing constant"}, @@ -83,6 +100,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL), "output buffer too small"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL), + "pss saltlen too small"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_READ_KEY), "read key"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOTSET), "tag notset"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"}, diff --git a/providers/defltprov.c b/providers/defltprov.c index 0b2390a291..5bebf6665d 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -384,6 +384,7 @@ static const OSSL_ALGORITHM deflt_signature[] = { #ifndef OPENSSL_NO_DSA { "DSA:dsaEncryption", "provider=default", dsa_signature_functions }, #endif + { "RSA:rsaEncryption", "default=yes", rsa_signature_functions }, { NULL, NULL, NULL } }; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index ec0507d86b..6d6a26d1e0 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -269,6 +269,7 @@ extern const OSSL_DISPATCH ecdh_keyexch_functions[]; /* Signature */ extern const OSSL_DISPATCH dsa_signature_functions[]; +extern const OSSL_DISPATCH rsa_signature_functions[]; /* Asym Cipher */ extern const OSSL_DISPATCH rsa_asym_cipher_functions[]; diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index a9687fc929..22b55dcf54 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -2,9 +2,12 @@ # switch each to the Legacy provider when needed. $DSA_GOAL=../../libimplementations.a +$RSA_GOAL=../../libimplementations.a IF[{- !$disabled{dsa} -}] SOURCE[$DSA_GOAL]=dsa.c ENDIF +SOURCE[$RSA_GOAL]=rsa.c + diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c new file mode 100644 index 0000000000..3f941b1032 --- /dev/null +++ b/providers/implementations/signature/rsa.c @@ -0,0 +1,1113 @@ +/* + * Copyright 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 + */ + +/* + * RSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include <string.h> +#include <openssl/crypto.h> +#include <openssl/core_numbers.h> +#include <openssl/core_names.h> +#include <openssl/err.h> +#include <openssl/rsa.h> +#include <openssl/params.h> +#include <openssl/evp.h> +#include "internal/cryptlib.h" +#include "internal/nelem.h" +#include "internal/sizes.h" +#include "crypto/rsa.h" +#include "prov/providercommonerr.h" +#include "prov/implementations.h" +#include "prov/provider_ctx.h" + +static OSSL_OP_signature_newctx_fn rsa_newctx; +static OSSL_OP_signature_sign_init_fn rsa_signature_init; +static OSSL_OP_signature_verify_init_fn rsa_signature_init; +static OSSL_OP_signature_verify_recover_init_fn rsa_signature_init; +static OSSL_OP_signature_sign_fn rsa_sign; +static OSSL_OP_signature_verify_fn rsa_verify; +static OSSL_OP_signature_verify_recover_fn rsa_verify_recover; +static OSSL_OP_signature_digest_sign_init_fn rsa_digest_signverify_init; +static OSSL_OP_signature_digest_sign_update_fn rsa_digest_signverify_update; +static OSSL_OP_signature_digest_sign_final_fn rsa_digest_sign_final; +static OSSL_OP_signature_digest_verify_init_fn rsa_digest_signverify_init; +static OSSL_OP_signature_digest_verify_update_fn rsa_digest_signverify_update; +static OSSL_OP_signature_digest_verify_final_fn rsa_digest_verify_final; +static OSSL_OP_signature_freectx_fn rsa_freectx; +static OSSL_OP_signature_dupctx_fn rsa_dupctx; +static OSSL_OP_signature_get_ctx_params_fn rsa_get_ctx_params; +static OSSL_OP_signature_gettable_ctx_params_fn rsa_gettable_ctx_params; +static OSSL_OP_signature_set_ctx_params_fn rsa_set_ctx_params; +static OSSL_OP_signature_settable_ctx_params_fn rsa_settable_ctx_params; +static OSSL_OP_signature_get_ctx_md_params_fn rsa_get_ctx_md_params; +static OSSL_OP_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params; +static OSSL_OP_signature_set_ctx_md_params_fn rsa_set_ctx_md_params; +static OSSL_OP_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params; + +static OSSL_ITEM padding_item[] = { + { RSA_PKCS1_PADDING, "pkcs1" }, + { RSA_SSLV23_PADDING, "sslv23" }, + { RSA_NO_PADDING, "none" }, + { RSA_PKCS1_OAEP_PADDING, "oaep" }, /* Correct spelling first */ + { RSA_PKCS1_OAEP_PADDING, "oeap" }, + { RSA_X931_PADDING, "x931" }, + { RSA_PKCS1_PSS_PADDING, "pss" }, + { 0, NULL } +}; + +/* + * What's passed as an actual key is defined by the KEYMGMT interface. + * We happen to know that our KEYMGMT simply passes RSA structures, so + * we use that here too. + */ + +typedef struct { + OPENSSL_CTX *libctx; + RSA *rsa; + + /* + * Flag to determine if the hash function can be changed (1) or not (0) + * Because it's dangerous to change during a DigestSign or DigestVerify + * operation, this flag is cleared by their Init function, and set again + * by their Final function. + */ + unsigned int flag_allow_md : 1; + + /* The Algorithm Identifier of the combined signature agorithm */ + unsigned char aid[128]; + size_t aid_len; + + /* main digest */ + EVP_MD *md; + EVP_MD_CTX *mdctx; + int mdnid; + char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */ + + /* RSA padding mode */ + int pad_mode; + /* message digest for MGF1 */ + EVP_MD *mgf1_md; + char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */ + /* PSS salt length */ + int saltlen; + /* Minimum salt length or -1 if no PSS parameter restriction */ + int min_saltlen; + + /* Temp buffer */ + unsigned char *tbuf; + +} PROV_RSA_CTX; + +static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx) +{ + if (prsactx->md != NULL) + return EVP_MD_size(prsactx->md); + return 0; +} + +static int rsa_get_md_nid(const EVP_MD *md) +{ + /* + * Because the RSA library deals with NIDs, we need to translate. + * We do so using EVP_MD_is_a(), and therefore need a name to NID + * map. + */ + static const OSSL_ITEM name_to_nid[] = { + { NID_sha1, OSSL_DIGEST_NAME_SHA1 }, + { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 }, + { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 }, + { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 }, + { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 }, + { NID_md5, OSSL_DIGEST_NAME_MD5 }, + { NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 }, + { NID_md2, OSSL_DIGEST_NAME_MD2 }, + { NID_md4, OSSL_DIGEST_NAME_MD4 }, + { NID_mdc2, OSSL_DIGEST_NAME_MDC2 }, + { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 }, + { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 }, + { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 }, + { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 }, + { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 }, + }; + size_t i; + int mdnid = NID_undef; + + if (md == NULL) + goto end; + + for (i = 0; i < OSSL_NELEM(name_to_nid); i++) { + if (EVP_MD_is_a(md, name_to_nid[i].ptr)) { + mdnid = (int)name_to_nid[i].id; + break; + } + } + + if (mdnid == NID_undef) + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + + end: + return mdnid; +} + +static int rsa_check_padding(int mdnid, int padding) +{ + if (padding == RSA_NO_PADDING) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE); + return 0; + } + + if (padding == RSA_X931_PADDING) { + if (RSA_X931_hash_id(mdnid) == -1) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST); + return 0; + } + } + + return 1; +} + +static void *rsa_newctx(void *provctx) +{ + PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX)); + + if (prsactx == NULL) + return NULL; + + prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); + prsactx->flag_allow_md = 1; + return prsactx; +} + +/* True if PSS parameters are restricted */ +#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1) + +static int rsa_signature_init(void *vprsactx, void *vrsa) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa)) + return 0; + + RSA_free(prsactx->rsa); + prsactx->rsa = vrsa; + if (RSA_get0_pss_params(prsactx->rsa) != NULL) + prsactx->pad_mode = RSA_PKCS1_PSS_PADDING; + else + prsactx->pad_mode = RSA_PKCS1_PADDING; + /* Maximum for sign, auto for verify */ + prsactx->saltlen = RSA_PSS_SALTLEN_AUTO; + prsactx->min_saltlen = -1; + + return 1; +} + +static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, + const char *mdprops) +{ + if (mdname != NULL) { + EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); + int md_nid = rsa_get_md_nid(md); + size_t algorithmidentifier_len = 0; + const unsigned char *algorithmidentifier = NULL; + + if (md == NULL) + return 0; + + if (!rsa_check_padding(md_nid, ctx->pad_mode)) { + EVP_MD_free(md); + return 0; + } + + EVP_MD_CTX_free(ctx->mdctx); + EVP_MD_free(ctx->md); + ctx->md = NULL; + ctx->mdctx = NULL; + ctx->mdname[0] = '\0'; + ctx->aid[0] = '\0'; + ctx->aid_len = 0; + + algorithmidentifier = + rsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len); + + ctx->md = md; + ctx->mdnid = md_nid; + OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); + if (algorithmidentifier != NULL) { + memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len); + ctx->aid_len = algorithmidentifier_len; + } + } + + return 1; +} + +static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, + const char *props) +{ + if (ctx->mgf1_mdname[0] != '\0') + EVP_MD_free(ctx->mgf1_md); + + if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, props)) == NULL) + return 0; + OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname)); + + return 1; +} + +static int setup_tbuf(PROV_RSA_CTX *ctx) +{ + if (ctx->tbuf != NULL) + return 1; + if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static void clean_tbuf(PROV_RSA_CTX *ctx) +{ + if (ctx->tbuf != NULL) + OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa)); +} + +static void free_tbuf(PROV_RSA_CTX *ctx) +{ + OPENSSL_clear_free(ctx->tbuf, RSA_size(ctx->rsa)); + ctx->tbuf = NULL; +} + +static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + int ret; + size_t rsasize = RSA_size(prsactx->rsa); + size_t mdsize = rsa_get_md_size(prsactx); + + if (sig == NULL) { + *siglen = rsasize; + return 1; + } + + if (sigsize < (size_t)rsasize) + return 0; + + if (mdsize != 0) { + if (tbslen != mdsize) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); + return 0; + } + + if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) { + unsigned int sltmp; + + if (prsactx->pad_mode != RSA_PKCS1_PADDING) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, + "only PKCS#1 padding supported with MDC2"); + return 0; + } + ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp, + prsactx->rsa); + + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret = sltmp; + goto end; + } + + switch (prsactx->pad_mode) { + case RSA_X931_PADDING: + if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) { + ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL); + return 0; + } + if (!setup_tbuf(prsactx)) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(prsactx->tbuf, tbs, tbslen); + prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid); + ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf, + sig, prsactx->rsa, RSA_X931_PADDING); + clean_tbuf(prsactx); + break; + + case RSA_PKCS1_PADDING: + { + unsigned int sltmp; + + ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp, + prsactx->rsa); + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret = sltmp; + } + break; + + case RSA_PKCS1_PSS_PADDING: + /* Check PSS restrictions */ + if (rsa_pss_restricted(prsactx)) { + switch (prsactx->saltlen) { + case RSA_PSS_SALTLEN_DIGEST: + if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) { + ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + /* FALLTHRU */ + default: + if (prsactx->saltlen >= 0 + && prsactx->saltlen < prsactx->min_saltlen) { + ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + break; + } + } + if (!setup_tbuf(prsactx)) + return 0; + if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa, + prsactx->tbuf, tbs, + prsactx->md, prsactx->mgf1_md, + prsactx->saltlen)) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf, + sig, prsactx->rsa, RSA_NO_PADDING); + clean_tbuf(prsactx); + break; + + default: + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, + "Only X.931, PKCS#1 v1.5 or PSS padding allowed"); + return 0; + } + } else { + ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa, + prsactx->pad_mode); + } + +#ifdef LEGACY_MODE + end: +#endif + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + + *siglen = ret; + return 1; +} + +static int rsa_verify_recover(void *vprsactx, + unsigned char *rout, + size_t *routlen, + size_t routsize, + const unsigned char *sig, + size_t siglen) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + int ret; + + if (rout == NULL) { + *routlen = RSA_size(prsactx->rsa); + return 1; + } + + if (prsactx->md != NULL) { + switch (prsactx->pad_mode) { + case RSA_X931_PADDING: + if (!setup_tbuf(prsactx)) + return 0; + ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa, + RSA_X931_PADDING); + if (ret < 1) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret--; + if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) { + ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH); + return 0; + } + if (ret != EVP_MD_size(prsactx->md)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH, + "Should be %d, but got %d", + EVP_MD_size(prsactx->md), ret); + return 0; + } + + *routlen = ret; + if (routsize < (size_t)ret) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + memcpy(rout, prsactx->tbuf, ret); + break; + + case RSA_PKCS1_PADDING: + { + size_t sltmp; + + ret = int_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp, + sig, siglen, prsactx->rsa); + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret = sltmp; + } + break; + + default: + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, + "Only X.931 or PKCS#1 v1.5 padding allowed"); + return 0; + } + } else { + ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa, + prsactx->pad_mode); + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + } + *routlen = ret; + return 1; +} + +static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + size_t rslen; + + if (prsactx->md != NULL) { + switch (prsactx->pad_mode) { + case RSA_PKCS1_PADDING: + if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen, + prsactx->rsa)) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + return 1; + case RSA_X931_PADDING: + if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0) + return 0; + break; + case RSA_PKCS1_PSS_PADDING: + { + int ret; + size_t mdsize; + + /* Check PSS restrictions */ + if (rsa_pss_restricted(prsactx)) { + switch (prsactx->saltlen) { + case RSA_PSS_SALTLEN_AUTO: + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN); + return 0; + case RSA_PSS_SALTLEN_DIGEST: + if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) { + ERR_raise(ERR_LIB_PROV, + PROV_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + /* FALLTHRU */ + default: + if (prsactx->saltlen >= 0 + && prsactx->saltlen < prsactx->min_saltlen) { + ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL); + return 0; + } + break; + } + } + + /* + * We need to check this for the RSA_verify_PKCS1_PSS_mgf1() + * call + */ + mdsize = rsa_get_md_size(prsactx); + if (tbslen != mdsize) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH, + "Should be %d, but got %d", + mdsize, tbslen); + return 0; + } + + if (!setup_tbuf(prsactx)) + return 0; + ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, + prsactx->rsa, RSA_NO_PADDING); + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs, + prsactx->md, prsactx->mgf1_md, + prsactx->tbuf, + prsactx->saltlen); + if (ret <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + return 1; + } + default: + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, + "Only X.931, PKCS#1 v1.5 or PSS padding allowed"); + return 0; + } + } else { + if (!setup_tbuf(prsactx)) + return 0; + rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa, + prsactx->pad_mode); + if (rslen == 0) { + ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA); + return 0; + } + } + + if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen)) + return 0; + + return 1; +} + +static int rsa_digest_signverify_init(void *vprsactx, const char *mdname, + const char *props, void *vrsa) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + prsactx->flag_allow_md = 0; + if (!rsa_signature_init(vprsactx, vrsa) + || !rsa_setup_md(prsactx, mdname, props)) + return 0; + + prsactx->mdctx = EVP_MD_CTX_new(); + if (prsactx->mdctx == NULL) + goto error; + + if (!EVP_DigestInit_ex(prsactx->mdctx, prsactx->md, NULL)) + goto error; + + return 1; + + error: + EVP_MD_CTX_free(prsactx->mdctx); + EVP_MD_free(prsactx->md); + prsactx->mdctx = NULL; + prsactx->md = NULL; + return 0; +} + +int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data, + size_t datalen) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx == NULL || prsactx->mdctx == NULL) + return 0; + + return EVP_DigestUpdate(prsactx->mdctx, data, datalen); +} + +int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen, + size_t sigsize) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + + prsactx->flag_allow_md = 1; + if (prsactx == NULL || prsactx->mdctx == NULL) + return 0; + + /* + * If sig is NULL then we're just finding out the sig size. Other fields + * are ignored. Defer to rsa_sign. + */ + if (sig != NULL) { + /* + * TODO(3.0): There is the possibility that some externally provided + * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - + * but that problem is much larger than just in RSA. + */ + if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen)) + return 0; + } + + return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen); +} + + +int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig, + size_t siglen) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + + prsactx->flag_allow_md = 1; + if (prsactx == NULL || prsactx->mdctx == NULL) + return 0; + + /* + * TODO(3.0): There is the possibility that some externally provided + * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - + * but that problem is much larger than just in RSA. + */ + if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen)) + return 0; + + return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen); +} + +static void rsa_freectx(void *vprsactx) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx == NULL) + return; + + RSA_free(prsactx->rsa); + EVP_MD_CTX_free(prsactx->mdctx); + EVP_MD_free(prsactx->md); + EVP_MD_free(prsactx->mgf1_md); + free_tbuf(prsactx); + + OPENSSL_clear_free(prsactx, sizeof(prsactx)); +} + +static void *rsa_dupctx(void *vprsactx) +{ + PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx; + PROV_RSA_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + dstctx->rsa = NULL; + dstctx->md = NULL; + dstctx->mdctx = NULL; + dstctx->tbuf = NULL; + + if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa)) + goto err; + dstctx->rsa = srcctx->rsa; + + if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md)) + goto err; + dstctx->md = srcctx->md; + + if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md)) + goto err; + dstctx->mgf1_md = srcctx->mgf1_md; + + if (srcctx->mdctx != NULL) { + dstctx->mdctx = EVP_MD_CTX_new(); + if (dstctx->mdctx == NULL + || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx)) + goto err; + } + + return dstctx; + err: + rsa_freectx(dstctx); + return NULL; +} + +static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + OSSL_PARAM *p; + + if (prsactx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); + if (p != NULL + && !OSSL_PARAM_set_octet_string(p, prsactx->aid, prsactx->aid_len)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE); + if (p != NULL) + switch (p->data_type) { + case OSSL_PARAM_INTEGER: + if (!OSSL_PARAM_set_int(p, prsactx->pad_mode)) + return 0; + break; + case OSSL_PARAM_UTF8_STRING: + { + int i; + const char *word = NULL; + + for (i = 0; padding_item[i].id != 0; i++) { + if (prsactx->pad_mode == (int)padding_item[i].id) { + word = padding_item[i].ptr; + break; + } + } + + if (word != NULL) { + if (!OSSL_PARAM_set_utf8_string(p, word)) + return 0; + } else { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + } + } + break; + default: + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); + if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST); + if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN); + if (p != NULL) { + if (p->data_type == OSSL_PARAM_INTEGER) { + if (!OSSL_PARAM_set_int(p, prsactx->saltlen)) + return 0; + } else if (p->data_type == OSSL_PARAM_UTF8_STRING) { + switch (prsactx->saltlen) { + case RSA_PSS_SALTLEN_DIGEST: + if (!OSSL_PARAM_set_utf8_string(p, "digest")) + return 0; + break; + case RSA_PSS_SALTLEN_MAX: + if (!OSSL_PARAM_set_utf8_string(p, "max")) + return 0; + break; + case RSA_PSS_SALTLEN_AUTO: + if (!OSSL_PARAM_set_utf8_string(p, "auto")) + return 0; + break; + default: + if (BIO_snprintf(p->data, p->data_size, "%d", prsactx->saltlen) + <= 0) + return 0; + break; + } + } + } + + return 1; +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *rsa_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + const OSSL_PARAM *p; + + if (prsactx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); + /* Not allowed during certain operations */ + if (p != NULL && !prsactx->flag_allow_md) + return 0; + if (p != NULL) { + char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname; + char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops; + const OSSL_PARAM *propsp = + OSSL_PARAM_locate_const(params, + OSSL_SIGNATURE_PARAM_PROPERTIES); + + if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname))) + return 0; + if (propsp != NULL + && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) + return 0; + + /* TODO(3.0) PSS check needs more work */ + if (rsa_pss_restricted(prsactx)) { + /* TODO(3.0) figure out what to do for prsactx->md == NULL */ + if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname)) + return 1; + ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED); + return 0; + } + + /* non-PSS code follows */ + if (!rsa_setup_md(prsactx, mdname, mdprops)) + return 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE); + if (p != NULL) { + int pad_mode = 0; + + switch (p->data_type) { + case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */ + if (!OSSL_PARAM_get_int(p, &pad_mode)) + return 0; + break; + case OSSL_PARAM_UTF8_STRING: + { + int i; + + if (p->data == NULL) + return 0; + + for (i = 0; padding_item[i].id != 0; i++) { + if (strcmp(p->data, padding_item[i].ptr) == 0) { + pad_mode = padding_item[i].id; + break; + } + } + } + break; + default: + return 0; + } + + switch (pad_mode) { + case RSA_PKCS1_OAEP_PADDING: + /* + * OAEP padding is for asymmetric cipher only so is not compatible + * with signature use. + */ + ERR_raise_data(ERR_LIB_PROV, + PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE, + "OAEP padding not allowed for signing / verifying"); + return 0; + case RSA_PKCS1_PSS_PADDING: + if (prsactx->mdname[0] == '\0') + rsa_setup_md(prsactx, "SHA1", ""); + goto cont; + case RSA_PKCS1_PADDING: + case RSA_SSLV23_PADDING: + case RSA_NO_PADDING: + case RSA_X931_PADDING: + if (RSA_get0_pss_params(prsactx->rsa) != NULL) { + ERR_raise_data(ERR_LIB_PROV, + PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE, + "X.931 padding not allowed with RSA-PSS"); + return 0; + } + cont: + if (!rsa_check_padding(prsactx->mdnid, pad_mode)) + return 0; + break; + default: + return 0; + } + prsactx->pad_mode = pad_mode; + } + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN); + if (p != NULL) { + int saltlen; + + if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED, + "PSS saltlen can only be specified if " + "PSS padding has been specified first"); + return 0; + } + + switch (p->data_type) { + case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */ + if (!OSSL_PARAM_get_int(p, &saltlen)) + return 0; + break; + case OSSL_PARAM_UTF8_STRING: + if (strcmp(p->data, "digest") == 0) + saltlen = RSA_PSS_SALTLEN_DIGEST; + else if (strcmp(p->data, "max") == 0) + saltlen = RSA_PSS_SALTLEN_MAX; + else if (strcmp(p->data, "auto") == 0) + saltlen = RSA_PSS_SALTLEN_AUTO; + else + saltlen = atoi(p->data); + break; + default: + return 0; + } + + /* + * RSA_PSS_SALTLEN_MAX seems curiously named in this check. + * Contrary to what it's name suggests, it's the currently + * lowest saltlen number possible. + */ + if (saltlen < RSA_PSS_SALTLEN_MAX) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN); + return 0; + } + + prsactx->saltlen = saltlen; + } + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST); + if (p != NULL) { + char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname; + char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops; + const OSSL_PARAM *propsp = + OSSL_PARAM_locate_const(params, + OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES); + + if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname))) + return 0; + if (propsp != NULL + && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) + return 0; + + if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD); + return 0; + } + + /* TODO(3.0) PSS check needs more work */ + if (rsa_pss_restricted(prsactx)) { + /* TODO(3.0) figure out what to do for prsactx->md == NULL */ + if (prsactx->mgf1_md == NULL + || EVP_MD_is_a(prsactx->mgf1_md, mdname)) + return 1; + ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED); + return 0; + } + + /* non-PSS code follows */ + if (!rsa_setup_mgf1_md(prsactx, mdname, mdprops)) + return 0; + } + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *rsa_settable_ctx_params(void) +{ + /* + * TODO(3.0): Should this function return a different set of settable ctx + * params if the ctx is being used for a DigestSign/DigestVerify? In that + * case it is not allowed to set the digest size/digest name because the + * digest is explicitly set as part of the init. + */ + return known_settable_ctx_params; +} + +static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx->mdctx == NULL) + return 0; + + return EVP_MD_CTX_get_params(prsactx->mdctx, params); +} + +static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx->md == NULL) + return 0; + + return EVP_MD_gettable_ctx_params(prsactx->md); +} + +static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[]) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx->mdctx == NULL) + return 0; + + return EVP_MD_CTX_set_params(prsactx->mdctx, params); +} + +static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx) +{ + PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + + if (prsactx->md == NULL) + return 0; + + return EVP_MD_settable_ctx_params(prsactx->md); +} + +const OSSL_DISPATCH rsa_signature_functions[] = { + { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx }, + { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_signature_init }, + { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign }, + { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_signature_init }, + { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify }, + { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))rsa_signature_init }, + { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))rsa_verify_recover }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))rsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, + (void (*)(void))rsa_digest_signverify_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, + (void (*)(void))rsa_digest_sign_final }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))rsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, + (void (*)(void))rsa_digest_signverify_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, + (void (*)(void))rsa_digest_verify_final }, + { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx }, + { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, + (void (*)(void))rsa_gettable_ctx_params }, + { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params }, + { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, + (void (*)(void))rsa_settable_ctx_params }, + { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, + (void (*)(void))rsa_get_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, + (void (*)(void))rsa_gettable_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, + (void (*)(void))rsa_set_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, + (void (*)(void))rsa_settable_ctx_md_params }, + { 0, NULL } +}; diff --git a/util/libcrypto.num b/util/libcrypto.num index db4532f0e4..6c8487e20b 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4945,3 +4945,5 @@ EVP_PKEY_CTX_set_ecdh_kdf_outlen ? 3_0_0 EXIST::FUNCTION:EC EVP_PKEY_CTX_get_ecdh_kdf_outlen ? 3_0_0 EXIST::FUNCTION:EC EVP_PKEY_CTX_set0_ecdh_kdf_ukm ? 3_0_0 EXIST::FUNCTION:EC EVP_PKEY_CTX_get0_ecdh_kdf_ukm ? 3_0_0 EXIST::FUNCTION:EC +EVP_PKEY_CTX_set_rsa_pss_saltlen ? 3_0_0 EXIST::FUNCTION:RSA +EVP_PKEY_CTX_get_rsa_pss_saltlen ? 3_0_0 EXIST::FUNCTION:RSA |