1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci/* 13e1051a39Sopenharmony_ci * See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL: 14e1051a39Sopenharmony_ci * http://www.shoup.net/papers/oaep.ps.Z> for problems with the security 15e1051a39Sopenharmony_ci * proof for the original OAEP scheme, which EME-OAEP is based on. A new 16e1051a39Sopenharmony_ci * proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern, 17e1051a39Sopenharmony_ci * "RSA-OEAP is Still Alive!", Dec. 2000, <URL: 18e1051a39Sopenharmony_ci * http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements 19e1051a39Sopenharmony_ci * for the underlying permutation: "partial-one-wayness" instead of 20e1051a39Sopenharmony_ci * one-wayness. For the RSA function, this is an equivalent notion. 21e1051a39Sopenharmony_ci */ 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci/* 24e1051a39Sopenharmony_ci * RSA low level APIs are deprecated for public use, but still ok for 25e1051a39Sopenharmony_ci * internal use. 26e1051a39Sopenharmony_ci */ 27e1051a39Sopenharmony_ci#include "internal/deprecated.h" 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci#include "internal/constant_time.h" 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci#include <stdio.h> 32e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 33e1051a39Sopenharmony_ci#include <openssl/bn.h> 34e1051a39Sopenharmony_ci#include <openssl/evp.h> 35e1051a39Sopenharmony_ci#include <openssl/rand.h> 36e1051a39Sopenharmony_ci#include <openssl/sha.h> 37e1051a39Sopenharmony_ci#include "rsa_local.h" 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ciint RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, 40e1051a39Sopenharmony_ci const unsigned char *from, int flen, 41e1051a39Sopenharmony_ci const unsigned char *param, int plen) 42e1051a39Sopenharmony_ci{ 43e1051a39Sopenharmony_ci return ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(NULL, to, tlen, from, flen, 44e1051a39Sopenharmony_ci param, plen, NULL, NULL); 45e1051a39Sopenharmony_ci} 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci/* 48e1051a39Sopenharmony_ci * Perform the padding as per NIST 800-56B 7.2.2.3 49e1051a39Sopenharmony_ci * from (K) is the key material. 50e1051a39Sopenharmony_ci * param (A) is the additional input. 51e1051a39Sopenharmony_ci * Step numbers are included here but not in the constant time inverse below 52e1051a39Sopenharmony_ci * to avoid complicating an already difficult enough function. 53e1051a39Sopenharmony_ci */ 54e1051a39Sopenharmony_ciint ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(OSSL_LIB_CTX *libctx, 55e1051a39Sopenharmony_ci unsigned char *to, int tlen, 56e1051a39Sopenharmony_ci const unsigned char *from, int flen, 57e1051a39Sopenharmony_ci const unsigned char *param, 58e1051a39Sopenharmony_ci int plen, const EVP_MD *md, 59e1051a39Sopenharmony_ci const EVP_MD *mgf1md) 60e1051a39Sopenharmony_ci{ 61e1051a39Sopenharmony_ci int rv = 0; 62e1051a39Sopenharmony_ci int i, emlen = tlen - 1; 63e1051a39Sopenharmony_ci unsigned char *db, *seed; 64e1051a39Sopenharmony_ci unsigned char *dbmask = NULL; 65e1051a39Sopenharmony_ci unsigned char seedmask[EVP_MAX_MD_SIZE]; 66e1051a39Sopenharmony_ci int mdlen, dbmask_len = 0; 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci if (md == NULL) { 69e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 70e1051a39Sopenharmony_ci md = EVP_sha1(); 71e1051a39Sopenharmony_ci#else 72e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); 73e1051a39Sopenharmony_ci return 0; 74e1051a39Sopenharmony_ci#endif 75e1051a39Sopenharmony_ci } 76e1051a39Sopenharmony_ci if (mgf1md == NULL) 77e1051a39Sopenharmony_ci mgf1md = md; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci mdlen = EVP_MD_get_size(md); 80e1051a39Sopenharmony_ci if (mdlen <= 0) { 81e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_LENGTH); 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci } 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci /* step 2b: check KLen > nLen - 2 HLen - 2 */ 86e1051a39Sopenharmony_ci if (flen > emlen - 2 * mdlen - 1) { 87e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 88e1051a39Sopenharmony_ci return 0; 89e1051a39Sopenharmony_ci } 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci if (emlen < 2 * mdlen + 1) { 92e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL); 93e1051a39Sopenharmony_ci return 0; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci /* step 3i: EM = 00000000 || maskedMGF || maskedDB */ 97e1051a39Sopenharmony_ci to[0] = 0; 98e1051a39Sopenharmony_ci seed = to + 1; 99e1051a39Sopenharmony_ci db = to + mdlen + 1; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci /* step 3a: hash the additional input */ 102e1051a39Sopenharmony_ci if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) 103e1051a39Sopenharmony_ci goto err; 104e1051a39Sopenharmony_ci /* step 3b: zero bytes array of length nLen - KLen - 2 HLen -2 */ 105e1051a39Sopenharmony_ci memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1); 106e1051a39Sopenharmony_ci /* step 3c: DB = HA || PS || 00000001 || K */ 107e1051a39Sopenharmony_ci db[emlen - flen - mdlen - 1] = 0x01; 108e1051a39Sopenharmony_ci memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); 109e1051a39Sopenharmony_ci /* step 3d: generate random byte string */ 110e1051a39Sopenharmony_ci if (RAND_bytes_ex(libctx, seed, mdlen, 0) <= 0) 111e1051a39Sopenharmony_ci goto err; 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci dbmask_len = emlen - mdlen; 114e1051a39Sopenharmony_ci dbmask = OPENSSL_malloc(dbmask_len); 115e1051a39Sopenharmony_ci if (dbmask == NULL) { 116e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); 117e1051a39Sopenharmony_ci goto err; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci /* step 3e: dbMask = MGF(mgfSeed, nLen - HLen - 1) */ 121e1051a39Sopenharmony_ci if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0) 122e1051a39Sopenharmony_ci goto err; 123e1051a39Sopenharmony_ci /* step 3f: maskedDB = DB XOR dbMask */ 124e1051a39Sopenharmony_ci for (i = 0; i < dbmask_len; i++) 125e1051a39Sopenharmony_ci db[i] ^= dbmask[i]; 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ci /* step 3g: mgfSeed = MGF(maskedDB, HLen) */ 128e1051a39Sopenharmony_ci if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0) 129e1051a39Sopenharmony_ci goto err; 130e1051a39Sopenharmony_ci /* stepo 3h: maskedMGFSeed = mgfSeed XOR mgfSeedMask */ 131e1051a39Sopenharmony_ci for (i = 0; i < mdlen; i++) 132e1051a39Sopenharmony_ci seed[i] ^= seedmask[i]; 133e1051a39Sopenharmony_ci rv = 1; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci err: 136e1051a39Sopenharmony_ci OPENSSL_cleanse(seedmask, sizeof(seedmask)); 137e1051a39Sopenharmony_ci OPENSSL_clear_free(dbmask, dbmask_len); 138e1051a39Sopenharmony_ci return rv; 139e1051a39Sopenharmony_ci} 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ciint RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, 142e1051a39Sopenharmony_ci const unsigned char *from, int flen, 143e1051a39Sopenharmony_ci const unsigned char *param, int plen, 144e1051a39Sopenharmony_ci const EVP_MD *md, const EVP_MD *mgf1md) 145e1051a39Sopenharmony_ci{ 146e1051a39Sopenharmony_ci return ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(NULL, to, tlen, from, flen, 147e1051a39Sopenharmony_ci param, plen, md, mgf1md); 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ciint RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, 151e1051a39Sopenharmony_ci const unsigned char *from, int flen, int num, 152e1051a39Sopenharmony_ci const unsigned char *param, int plen) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num, 155e1051a39Sopenharmony_ci param, plen, NULL, NULL); 156e1051a39Sopenharmony_ci} 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ciint RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, 159e1051a39Sopenharmony_ci const unsigned char *from, int flen, 160e1051a39Sopenharmony_ci int num, const unsigned char *param, 161e1051a39Sopenharmony_ci int plen, const EVP_MD *md, 162e1051a39Sopenharmony_ci const EVP_MD *mgf1md) 163e1051a39Sopenharmony_ci{ 164e1051a39Sopenharmony_ci int i, dblen = 0, mlen = -1, one_index = 0, msg_index; 165e1051a39Sopenharmony_ci unsigned int good = 0, found_one_byte, mask; 166e1051a39Sopenharmony_ci const unsigned char *maskedseed, *maskeddb; 167e1051a39Sopenharmony_ci /* 168e1051a39Sopenharmony_ci * |em| is the encoded message, zero-padded to exactly |num| bytes: em = 169e1051a39Sopenharmony_ci * Y || maskedSeed || maskedDB 170e1051a39Sopenharmony_ci */ 171e1051a39Sopenharmony_ci unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE], 172e1051a39Sopenharmony_ci phash[EVP_MAX_MD_SIZE]; 173e1051a39Sopenharmony_ci int mdlen; 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ci if (md == NULL) { 176e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 177e1051a39Sopenharmony_ci md = EVP_sha1(); 178e1051a39Sopenharmony_ci#else 179e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); 180e1051a39Sopenharmony_ci return -1; 181e1051a39Sopenharmony_ci#endif 182e1051a39Sopenharmony_ci } 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci if (mgf1md == NULL) 185e1051a39Sopenharmony_ci mgf1md = md; 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci mdlen = EVP_MD_get_size(md); 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci if (tlen <= 0 || flen <= 0) 190e1051a39Sopenharmony_ci return -1; 191e1051a39Sopenharmony_ci /* 192e1051a39Sopenharmony_ci * |num| is the length of the modulus; |flen| is the length of the 193e1051a39Sopenharmony_ci * encoded message. Therefore, for any |from| that was obtained by 194e1051a39Sopenharmony_ci * decrypting a ciphertext, we must have |flen| <= |num|. Similarly, 195e1051a39Sopenharmony_ci * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective of 196e1051a39Sopenharmony_ci * the ciphertext, see PKCS #1 v2.2, section 7.1.2. 197e1051a39Sopenharmony_ci * This does not leak any side-channel information. 198e1051a39Sopenharmony_ci */ 199e1051a39Sopenharmony_ci if (num < flen || num < 2 * mdlen + 2) { 200e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR); 201e1051a39Sopenharmony_ci return -1; 202e1051a39Sopenharmony_ci } 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci dblen = num - mdlen - 1; 205e1051a39Sopenharmony_ci db = OPENSSL_malloc(dblen); 206e1051a39Sopenharmony_ci if (db == NULL) { 207e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); 208e1051a39Sopenharmony_ci goto cleanup; 209e1051a39Sopenharmony_ci } 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ci em = OPENSSL_malloc(num); 212e1051a39Sopenharmony_ci if (em == NULL) { 213e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); 214e1051a39Sopenharmony_ci goto cleanup; 215e1051a39Sopenharmony_ci } 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci /* 218e1051a39Sopenharmony_ci * Caller is encouraged to pass zero-padded message created with 219e1051a39Sopenharmony_ci * BN_bn2binpad. Trouble is that since we can't read out of |from|'s 220e1051a39Sopenharmony_ci * bounds, it's impossible to have an invariant memory access pattern 221e1051a39Sopenharmony_ci * in case |from| was not zero-padded in advance. 222e1051a39Sopenharmony_ci */ 223e1051a39Sopenharmony_ci for (from += flen, em += num, i = 0; i < num; i++) { 224e1051a39Sopenharmony_ci mask = ~constant_time_is_zero(flen); 225e1051a39Sopenharmony_ci flen -= 1 & mask; 226e1051a39Sopenharmony_ci from -= 1 & mask; 227e1051a39Sopenharmony_ci *--em = *from & mask; 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci /* 231e1051a39Sopenharmony_ci * The first byte must be zero, however we must not leak if this is 232e1051a39Sopenharmony_ci * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA 233e1051a39Sopenharmony_ci * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). 234e1051a39Sopenharmony_ci */ 235e1051a39Sopenharmony_ci good = constant_time_is_zero(em[0]); 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ci maskedseed = em + 1; 238e1051a39Sopenharmony_ci maskeddb = em + 1 + mdlen; 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_ci if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) 241e1051a39Sopenharmony_ci goto cleanup; 242e1051a39Sopenharmony_ci for (i = 0; i < mdlen; i++) 243e1051a39Sopenharmony_ci seed[i] ^= maskedseed[i]; 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) 246e1051a39Sopenharmony_ci goto cleanup; 247e1051a39Sopenharmony_ci for (i = 0; i < dblen; i++) 248e1051a39Sopenharmony_ci db[i] ^= maskeddb[i]; 249e1051a39Sopenharmony_ci 250e1051a39Sopenharmony_ci if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) 251e1051a39Sopenharmony_ci goto cleanup; 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ci good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci found_one_byte = 0; 256e1051a39Sopenharmony_ci for (i = mdlen; i < dblen; i++) { 257e1051a39Sopenharmony_ci /* 258e1051a39Sopenharmony_ci * Padding consists of a number of 0-bytes, followed by a 1. 259e1051a39Sopenharmony_ci */ 260e1051a39Sopenharmony_ci unsigned int equals1 = constant_time_eq(db[i], 1); 261e1051a39Sopenharmony_ci unsigned int equals0 = constant_time_is_zero(db[i]); 262e1051a39Sopenharmony_ci one_index = constant_time_select_int(~found_one_byte & equals1, 263e1051a39Sopenharmony_ci i, one_index); 264e1051a39Sopenharmony_ci found_one_byte |= equals1; 265e1051a39Sopenharmony_ci good &= (found_one_byte | equals0); 266e1051a39Sopenharmony_ci } 267e1051a39Sopenharmony_ci 268e1051a39Sopenharmony_ci good &= found_one_byte; 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci /* 271e1051a39Sopenharmony_ci * At this point |good| is zero unless the plaintext was valid, 272e1051a39Sopenharmony_ci * so plaintext-awareness ensures timing side-channels are no longer a 273e1051a39Sopenharmony_ci * concern. 274e1051a39Sopenharmony_ci */ 275e1051a39Sopenharmony_ci msg_index = one_index + 1; 276e1051a39Sopenharmony_ci mlen = dblen - msg_index; 277e1051a39Sopenharmony_ci 278e1051a39Sopenharmony_ci /* 279e1051a39Sopenharmony_ci * For good measure, do this check in constant time as well. 280e1051a39Sopenharmony_ci */ 281e1051a39Sopenharmony_ci good &= constant_time_ge(tlen, mlen); 282e1051a39Sopenharmony_ci 283e1051a39Sopenharmony_ci /* 284e1051a39Sopenharmony_ci * Move the result in-place by |dblen|-|mdlen|-1-|mlen| bytes to the left. 285e1051a39Sopenharmony_ci * Then if |good| move |mlen| bytes from |db|+|mdlen|+1 to |to|. 286e1051a39Sopenharmony_ci * Otherwise leave |to| unchanged. 287e1051a39Sopenharmony_ci * Copy the memory back in a way that does not reveal the size of 288e1051a39Sopenharmony_ci * the data being copied via a timing side channel. This requires copying 289e1051a39Sopenharmony_ci * parts of the buffer multiple times based on the bits set in the real 290e1051a39Sopenharmony_ci * length. Clear bits do a non-copy with identical access pattern. 291e1051a39Sopenharmony_ci * The loop below has overall complexity of O(N*log(N)). 292e1051a39Sopenharmony_ci */ 293e1051a39Sopenharmony_ci tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen), 294e1051a39Sopenharmony_ci dblen - mdlen - 1, tlen); 295e1051a39Sopenharmony_ci for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) { 296e1051a39Sopenharmony_ci mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0); 297e1051a39Sopenharmony_ci for (i = mdlen + 1; i < dblen - msg_index; i++) 298e1051a39Sopenharmony_ci db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]); 299e1051a39Sopenharmony_ci } 300e1051a39Sopenharmony_ci for (i = 0; i < tlen; i++) { 301e1051a39Sopenharmony_ci mask = good & constant_time_lt(i, mlen); 302e1051a39Sopenharmony_ci to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]); 303e1051a39Sopenharmony_ci } 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 306e1051a39Sopenharmony_ci /* 307e1051a39Sopenharmony_ci * To avoid chosen ciphertext attacks, the error message should not 308e1051a39Sopenharmony_ci * reveal which kind of decoding error happened. 309e1051a39Sopenharmony_ci * 310e1051a39Sopenharmony_ci * This trick doesn't work in the FIPS provider because libcrypto manages 311e1051a39Sopenharmony_ci * the error stack. Instead we opt not to put an error on the stack at all 312e1051a39Sopenharmony_ci * in case of padding failure in the FIPS provider. 313e1051a39Sopenharmony_ci */ 314e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_OAEP_DECODING_ERROR); 315e1051a39Sopenharmony_ci err_clear_last_constant_time(1 & good); 316e1051a39Sopenharmony_ci#endif 317e1051a39Sopenharmony_ci cleanup: 318e1051a39Sopenharmony_ci OPENSSL_cleanse(seed, sizeof(seed)); 319e1051a39Sopenharmony_ci OPENSSL_clear_free(db, dblen); 320e1051a39Sopenharmony_ci OPENSSL_clear_free(em, num); 321e1051a39Sopenharmony_ci 322e1051a39Sopenharmony_ci return constant_time_select_int(good, mlen, -1); 323e1051a39Sopenharmony_ci} 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci/* 326e1051a39Sopenharmony_ci * Mask Generation Function corresponding to section 7.2.2.2 of NIST SP 800-56B. 327e1051a39Sopenharmony_ci * The variables are named differently to NIST: 328e1051a39Sopenharmony_ci * mask (T) and len (maskLen)are the returned mask. 329e1051a39Sopenharmony_ci * seed (mgfSeed). 330e1051a39Sopenharmony_ci * The range checking steps inm the process are performed outside. 331e1051a39Sopenharmony_ci */ 332e1051a39Sopenharmony_ciint PKCS1_MGF1(unsigned char *mask, long len, 333e1051a39Sopenharmony_ci const unsigned char *seed, long seedlen, const EVP_MD *dgst) 334e1051a39Sopenharmony_ci{ 335e1051a39Sopenharmony_ci long i, outlen = 0; 336e1051a39Sopenharmony_ci unsigned char cnt[4]; 337e1051a39Sopenharmony_ci EVP_MD_CTX *c = EVP_MD_CTX_new(); 338e1051a39Sopenharmony_ci unsigned char md[EVP_MAX_MD_SIZE]; 339e1051a39Sopenharmony_ci int mdlen; 340e1051a39Sopenharmony_ci int rv = -1; 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci if (c == NULL) 343e1051a39Sopenharmony_ci goto err; 344e1051a39Sopenharmony_ci mdlen = EVP_MD_get_size(dgst); 345e1051a39Sopenharmony_ci if (mdlen < 0) 346e1051a39Sopenharmony_ci goto err; 347e1051a39Sopenharmony_ci /* step 4 */ 348e1051a39Sopenharmony_ci for (i = 0; outlen < len; i++) { 349e1051a39Sopenharmony_ci /* step 4a: D = I2BS(counter, 4) */ 350e1051a39Sopenharmony_ci cnt[0] = (unsigned char)((i >> 24) & 255); 351e1051a39Sopenharmony_ci cnt[1] = (unsigned char)((i >> 16) & 255); 352e1051a39Sopenharmony_ci cnt[2] = (unsigned char)((i >> 8)) & 255; 353e1051a39Sopenharmony_ci cnt[3] = (unsigned char)(i & 255); 354e1051a39Sopenharmony_ci /* step 4b: T =T || hash(mgfSeed || D) */ 355e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(c, dgst, NULL) 356e1051a39Sopenharmony_ci || !EVP_DigestUpdate(c, seed, seedlen) 357e1051a39Sopenharmony_ci || !EVP_DigestUpdate(c, cnt, 4)) 358e1051a39Sopenharmony_ci goto err; 359e1051a39Sopenharmony_ci if (outlen + mdlen <= len) { 360e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(c, mask + outlen, NULL)) 361e1051a39Sopenharmony_ci goto err; 362e1051a39Sopenharmony_ci outlen += mdlen; 363e1051a39Sopenharmony_ci } else { 364e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(c, md, NULL)) 365e1051a39Sopenharmony_ci goto err; 366e1051a39Sopenharmony_ci memcpy(mask + outlen, md, len - outlen); 367e1051a39Sopenharmony_ci outlen = len; 368e1051a39Sopenharmony_ci } 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci rv = 0; 371e1051a39Sopenharmony_ci err: 372e1051a39Sopenharmony_ci OPENSSL_cleanse(md, sizeof(md)); 373e1051a39Sopenharmony_ci EVP_MD_CTX_free(c); 374e1051a39Sopenharmony_ci return rv; 375e1051a39Sopenharmony_ci} 376