Merge branch 'master' of git.openssl.org:openssl
[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
97         env = cms_get0_enveloped(cms);
98         if (!env)
99                 return NULL;
100
101         if (wrap_nid <= 0)
102                 wrap_nid = NID_id_alg_PWRI_KEK;
103
104         if (pbe_nid <= 0)
105                 pbe_nid = NID_id_pbkdf2;
106
107         /* Get from enveloped data */
108         if (kekciph == NULL)
109                 kekciph = env->encryptedContentInfo->cipher;
110
111         if (kekciph == NULL)
112                 {
113                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
114                 return NULL;
115                 }
116         if (wrap_nid != NID_id_alg_PWRI_KEK)
117                 {
118                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
119                                 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
120                 return NULL;
121                 }
122
123         /* Setup algorithm identifier for cipher */
124         encalg = X509_ALGOR_new();
125         EVP_CIPHER_CTX_init(&ctx);
126
127         if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0)
128                 {
129                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
130                 goto err;
131                 }
132
133         ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
134
135         if (ivlen > 0)
136                 {
137                 if (RAND_pseudo_bytes(iv, ivlen) <= 0)
138                         goto err;
139                 if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0)
140                         {
141                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
142                                                         ERR_R_EVP_LIB);
143                         goto err;
144                         }
145                 encalg->parameter = ASN1_TYPE_new();
146                 if (!encalg->parameter)
147                         {
148                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
149                                                         ERR_R_MALLOC_FAILURE);
150                         goto err;
151                         }
152                 if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0)
153                         {
154                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
155                                 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
156                         goto err;
157                         }
158                 }
159
160
161         encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx));
162
163         EVP_CIPHER_CTX_cleanup(&ctx);
164
165         /* Initialize recipient info */
166         ri = M_ASN1_new_of(CMS_RecipientInfo);
167         if (!ri)
168                 goto merr;
169
170         ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
171         if (!ri->d.pwri)
172                 goto merr;
173         ri->type = CMS_RECIPINFO_PASS;
174
175         pwri = ri->d.pwri;
176         /* Since this is overwritten, free up empty structure already there */
177         X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
178         pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
179         if (!pwri->keyEncryptionAlgorithm)
180                 goto merr;
181         pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
182         pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
183         if (!pwri->keyEncryptionAlgorithm->parameter)
184                 goto merr;
185
186         if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
187             &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
188                 goto merr;
189         pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
190
191         X509_ALGOR_free(encalg);
192         encalg = NULL;
193
194         /* Setup PBE algorithm */
195
196         pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
197
198         if (!pwri->keyDerivationAlgorithm)
199                 goto err;
200
201         CMS_RecipientInfo_set0_password(ri, pass, passlen);
202         pwri->version = 0;
203
204         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
205                 goto merr;
206
207         return ri;
208
209         merr:
210         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
211         err:
212         EVP_CIPHER_CTX_cleanup(&ctx);
213         if (ri)
214                 M_ASN1_free_of(ri, CMS_RecipientInfo);
215         if (encalg)
216                 X509_ALGOR_free(encalg);
217         return NULL;
218
219         }
220
221 /* This is an implementation of the key wrapping mechanism in RFC3211,
222  * at some point this should go into EVP.
223  */
224
225 static int kek_unwrap_key(unsigned char *out, size_t *outlen,
226                 const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
227         {
228         size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
229         unsigned char *tmp;
230         int outl, rv = 0;
231         if (inlen < 2 * blocklen)
232                 {
233                 /* too small */
234                 return 0;
235                 }
236         if (inlen % blocklen)
237                 {
238                 /* Invalid size */
239                 return 0;
240                 }
241         tmp = OPENSSL_malloc(inlen);
242         /* setup IV by decrypting last two blocks */
243         if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
244                                in  + inlen - 2 * blocklen, blocklen * 2)
245         /* Do a decrypt of last decrypted block to set IV to correct value
246          * output it to start of buffer so we don't corrupt decrypted block
247          * this works because buffer is at least two block lengths long.
248          */
249             || !EVP_DecryptUpdate(ctx, tmp, &outl,
250                                   tmp  + inlen - blocklen, blocklen)
251         /* Can now decrypt first n - 1 blocks */
252             || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen)
253
254         /* Reset IV to original value */
255             || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL)
256         /* Decrypt again */
257             || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen))
258                 goto err;
259         /* Check check bytes */
260         if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff)
261                 {
262                 /* Check byte failure */
263                 goto err;
264                 }
265         if (inlen < (size_t)(tmp[0] - 4 ))
266                 {
267                 /* Invalid length value */
268                 goto err;
269                 }
270         *outlen = (size_t)tmp[0];
271         memcpy(out, tmp + 4, *outlen);
272         rv = 1;
273         err:
274         OPENSSL_cleanse(tmp, inlen);
275         OPENSSL_free(tmp);
276         return rv;
277
278         }
279
280 static int kek_wrap_key(unsigned char *out, size_t *outlen,
281                 const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
282         {
283         size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
284         size_t olen;
285         int dummy;
286         /* First decide length of output buffer: need header and round up to
287          * multiple of block length.
288          */
289         olen = (inlen + 4 + blocklen - 1)/blocklen;
290         olen *= blocklen;
291         if (olen < 2 * blocklen)
292                 {
293                 /* Key too small */
294                 return 0;
295                 }
296         if (inlen > 0xFF)
297                 {
298                 /* Key too large */
299                 return 0;
300                 }
301         if (out)
302                 {
303                 /* Set header */
304                 out[0] = (unsigned char)inlen;
305                 out[1] = in[0] ^ 0xFF;
306                 out[2] = in[1] ^ 0xFF;
307                 out[3] = in[2] ^ 0xFF;
308                 memcpy(out + 4, in, inlen);
309                 /* Add random padding to end */
310                 if (olen > inlen + 4)
311                         RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen);
312                 /* Encrypt twice */
313                 if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen)
314                     || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen))
315                         return 0;
316                 }
317
318         *outlen = olen;
319
320         return 1;
321         }
322
323 /* Encrypt/Decrypt content key in PWRI recipient info */
324
325 int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
326                                                         int en_de)
327         {
328         CMS_EncryptedContentInfo *ec;
329         CMS_PasswordRecipientInfo *pwri;
330         const unsigned char *p = NULL;
331         int plen;
332         int r = 0;
333         X509_ALGOR *algtmp, *kekalg = NULL;
334         EVP_CIPHER_CTX kekctx;
335         const EVP_CIPHER *kekcipher;
336         unsigned char *key = NULL;
337         size_t keylen;
338
339         ec = cms->d.envelopedData->encryptedContentInfo;
340
341         pwri = ri->d.pwri;
342         EVP_CIPHER_CTX_init(&kekctx);
343
344         if (!pwri->pass)
345                 {
346                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
347                 return 0;
348                 }
349         algtmp = pwri->keyEncryptionAlgorithm;
350
351         if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK)
352                 {
353                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
354                                 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
355                 return 0;
356                 }
357
358         if (algtmp->parameter->type == V_ASN1_SEQUENCE)
359                 {
360                 p = algtmp->parameter->value.sequence->data;
361                 plen = algtmp->parameter->value.sequence->length;
362                 kekalg = d2i_X509_ALGOR(NULL, &p, plen);
363                 }
364         if (kekalg == NULL)
365                 {
366                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
367                                 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
368                 return 0;
369                 }
370
371         kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
372                 
373         if(!kekcipher)
374                 {
375                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
376                                 CMS_R_UNKNOWN_CIPHER);
377                 goto err;
378                 }
379
380         /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
381         if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
382                 goto err;
383         EVP_CIPHER_CTX_set_padding(&kekctx, 0);
384         if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0)
385                 {
386                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
387                                 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
388                 goto err;
389                 }
390
391         algtmp = pwri->keyDerivationAlgorithm;
392
393         /* Finish password based key derivation to setup key in "ctx" */
394
395         if (EVP_PBE_CipherInit(algtmp->algorithm,
396                                 (char *)pwri->pass, pwri->passlen,
397                                 algtmp->parameter, &kekctx, en_de) < 0)
398                 {
399                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
400                 goto err;
401                 }
402
403         /* Finally wrap/unwrap the key */
404
405         if (en_de)
406                 {
407
408                 if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
409                         goto err;
410
411                 key = OPENSSL_malloc(keylen);
412
413                 if (!key)
414                         goto err;
415
416                 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
417                         goto err;
418                 pwri->encryptedKey->data = key;
419                 pwri->encryptedKey->length = keylen;
420                 }
421         else
422                 {
423                 key = OPENSSL_malloc(pwri->encryptedKey->length);
424
425                 if (!key)
426                         {
427                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
428                                                         ERR_R_MALLOC_FAILURE);
429                         goto err;
430                         }
431                 if (!kek_unwrap_key(key, &keylen,
432                                         pwri->encryptedKey->data,
433                                         pwri->encryptedKey->length, &kekctx))
434                         {
435                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
436                                                         CMS_R_UNWRAP_FAILURE);
437                         goto err;
438                         }
439
440                 ec->key = key;
441                 ec->keylen = keylen;
442
443                 }
444
445         r = 1;
446
447         err:
448
449         EVP_CIPHER_CTX_cleanup(&kekctx);
450
451         if (!r && key)
452                 OPENSSL_free(key);
453         X509_ALGOR_free(kekalg);
454
455         return r;
456
457         }