1 |
wellsi |
1.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 |