Import OpenSSL-1.0.1i.
[dragonfly.git] / crypto / openssl / 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         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         /* 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                 EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
313                 EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
314                 }
315
316         *outlen = olen;
317
318         return 1;
319         }
320
321 /* Encrypt/Decrypt content key in PWRI recipient info */
322
323 int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
324                                                         int en_de)
325         {
326         CMS_EncryptedContentInfo *ec;
327         CMS_PasswordRecipientInfo *pwri;
328         const unsigned char *p = NULL;
329         int plen;
330         int r = 0;
331         X509_ALGOR *algtmp, *kekalg = NULL;
332         EVP_CIPHER_CTX kekctx;
333         const EVP_CIPHER *kekcipher;
334         unsigned char *key = NULL;
335         size_t keylen;
336
337         ec = cms->d.envelopedData->encryptedContentInfo;
338
339         pwri = ri->d.pwri;
340         EVP_CIPHER_CTX_init(&kekctx);
341
342         if (!pwri->pass)
343                 {
344                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
345                 return 0;
346                 }
347         algtmp = pwri->keyEncryptionAlgorithm;
348
349         if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK)
350                 {
351                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
352                                 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
353                 return 0;
354                 }
355
356         if (algtmp->parameter->type == V_ASN1_SEQUENCE)
357                 {
358                 p = algtmp->parameter->value.sequence->data;
359                 plen = algtmp->parameter->value.sequence->length;
360                 kekalg = d2i_X509_ALGOR(NULL, &p, plen);
361                 }
362         if (kekalg == NULL)
363                 {
364                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
365                                 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
366                 return 0;
367                 }
368
369         kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
370                 
371         if(!kekcipher)
372                 {
373                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
374                                 CMS_R_UNKNOWN_CIPHER);
375                 goto err;
376                 }
377
378         /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
379         if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
380                 goto err;
381         EVP_CIPHER_CTX_set_padding(&kekctx, 0);
382         if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0)
383                 {
384                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
385                                 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
386                 goto err;
387                 }
388
389         algtmp = pwri->keyDerivationAlgorithm;
390
391         /* Finish password based key derivation to setup key in "ctx" */
392
393         if (EVP_PBE_CipherInit(algtmp->algorithm,
394                                 (char *)pwri->pass, pwri->passlen,
395                                 algtmp->parameter, &kekctx, en_de) < 0)
396                 {
397                 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
398                 goto err;
399                 }
400
401         /* Finally wrap/unwrap the key */
402
403         if (en_de)
404                 {
405
406                 if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
407                         goto err;
408
409                 key = OPENSSL_malloc(keylen);
410
411                 if (!key)
412                         goto err;
413
414                 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
415                         goto err;
416                 pwri->encryptedKey->data = key;
417                 pwri->encryptedKey->length = keylen;
418                 }
419         else
420                 {
421                 key = OPENSSL_malloc(pwri->encryptedKey->length);
422
423                 if (!key)
424                         {
425                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
426                                                         ERR_R_MALLOC_FAILURE);
427                         goto err;
428                         }
429                 if (!kek_unwrap_key(key, &keylen,
430                                         pwri->encryptedKey->data,
431                                         pwri->encryptedKey->length, &kekctx))
432                         {
433                         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
434                                                         CMS_R_UNWRAP_FAILURE);
435                         goto err;
436                         }
437
438                 ec->key = key;
439                 ec->keylen = keylen;
440
441                 }
442
443         r = 1;
444
445         err:
446
447         EVP_CIPHER_CTX_cleanup(&kekctx);
448
449         if (!r && key)
450                 OPENSSL_free(key);
451         X509_ALGOR_free(kekalg);
452
453         return r;
454
455         }