1/* crypto/rsa/rsa_oaep.c */ 2/* 3 * Written by Ulf Moeller. This software is distributed on an "AS IS" basis, 4 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 5 */ 6 7/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ 8 9/* 10 * See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL: 11 * http://www.shoup.net/papers/oaep.ps.Z> for problems with the security 12 * proof for the original OAEP scheme, which EME-OAEP is based on. A new 13 * proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern, 14 * "RSA-OEAP is Still Alive!", Dec. 2000, <URL: 15 * http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements 16 * for the underlying permutation: "partial-one-wayness" instead of 17 * one-wayness. For the RSA function, this is an equivalent notion. 18 */ 19 20#include "constant_time_locl.h" 21 22#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) 23# include <stdio.h> 24# include "cryptlib.h" 25# include <openssl/bn.h> 26# include <openssl/rsa.h> 27# include <openssl/evp.h> 28# include <openssl/rand.h> 29# include <openssl/sha.h> 30 31int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, 32 const unsigned char *from, int flen, 33 const unsigned char *param, int plen) 34{ 35 return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen, 36 param, plen, NULL, NULL); 37} 38 39int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, 40 const unsigned char *from, int flen, 41 const unsigned char *param, int plen, 42 const EVP_MD *md, const EVP_MD *mgf1md) 43{ 44 int i, emlen = tlen - 1; 45 unsigned char *db, *seed; 46 unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE]; 47 int mdlen; 48 49 if (md == NULL) 50 md = EVP_sha1(); 51 if (mgf1md == NULL) 52 mgf1md = md; 53 54 mdlen = EVP_MD_size(md); 55 56 if (flen > emlen - 2 * mdlen - 1) { 57 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 58 RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 59 return 0; 60 } 61 62 if (emlen < 2 * mdlen + 1) { 63 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 64 RSA_R_KEY_SIZE_TOO_SMALL); 65 return 0; 66 } 67 68 to[0] = 0; 69 seed = to + 1; 70 db = to + mdlen + 1; 71 72 if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) 73 return 0; 74 memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1); 75 db[emlen - flen - mdlen - 1] = 0x01; 76 memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); 77 if (RAND_bytes(seed, mdlen) <= 0) 78 return 0; 79# ifdef PKCS_TESTVECT 80 memcpy(seed, 81 "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", 82 20); 83# endif 84 85 dbmask = OPENSSL_malloc(emlen - mdlen); 86 if (dbmask == NULL) { 87 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); 88 return 0; 89 } 90 91 if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) 92 return 0; 93 for (i = 0; i < emlen - mdlen; i++) 94 db[i] ^= dbmask[i]; 95 96 if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) 97 return 0; 98 for (i = 0; i < mdlen; i++) 99 seed[i] ^= seedmask[i]; 100 101 OPENSSL_free(dbmask); 102 return 1; 103} 104 105int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, 106 const unsigned char *from, int flen, int num, 107 const unsigned char *param, int plen) 108{ 109 return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num, 110 param, plen, NULL, NULL); 111} 112 113int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, 114 const unsigned char *from, int flen, 115 int num, const unsigned char *param, 116 int plen, const EVP_MD *md, 117 const EVP_MD *mgf1md) 118{ 119 int i, dblen, mlen = -1, one_index = 0, msg_index; 120 unsigned int good, found_one_byte; 121 const unsigned char *maskedseed, *maskeddb; 122 /* 123 * |em| is the encoded message, zero-padded to exactly |num| bytes: em = 124 * Y || maskedSeed || maskedDB 125 */ 126 unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE], 127 phash[EVP_MAX_MD_SIZE]; 128 int mdlen; 129 130 if (md == NULL) 131 md = EVP_sha1(); 132 if (mgf1md == NULL) 133 mgf1md = md; 134 135 mdlen = EVP_MD_size(md); 136 137 if (tlen <= 0 || flen <= 0) 138 return -1; 139 /* 140 * |num| is the length of the modulus; |flen| is the length of the 141 * encoded message. Therefore, for any |from| that was obtained by 142 * decrypting a ciphertext, we must have |flen| <= |num|. Similarly, 143 * num < 2 * mdlen + 2 must hold for the modulus irrespective of 144 * the ciphertext, see PKCS #1 v2.2, section 7.1.2. 145 * This does not leak any side-channel information. 146 */ 147 if (num < flen || num < 2 * mdlen + 2) 148 goto decoding_err; 149 150 dblen = num - mdlen - 1; 151 db = OPENSSL_malloc(dblen); 152 em = OPENSSL_malloc(num); 153 if (db == NULL || em == NULL) { 154 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); 155 goto cleanup; 156 } 157 158 /* 159 * Always do this zero-padding copy (even when num == flen) to avoid 160 * leaking that information. The copy still leaks some side-channel 161 * information, but it's impossible to have a fixed memory access 162 * pattern since we can't read out of the bounds of |from|. 163 * 164 * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL. 165 */ 166 memset(em, 0, num); 167 memcpy(em + num - flen, from, flen); 168 169 /* 170 * The first byte must be zero, however we must not leak if this is 171 * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA 172 * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). 173 */ 174 good = constant_time_is_zero(em[0]); 175 176 maskedseed = em + 1; 177 maskeddb = em + 1 + mdlen; 178 179 if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) 180 goto cleanup; 181 for (i = 0; i < mdlen; i++) 182 seed[i] ^= maskedseed[i]; 183 184 if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) 185 goto cleanup; 186 for (i = 0; i < dblen; i++) 187 db[i] ^= maskeddb[i]; 188 189 if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) 190 goto cleanup; 191 192 good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); 193 194 found_one_byte = 0; 195 for (i = mdlen; i < dblen; i++) { 196 /* 197 * Padding consists of a number of 0-bytes, followed by a 1. 198 */ 199 unsigned int equals1 = constant_time_eq(db[i], 1); 200 unsigned int equals0 = constant_time_is_zero(db[i]); 201 one_index = constant_time_select_int(~found_one_byte & equals1, 202 i, one_index); 203 found_one_byte |= equals1; 204 good &= (found_one_byte | equals0); 205 } 206 207 good &= found_one_byte; 208 209 /* 210 * At this point |good| is zero unless the plaintext was valid, 211 * so plaintext-awareness ensures timing side-channels are no longer a 212 * concern. 213 */ 214 if (!good) 215 goto decoding_err; 216 217 msg_index = one_index + 1; 218 mlen = dblen - msg_index; 219 220 if (tlen < mlen) { 221 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE); 222 mlen = -1; 223 } else { 224 memcpy(to, db + msg_index, mlen); 225 goto cleanup; 226 } 227 228 decoding_err: 229 /* 230 * To avoid chosen ciphertext attacks, the error message should not 231 * reveal which kind of decoding error happened. 232 */ 233 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 234 RSA_R_OAEP_DECODING_ERROR); 235 cleanup: 236 if (db != NULL) 237 OPENSSL_free(db); 238 if (em != NULL) 239 OPENSSL_free(em); 240 return mlen; 241} 242 243int PKCS1_MGF1(unsigned char *mask, long len, 244 const unsigned char *seed, long seedlen, const EVP_MD *dgst) 245{ 246 long i, outlen = 0; 247 unsigned char cnt[4]; 248 EVP_MD_CTX c; 249 unsigned char md[EVP_MAX_MD_SIZE]; 250 int mdlen; 251 int rv = -1; 252 253 EVP_MD_CTX_init(&c); 254 mdlen = EVP_MD_size(dgst); 255 if (mdlen < 0) 256 goto err; 257 for (i = 0; outlen < len; i++) { 258 cnt[0] = (unsigned char)((i >> 24) & 255); 259 cnt[1] = (unsigned char)((i >> 16) & 255); 260 cnt[2] = (unsigned char)((i >> 8)) & 255; 261 cnt[3] = (unsigned char)(i & 255); 262 if (!EVP_DigestInit_ex(&c, dgst, NULL) 263 || !EVP_DigestUpdate(&c, seed, seedlen) 264 || !EVP_DigestUpdate(&c, cnt, 4)) 265 goto err; 266 if (outlen + mdlen <= len) { 267 if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL)) 268 goto err; 269 outlen += mdlen; 270 } else { 271 if (!EVP_DigestFinal_ex(&c, md, NULL)) 272 goto err; 273 memcpy(mask + outlen, md, len - outlen); 274 outlen = len; 275 } 276 } 277 rv = 0; 278 err: 279 EVP_MD_CTX_cleanup(&c); 280 return rv; 281} 282 283#endif 284