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); |
