Fix for CMS/PKCS7 MMA. If RSA decryption fails use a random key and
[openssl.git] / crypto / cms / cms_pwri.c
1 /* crypto/cms/cms_pwri.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2009 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 #include "cryptlib.h"
55 #include <openssl/asn1t.h>
56 #include <openssl/pem.h>
57 #include <openssl/x509v3.h>
58 #include <openssl/err.h>
59 #include <openssl/cms.h>
60 #include <openssl/rand.h>
61 #include <openssl/aes.h>
62 #include "cms_lcl.h"
63 #include "asn1_locl.h"
64
65 int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, 
66                                 unsigned char *pass, ossl_ssize_t passlen)
67         {
68         CMS_PasswordRecipientInfo *pwri;
69         if (ri->type != CMS_RECIPINFO_PASS)
70                 {
71                 CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
72                 return 0;
73                 }
74
75         pwri = ri->d.pwri;
76         pwri->pass = pass;
77         if (pass && passlen < 0)
78                 passlen = strlen((char *)pass);
79         pwri->passlen = passlen;
80         return 1;
81         }
82
83 CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
84                                         int iter, int wrap_nid, int pbe_nid,
85                                         unsigned char *pass,
86                                         ossl_ssize_t passlen,
87                                         const EVP_CIPHER *kekciph)
88         {
89         CMS_RecipientInfo *ri = NULL;
90         CMS_EnvelopedData *env;
91         CMS_PasswordRecipientInfo *pwri;
92         EVP_CIPHER_CTX ctx;
93         X509_ALGOR *encalg = NULL;
94         unsigned char iv[EVP_MAX_IV_LENGTH];
95         int ivlen;
96         env = cms_get0_enveloped(cms);
97         if (!env)
98                 goto err;
99
100         if (wrap_nid <= 0)
101                 wrap_nid = NID_id_alg_PWRI_KEK;
102
103         if (pbe_nid <= 0)
104                 pbe_nid = NID_id_pbkdf2;
105
106         /* Get from enveloped data */
107         if (kekciph == NULL)
108                 kekciph = env->encryptedContentInfo->cipher;
109
110         if (kekciph == NULL)
111                 {
112                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
113                 return NULL;
114                 }
115         if (wrap_nid != NID_id_alg_PWRI_KEK)
116                 {
117                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
118                                 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
119                 return NULL;
120                 }
121
122         /* Setup algorithm identifier for cipher */
123         encalg = X509_ALGOR_new();
124         EVP_CIPHER_CTX_init(&ctx);
125
126         if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0)
127                 {
128                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
129                 goto err;
130                 }
131
132         ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
133
134         if (ivlen > 0)
135                 {
136                 if (RAND_pseudo_bytes(iv, ivlen) <= 0)
137                         goto err;
138                 if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0)
139                         {
140                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
141                                                         ERR_R_EVP_LIB);
142                         goto err;
143                         }
144                 encalg->parameter = ASN1_TYPE_new();
145                 if (!encalg->parameter)
146                         {
147                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
148                                                         ERR_R_MALLOC_FAILURE);
149                         goto err;
150                         }
151                 if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0)
152                         {
153                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
154                                 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
155                         goto err;
156                         }
157                 }
158
159
160         encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx));
161
162         EVP_CIPHER_CTX_cleanup(&ctx);
163
164         /* Initialize recipient info */
165         ri = M_ASN1_new_of(CMS_RecipientInfo);
166         if (!ri)
167                 goto merr;
168
169         ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
170         if (!ri->d.pwri)
171                 goto merr;
172         ri->type = CMS_RECIPINFO_PASS;
173
174         pwri = ri->d.pwri;
175         /* Since this is overwritten, free up empty structure already there */
176         X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
177         pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
178         if (!pwri->keyEncryptionAlgorithm)
179                 goto merr;
180         pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
181         pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
182         if (!pwri->keyEncryptionAlgorithm->parameter)
183                 goto merr;
184
185         if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
186             &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
187                 goto merr;
188         pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
189
190         X509_ALGOR_free(encalg);
191         encalg = NULL;
192
193         /* Setup PBE algorithm */
194
195         pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
196
197         if (!pwri->keyDerivationAlgorithm)
198                 goto err;
199
200         CMS_RecipientInfo_set0_password(ri, pass, passlen);
201         pwri->version = 0;
202
203         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
204                 goto merr;
205
206         return ri;
207
208         merr:
209         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
210         err:
211         EVP_CIPHER_CTX_cleanup(&ctx);
212         if (ri)
213                 M_ASN1_free_of(ri, CMS_RecipientInfo);
214         if (encalg)
215                 X509_ALGOR_free(encalg);
216         return NULL;
217
218         }
219
220 /* This is an implementation of the key wrapping mechanism in RFC3211,
221  * at some point this should go into EVP.
222  */
223
224 static int kek_unwrap_key(unsigned char *out, size_t *outlen,
225                 const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
226         {
227         size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
228         unsigned char *tmp;
229         int outl, rv = 0;
230         if (inlen < 2 * blocklen)
231                 {
232                 /* too small */
233                 return 0;
234                 }
235         if (inlen % blocklen)
236                 {
237                 /* Invalid size */
238                 return 0;
239                 }
240         tmp = OPENSSL_malloc(inlen);
241         /* setup IV by decrypting last two blocks */
242         if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
243                                in  + inlen - 2 * blocklen, blocklen * 2)
244         /* Do a decrypt of last decrypted block to set IV to correct value
245          * output it to start of buffer so we don't corrupt decrypted block
246          * this works because buffer is at least two block lengths long.
247          */
248             || !EVP_DecryptUpdate(ctx, tmp, &outl,
249                                   tmp  + inlen - blocklen, blocklen)
250         /* Can now decrypt first n - 1 blocks */
251             || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen)
252
253         /* Reset IV to original value */
254             || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL)
255         /* Decrypt again */
256             || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen))
257                 goto err;
258         /* Check check bytes */
259         if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff)
260                 {
261                 /* Check byte failure */
262                 goto err;
263                 }
264         if (inlen < (size_t)(tmp[0] - 4 ))
265                 {
266                 /* Invalid length value */
267                 goto err;
268                 }
269         *outlen = (size_t)tmp[0];
270         memcpy(out, tmp + 4, *outlen);
271         rv = 1;
272         err:
273         OPENSSL_cleanse(tmp, inlen);
274         OPENSSL_free(tmp);
275         return rv;
276
277         }
278
279 static int kek_wrap_key(unsigned char *out, size_t *outlen,
280                 const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
281         {
282         size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
283         size_t olen;
284         int dummy;
285         /* First decide length of output buffer: need header and round up to
286          * multiple of block length.
287          */
288         olen = (inlen + 4 + blocklen - 1)/blocklen;
289         olen *= blocklen;
290         if (olen < 2 * blocklen)
291                 {
292                 /* Key too small */
293                 return 0;
294                 }
295         if (inlen > 0xFF)
296                 {
297                 /* Key too large */
298                 return 0;
299                 }
300         if (out)
301                 {
302                 /* Set header */
303                 out[0] = (unsigned char)inlen;
304                 out[1] = in[0] ^ 0xFF;
305                 out[2] = in[1] ^ 0xFF;
306                 out[3] = in[2] ^ 0xFF;
307                 memcpy(out + 4, in, inlen);
308                 /* Add random padding to end */
309                 if (olen > inlen + 4)
310                         RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen);
311                 /* Encrypt twice */
312                 if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen)
313                     || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen))
314                         return 0;
315                 }
316
317         *outlen = olen;
318
319         return 1;
320         }
321
322 /* Encrypt/Decrypt content key in PWRI recipient info */
323
324 int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
325                                                         int en_de)
326         {
327         CMS_EncryptedContentInfo *ec;
328         CMS_PasswordRecipientInfo *pwri;
329         const unsigned char *p = NULL;
330         int plen;
331         int r = 0;
332         X509_ALGOR *algtmp, *kekalg = NULL;
333         EVP_CIPHER_CTX kekctx;
334         const EVP_CIPHER *kekcipher;
335         unsigned char *key = NULL;
336         size_t keylen;
337
338         ec = cms->d.envelopedData->encryptedContentInfo;
339
340         pwri = ri->d.pwri;
341         EVP_CIPHER_CTX_init(&kekctx);
342
343         if (!pwri->pass)
344                 {
345                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
346                 return 0;
347                 }
348         algtmp = pwri->keyEncryptionAlgorithm;
349
350         if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK)
351                 {
352                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
353                                 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
354                 return 0;
355                 }
356
357         if (algtmp->parameter->type == V_ASN1_SEQUENCE)
358                 {
359                 p = algtmp->parameter->value.sequence->data;
360                 plen = algtmp->parameter->value.sequence->length;
361                 kekalg = d2i_X509_ALGOR(NULL, &p, plen);
362                 }
363         if (kekalg == NULL)
364                 {
365                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
366                                 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
367                 return 0;
368                 }
369
370         kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
371                 
372         if(!kekcipher)
373                 {
374                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
375                                 CMS_R_UNKNOWN_CIPHER);
376                 goto err;
377                 }
378
379         /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
380         if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
381                 goto err;
382         EVP_CIPHER_CTX_set_padding(&kekctx, 0);
383         if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0)
384                 {
385                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
386                                 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
387                 goto err;
388                 }
389
390         algtmp = pwri->keyDerivationAlgorithm;
391
392         /* Finish password based key derivation to setup key in "ctx" */
393
394         if (EVP_PBE_CipherInit(algtmp->algorithm,
395                                 (char *)pwri->pass, pwri->passlen,
396                                 algtmp->parameter, &kekctx, en_de) < 0)
397                 {
398                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
399                 goto err;
400                 }
401
402         /* Finally wrap/unwrap the key */
403
404         if (en_de)
405                 {
406
407                 if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
408                         goto err;
409
410                 key = OPENSSL_malloc(keylen);
411
412                 if (!key)
413                         goto err;
414
415                 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
416                         goto err;
417                 pwri->encryptedKey->data = key;
418                 pwri->encryptedKey->length = keylen;
419                 }
420         else
421                 {
422                 key = OPENSSL_malloc(pwri->encryptedKey->length);
423
424                 if (!key)
425                         {
426                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
427                                                         ERR_R_MALLOC_FAILURE);
428                         goto err;
429                         }
430                 if (!kek_unwrap_key(key, &keylen,
431                                         pwri->encryptedKey->data,
432                                         pwri->encryptedKey->length, &kekctx))
433                         {
434                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
435                                                         CMS_R_UNWRAP_FAILURE);
436                         goto err;
437                         }
438
439                 ec->key = key;
440                 ec->keylen = keylen;
441
442                 }
443
444         r = 1;
445
446         err:
447
448         EVP_CIPHER_CTX_cleanup(&kekctx);
449
450         if (!r && key)
451                 OPENSSL_free(key);
452         X509_ALGOR_free(kekalg);
453
454         return r;
455
456         }