summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/rsa/rsa_oaep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/rsa/rsa_oaep.c')
-rw-r--r--src/lib/libcrypto/rsa/rsa_oaep.c292
1 files changed, 168 insertions, 124 deletions
diff --git a/src/lib/libcrypto/rsa/rsa_oaep.c b/src/lib/libcrypto/rsa/rsa_oaep.c
index 843c40c864..e3f7c608ec 100644
--- a/src/lib/libcrypto/rsa/rsa_oaep.c
+++ b/src/lib/libcrypto/rsa/rsa_oaep.c
@@ -2,161 +2,205 @@
2/* Written by Ulf Moeller. This software is distributed on an "AS IS" 2/* Written by Ulf Moeller. This software is distributed on an "AS IS"
3 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */ 3 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */
4 4
5/* EME_OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ 5/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
6 6
7#if !defined(NO_SHA) && !defined(NO_SHA1) 7/* See Victor Shoup, "OAEP reconsidered," Nov. 2000,
8 * <URL: http://www.shoup.net/papers/oaep.ps.Z>
9 * for problems with the security proof for the
10 * original OAEP scheme, which EME-OAEP is based on.
11 *
12 * A new proof can be found in E. Fujisaki, T. Okamoto,
13 * D. Pointcheval, J. Stern, "RSA-OEAP is Still Alive!",
14 * Dec. 2000, <URL: http://eprint.iacr.org/2000/061/>.
15 * The new proof has stronger requirements for the
16 * underlying permutation: "partial-one-wayness" instead
17 * of one-wayness. For the RSA function, this is
18 * an equivalent notion.
19 */
20
21
22#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
8#include <stdio.h> 23#include <stdio.h>
9#include "cryptlib.h" 24#include "cryptlib.h"
10#include <openssl/bn.h> 25#include <openssl/bn.h>
11#include <openssl/rsa.h> 26#include <openssl/rsa.h>
12#include <openssl/sha.h> 27#include <openssl/evp.h>
13#include <openssl/rand.h> 28#include <openssl/rand.h>
29#include <openssl/sha.h>
14 30
15int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen); 31int MGF1(unsigned char *mask, long len,
32 const unsigned char *seed, long seedlen);
16 33
17int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, 34int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
18 unsigned char *from, int flen, unsigned char *param, int plen) 35 const unsigned char *from, int flen,
19 { 36 const unsigned char *param, int plen)
20 int i, emlen = tlen - 1;
21 unsigned char *db, *seed;
22 unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH];
23
24 if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1)
25 { 37 {
26 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, 38 int i, emlen = tlen - 1;
27 RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 39 unsigned char *db, *seed;
28 return (0); 40 unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH];
29 }
30 41
31 if (emlen < 2 * SHA_DIGEST_LENGTH + 1) 42 if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1)
32 { 43 {
33 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL); 44 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
34 return (0); 45 RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
35 } 46 return 0;
36 47 }
37 dbmask = Malloc(emlen - SHA_DIGEST_LENGTH); 48
38 if (dbmask == NULL) 49 if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
39 { 50 {
40 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); 51 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
41 return (0); 52 return 0;
42 } 53 }
43 54
44 to[0] = 0; 55 dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
45 seed = to + 1; 56 if (dbmask == NULL)
46 db = to + SHA_DIGEST_LENGTH + 1; 57 {
58 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
59 return 0;
60 }
47 61
48 SHA1(param, plen, db); 62 to[0] = 0;
49 memset(db + SHA_DIGEST_LENGTH, 0, 63 seed = to + 1;
50 emlen - flen - 2 * SHA_DIGEST_LENGTH - 1); 64 db = to + SHA_DIGEST_LENGTH + 1;
51 db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01; 65
52 memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen); 66 EVP_Digest((void *)param, plen, db, NULL, EVP_sha1(), NULL);
53 RAND_bytes(seed, SHA_DIGEST_LENGTH); 67 memset(db + SHA_DIGEST_LENGTH, 0,
68 emlen - flen - 2 * SHA_DIGEST_LENGTH - 1);
69 db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
70 memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
71 if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
72 return 0;
54#ifdef PKCS_TESTVECT 73#ifdef PKCS_TESTVECT
55 memcpy(seed, 74 memcpy(seed,
56 "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", 75 "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
57 20); 76 20);
58#endif 77#endif
59 78
60 MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); 79 MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH);
61 for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) 80 for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++)
62 db[i] ^= dbmask[i]; 81 db[i] ^= dbmask[i];
63 82
64 MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); 83 MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH);
65 for (i = 0; i < SHA_DIGEST_LENGTH; i++) 84 for (i = 0; i < SHA_DIGEST_LENGTH; i++)
66 seed[i] ^= seedmask[i]; 85 seed[i] ^= seedmask[i];
67 86
68 Free(dbmask); 87 OPENSSL_free(dbmask);
69 return (1); 88 return 1;
70 } 89 }
71 90
72int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, 91int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
73 unsigned char *from, int flen, int num, unsigned char *param, 92 const unsigned char *from, int flen, int num,
74 int plen) 93 const unsigned char *param, int plen)
75 {
76 int i, dblen, mlen = -1;
77 unsigned char *maskeddb;
78 int lzero;
79 unsigned char *db, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
80
81 if (--num < 2 * SHA_DIGEST_LENGTH + 1)
82 { 94 {
83 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); 95 int i, dblen, mlen = -1;
84 return (-1); 96 const unsigned char *maskeddb;
85 } 97 int lzero;
98 unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
99 int bad = 0;
100
101 if (--num < 2 * SHA_DIGEST_LENGTH + 1)
102 /* 'num' is the length of the modulus, i.e. does not depend on the
103 * particular ciphertext. */
104 goto decoding_err;
105
106 lzero = num - flen;
107 if (lzero < 0)
108 {
109 /* lzero == -1 */
110
111 /* signalling this error immediately after detection might allow
112 * for side-channel attacks (e.g. timing if 'plen' is huge
113 * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
114 * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
115 * so we use a 'bad' flag */
116 bad = 1;
117 lzero = 0;
118 }
119 maskeddb = from - lzero + SHA_DIGEST_LENGTH;
86 120
87 dblen = num - SHA_DIGEST_LENGTH; 121 dblen = num - SHA_DIGEST_LENGTH;
88 db = Malloc(dblen); 122 db = OPENSSL_malloc(dblen);
89 if (db == NULL) 123 if (db == NULL)
90 { 124 {
91 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); 125 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
92 return (-1); 126 return -1;
93 } 127 }
94 128
95 lzero = num - flen; 129 MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
96 maskeddb = from - lzero + SHA_DIGEST_LENGTH; 130 for (i = lzero; i < SHA_DIGEST_LENGTH; i++)
97 131 seed[i] ^= from[i - lzero];
98 MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
99 for (i = lzero; i < SHA_DIGEST_LENGTH; i++)
100 seed[i] ^= from[i - lzero];
101 132
102 MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); 133 MGF1(db, dblen, seed, SHA_DIGEST_LENGTH);
103 for (i = 0; i < dblen; i++) 134 for (i = 0; i < dblen; i++)
104 db[i] ^= maskeddb[i]; 135 db[i] ^= maskeddb[i];
105 136
106 SHA1(param, plen, phash); 137 EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL);
107 138
108 if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0) 139 if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
109 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); 140 goto decoding_err;
110 else
111 {
112 for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
113 if (db[i] != 0x00)
114 break;
115 if (db[i] != 0x01 || i++ >= dblen)
116 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP,
117 RSA_R_OAEP_DECODING_ERROR);
118 else 141 else
119 {
120 mlen = dblen - i;
121 if (tlen < mlen)
122 { 142 {
123 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); 143 for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
124 mlen = -1; 144 if (db[i] != 0x00)
145 break;
146 if (db[i] != 0x01 || i++ >= dblen)
147 goto decoding_err;
148 else
149 {
150 /* everything looks OK */
151
152 mlen = dblen - i;
153 if (tlen < mlen)
154 {
155 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
156 mlen = -1;
157 }
158 else
159 memcpy(to, db + i, mlen);
160 }
125 } 161 }
126 else 162 OPENSSL_free(db);
127 memcpy(to, db + i, mlen); 163 return mlen;
128 } 164
165decoding_err:
166 /* to avoid chosen ciphertext attacks, the error message should not reveal
167 * which kind of decoding error happened */
168 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
169 if (db != NULL) OPENSSL_free(db);
170 return -1;
129 } 171 }
130 Free(db); 172
131 return (mlen); 173int MGF1(unsigned char *mask, long len,
132 } 174 const unsigned char *seed, long seedlen)
133
134int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen)
135 {
136 long i, outlen = 0;
137 unsigned char cnt[4];
138 SHA_CTX c;
139 unsigned char md[SHA_DIGEST_LENGTH];
140
141 for (i = 0; outlen < len; i++)
142 { 175 {
143 cnt[0] = (i >> 24) & 255, cnt[1] = (i >> 16) & 255, 176 long i, outlen = 0;
144 cnt[2] = (i >> 8) & 255, cnt[3] = i & 255; 177 unsigned char cnt[4];
145 SHA1_Init(&c); 178 EVP_MD_CTX c;
146 SHA1_Update(&c, seed, seedlen); 179 unsigned char md[SHA_DIGEST_LENGTH];
147 SHA1_Update(&c, cnt, 4); 180
148 if (outlen + SHA_DIGEST_LENGTH <= len) 181 EVP_MD_CTX_init(&c);
149 { 182 for (i = 0; outlen < len; i++)
150 SHA1_Final(mask + outlen, &c); 183 {
151 outlen += SHA_DIGEST_LENGTH; 184 cnt[0] = (unsigned char)((i >> 24) & 255);
152 } 185 cnt[1] = (unsigned char)((i >> 16) & 255);
153 else 186 cnt[2] = (unsigned char)((i >> 8)) & 255;
154 { 187 cnt[3] = (unsigned char)(i & 255);
155 SHA1_Final(md, &c); 188 EVP_DigestInit_ex(&c,EVP_sha1(), NULL);
156 memcpy(mask + outlen, md, len - outlen); 189 EVP_DigestUpdate(&c, seed, seedlen);
157 outlen = len; 190 EVP_DigestUpdate(&c, cnt, 4);
158 } 191 if (outlen + SHA_DIGEST_LENGTH <= len)
192 {
193 EVP_DigestFinal_ex(&c, mask + outlen, NULL);
194 outlen += SHA_DIGEST_LENGTH;
195 }
196 else
197 {
198 EVP_DigestFinal_ex(&c, md, NULL);
199 memcpy(mask + outlen, md, len - outlen);
200 outlen = len;
201 }
202 }
203 EVP_MD_CTX_cleanup(&c);
204 return 0;
159 } 205 }
160 return (0);
161 }
162#endif 206#endif