1 |
Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness |
2 |
in PKCS7 code. When RSA decryption fails use a random key for |
3 |
content decryption and always return the same error. |
4 |
diff -up openssl-fips-0.9.8e/crypto/pkcs7/pk7_doit.c.pk7-mma openssl-fips-0.9.8e/crypto/pkcs7/pk7_doit.c |
5 |
--- openssl-fips-0.9.8e/crypto/pkcs7/pk7_doit.c.pk7-mma 2007-02-03 10:51:58.000000000 +0100 |
6 |
+++ openssl-fips-0.9.8e/crypto/pkcs7/pk7_doit.c 2012-03-19 17:51:35.879037258 +0100 |
7 |
@@ -423,6 +423,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE |
8 |
int max; |
9 |
X509_OBJECT ret; |
10 |
#endif |
11 |
+ unsigned char *tkey = NULL; |
12 |
+ int tkeylen; |
13 |
int jj; |
14 |
|
15 |
if ((etmp=BIO_new(BIO_f_cipher())) == NULL) |
16 |
@@ -464,36 +466,42 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE |
17 |
|
18 |
if (pcert == NULL) |
19 |
{ |
20 |
+ /* Temporary storage in case EVP_PKEY_decrypt |
21 |
+ * overwrites output buffer on error. |
22 |
+ */ |
23 |
+ unsigned char *tmp2; |
24 |
+ tmp2 = OPENSSL_malloc(jj); |
25 |
+ if (!tmp2) |
26 |
+ goto err; |
27 |
+ jj = -1; |
28 |
+ /* Always attempt to decrypt all cases to avoid |
29 |
+ * leaking timing information about a successful |
30 |
+ * decrypt. |
31 |
+ */ |
32 |
for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) |
33 |
{ |
34 |
+ int tret; |
35 |
ri=sk_PKCS7_RECIP_INFO_value(rsk,i); |
36 |
- jj=EVP_PKEY_decrypt(tmp, |
37 |
+ tret=EVP_PKEY_decrypt(tmp2, |
38 |
M_ASN1_STRING_data(ri->enc_key), |
39 |
M_ASN1_STRING_length(ri->enc_key), |
40 |
pkey); |
41 |
- if (jj > 0) |
42 |
- break; |
43 |
+ if (tret > 0) |
44 |
+ { |
45 |
+ memcpy(tmp, tmp2, tret); |
46 |
+ OPENSSL_cleanse(tmp2, tret); |
47 |
+ jj = tret; |
48 |
+ } |
49 |
ERR_clear_error(); |
50 |
- ri = NULL; |
51 |
- } |
52 |
- if (ri == NULL) |
53 |
- { |
54 |
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
55 |
- PKCS7_R_NO_RECIPIENT_MATCHES_KEY); |
56 |
- goto err; |
57 |
} |
58 |
+ OPENSSL_free(tmp2); |
59 |
} |
60 |
else |
61 |
{ |
62 |
jj=EVP_PKEY_decrypt(tmp, |
63 |
M_ASN1_STRING_data(ri->enc_key), |
64 |
M_ASN1_STRING_length(ri->enc_key), pkey); |
65 |
- if (jj <= 0) |
66 |
- { |
67 |
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
68 |
- ERR_R_EVP_LIB); |
69 |
- goto err; |
70 |
- } |
71 |
+ ERR_clear_error(); |
72 |
} |
73 |
|
74 |
evp_ctx=NULL; |
75 |
@@ -502,24 +510,49 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKE |
76 |
goto err; |
77 |
if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) |
78 |
goto err; |
79 |
+ /* Generate random key to counter MMA */ |
80 |
+ tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); |
81 |
+ tkey = OPENSSL_malloc(tkeylen); |
82 |
+ if (!tkey) |
83 |
+ goto err; |
84 |
+ if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) |
85 |
+ goto err; |
86 |
+ /* If we have no key use random key */ |
87 |
+ if (jj <= 0) |
88 |
+ { |
89 |
+ OPENSSL_free(tmp); |
90 |
+ jj = tkeylen; |
91 |
+ tmp = tkey; |
92 |
+ tkey = NULL; |
93 |
+ } |
94 |
|
95 |
- if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { |
96 |
+ if (jj != tkeylen) { |
97 |
/* Some S/MIME clients don't use the same key |
98 |
* and effective key length. The key length is |
99 |
* determined by the size of the decrypted RSA key. |
100 |
*/ |
101 |
if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) |
102 |
{ |
103 |
- PKCS7err(PKCS7_F_PKCS7_DATADECODE, |
104 |
- PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); |
105 |
- goto err; |
106 |
+ /* As MMA defence use random key instead */ |
107 |
+ OPENSSL_cleanse(tmp, jj); |
108 |
+ OPENSSL_free(tmp); |
109 |
+ jj = tkeylen; |
110 |
+ tmp = tkey; |
111 |
+ tkey = NULL; |
112 |
} |
113 |
} |
114 |
+ ERR_clear_error(); |
115 |
if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) |
116 |
goto err; |
117 |
|
118 |
OPENSSL_cleanse(tmp,jj); |
119 |
|
120 |
+ if (tkey) |
121 |
+ { |
122 |
+ OPENSSL_cleanse(tkey, tkeylen); |
123 |
+ OPENSSL_free(tkey); |
124 |
+ } |
125 |
+ |
126 |
if (out == NULL) |
127 |
out=etmp; |
128 |
else |