rsa_oaep.c revision 325337
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 goto err; 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 goto err; 98 for (i = 0; i < mdlen; i++) 99 seed[i] ^= seedmask[i]; 100 101 OPENSSL_free(dbmask); 102 return 1; 103 104 err: 105 OPENSSL_free(dbmask); 106 return 0; 107} 108 109int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, 110 const unsigned char *from, int flen, int num, 111 const unsigned char *param, int plen) 112{ 113 return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num, 114 param, plen, NULL, NULL); 115} 116 117int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, 118 const unsigned char *from, int flen, 119 int num, const unsigned char *param, 120 int plen, const EVP_MD *md, 121 const EVP_MD *mgf1md) 122{ 123 int i, dblen, mlen = -1, one_index = 0, msg_index; 124 unsigned int good, found_one_byte; 125 const unsigned char *maskedseed, *maskeddb; 126 /* 127 * |em| is the encoded message, zero-padded to exactly |num| bytes: em = 128 * Y || maskedSeed || maskedDB 129 */ 130 unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE], 131 phash[EVP_MAX_MD_SIZE]; 132 int mdlen; 133 134 if (md == NULL) 135 md = EVP_sha1(); 136 if (mgf1md == NULL) 137 mgf1md = md; 138 139 mdlen = EVP_MD_size(md); 140 141 if (tlen <= 0 || flen <= 0) 142 return -1; 143 /* 144 * |num| is the length of the modulus; |flen| is the length of the 145 * encoded message. Therefore, for any |from| that was obtained by 146 * decrypting a ciphertext, we must have |flen| <= |num|. Similarly, 147 * num < 2 * mdlen + 2 must hold for the modulus irrespective of 148 * the ciphertext, see PKCS #1 v2.2, section 7.1.2. 149 * This does not leak any side-channel information. 150 */ 151 if (num < flen || num < 2 * mdlen + 2) 152 goto decoding_err; 153 154 dblen = num - mdlen - 1; 155 db = OPENSSL_malloc(dblen); 156 em = OPENSSL_malloc(num); 157 if (db == NULL || em == NULL) { 158 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); 159 goto cleanup; 160 } 161 162 /* 163 * Always do this zero-padding copy (even when num == flen) to avoid 164 * leaking that information. The copy still leaks some side-channel 165 * information, but it's impossible to have a fixed memory access 166 * pattern since we can't read out of the bounds of |from|. 167 * 168 * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL. 169 */ 170 memset(em, 0, num); 171 memcpy(em + num - flen, from, flen); 172 173 /* 174 * The first byte must be zero, however we must not leak if this is 175 * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA 176 * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). 177 */ 178 good = constant_time_is_zero(em[0]); 179 180 maskedseed = em + 1; 181 maskeddb = em + 1 + mdlen; 182 183 if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) 184 goto cleanup; 185 for (i = 0; i < mdlen; i++) 186 seed[i] ^= maskedseed[i]; 187 188 if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) 189 goto cleanup; 190 for (i = 0; i < dblen; i++) 191 db[i] ^= maskeddb[i]; 192 193 if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) 194 goto cleanup; 195 196 good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); 197 198 found_one_byte = 0; 199 for (i = mdlen; i < dblen; i++) { 200 /* 201 * Padding consists of a number of 0-bytes, followed by a 1. 202 */ 203 unsigned int equals1 = constant_time_eq(db[i], 1); 204 unsigned int equals0 = constant_time_is_zero(db[i]); 205 one_index = constant_time_select_int(~found_one_byte & equals1, 206 i, one_index); 207 found_one_byte |= equals1; 208 good &= (found_one_byte | equals0); 209 } 210 211 good &= found_one_byte; 212 213 /* 214 * At this point |good| is zero unless the plaintext was valid, 215 * so plaintext-awareness ensures timing side-channels are no longer a 216 * concern. 217 */ 218 if (!good) 219 goto decoding_err; 220 221 msg_index = one_index + 1; 222 mlen = dblen - msg_index; 223 224 if (tlen < mlen) { 225 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE); 226 mlen = -1; 227 } else { 228 memcpy(to, db + msg_index, mlen); 229 goto cleanup; 230 } 231 232 decoding_err: 233 /* 234 * To avoid chosen ciphertext attacks, the error message should not 235 * reveal which kind of decoding error happened. 236 */ 237 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 238 RSA_R_OAEP_DECODING_ERROR); 239 cleanup: 240 if (db != NULL) { 241 OPENSSL_cleanse(db, dblen); 242 OPENSSL_free(db); 243 } 244 if (em != NULL) { 245 OPENSSL_cleanse(em, num); 246 OPENSSL_free(em); 247 } 248 return mlen; 249} 250 251int PKCS1_MGF1(unsigned char *mask, long len, 252 const unsigned char *seed, long seedlen, const EVP_MD *dgst) 253{ 254 long i, outlen = 0; 255 unsigned char cnt[4]; 256 EVP_MD_CTX c; 257 unsigned char md[EVP_MAX_MD_SIZE]; 258 int mdlen; 259 int rv = -1; 260 261 EVP_MD_CTX_init(&c); 262 mdlen = EVP_MD_size(dgst); 263 if (mdlen < 0) 264 goto err; 265 for (i = 0; outlen < len; i++) { 266 cnt[0] = (unsigned char)((i >> 24) & 255); 267 cnt[1] = (unsigned char)((i >> 16) & 255); 268 cnt[2] = (unsigned char)((i >> 8)) & 255; 269 cnt[3] = (unsigned char)(i & 255); 270 if (!EVP_DigestInit_ex(&c, dgst, NULL) 271 || !EVP_DigestUpdate(&c, seed, seedlen) 272 || !EVP_DigestUpdate(&c, cnt, 4)) 273 goto err; 274 if (outlen + mdlen <= len) { 275 if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL)) 276 goto err; 277 outlen += mdlen; 278 } else { 279 if (!EVP_DigestFinal_ex(&c, md, NULL)) 280 goto err; 281 memcpy(mask + outlen, md, len - outlen); 282 outlen = len; 283 } 284 } 285 rv = 0; 286 err: 287 EVP_MD_CTX_cleanup(&c); 288 return rv; 289} 290 291#endif 292