1160814Ssimon/* rsa_pss.c */ 2296341Sdelphij/* 3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296341Sdelphij * 2005. 5160814Ssimon */ 6160814Ssimon/* ==================================================================== 7160814Ssimon * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 8160814Ssimon * 9160814Ssimon * Redistribution and use in source and binary forms, with or without 10160814Ssimon * modification, are permitted provided that the following conditions 11160814Ssimon * are met: 12160814Ssimon * 13160814Ssimon * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 15160814Ssimon * 16160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17160814Ssimon * notice, this list of conditions and the following disclaimer in 18160814Ssimon * the documentation and/or other materials provided with the 19160814Ssimon * distribution. 20160814Ssimon * 21160814Ssimon * 3. All advertising materials mentioning features or use of this 22160814Ssimon * software must display the following acknowledgment: 23160814Ssimon * "This product includes software developed by the OpenSSL Project 24160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25160814Ssimon * 26160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27160814Ssimon * endorse or promote products derived from this software without 28160814Ssimon * prior written permission. For written permission, please contact 29160814Ssimon * licensing@OpenSSL.org. 30160814Ssimon * 31160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32160814Ssimon * nor may "OpenSSL" appear in their names without prior written 33160814Ssimon * permission of the OpenSSL Project. 34160814Ssimon * 35160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 36160814Ssimon * acknowledgment: 37160814Ssimon * "This product includes software developed by the OpenSSL Project 38160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39160814Ssimon * 40160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52160814Ssimon * ==================================================================== 53160814Ssimon * 54160814Ssimon * This product includes cryptographic software written by Eric Young 55160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 56160814Ssimon * Hudson (tjh@cryptsoft.com). 57160814Ssimon * 58160814Ssimon */ 59160814Ssimon 60160814Ssimon#include <stdio.h> 61160814Ssimon#include "cryptlib.h" 62160814Ssimon#include <openssl/bn.h> 63160814Ssimon#include <openssl/rsa.h> 64160814Ssimon#include <openssl/evp.h> 65160814Ssimon#include <openssl/rand.h> 66160814Ssimon#include <openssl/sha.h> 67160814Ssimon 68296341Sdelphijstatic const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 69160814Ssimon 70160814Ssimon#if defined(_MSC_VER) && defined(_ARM_) 71296341Sdelphij# pragma optimize("g", off) 72160814Ssimon#endif 73160814Ssimon 74160814Ssimonint RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, 75296341Sdelphij const EVP_MD *Hash, const unsigned char *EM, 76296341Sdelphij int sLen) 77296341Sdelphij{ 78296341Sdelphij return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen); 79296341Sdelphij} 80238405Sjkim 81238405Sjkimint RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, 82296341Sdelphij const EVP_MD *Hash, const EVP_MD *mgf1Hash, 83296341Sdelphij const unsigned char *EM, int sLen) 84296341Sdelphij{ 85296341Sdelphij int i; 86296341Sdelphij int ret = 0; 87296341Sdelphij int hLen, maskedDBLen, MSBits, emLen; 88296341Sdelphij const unsigned char *H; 89296341Sdelphij unsigned char *DB = NULL; 90296341Sdelphij EVP_MD_CTX ctx; 91296341Sdelphij unsigned char H_[EVP_MAX_MD_SIZE]; 92296341Sdelphij EVP_MD_CTX_init(&ctx); 93160814Ssimon 94296341Sdelphij if (mgf1Hash == NULL) 95296341Sdelphij mgf1Hash = Hash; 96238405Sjkim 97296341Sdelphij hLen = EVP_MD_size(Hash); 98296341Sdelphij if (hLen < 0) 99296341Sdelphij goto err; 100296341Sdelphij /*- 101296341Sdelphij * Negative sLen has special meanings: 102296341Sdelphij * -1 sLen == hLen 103296341Sdelphij * -2 salt length is autorecovered from signature 104296341Sdelphij * -N reserved 105296341Sdelphij */ 106296341Sdelphij if (sLen == -1) 107296341Sdelphij sLen = hLen; 108296341Sdelphij else if (sLen == -2) 109296341Sdelphij sLen = -2; 110296341Sdelphij else if (sLen < -2) { 111296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); 112296341Sdelphij goto err; 113296341Sdelphij } 114160814Ssimon 115296341Sdelphij MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; 116296341Sdelphij emLen = RSA_size(rsa); 117296341Sdelphij if (EM[0] & (0xFF << MSBits)) { 118296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID); 119296341Sdelphij goto err; 120296341Sdelphij } 121296341Sdelphij if (MSBits == 0) { 122296341Sdelphij EM++; 123296341Sdelphij emLen--; 124296341Sdelphij } 125296341Sdelphij if (emLen < (hLen + sLen + 2)) { /* sLen can be small negative */ 126296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE); 127296341Sdelphij goto err; 128296341Sdelphij } 129296341Sdelphij if (EM[emLen - 1] != 0xbc) { 130296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID); 131296341Sdelphij goto err; 132296341Sdelphij } 133296341Sdelphij maskedDBLen = emLen - hLen - 1; 134296341Sdelphij H = EM + maskedDBLen; 135296341Sdelphij DB = OPENSSL_malloc(maskedDBLen); 136296341Sdelphij if (!DB) { 137296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE); 138296341Sdelphij goto err; 139296341Sdelphij } 140296341Sdelphij if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) 141296341Sdelphij goto err; 142296341Sdelphij for (i = 0; i < maskedDBLen; i++) 143296341Sdelphij DB[i] ^= EM[i]; 144296341Sdelphij if (MSBits) 145296341Sdelphij DB[0] &= 0xFF >> (8 - MSBits); 146296341Sdelphij for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ; 147296341Sdelphij if (DB[i++] != 0x1) { 148296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED); 149296341Sdelphij goto err; 150296341Sdelphij } 151296341Sdelphij if (sLen >= 0 && (maskedDBLen - i) != sLen) { 152296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); 153296341Sdelphij goto err; 154296341Sdelphij } 155296341Sdelphij if (!EVP_DigestInit_ex(&ctx, Hash, NULL) 156296341Sdelphij || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) 157296341Sdelphij || !EVP_DigestUpdate(&ctx, mHash, hLen)) 158296341Sdelphij goto err; 159296341Sdelphij if (maskedDBLen - i) { 160296341Sdelphij if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) 161296341Sdelphij goto err; 162296341Sdelphij } 163296341Sdelphij if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) 164296341Sdelphij goto err; 165296341Sdelphij if (memcmp(H_, H, hLen)) { 166296341Sdelphij RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE); 167296341Sdelphij ret = 0; 168296341Sdelphij } else 169296341Sdelphij ret = 1; 170160814Ssimon 171296341Sdelphij err: 172296341Sdelphij if (DB) 173296341Sdelphij OPENSSL_free(DB); 174296341Sdelphij EVP_MD_CTX_cleanup(&ctx); 175160814Ssimon 176296341Sdelphij return ret; 177160814Ssimon 178296341Sdelphij} 179160814Ssimon 180160814Ssimonint RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, 181296341Sdelphij const unsigned char *mHash, 182296341Sdelphij const EVP_MD *Hash, int sLen) 183296341Sdelphij{ 184296341Sdelphij return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen); 185296341Sdelphij} 186238405Sjkim 187238405Sjkimint RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, 188296341Sdelphij const unsigned char *mHash, 189296341Sdelphij const EVP_MD *Hash, const EVP_MD *mgf1Hash, 190296341Sdelphij int sLen) 191296341Sdelphij{ 192296341Sdelphij int i; 193296341Sdelphij int ret = 0; 194296341Sdelphij int hLen, maskedDBLen, MSBits, emLen; 195296341Sdelphij unsigned char *H, *salt = NULL, *p; 196296341Sdelphij EVP_MD_CTX ctx; 197160814Ssimon 198296341Sdelphij if (mgf1Hash == NULL) 199296341Sdelphij mgf1Hash = Hash; 200238405Sjkim 201296341Sdelphij hLen = EVP_MD_size(Hash); 202296341Sdelphij if (hLen < 0) 203296341Sdelphij goto err; 204296341Sdelphij /*- 205296341Sdelphij * Negative sLen has special meanings: 206296341Sdelphij * -1 sLen == hLen 207296341Sdelphij * -2 salt length is maximized 208296341Sdelphij * -N reserved 209296341Sdelphij */ 210296341Sdelphij if (sLen == -1) 211296341Sdelphij sLen = hLen; 212296341Sdelphij else if (sLen == -2) 213296341Sdelphij sLen = -2; 214296341Sdelphij else if (sLen < -2) { 215296341Sdelphij RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED); 216296341Sdelphij goto err; 217296341Sdelphij } 218160814Ssimon 219296341Sdelphij MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; 220296341Sdelphij emLen = RSA_size(rsa); 221296341Sdelphij if (MSBits == 0) { 222296341Sdelphij *EM++ = 0; 223296341Sdelphij emLen--; 224296341Sdelphij } 225296341Sdelphij if (sLen == -2) { 226296341Sdelphij sLen = emLen - hLen - 2; 227296341Sdelphij } else if (emLen < (hLen + sLen + 2)) { 228296341Sdelphij RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, 229296341Sdelphij RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 230296341Sdelphij goto err; 231296341Sdelphij } 232296341Sdelphij if (sLen > 0) { 233296341Sdelphij salt = OPENSSL_malloc(sLen); 234296341Sdelphij if (!salt) { 235296341Sdelphij RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, 236296341Sdelphij ERR_R_MALLOC_FAILURE); 237296341Sdelphij goto err; 238296341Sdelphij } 239296341Sdelphij if (RAND_bytes(salt, sLen) <= 0) 240296341Sdelphij goto err; 241296341Sdelphij } 242296341Sdelphij maskedDBLen = emLen - hLen - 1; 243296341Sdelphij H = EM + maskedDBLen; 244296341Sdelphij EVP_MD_CTX_init(&ctx); 245296341Sdelphij if (!EVP_DigestInit_ex(&ctx, Hash, NULL) 246296341Sdelphij || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) 247296341Sdelphij || !EVP_DigestUpdate(&ctx, mHash, hLen)) 248296341Sdelphij goto err; 249296341Sdelphij if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) 250296341Sdelphij goto err; 251296341Sdelphij if (!EVP_DigestFinal_ex(&ctx, H, NULL)) 252296341Sdelphij goto err; 253296341Sdelphij EVP_MD_CTX_cleanup(&ctx); 254160814Ssimon 255296341Sdelphij /* Generate dbMask in place then perform XOR on it */ 256296341Sdelphij if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) 257296341Sdelphij goto err; 258160814Ssimon 259296341Sdelphij p = EM; 260160814Ssimon 261296341Sdelphij /* 262296341Sdelphij * Initial PS XORs with all zeroes which is a NOP so just update pointer. 263296341Sdelphij * Note from a test above this value is guaranteed to be non-negative. 264296341Sdelphij */ 265296341Sdelphij p += emLen - sLen - hLen - 2; 266296341Sdelphij *p++ ^= 0x1; 267296341Sdelphij if (sLen > 0) { 268296341Sdelphij for (i = 0; i < sLen; i++) 269296341Sdelphij *p++ ^= salt[i]; 270296341Sdelphij } 271296341Sdelphij if (MSBits) 272296341Sdelphij EM[0] &= 0xFF >> (8 - MSBits); 273160814Ssimon 274296341Sdelphij /* H is already in place so just set final 0xbc */ 275160814Ssimon 276296341Sdelphij EM[emLen - 1] = 0xbc; 277160814Ssimon 278296341Sdelphij ret = 1; 279160814Ssimon 280296341Sdelphij err: 281296341Sdelphij if (salt) 282296341Sdelphij OPENSSL_free(salt); 283160814Ssimon 284296341Sdelphij return ret; 285160814Ssimon 286296341Sdelphij} 287160814Ssimon 288160814Ssimon#if defined(_MSC_VER) 289296341Sdelphij# pragma optimize("",on) 290160814Ssimon#endif 291