rsa_oaep.c revision 337982
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 = 0, 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 if (db == NULL) { 157 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); 158 goto cleanup; 159 } 160 161 if (flen != num) { 162 em = OPENSSL_malloc(num); 163 if (em == NULL) { 164 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 165 ERR_R_MALLOC_FAILURE); 166 goto cleanup; 167 } 168 169 /* 170 * Caller is encouraged to pass zero-padded message created with 171 * BN_bn2binpad, but if it doesn't, we do this zero-padding copy 172 * to avoid leaking that information. The copy still leaks some 173 * side-channel information, but it's impossible to have a fixed 174 * memory access pattern since we can't read out of the bounds of 175 * |from|. 176 */ 177 memset(em, 0, num); 178 memcpy(em + num - flen, from, flen); 179 from = em; 180 } 181 182 /* 183 * The first byte must be zero, however we must not leak if this is 184 * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA 185 * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). 186 */ 187 good = constant_time_is_zero(from[0]); 188 189 maskedseed = from + 1; 190 maskeddb = from + 1 + mdlen; 191 192 if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) 193 goto cleanup; 194 for (i = 0; i < mdlen; i++) 195 seed[i] ^= maskedseed[i]; 196 197 if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) 198 goto cleanup; 199 for (i = 0; i < dblen; i++) 200 db[i] ^= maskeddb[i]; 201 202 if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) 203 goto cleanup; 204 205 good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); 206 207 found_one_byte = 0; 208 for (i = mdlen; i < dblen; i++) { 209 /* 210 * Padding consists of a number of 0-bytes, followed by a 1. 211 */ 212 unsigned int equals1 = constant_time_eq(db[i], 1); 213 unsigned int equals0 = constant_time_is_zero(db[i]); 214 one_index = constant_time_select_int(~found_one_byte & equals1, 215 i, one_index); 216 found_one_byte |= equals1; 217 good &= (found_one_byte | equals0); 218 } 219 220 good &= found_one_byte; 221 222 /* 223 * At this point |good| is zero unless the plaintext was valid, 224 * so plaintext-awareness ensures timing side-channels are no longer a 225 * concern. 226 */ 227 if (!good) 228 goto decoding_err; 229 230 msg_index = one_index + 1; 231 mlen = dblen - msg_index; 232 233 if (tlen < mlen) { 234 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE); 235 mlen = -1; 236 } else { 237 memcpy(to, db + msg_index, mlen); 238 goto cleanup; 239 } 240 241 decoding_err: 242 /* 243 * To avoid chosen ciphertext attacks, the error message should not 244 * reveal which kind of decoding error happened. 245 */ 246 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 247 RSA_R_OAEP_DECODING_ERROR); 248 cleanup: 249 if (db != NULL) { 250 OPENSSL_cleanse(db, dblen); 251 OPENSSL_free(db); 252 } 253 if (em != NULL) { 254 OPENSSL_cleanse(em, num); 255 OPENSSL_free(em); 256 } 257 return mlen; 258} 259 260int PKCS1_MGF1(unsigned char *mask, long len, 261 const unsigned char *seed, long seedlen, const EVP_MD *dgst) 262{ 263 long i, outlen = 0; 264 unsigned char cnt[4]; 265 EVP_MD_CTX c; 266 unsigned char md[EVP_MAX_MD_SIZE]; 267 int mdlen; 268 int rv = -1; 269 270 EVP_MD_CTX_init(&c); 271 mdlen = EVP_MD_size(dgst); 272 if (mdlen < 0) 273 goto err; 274 for (i = 0; outlen < len; i++) { 275 cnt[0] = (unsigned char)((i >> 24) & 255); 276 cnt[1] = (unsigned char)((i >> 16) & 255); 277 cnt[2] = (unsigned char)((i >> 8)) & 255; 278 cnt[3] = (unsigned char)(i & 255); 279 if (!EVP_DigestInit_ex(&c, dgst, NULL) 280 || !EVP_DigestUpdate(&c, seed, seedlen) 281 || !EVP_DigestUpdate(&c, cnt, 4)) 282 goto err; 283 if (outlen + mdlen <= len) { 284 if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL)) 285 goto err; 286 outlen += mdlen; 287 } else { 288 if (!EVP_DigestFinal_ex(&c, md, NULL)) 289 goto err; 290 memcpy(mask + outlen, md, len - outlen); 291 outlen = len; 292 } 293 } 294 rv = 0; 295 err: 296 EVP_MD_CTX_cleanup(&c); 297 return rv; 298} 299 300#endif 301