69e7730f3c851103b2301a28835ee8fe535475d0
[metze/samba/wip.git] / source / heimdal / lib / hx509 / cms.c
1 /*
2  * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "hx_locl.h"
35 RCSID("$Id: cms.c 23268 2008-06-23 03:23:47Z lha $");
36
37 /**
38  * @page page_cms CMS/PKCS7 message functions.
39  *
40  * CMS is defined in RFC 3369 and is an continuation of the RSA Labs
41  * standard PKCS7. The basic messages in CMS is 
42  *
43  * - SignedData
44  *   Data signed with private key (RSA, DSA, ECDSA) or secret
45  *   (symmetric) key
46  * - EnvelopedData
47  *   Data encrypted with private key (RSA)
48  * - EncryptedData
49  *   Data encrypted with secret (symmetric) key.
50  * - ContentInfo
51  *   Wrapper structure including type and data.
52  *
53  *
54  * See the library functions here: @ref hx509_cms
55  */
56
57 #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
58 #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
59
60 /**
61  * Wrap data and oid in a ContentInfo and encode it.
62  *
63  * @param oid type of the content.
64  * @param buf data to be wrapped. If a NULL pointer is passed in, the
65  * optional content field in the ContentInfo is not going be filled
66  * in.
67  * @param res the encoded buffer, the result should be freed with
68  * der_free_octet_string().
69  *
70  * @return Returns an hx509 error code.
71  * 
72  * @ingroup hx509_cms
73  */
74
75 int
76 hx509_cms_wrap_ContentInfo(const heim_oid *oid,
77                            const heim_octet_string *buf,
78                            heim_octet_string *res)
79 {
80     ContentInfo ci;
81     size_t size;
82     int ret;
83
84     memset(res, 0, sizeof(*res));
85     memset(&ci, 0, sizeof(ci));
86
87     ret = der_copy_oid(oid, &ci.contentType);
88     if (ret)
89         return ret;
90     if (buf) {
91         ALLOC(ci.content, 1);
92         if (ci.content == NULL) {
93             free_ContentInfo(&ci);
94             return ENOMEM;
95         }
96         ci.content->data = malloc(buf->length);
97         if (ci.content->data == NULL) {
98             free_ContentInfo(&ci);
99             return ENOMEM;
100         }
101         memcpy(ci.content->data, buf->data, buf->length);
102         ci.content->length = buf->length;
103     }
104
105     ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret);
106     free_ContentInfo(&ci);
107     if (ret)
108         return ret;
109     if (res->length != size)
110         _hx509_abort("internal ASN.1 encoder error");
111
112     return 0;
113 }
114
115 /**
116  * Decode an ContentInfo and unwrap data and oid it.
117  *
118  * @param in the encoded buffer.
119  * @param oid type of the content.
120  * @param out data to be wrapped.
121  * @param have_data since the data is optional, this flags show dthe
122  * diffrence between no data and the zero length data.
123  *
124  * @return Returns an hx509 error code.
125  * 
126  * @ingroup hx509_cms
127  */
128
129 int
130 hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
131                              heim_oid *oid,
132                              heim_octet_string *out,
133                              int *have_data)
134 {
135     ContentInfo ci;
136     size_t size;
137     int ret;
138
139     memset(oid, 0, sizeof(*oid));
140     memset(out, 0, sizeof(*out));
141
142     ret = decode_ContentInfo(in->data, in->length, &ci, &size);
143     if (ret)
144         return ret;
145
146     ret = der_copy_oid(&ci.contentType, oid);
147     if (ret) {
148         free_ContentInfo(&ci);
149         return ret;
150     }
151     if (ci.content) {
152         ret = der_copy_octet_string(ci.content, out);
153         if (ret) {
154             der_free_oid(oid);
155             free_ContentInfo(&ci);
156             return ret;
157         }
158     } else
159         memset(out, 0, sizeof(*out));
160
161     if (have_data)
162         *have_data = (ci.content != NULL) ? 1 : 0;
163
164     free_ContentInfo(&ci);
165
166     return 0;
167 }
168
169 #define CMS_ID_SKI      0
170 #define CMS_ID_NAME     1
171
172 static int
173 fill_CMSIdentifier(const hx509_cert cert,
174                    int type,
175                    CMSIdentifier *id)
176 {
177     int ret;
178
179     switch (type) {
180     case CMS_ID_SKI:
181         id->element = choice_CMSIdentifier_subjectKeyIdentifier;
182         ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
183                                                    &id->u.subjectKeyIdentifier);
184         if (ret == 0)
185             break;
186         /* FALL THOUGH */
187     case CMS_ID_NAME: {
188         hx509_name name;
189
190         id->element = choice_CMSIdentifier_issuerAndSerialNumber;
191         ret = hx509_cert_get_issuer(cert, &name);
192         if (ret)
193             return ret;
194         ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
195         hx509_name_free(&name);
196         if (ret)
197             return ret;
198
199         ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
200         break;
201     }
202     default:
203         _hx509_abort("CMS fill identifier with unknown type");
204     }
205     return ret;
206 }
207
208 static int
209 unparse_CMSIdentifier(hx509_context context,
210                       CMSIdentifier *id,
211                       char **str)
212 {
213     int ret;
214
215     *str = NULL;
216     switch (id->element) {
217     case choice_CMSIdentifier_issuerAndSerialNumber: {
218         IssuerAndSerialNumber *iasn;
219         char *serial, *name;
220
221         iasn = &id->u.issuerAndSerialNumber;
222
223         ret = _hx509_Name_to_string(&iasn->issuer, &name);
224         if(ret)
225             return ret;
226         ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial);
227         if (ret) {
228             free(name);
229             return ret;
230         }
231         asprintf(str, "certificate issued by %s with serial number %s",
232                  name, serial);
233         free(name);
234         free(serial);
235         break;
236     }
237     case choice_CMSIdentifier_subjectKeyIdentifier: {
238         KeyIdentifier *ki  = &id->u.subjectKeyIdentifier;
239         char *keyid;
240         ssize_t len;
241
242         len = hex_encode(ki->data, ki->length, &keyid);
243         if (len < 0)
244             return ENOMEM;
245
246         asprintf(str, "certificate with id %s", keyid);
247         free(keyid);
248         break;
249     }
250     default:
251         asprintf(str, "certificate have unknown CMSidentifier type");
252         break;
253     }
254     if (*str == NULL)
255         return ENOMEM;
256     return 0;
257 }
258
259 static int
260 find_CMSIdentifier(hx509_context context,
261                    CMSIdentifier *client,
262                    hx509_certs certs,
263                    time_t time_now,
264                    hx509_cert *signer_cert,
265                    int match)
266 {
267     hx509_query q;
268     hx509_cert cert;
269     Certificate c;
270     int ret;
271
272     memset(&c, 0, sizeof(c));
273     _hx509_query_clear(&q);
274
275     *signer_cert = NULL;
276
277     switch (client->element) {
278     case choice_CMSIdentifier_issuerAndSerialNumber:
279         q.serial = &client->u.issuerAndSerialNumber.serialNumber;
280         q.issuer_name = &client->u.issuerAndSerialNumber.issuer;
281         q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
282         break;
283     case choice_CMSIdentifier_subjectKeyIdentifier:
284         q.subject_id = &client->u.subjectKeyIdentifier;
285         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
286         break;
287     default:
288         hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE,
289                                "unknown CMS identifier element");
290         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
291     }
292
293     q.match |= match;
294
295     q.match |= HX509_QUERY_MATCH_TIME;
296     if (time_now)
297         q.timenow = time_now;
298     else
299         q.timenow = time(NULL);
300
301     ret = hx509_certs_find(context, certs, &q, &cert);
302     if (ret == HX509_CERT_NOT_FOUND) {
303         char *str;
304
305         ret = unparse_CMSIdentifier(context, client, &str);
306         if (ret == 0) {
307             hx509_set_error_string(context, 0,
308                                    HX509_CMS_NO_RECIPIENT_CERTIFICATE,
309                                    "Failed to find %s", str);
310         } else
311             hx509_clear_error_string(context);
312         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
313     } else if (ret) {
314         hx509_set_error_string(context, HX509_ERROR_APPEND,
315                                HX509_CMS_NO_RECIPIENT_CERTIFICATE,
316                                "Failed to find CMS id in cert store");
317         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
318     }
319
320     *signer_cert = cert;
321
322     return 0;
323 }
324
325 /**
326  * Decode and unencrypt EnvelopedData.
327  *
328  * Extract data and parameteres from from the EnvelopedData. Also
329  * supports using detached EnvelopedData.
330  *
331  * @param context A hx509 context.
332  * @param certs Certificate that can decrypt the EnvelopedData
333  * encryption key.
334  * @param flags HX509_CMS_UE flags to control the behavior.
335  * @param data pointer the structure the contains the DER/BER encoded
336  * EnvelopedData stucture.
337  * @param length length of the data that data point to.
338  * @param encryptedContent in case of detached signature, this
339  * contains the actual encrypted data, othersize its should be NULL.
340  * @param time_now set the current time, if zero the library uses now as the date.
341  * @param contentType output type oid, should be freed with der_free_oid().
342  * @param content the data, free with der_free_octet_string().
343  *
344  * @ingroup hx509_cms
345  */
346
347 int
348 hx509_cms_unenvelope(hx509_context context,
349                      hx509_certs certs,
350                      int flags,
351                      const void *data,
352                      size_t length,
353                      const heim_octet_string *encryptedContent,
354                      time_t time_now,
355                      heim_oid *contentType,
356                      heim_octet_string *content)
357 {
358     heim_octet_string key;
359     EnvelopedData ed;
360     hx509_cert cert;
361     AlgorithmIdentifier *ai;
362     const heim_octet_string *enccontent;
363     heim_octet_string *params, params_data;
364     heim_octet_string ivec;
365     size_t size;
366     int ret, i, matched = 0, findflags = 0;
367
368
369     memset(&key, 0, sizeof(key));
370     memset(&ed, 0, sizeof(ed));
371     memset(&ivec, 0, sizeof(ivec));
372     memset(content, 0, sizeof(*content));
373     memset(contentType, 0, sizeof(*contentType));
374
375     if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0)
376         findflags |= HX509_QUERY_KU_ENCIPHERMENT;
377
378     ret = decode_EnvelopedData(data, length, &ed, &size);
379     if (ret) {
380         hx509_set_error_string(context, 0, ret,
381                                "Failed to decode EnvelopedData");
382         return ret;
383     }
384
385     if (ed.recipientInfos.len == 0) {
386         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
387         hx509_set_error_string(context, 0, ret,
388                                "No recipient info in enveloped data");
389         goto out;
390     }
391
392     enccontent = ed.encryptedContentInfo.encryptedContent;
393     if (enccontent == NULL) {
394         if (encryptedContent == NULL) {
395             ret = HX509_CMS_NO_DATA_AVAILABLE;
396             hx509_set_error_string(context, 0, ret,
397                                    "Content missing from encrypted data");
398             goto out;
399         }
400         enccontent = encryptedContent;
401     } else if (encryptedContent != NULL) {
402         ret = HX509_CMS_NO_DATA_AVAILABLE;
403         hx509_set_error_string(context, 0, ret,
404                                "Both internal and external encrypted data");
405         goto out;
406     }
407
408     cert = NULL;
409     for (i = 0; i < ed.recipientInfos.len; i++) {
410         KeyTransRecipientInfo *ri;
411         char *str;
412         int ret2;
413
414         ri = &ed.recipientInfos.val[i];
415
416         ret = find_CMSIdentifier(context, &ri->rid, certs,
417                                  time_now, &cert,
418                                  HX509_QUERY_PRIVATE_KEY|findflags);
419         if (ret)
420             continue;
421
422         matched = 1; /* found a matching certificate, let decrypt */
423
424         ret = _hx509_cert_private_decrypt(context,
425                                           &ri->encryptedKey,
426                                           &ri->keyEncryptionAlgorithm.algorithm,
427                                           cert, &key);
428
429         hx509_cert_free(cert);
430         if (ret == 0)
431             break; /* succuessfully decrypted cert */
432         cert = NULL;
433         ret2 = unparse_CMSIdentifier(context, &ri->rid, &str);
434         if (ret2 == 0) {
435             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
436                                    "Failed to decrypt with %s", str);
437             free(str);
438         }
439     }
440
441     if (!matched) {
442         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
443         hx509_set_error_string(context, 0, ret,
444                                "No private key matched any certificate");
445         goto out;
446     }
447
448     if (cert == NULL) {
449         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
450         hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
451                                "No private key decrypted the transfer key");
452         goto out;
453     }
454
455     ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);
456     if (ret) {
457         hx509_set_error_string(context, 0, ret,
458                                "Failed to copy EnvelopedData content oid");
459         goto out;
460     }
461
462     ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
463     if (ai->parameters) {
464         params_data.data = ai->parameters->data;
465         params_data.length = ai->parameters->length;
466         params = &params_data;
467     } else
468         params = NULL;
469
470     {
471         hx509_crypto crypto;
472
473         ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto);
474         if (ret)
475             goto out;
476         
477         if (params) {
478             ret = hx509_crypto_set_params(context, crypto, params, &ivec);
479             if (ret) {
480                 hx509_crypto_destroy(crypto);
481                 goto out;
482             }
483         }
484
485         ret = hx509_crypto_set_key_data(crypto, key.data, key.length);
486         if (ret) {
487             hx509_crypto_destroy(crypto);
488             hx509_set_error_string(context, 0, ret,
489                                    "Failed to set key for decryption "
490                                    "of EnvelopedData");
491             goto out;
492         }
493         
494         ret = hx509_crypto_decrypt(crypto,
495                                    enccontent->data,
496                                    enccontent->length,
497                                    ivec.length ? &ivec : NULL,
498                                    content);
499         hx509_crypto_destroy(crypto);
500         if (ret) {
501             hx509_set_error_string(context, 0, ret,
502                                    "Failed to decrypt EnvelopedData");
503             goto out;
504         }
505     }
506
507 out:
508
509     free_EnvelopedData(&ed);
510     der_free_octet_string(&key);
511     if (ivec.length)
512         der_free_octet_string(&ivec);
513     if (ret) {
514         der_free_oid(contentType);
515         der_free_octet_string(content);
516     }
517
518     return ret;
519 }
520
521 /**
522  * Encrypt end encode EnvelopedData.
523  *
524  * Encrypt and encode EnvelopedData. The data is encrypted with a
525  * random key and the the random key is encrypted with the
526  * certificates private key. This limits what private key type can be
527  * used to RSA.
528  *
529  * @param context A hx509 context.
530  * @param flags flags to control the behavior, no flags today
531  * @param cert Certificate to encrypt the EnvelopedData encryption key
532  * with.
533  * @param data pointer the data to encrypt.
534  * @param length length of the data that data point to.
535  * @param encryption_type Encryption cipher to use for the bulk data,
536  * use NULL to get default.
537  * @param contentType type of the data that is encrypted
538  * @param content the output of the function,
539  * free with der_free_octet_string().
540  *
541  * @ingroup hx509_cms
542  */
543
544 int
545 hx509_cms_envelope_1(hx509_context context,
546                      int flags,
547                      hx509_cert cert,
548                      const void *data,
549                      size_t length,
550                      const heim_oid *encryption_type,
551                      const heim_oid *contentType,
552                      heim_octet_string *content)
553 {
554     KeyTransRecipientInfo *ri;
555     heim_octet_string ivec;
556     heim_octet_string key;
557     hx509_crypto crypto = NULL;
558     EnvelopedData ed;
559     size_t size;
560     int ret;
561
562     memset(&ivec, 0, sizeof(ivec));
563     memset(&key, 0, sizeof(key));
564     memset(&ed, 0, sizeof(ed));
565     memset(content, 0, sizeof(*content));
566
567     if (encryption_type == NULL)
568         encryption_type = oid_id_aes_256_cbc();
569
570     ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE);
571     if (ret)
572         goto out;
573
574     ret = hx509_crypto_init(context, NULL, encryption_type, &crypto);
575     if (ret)
576         goto out;
577
578     ret = hx509_crypto_set_random_key(crypto, &key);
579     if (ret) {
580         hx509_set_error_string(context, 0, ret,
581                                "Create random key for EnvelopedData content");
582         goto out;
583     }
584
585     ret = hx509_crypto_random_iv(crypto, &ivec);
586     if (ret) {
587         hx509_set_error_string(context, 0, ret,
588                                "Failed to create a random iv");
589         goto out;
590     }
591
592     ret = hx509_crypto_encrypt(crypto,
593                                data,
594                                length,
595                                &ivec,
596                                &ed.encryptedContentInfo.encryptedContent);
597     if (ret) {
598         hx509_set_error_string(context, 0, ret,
599                                "Failed to encrypt EnvelopedData content");
600         goto out;
601     }
602
603     {
604         AlgorithmIdentifier *enc_alg;
605         enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
606         ret = der_copy_oid(encryption_type, &enc_alg->algorithm);
607         if (ret) {
608             hx509_set_error_string(context, 0, ret,
609                                    "Failed to set crypto oid "
610                                    "for EnvelopedData");
611             goto out;
612         }       
613         ALLOC(enc_alg->parameters, 1);
614         if (enc_alg->parameters == NULL) {
615             ret = ENOMEM;
616             hx509_set_error_string(context, 0, ret,
617                                    "Failed to allocate crypto paramaters "
618                                    "for EnvelopedData");
619             goto out;
620         }
621
622         ret = hx509_crypto_get_params(context,
623                                       crypto,
624                                       &ivec,
625                                       enc_alg->parameters);
626         if (ret) {
627             goto out;
628         }
629     }
630
631     ALLOC_SEQ(&ed.recipientInfos, 1);
632     if (ed.recipientInfos.val == NULL) {
633         ret = ENOMEM;
634         hx509_set_error_string(context, 0, ret,
635                                "Failed to allocate recipients info "
636                                "for EnvelopedData");
637         goto out;
638     }
639
640     ri = &ed.recipientInfos.val[0];
641
642     ri->version = 0;
643     ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid);
644     if (ret) {
645         hx509_set_error_string(context, 0, ret,
646                                "Failed to set CMS identifier info "
647                                "for EnvelopedData");
648         goto out;
649     }
650
651     ret = _hx509_cert_public_encrypt(context,
652                                      &key, cert,
653                                      &ri->keyEncryptionAlgorithm.algorithm,
654                                      &ri->encryptedKey);
655     if (ret) {
656         hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
657                                "Failed to encrypt transport key for "
658                                "EnvelopedData");
659         goto out;
660     }
661
662     /*
663      *
664      */
665
666     ed.version = 0;
667     ed.originatorInfo = NULL;
668
669     ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType);
670     if (ret) {
671         hx509_set_error_string(context, 0, ret,
672                                "Failed to copy content oid for "
673                                "EnvelopedData");
674         goto out;
675     }
676
677     ed.unprotectedAttrs = NULL;
678
679     ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length,
680                        &ed, &size, ret);
681     if (ret) {
682         hx509_set_error_string(context, 0, ret,
683                                "Failed to encode EnvelopedData");
684         goto out;
685     }
686     if (size != content->length)
687         _hx509_abort("internal ASN.1 encoder error");
688
689 out:
690     if (crypto)
691         hx509_crypto_destroy(crypto);
692     if (ret)
693         der_free_octet_string(content);
694     der_free_octet_string(&key);
695     der_free_octet_string(&ivec);
696     free_EnvelopedData(&ed);
697
698     return ret;
699 }
700
701 static int
702 any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
703 {
704     int ret, i;
705
706     if (sd->certificates == NULL)
707         return 0;
708
709     for (i = 0; i < sd->certificates->len; i++) {
710         hx509_cert c;
711
712         ret = hx509_cert_init_data(context, 
713                                    sd->certificates->val[i].data, 
714                                    sd->certificates->val[i].length,
715                                    &c);
716         if (ret)
717             return ret;
718         ret = hx509_certs_add(context, certs, c);
719         hx509_cert_free(c);
720         if (ret)
721             return ret;
722     }
723
724     return 0;
725 }
726
727 static const Attribute *
728 find_attribute(const CMSAttributes *attr, const heim_oid *oid)
729 {
730     int i;
731     for (i = 0; i < attr->len; i++)
732         if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0)
733             return &attr->val[i];
734     return NULL;
735 }
736
737 /**
738  * Decode SignedData and verify that the signature is correct.
739  *
740  * @param context A hx509 context.
741  * @param ctx a hx509 version context
742  * @param data
743  * @param length length of the data that data point to.
744  * @param signedContent
745  * @param pool certificate pool to build certificates paths.
746  * @param contentType free with der_free_oid()
747  * @param content the output of the function, free with
748  * der_free_octet_string().
749  * @param signer_certs list of the cerficates used to sign this
750  * request, free with hx509_certs_free().
751  *
752  * @ingroup hx509_cms
753  */
754
755 int
756 hx509_cms_verify_signed(hx509_context context,
757                         hx509_verify_ctx ctx,
758                         const void *data,
759                         size_t length,
760                         const heim_octet_string *signedContent,
761                         hx509_certs pool,
762                         heim_oid *contentType,
763                         heim_octet_string *content,
764                         hx509_certs *signer_certs)
765 {
766     SignerInfo *signer_info;
767     hx509_cert cert = NULL;
768     hx509_certs certs = NULL;
769     SignedData sd;
770     size_t size;
771     int ret, i, found_valid_sig;
772
773     *signer_certs = NULL;
774     content->data = NULL;
775     content->length = 0;
776     contentType->length = 0;
777     contentType->components = NULL;
778
779     memset(&sd, 0, sizeof(sd));
780
781     ret = decode_SignedData(data, length, &sd, &size);
782     if (ret) {
783         hx509_set_error_string(context, 0, ret,
784                                "Failed to decode SignedData");
785         goto out;
786     }
787
788     if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) {
789         ret = HX509_CMS_NO_DATA_AVAILABLE;
790         hx509_set_error_string(context, 0, ret,
791                                "No content data in SignedData");
792         goto out;
793     }
794     if (sd.encapContentInfo.eContent && signedContent) {
795         ret = HX509_CMS_NO_DATA_AVAILABLE;
796         hx509_set_error_string(context, 0, ret,
797                                "Both external and internal SignedData");
798         goto out;
799     }
800     if (sd.encapContentInfo.eContent)
801         signedContent = sd.encapContentInfo.eContent;
802
803     ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer",
804                            0, NULL, &certs);
805     if (ret)
806         goto out;
807
808     ret = hx509_certs_init(context, "MEMORY:cms-signer-certs",
809                            0, NULL, signer_certs);
810     if (ret)
811         goto out;
812
813     /* XXX Check CMS version */
814
815     ret = any_to_certs(context, &sd, certs);
816     if (ret)
817         goto out;
818
819     if (pool) {
820         ret = hx509_certs_merge(context, certs, pool);
821         if (ret)
822             goto out;
823     }
824
825     for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) {
826         heim_octet_string *signed_data;
827         const heim_oid *match_oid;
828         heim_oid decode_oid;
829
830         signer_info = &sd.signerInfos.val[i];
831         match_oid = NULL;
832
833         if (signer_info->signature.length == 0) {
834             ret = HX509_CMS_MISSING_SIGNER_DATA;
835             hx509_set_error_string(context, 0, ret,
836                                    "SignerInfo %d in SignedData "
837                                    "missing sigature", i);
838             continue;
839         }
840
841         ret = find_CMSIdentifier(context, &signer_info->sid, certs, 
842                                  _hx509_verify_get_time(ctx), &cert,
843                                  HX509_QUERY_KU_DIGITALSIGNATURE);
844         if (ret)
845             continue;
846
847         if (signer_info->signedAttrs) {
848             const Attribute *attr;
849         
850             CMSAttributes sa;
851             heim_octet_string os;
852
853             sa.val = signer_info->signedAttrs->val;
854             sa.len = signer_info->signedAttrs->len;
855
856             /* verify that sigature exists */
857             attr = find_attribute(&sa, oid_id_pkcs9_messageDigest());
858             if (attr == NULL) {
859                 ret = HX509_CRYPTO_SIGNATURE_MISSING;
860                 hx509_set_error_string(context, 0, ret,
861                                        "SignerInfo have signed attributes "
862                                        "but messageDigest (signature) "
863                                        "is missing");
864                 goto next_sigature;
865             }
866             if (attr->value.len != 1) {
867                 ret = HX509_CRYPTO_SIGNATURE_MISSING;
868                 hx509_set_error_string(context, 0, ret,
869                                        "SignerInfo have more then one "
870                                        "messageDigest (signature)");
871                 goto next_sigature;
872             }
873         
874             ret = decode_MessageDigest(attr->value.val[0].data,
875                                        attr->value.val[0].length,
876                                        &os,
877                                        &size);
878             if (ret) {
879                 hx509_set_error_string(context, 0, ret,
880                                        "Failed to decode "
881                                        "messageDigest (signature)");
882                 goto next_sigature;
883             }
884
885             ret = _hx509_verify_signature(context,
886                                           NULL,
887                                           &signer_info->digestAlgorithm,
888                                           signedContent,
889                                           &os);
890             der_free_octet_string(&os);
891             if (ret) {
892                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
893                                        "Failed to verify messageDigest");
894                 goto next_sigature;
895             }
896
897             /*
898              * Fetch content oid inside signedAttrs or set it to
899              * id-pkcs7-data.
900              */
901             attr = find_attribute(&sa, oid_id_pkcs9_contentType());
902             if (attr == NULL) {
903                 match_oid = oid_id_pkcs7_data();
904             } else {
905                 if (attr->value.len != 1) {
906                     ret = HX509_CMS_DATA_OID_MISMATCH;
907                     hx509_set_error_string(context, 0, ret,
908                                            "More then one oid in signedAttrs");
909                     goto next_sigature;
910
911                 }
912                 ret = decode_ContentType(attr->value.val[0].data,
913                                          attr->value.val[0].length,
914                                          &decode_oid,
915                                          &size);
916                 if (ret) {
917                     hx509_set_error_string(context, 0, ret,
918                                            "Failed to decode "
919                                            "oid in signedAttrs");
920                     goto next_sigature;
921                 }
922                 match_oid = &decode_oid;
923             }
924
925             ALLOC(signed_data, 1);
926             if (signed_data == NULL) {
927                 if (match_oid == &decode_oid)
928                     der_free_oid(&decode_oid);
929                 ret = ENOMEM;
930                 hx509_clear_error_string(context);
931                 goto next_sigature;
932             }
933         
934             ASN1_MALLOC_ENCODE(CMSAttributes,
935                                signed_data->data,
936                                signed_data->length,
937                                &sa,
938                                &size, ret);
939             if (ret) {
940                 if (match_oid == &decode_oid)
941                     der_free_oid(&decode_oid);
942                 free(signed_data);
943                 hx509_clear_error_string(context);
944                 goto next_sigature;
945             }
946             if (size != signed_data->length)
947                 _hx509_abort("internal ASN.1 encoder error");
948
949         } else {
950             signed_data = rk_UNCONST(signedContent);
951             match_oid = oid_id_pkcs7_data();
952         }
953
954         if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) {
955             ret = HX509_CMS_DATA_OID_MISMATCH;
956             hx509_set_error_string(context, 0, ret,
957                                    "Oid in message mismatch from the expected");
958         }
959         if (match_oid == &decode_oid)
960             der_free_oid(&decode_oid);
961
962         if (ret == 0) {
963             ret = hx509_verify_signature(context,
964                                          cert,
965                                          &signer_info->signatureAlgorithm,
966                                          signed_data,
967                                          &signer_info->signature);
968             if (ret)
969                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
970                                        "Failed to verify sigature in "
971                                        "CMS SignedData");
972         }
973         if (signed_data != signedContent) {
974             der_free_octet_string(signed_data);
975             free(signed_data);
976         }
977         if (ret)
978             goto next_sigature;
979
980         ret = hx509_verify_path(context, ctx, cert, certs);
981         if (ret)
982             goto next_sigature;
983
984         ret = hx509_certs_add(context, *signer_certs, cert);
985         if (ret)
986             goto next_sigature;
987
988         found_valid_sig++;
989
990     next_sigature:
991         if (cert)
992             hx509_cert_free(cert);
993         cert = NULL;
994     }
995     if (found_valid_sig == 0) {
996         if (ret == 0) {
997             ret = HX509_CMS_SIGNER_NOT_FOUND;
998             hx509_set_error_string(context, 0, ret,
999                                    "No signers where found");
1000         }
1001         goto out;
1002     }
1003
1004     ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType);
1005     if (ret) {
1006         hx509_clear_error_string(context);
1007         goto out;
1008     }
1009
1010     content->data = malloc(signedContent->length);
1011     if (content->data == NULL) {
1012         hx509_clear_error_string(context);
1013         ret = ENOMEM;
1014         goto out;
1015     }
1016     content->length = signedContent->length;
1017     memcpy(content->data, signedContent->data, content->length);
1018
1019 out:
1020     free_SignedData(&sd);
1021     if (certs)
1022         hx509_certs_free(&certs);
1023     if (ret) {
1024         if (*signer_certs)
1025             hx509_certs_free(signer_certs);
1026         der_free_oid(contentType);
1027         der_free_octet_string(content);
1028     }
1029
1030     return ret;
1031 }
1032
1033 static int
1034 add_one_attribute(Attribute **attr,
1035                   unsigned int *len,
1036                   const heim_oid *oid,
1037                   heim_octet_string *data)
1038 {
1039     void *d;
1040     int ret;
1041
1042     d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1));
1043     if (d == NULL)
1044         return ENOMEM;
1045     (*attr) = d;
1046
1047     ret = der_copy_oid(oid, &(*attr)[*len].type);
1048     if (ret)
1049         return ret;
1050
1051     ALLOC_SEQ(&(*attr)[*len].value, 1);
1052     if ((*attr)[*len].value.val == NULL) {
1053         der_free_oid(&(*attr)[*len].type);
1054         return ENOMEM;
1055     }
1056
1057     (*attr)[*len].value.val[0].data = data->data;
1058     (*attr)[*len].value.val[0].length = data->length;
1059
1060     *len += 1;
1061
1062     return 0;
1063 }
1064         
1065 /**
1066  * Decode SignedData and verify that the signature is correct.
1067  *
1068  * @param context A hx509 context.
1069  * @param flags
1070  * @param eContentType the type of the data.
1071  * @param data data to sign
1072  * @param length length of the data that data point to.
1073  * @param digest_alg digest algorithm to use, use NULL to get the
1074  * default or the peer determined algorithm.
1075  * @param cert certificate to use for sign the data.
1076  * @param peer info about the peer the message to send the message to,
1077  * like what digest algorithm to use.
1078  * @param anchors trust anchors that the client will use, used to
1079  * polulate the certificates included in the message
1080  * @param pool certificates to use in try to build the path to the
1081  * trust anchors.
1082  * @param signed_data the output of the function, free with
1083  * der_free_octet_string().
1084  *
1085  * @ingroup hx509_cms
1086  */
1087
1088 int
1089 hx509_cms_create_signed_1(hx509_context context,
1090                           int flags,
1091                           const heim_oid *eContentType,
1092                           const void *data, size_t length,
1093                           const AlgorithmIdentifier *digest_alg,
1094                           hx509_cert cert,
1095                           hx509_peer_info peer,
1096                           hx509_certs anchors,
1097                           hx509_certs pool,
1098                           heim_octet_string *signed_data)
1099 {
1100     AlgorithmIdentifier digest;
1101     hx509_name name;
1102     SignerInfo *signer_info;
1103     heim_octet_string buf, content, sigdata = { 0, NULL };
1104     SignedData sd;
1105     int ret;
1106     size_t size;
1107     hx509_path path;
1108     int cmsidflag = CMS_ID_SKI;
1109
1110     memset(&sd, 0, sizeof(sd));
1111     memset(&name, 0, sizeof(name));
1112     memset(&path, 0, sizeof(path));
1113     memset(&digest, 0, sizeof(digest));
1114
1115     content.data = rk_UNCONST(data);
1116     content.length = length;
1117
1118     if (flags & HX509_CMS_SIGATURE_ID_NAME)
1119         cmsidflag = CMS_ID_NAME;
1120
1121     if (_hx509_cert_private_key(cert) == NULL) {
1122         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1123                                "Private key missing for signing");
1124         return HX509_PRIVATE_KEY_MISSING;
1125     }
1126
1127     if (digest_alg == NULL) {
1128         ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
1129                                   _hx509_cert_private_key(cert), peer, &digest);
1130     } else {
1131         ret = copy_AlgorithmIdentifier(digest_alg, &digest);
1132         if (ret)
1133             hx509_clear_error_string(context);
1134     }
1135     if (ret)
1136         goto out;
1137
1138     sd.version = CMSVersion_v3;
1139
1140     if (eContentType == NULL)
1141         eContentType = oid_id_pkcs7_data();
1142
1143     der_copy_oid(eContentType, &sd.encapContentInfo.eContentType);
1144
1145     /* */
1146     if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) {
1147         ALLOC(sd.encapContentInfo.eContent, 1);
1148         if (sd.encapContentInfo.eContent == NULL) {
1149             hx509_clear_error_string(context);
1150             ret = ENOMEM;
1151             goto out;
1152         }
1153         
1154         sd.encapContentInfo.eContent->data = malloc(length);
1155         if (sd.encapContentInfo.eContent->data == NULL) {
1156             hx509_clear_error_string(context);
1157             ret = ENOMEM;
1158             goto out;
1159         }
1160         memcpy(sd.encapContentInfo.eContent->data, data, length);
1161         sd.encapContentInfo.eContent->length = length;
1162     }
1163
1164     ALLOC_SEQ(&sd.signerInfos, 1);
1165     if (sd.signerInfos.val == NULL) {
1166         hx509_clear_error_string(context);
1167         ret = ENOMEM;
1168         goto out;
1169     }
1170
1171     signer_info = &sd.signerInfos.val[0];
1172
1173     signer_info->version = 1;
1174
1175     ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
1176     if (ret) {
1177         hx509_clear_error_string(context);
1178         goto out;
1179     }                   
1180
1181     signer_info->signedAttrs = NULL;
1182     signer_info->unsignedAttrs = NULL;
1183
1184
1185     ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
1186     if (ret) {
1187         hx509_clear_error_string(context);
1188         goto out;
1189     }
1190
1191     /*
1192      * If it isn't pkcs7-data send signedAttributes
1193      */
1194
1195     if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) {
1196         CMSAttributes sa;       
1197         heim_octet_string sig;
1198
1199         ALLOC(signer_info->signedAttrs, 1);
1200         if (signer_info->signedAttrs == NULL) {
1201             ret = ENOMEM;
1202             goto out;
1203         }
1204
1205         ret = _hx509_create_signature(context,
1206                                       NULL,
1207                                       &digest,
1208                                       &content,
1209                                       NULL,
1210                                       &sig);
1211         if (ret)
1212             goto out;
1213
1214         ASN1_MALLOC_ENCODE(MessageDigest,
1215                            buf.data,
1216                            buf.length,
1217                            &sig,
1218                            &size,
1219                            ret);
1220         der_free_octet_string(&sig);
1221         if (ret) {
1222             hx509_clear_error_string(context);
1223             goto out;
1224         }
1225         if (size != buf.length)
1226             _hx509_abort("internal ASN.1 encoder error");
1227
1228         ret = add_one_attribute(&signer_info->signedAttrs->val,
1229                                 &signer_info->signedAttrs->len,
1230                                 oid_id_pkcs9_messageDigest(),
1231                                 &buf);
1232         if (ret) {
1233             hx509_clear_error_string(context);
1234             goto out;
1235         }
1236
1237
1238         ASN1_MALLOC_ENCODE(ContentType,
1239                            buf.data,
1240                            buf.length,
1241                            eContentType,
1242                            &size,
1243                            ret);
1244         if (ret)
1245             goto out;
1246         if (size != buf.length)
1247             _hx509_abort("internal ASN.1 encoder error");
1248
1249         ret = add_one_attribute(&signer_info->signedAttrs->val,
1250                                 &signer_info->signedAttrs->len,
1251                                 oid_id_pkcs9_contentType(),
1252                                 &buf);
1253         if (ret) {
1254             hx509_clear_error_string(context);
1255             goto out;
1256         }
1257
1258         sa.val = signer_info->signedAttrs->val;
1259         sa.len = signer_info->signedAttrs->len;
1260         
1261         ASN1_MALLOC_ENCODE(CMSAttributes,
1262                            sigdata.data,
1263                            sigdata.length,
1264                            &sa,
1265                            &size,
1266                            ret);
1267         if (ret) {
1268             hx509_clear_error_string(context);
1269             goto out;
1270         }
1271         if (size != sigdata.length)
1272             _hx509_abort("internal ASN.1 encoder error");
1273     } else {
1274         sigdata.data = content.data;
1275         sigdata.length = content.length;
1276     }
1277
1278
1279     {
1280         AlgorithmIdentifier sigalg;
1281
1282         ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
1283                                   _hx509_cert_private_key(cert), peer,
1284                                   &sigalg);
1285         if (ret)
1286             goto out;
1287
1288         ret = _hx509_create_signature(context,
1289                                       _hx509_cert_private_key(cert),
1290                                       &sigalg,
1291                                       &sigdata,
1292                                       &signer_info->signatureAlgorithm,
1293                                       &signer_info->signature);
1294         free_AlgorithmIdentifier(&sigalg);
1295         if (ret)
1296             goto out;
1297     }
1298
1299     ALLOC_SEQ(&sd.digestAlgorithms, 1);
1300     if (sd.digestAlgorithms.val == NULL) {
1301         ret = ENOMEM;
1302         hx509_clear_error_string(context);
1303         goto out;
1304     }
1305
1306     ret = copy_AlgorithmIdentifier(&digest, &sd.digestAlgorithms.val[0]);
1307     if (ret) {
1308         hx509_clear_error_string(context);
1309         goto out;
1310     }
1311
1312     /*
1313      * Provide best effort path
1314      */
1315     if (pool) {
1316         _hx509_calculate_path(context,
1317                               HX509_CALCULATE_PATH_NO_ANCHOR,                         
1318                               time(NULL),
1319                               anchors,
1320                               0,
1321                               cert,
1322                               pool,
1323                               &path);
1324     } else
1325         _hx509_path_append(context, &path, cert);
1326
1327
1328     if (path.len) {
1329         int i;
1330
1331         ALLOC(sd.certificates, 1);
1332         if (sd.certificates == NULL) {
1333             hx509_clear_error_string(context);
1334             ret = ENOMEM;
1335             goto out;
1336         }
1337         ALLOC_SEQ(sd.certificates, path.len);
1338         if (sd.certificates->val == NULL) {
1339             hx509_clear_error_string(context);
1340             ret = ENOMEM;
1341             goto out;
1342         }
1343
1344         for (i = 0; i < path.len; i++) {
1345             ret = hx509_cert_binary(context, path.val[i],
1346                                     &sd.certificates->val[i]);
1347             if (ret) {
1348                 hx509_clear_error_string(context);
1349                 goto out;
1350             }
1351         }
1352     }
1353
1354     ASN1_MALLOC_ENCODE(SignedData,
1355                        signed_data->data, signed_data->length,
1356                        &sd, &size, ret);
1357     if (ret) {
1358         hx509_clear_error_string(context);
1359         goto out;
1360     }
1361     if (signed_data->length != size)
1362         _hx509_abort("internal ASN.1 encoder error");
1363
1364 out:
1365     if (sigdata.data != content.data)
1366         der_free_octet_string(&sigdata);
1367     free_AlgorithmIdentifier(&digest);
1368     _hx509_path_free(&path);
1369     free_SignedData(&sd);
1370
1371     return ret;
1372 }
1373
1374 int
1375 hx509_cms_decrypt_encrypted(hx509_context context,
1376                             hx509_lock lock,
1377                             const void *data,
1378                             size_t length,
1379                             heim_oid *contentType,
1380                             heim_octet_string *content)
1381 {
1382     heim_octet_string cont;
1383     CMSEncryptedData ed;
1384     AlgorithmIdentifier *ai;
1385     int ret;
1386
1387     memset(content, 0, sizeof(*content));
1388     memset(&cont, 0, sizeof(cont));
1389
1390     ret = decode_CMSEncryptedData(data, length, &ed, NULL);
1391     if (ret) {
1392         hx509_set_error_string(context, 0, ret,
1393                                "Failed to decode CMSEncryptedData");
1394         return ret;
1395     }
1396
1397     if (ed.encryptedContentInfo.encryptedContent == NULL) {
1398         ret = HX509_CMS_NO_DATA_AVAILABLE;
1399         hx509_set_error_string(context, 0, ret,
1400                                "No content in EncryptedData");
1401         goto out;
1402     }
1403
1404     ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);
1405     if (ret) {
1406         hx509_clear_error_string(context);
1407         goto out;
1408     }
1409
1410     ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
1411     if (ai->parameters == NULL) {
1412         ret = HX509_ALG_NOT_SUPP;
1413         hx509_clear_error_string(context);
1414         goto out;
1415     }
1416
1417     ret = _hx509_pbe_decrypt(context,
1418                              lock,
1419                              ai,
1420                              ed.encryptedContentInfo.encryptedContent,
1421                              &cont);
1422     if (ret)
1423         goto out;
1424
1425     *content = cont;
1426
1427 out:
1428     if (ret) {
1429         if (cont.data)
1430             free(cont.data);
1431     }
1432     free_CMSEncryptedData(&ed);
1433     return ret;
1434 }