diff options
Diffstat (limited to 'src/lib/libcrypto/rsa/rsa_oaep.c')
-rw-r--r-- | src/lib/libcrypto/rsa/rsa_oaep.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/src/lib/libcrypto/rsa/rsa_oaep.c b/src/lib/libcrypto/rsa/rsa_oaep.c index d43ecaca63..3652677a99 100644 --- a/src/lib/libcrypto/rsa/rsa_oaep.c +++ b/src/lib/libcrypto/rsa/rsa_oaep.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <openssl/rand.h> | 28 | #include <openssl/rand.h> |
29 | #include <openssl/sha.h> | 29 | #include <openssl/sha.h> |
30 | 30 | ||
31 | int MGF1(unsigned char *mask, long len, | ||
32 | const unsigned char *seed, long seedlen); | ||
33 | |||
31 | int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, | 34 | int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, |
32 | const unsigned char *from, int flen, | 35 | const unsigned char *from, int flen, |
33 | const unsigned char *param, int plen) | 36 | const unsigned char *param, int plen) |
@@ -73,13 +76,11 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, | |||
73 | 20); | 76 | 20); |
74 | #endif | 77 | #endif |
75 | 78 | ||
76 | PKCS1_MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH, | 79 | MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); |
77 | EVP_sha1()); | ||
78 | for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) | 80 | for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) |
79 | db[i] ^= dbmask[i]; | 81 | db[i] ^= dbmask[i]; |
80 | 82 | ||
81 | PKCS1_MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH, | 83 | MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); |
82 | EVP_sha1()); | ||
83 | for (i = 0; i < SHA_DIGEST_LENGTH; i++) | 84 | for (i = 0; i < SHA_DIGEST_LENGTH; i++) |
84 | seed[i] ^= seedmask[i]; | 85 | seed[i] ^= seedmask[i]; |
85 | 86 | ||
@@ -95,6 +96,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, | |||
95 | const unsigned char *maskeddb; | 96 | const unsigned char *maskeddb; |
96 | int lzero; | 97 | int lzero; |
97 | unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; | 98 | unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; |
99 | unsigned char *padded_from; | ||
98 | int bad = 0; | 100 | int bad = 0; |
99 | 101 | ||
100 | if (--num < 2 * SHA_DIGEST_LENGTH + 1) | 102 | if (--num < 2 * SHA_DIGEST_LENGTH + 1) |
@@ -105,8 +107,6 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, | |||
105 | lzero = num - flen; | 107 | lzero = num - flen; |
106 | if (lzero < 0) | 108 | if (lzero < 0) |
107 | { | 109 | { |
108 | /* lzero == -1 */ | ||
109 | |||
110 | /* signalling this error immediately after detection might allow | 110 | /* signalling this error immediately after detection might allow |
111 | * for side-channel attacks (e.g. timing if 'plen' is huge | 111 | * for side-channel attacks (e.g. timing if 'plen' is huge |
112 | * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal | 112 | * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal |
@@ -114,22 +114,30 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, | |||
114 | * so we use a 'bad' flag */ | 114 | * so we use a 'bad' flag */ |
115 | bad = 1; | 115 | bad = 1; |
116 | lzero = 0; | 116 | lzero = 0; |
117 | flen = num; /* don't overflow the memcpy to padded_from */ | ||
117 | } | 118 | } |
118 | maskeddb = from - lzero + SHA_DIGEST_LENGTH; | ||
119 | 119 | ||
120 | dblen = num - SHA_DIGEST_LENGTH; | 120 | dblen = num - SHA_DIGEST_LENGTH; |
121 | db = OPENSSL_malloc(dblen); | 121 | db = OPENSSL_malloc(dblen + num); |
122 | if (db == NULL) | 122 | if (db == NULL) |
123 | { | 123 | { |
124 | RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); | 124 | RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); |
125 | return -1; | 125 | return -1; |
126 | } | 126 | } |
127 | 127 | ||
128 | PKCS1_MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen, EVP_sha1()); | 128 | /* Always do this zero-padding copy (even when lzero == 0) |
129 | for (i = lzero; i < SHA_DIGEST_LENGTH; i++) | 129 | * to avoid leaking timing info about the value of lzero. */ |
130 | seed[i] ^= from[i - lzero]; | 130 | padded_from = db + dblen; |
131 | memset(padded_from, 0, lzero); | ||
132 | memcpy(padded_from + lzero, from, flen); | ||
133 | |||
134 | maskeddb = padded_from + SHA_DIGEST_LENGTH; | ||
135 | |||
136 | MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); | ||
137 | for (i = 0; i < SHA_DIGEST_LENGTH; i++) | ||
138 | seed[i] ^= padded_from[i]; | ||
131 | 139 | ||
132 | PKCS1_MGF1(db, dblen, seed, SHA_DIGEST_LENGTH, EVP_sha1()); | 140 | MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); |
133 | for (i = 0; i < dblen; i++) | 141 | for (i = 0; i < dblen; i++) |
134 | db[i] ^= maskeddb[i]; | 142 | db[i] ^= maskeddb[i]; |
135 | 143 | ||
@@ -142,13 +150,13 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, | |||
142 | for (i = SHA_DIGEST_LENGTH; i < dblen; i++) | 150 | for (i = SHA_DIGEST_LENGTH; i < dblen; i++) |
143 | if (db[i] != 0x00) | 151 | if (db[i] != 0x00) |
144 | break; | 152 | break; |
145 | if (db[i] != 0x01 || i++ >= dblen) | 153 | if (i == dblen || db[i] != 0x01) |
146 | goto decoding_err; | 154 | goto decoding_err; |
147 | else | 155 | else |
148 | { | 156 | { |
149 | /* everything looks OK */ | 157 | /* everything looks OK */ |
150 | 158 | ||
151 | mlen = dblen - i; | 159 | mlen = dblen - ++i; |
152 | if (tlen < mlen) | 160 | if (tlen < mlen) |
153 | { | 161 | { |
154 | RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); | 162 | RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); |