X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frsa%2Frsa_pss.c;h=e3a548d2e37fb45ea86ce1e907183a6ae93eda2d;hp=775c36114f5a4559b58f6b2925426753047b56eb;hb=23b2fc0b501d6635dd821014aec8ff16689cbb6a;hpb=0eab41fb78cf4d7c76e563fd677ab6c32fc28bb0 diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c index 775c36114f..e3a548d2e3 100644 --- a/crypto/rsa/rsa_pss.c +++ b/crypto/rsa/rsa_pss.c @@ -1,275 +1,397 @@ -/* rsa_pss.c */ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 2005. - */ -/* ==================================================================== - * Copyright (c) 2005 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 2005-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 -#include "cryptlib.h" +#include "internal/cryptlib.h" #include #include #include #include #include +#include "rsa_local.h" -static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0}; +static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; #if defined(_MSC_VER) && defined(_ARM_) -#pragma optimize("g", off) +# pragma optimize("g", off) #endif int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, - const EVP_MD *Hash, const unsigned char *EM, int sLen) - { - int i; - int ret = 0; - int hLen, maskedDBLen, MSBits, emLen; - const unsigned char *H; - unsigned char *DB = NULL; - EVP_MD_CTX ctx; - unsigned char H_[EVP_MAX_MD_SIZE]; - - hLen = EVP_MD_size(Hash); - if (hLen < 0) - goto err; - /* - * Negative sLen has special meanings: - * -1 sLen == hLen - * -2 salt length is autorecovered from signature - * -N reserved - */ - if (sLen == -1) sLen = hLen; - else if (sLen == -2) sLen = -2; - else if (sLen < -2) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); - goto err; - } - - MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; - emLen = RSA_size(rsa); - if (EM[0] & (0xFF << MSBits)) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_FIRST_OCTET_INVALID); - goto err; - } - if (MSBits == 0) - { - EM++; - emLen--; - } - if (emLen < (hLen + sLen + 2)) /* sLen can be small negative */ - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_DATA_TOO_LARGE); - goto err; - } - if (EM[emLen - 1] != 0xbc) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_LAST_OCTET_INVALID); - goto err; - } - maskedDBLen = emLen - hLen - 1; - H = EM + maskedDBLen; - DB = OPENSSL_malloc(maskedDBLen); - if (!DB) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, ERR_R_MALLOC_FAILURE); - goto err; - } - if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, Hash) < 0) - goto err; - for (i = 0; i < maskedDBLen; i++) - DB[i] ^= EM[i]; - if (MSBits) - DB[0] &= 0xFF >> (8 - MSBits); - for (i = 0; DB[i] == 0 && i < (maskedDBLen-1); i++) ; - if (DB[i++] != 0x1) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_RECOVERY_FAILED); - goto err; - } - if (sLen >= 0 && (maskedDBLen - i) != sLen) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); - goto err; - } - EVP_MD_CTX_init(&ctx); - EVP_DigestInit_ex(&ctx, Hash, NULL); - EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes); - EVP_DigestUpdate(&ctx, mHash, hLen); - if (maskedDBLen - i) - EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i); - EVP_DigestFinal(&ctx, H_, NULL); - EVP_MD_CTX_cleanup(&ctx); - if (memcmp(H_, H, hLen)) - { - RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_BAD_SIGNATURE); - ret = 0; - } - else - ret = 1; - - err: - if (DB) - OPENSSL_free(DB); - - return ret; - - } + const EVP_MD *Hash, const unsigned char *EM, + int sLen) +{ + return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen); +} + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int sLen) +{ + int i; + int ret = 0; + int hLen, maskedDBLen, MSBits, emLen; + const unsigned char *H; + unsigned char *DB = NULL; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + unsigned char H_[EVP_MAX_MD_SIZE]; + + if (ctx == NULL) + goto err; + + if (mgf1Hash == NULL) + mgf1Hash = Hash; + + hLen = EVP_MD_size(Hash); + if (hLen < 0) + goto err; + /*- + * Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is autorecovered from signature + * -3 salt length is maximized + * -N reserved + */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; + } else if (sLen < RSA_PSS_SALTLEN_MAX) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (EM[0] & (0xFF << MSBits)) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID); + goto err; + } + if (MSBits == 0) { + EM++; + emLen--; + } + if (emLen < hLen + 2) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); + goto err; + } + if (sLen == RSA_PSS_SALTLEN_MAX) { + sLen = emLen - hLen - 2; + } else if (sLen > emLen - hLen - 2) { /* sLen can be small negative */ + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); + goto err; + } + if (EM[emLen - 1] != 0xbc) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID); + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + DB = OPENSSL_malloc(maskedDBLen); + if (DB == NULL) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE); + goto err; + } + if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) + goto err; + for (i = 0; i < maskedDBLen; i++) + DB[i] ^= EM[i]; + if (MSBits) + DB[0] &= 0xFF >> (8 - MSBits); + for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ; + if (DB[i++] != 0x1) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED); + goto err; + } + if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + if (!EVP_DigestInit_ex(ctx, Hash, NULL) + || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) + || !EVP_DigestUpdate(ctx, mHash, hLen)) + goto err; + if (maskedDBLen - i) { + if (!EVP_DigestUpdate(ctx, DB + i, maskedDBLen - i)) + goto err; + } + if (!EVP_DigestFinal_ex(ctx, H_, NULL)) + goto err; + if (memcmp(H_, H, hLen)) { + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE); + ret = 0; + } else { + ret = 1; + } + + err: + OPENSSL_free(DB); + EVP_MD_CTX_free(ctx); + + return ret; + +} int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, - const unsigned char *mHash, - const EVP_MD *Hash, int sLen) - { - int i; - int ret = 0; - int hLen, maskedDBLen, MSBits, emLen; - unsigned char *H, *salt = NULL, *p; - EVP_MD_CTX ctx; - - hLen = EVP_MD_size(Hash); - if (hLen < 0) - goto err; - /* - * Negative sLen has special meanings: - * -1 sLen == hLen - * -2 salt length is maximized - * -N reserved - */ - if (sLen == -1) sLen = hLen; - else if (sLen == -2) sLen = -2; - else if (sLen < -2) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED); - goto err; - } - - MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; - emLen = RSA_size(rsa); - if (MSBits == 0) - { - *EM++ = 0; - emLen--; - } - if (sLen == -2) - { - sLen = emLen - hLen - 2; - } - else if (emLen < (hLen + sLen + 2)) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, - RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); - goto err; - } - if (sLen > 0) - { - salt = OPENSSL_malloc(sLen); - if (!salt) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, - ERR_R_MALLOC_FAILURE); - goto err; - } - if (!RAND_bytes(salt, sLen)) - goto err; - } - maskedDBLen = emLen - hLen - 1; - H = EM + maskedDBLen; - EVP_MD_CTX_init(&ctx); - EVP_DigestInit_ex(&ctx, Hash, NULL); - EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes); - EVP_DigestUpdate(&ctx, mHash, hLen); - if (sLen) - EVP_DigestUpdate(&ctx, salt, sLen); - EVP_DigestFinal(&ctx, H, NULL); - EVP_MD_CTX_cleanup(&ctx); - - /* Generate dbMask in place then perform XOR on it */ - if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, Hash)) - goto err; - - p = EM; - - /* Initial PS XORs with all zeroes which is a NOP so just update - * pointer. Note from a test above this value is guaranteed to - * be non-negative. - */ - p += emLen - sLen - hLen - 2; - *p++ ^= 0x1; - if (sLen > 0) - { - for (i = 0; i < sLen; i++) - *p++ ^= salt[i]; - } - if (MSBits) - EM[0] &= 0xFF >> (8 - MSBits); - - /* H is already in place so just set final 0xbc */ - - EM[emLen - 1] = 0xbc; - - ret = 1; - - err: - if (salt) - OPENSSL_free(salt); - - return ret; - - } + const unsigned char *mHash, + const EVP_MD *Hash, int sLen) +{ + return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen); +} + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen) +{ + int i; + int ret = 0; + int hLen, maskedDBLen, MSBits, emLen; + unsigned char *H, *salt = NULL, *p; + EVP_MD_CTX *ctx = NULL; + + if (mgf1Hash == NULL) + mgf1Hash = Hash; + + hLen = EVP_MD_size(Hash); + if (hLen < 0) + goto err; + /*- + * Negative sLen has special meanings: + * -1 sLen == hLen + * -2 salt length is maximized + * -3 same as above (on signing) + * -N reserved + */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; + } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) { + sLen = RSA_PSS_SALTLEN_MAX; + } else if (sLen < RSA_PSS_SALTLEN_MAX) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); + goto err; + } + + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; + emLen = RSA_size(rsa); + if (MSBits == 0) { + *EM++ = 0; + emLen--; + } + if (emLen < hLen + 2) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen == RSA_PSS_SALTLEN_MAX) { + sLen = emLen - hLen - 2; + } else if (sLen > emLen - hLen - 2) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; + } + if (sLen > 0) { + salt = OPENSSL_malloc(sLen); + if (salt == NULL) { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (RAND_bytes_ex(rsa->libctx, salt, sLen) <= 0) + goto err; + } + maskedDBLen = emLen - hLen - 1; + H = EM + maskedDBLen; + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto err; + if (!EVP_DigestInit_ex(ctx, Hash, NULL) + || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) + || !EVP_DigestUpdate(ctx, mHash, hLen)) + goto err; + if (sLen && !EVP_DigestUpdate(ctx, salt, sLen)) + goto err; + if (!EVP_DigestFinal_ex(ctx, H, NULL)) + goto err; + + /* Generate dbMask in place then perform XOR on it */ + if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) + goto err; + + p = EM; + + /* + * Initial PS XORs with all zeroes which is a NOP so just update pointer. + * Note from a test above this value is guaranteed to be non-negative. + */ + p += emLen - sLen - hLen - 2; + *p++ ^= 0x1; + if (sLen > 0) { + for (i = 0; i < sLen; i++) + *p++ ^= salt[i]; + } + if (MSBits) + EM[0] &= 0xFF >> (8 - MSBits); + + /* H is already in place so just set final 0xbc */ + + EM[emLen - 1] = 0xbc; + + ret = 1; + + err: + EVP_MD_CTX_free(ctx); + OPENSSL_clear_free(salt, (size_t)sLen); /* salt != NULL implies sLen > 0 */ + + return ret; + +} + +/* + * The defaults for PSS restrictions are defined in RFC 8017, A.2.3 RSASSA-PSS + * (https://tools.ietf.org/html/rfc8017#appendix-A.2.3): + * + * If the default values of the hashAlgorithm, maskGenAlgorithm, and + * trailerField fields of RSASSA-PSS-params are used, then the algorithm + * identifier will have the following value: + * + * rSASSA-PSS-Default-Identifier RSASSA-AlgorithmIdentifier ::= { + * algorithm id-RSASSA-PSS, + * parameters RSASSA-PSS-params : { + * hashAlgorithm sha1, + * maskGenAlgorithm mgf1SHA1, + * saltLength 20, + * trailerField trailerFieldBC + * } + * } + * + * RSASSA-AlgorithmIdentifier ::= AlgorithmIdentifier { + * {PKCS1Algorithms} + * } + */ +static const RSA_PSS_PARAMS_30 default_RSASSA_PSS_params = { + NID_sha1, /* default hashAlgorithm */ + { + NID_mgf1, /* default maskGenAlgorithm */ + NID_sha1 /* default MGF1 hash */ + }, + 20, /* default saltLength */ + 1 /* default trailerField (0xBC) */ +}; + +int ossl_rsa_pss_params_30_set_defaults(RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return 0; + *rsa_pss_params = default_RSASSA_PSS_params; + return 1; +} + +int ossl_rsa_pss_params_30_is_unrestricted(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + static RSA_PSS_PARAMS_30 pss_params_cmp = { 0, }; + + return rsa_pss_params == NULL + || memcmp(rsa_pss_params, &pss_params_cmp, + sizeof(*rsa_pss_params)) == 0; +} + +int ossl_rsa_pss_params_30_copy(RSA_PSS_PARAMS_30 *to, + const RSA_PSS_PARAMS_30 *from) +{ + memcpy(to, from, sizeof(*to)); + return 1; +} + +int ossl_rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params, + int hashalg_nid) +{ + if (rsa_pss_params == NULL) + return 0; + rsa_pss_params->hash_algorithm_nid = hashalg_nid; + return 1; +} + +int ossl_rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params, + int maskgenalg_nid) +{ + if (rsa_pss_params == NULL) + return 0; + rsa_pss_params->mask_gen.algorithm_nid = maskgenalg_nid; + return 1; +} + +int ossl_rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params, + int maskgenhashalg_nid) +{ + if (rsa_pss_params == NULL) + return 0; + rsa_pss_params->mask_gen.hash_algorithm_nid = maskgenhashalg_nid; + return 1; +} + +int ossl_rsa_pss_params_30_set_saltlen(RSA_PSS_PARAMS_30 *rsa_pss_params, + int saltlen) +{ + if (rsa_pss_params == NULL) + return 0; + rsa_pss_params->salt_len = saltlen; + return 1; +} + +int ossl_rsa_pss_params_30_set_trailerfield(RSA_PSS_PARAMS_30 *rsa_pss_params, + int trailerfield) +{ + if (rsa_pss_params == NULL) + return 0; + rsa_pss_params->trailer_field = trailerfield; + return 1; +} + +int ossl_rsa_pss_params_30_hashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return default_RSASSA_PSS_params.hash_algorithm_nid; + return rsa_pss_params->hash_algorithm_nid; +} + +int ossl_rsa_pss_params_30_maskgenalg(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return default_RSASSA_PSS_params.mask_gen.algorithm_nid; + return rsa_pss_params->mask_gen.algorithm_nid; +} + +int ossl_rsa_pss_params_30_maskgenhashalg(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return default_RSASSA_PSS_params.hash_algorithm_nid; + return rsa_pss_params->mask_gen.hash_algorithm_nid; +} + +int ossl_rsa_pss_params_30_saltlen(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return default_RSASSA_PSS_params.salt_len; + return rsa_pss_params->salt_len; +} + +int ossl_rsa_pss_params_30_trailerfield(const RSA_PSS_PARAMS_30 *rsa_pss_params) +{ + if (rsa_pss_params == NULL) + return default_RSASSA_PSS_params.trailer_field; + return rsa_pss_params->trailer_field; +} #if defined(_MSC_VER) -#pragma optimize("",on) +# pragma optimize("",on) #endif