Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hx509/cms.c
34879 views
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
36
/**
37
* @page page_cms CMS/PKCS7 message functions.
38
*
39
* CMS is defined in RFC 3369 and is an continuation of the RSA Labs
40
* standard PKCS7. The basic messages in CMS is
41
*
42
* - SignedData
43
* Data signed with private key (RSA, DSA, ECDSA) or secret
44
* (symmetric) key
45
* - EnvelopedData
46
* Data encrypted with private key (RSA)
47
* - EncryptedData
48
* Data encrypted with secret (symmetric) key.
49
* - ContentInfo
50
* Wrapper structure including type and data.
51
*
52
*
53
* See the library functions here: @ref hx509_cms
54
*/
55
56
#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
57
#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
58
59
/**
60
* Wrap data and oid in a ContentInfo and encode it.
61
*
62
* @param oid type of the content.
63
* @param buf data to be wrapped. If a NULL pointer is passed in, the
64
* optional content field in the ContentInfo is not going be filled
65
* in.
66
* @param res the encoded buffer, the result should be freed with
67
* der_free_octet_string().
68
*
69
* @return Returns an hx509 error code.
70
*
71
* @ingroup hx509_cms
72
*/
73
74
int
75
hx509_cms_wrap_ContentInfo(const heim_oid *oid,
76
const heim_octet_string *buf,
77
heim_octet_string *res)
78
{
79
ContentInfo ci;
80
size_t size;
81
int ret;
82
83
memset(res, 0, sizeof(*res));
84
memset(&ci, 0, sizeof(ci));
85
86
ret = der_copy_oid(oid, &ci.contentType);
87
if (ret)
88
return ret;
89
if (buf) {
90
ALLOC(ci.content, 1);
91
if (ci.content == NULL) {
92
free_ContentInfo(&ci);
93
return ENOMEM;
94
}
95
ci.content->data = malloc(buf->length);
96
if (ci.content->data == NULL) {
97
free_ContentInfo(&ci);
98
return ENOMEM;
99
}
100
memcpy(ci.content->data, buf->data, buf->length);
101
ci.content->length = buf->length;
102
}
103
104
ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret);
105
free_ContentInfo(&ci);
106
if (ret)
107
return ret;
108
if (res->length != size)
109
_hx509_abort("internal ASN.1 encoder error");
110
111
return 0;
112
}
113
114
/**
115
* Decode an ContentInfo and unwrap data and oid it.
116
*
117
* @param in the encoded buffer.
118
* @param oid type of the content.
119
* @param out data to be wrapped.
120
* @param have_data since the data is optional, this flags show dthe
121
* diffrence between no data and the zero length data.
122
*
123
* @return Returns an hx509 error code.
124
*
125
* @ingroup hx509_cms
126
*/
127
128
int
129
hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
130
heim_oid *oid,
131
heim_octet_string *out,
132
int *have_data)
133
{
134
ContentInfo ci;
135
size_t size;
136
int ret;
137
138
memset(oid, 0, sizeof(*oid));
139
memset(out, 0, sizeof(*out));
140
141
ret = decode_ContentInfo(in->data, in->length, &ci, &size);
142
if (ret)
143
return ret;
144
145
ret = der_copy_oid(&ci.contentType, oid);
146
if (ret) {
147
free_ContentInfo(&ci);
148
return ret;
149
}
150
if (ci.content) {
151
ret = der_copy_octet_string(ci.content, out);
152
if (ret) {
153
der_free_oid(oid);
154
free_ContentInfo(&ci);
155
return ret;
156
}
157
} else
158
memset(out, 0, sizeof(*out));
159
160
if (have_data)
161
*have_data = (ci.content != NULL) ? 1 : 0;
162
163
free_ContentInfo(&ci);
164
165
return 0;
166
}
167
168
#define CMS_ID_SKI 0
169
#define CMS_ID_NAME 1
170
171
static int
172
fill_CMSIdentifier(const hx509_cert cert,
173
int type,
174
CMSIdentifier *id)
175
{
176
int ret;
177
178
switch (type) {
179
case CMS_ID_SKI:
180
id->element = choice_CMSIdentifier_subjectKeyIdentifier;
181
ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
182
&id->u.subjectKeyIdentifier);
183
if (ret == 0)
184
break;
185
/* FALL THOUGH */
186
case CMS_ID_NAME: {
187
hx509_name name;
188
189
id->element = choice_CMSIdentifier_issuerAndSerialNumber;
190
ret = hx509_cert_get_issuer(cert, &name);
191
if (ret)
192
return ret;
193
ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
194
hx509_name_free(&name);
195
if (ret)
196
return ret;
197
198
ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
199
break;
200
}
201
default:
202
_hx509_abort("CMS fill identifier with unknown type");
203
}
204
return ret;
205
}
206
207
static int
208
unparse_CMSIdentifier(hx509_context context,
209
CMSIdentifier *id,
210
char **str)
211
{
212
int ret;
213
214
*str = NULL;
215
switch (id->element) {
216
case choice_CMSIdentifier_issuerAndSerialNumber: {
217
IssuerAndSerialNumber *iasn;
218
char *serial, *name;
219
220
iasn = &id->u.issuerAndSerialNumber;
221
222
ret = _hx509_Name_to_string(&iasn->issuer, &name);
223
if(ret)
224
return ret;
225
ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial);
226
if (ret) {
227
free(name);
228
return ret;
229
}
230
asprintf(str, "certificate issued by %s with serial number %s",
231
name, serial);
232
free(name);
233
free(serial);
234
break;
235
}
236
case choice_CMSIdentifier_subjectKeyIdentifier: {
237
KeyIdentifier *ki = &id->u.subjectKeyIdentifier;
238
char *keyid;
239
ssize_t len;
240
241
len = hex_encode(ki->data, ki->length, &keyid);
242
if (len < 0)
243
return ENOMEM;
244
245
asprintf(str, "certificate with id %s", keyid);
246
free(keyid);
247
break;
248
}
249
default:
250
asprintf(str, "certificate have unknown CMSidentifier type");
251
break;
252
}
253
if (*str == NULL)
254
return ENOMEM;
255
return 0;
256
}
257
258
static int
259
find_CMSIdentifier(hx509_context context,
260
CMSIdentifier *client,
261
hx509_certs certs,
262
time_t time_now,
263
hx509_cert *signer_cert,
264
int match)
265
{
266
hx509_query q;
267
hx509_cert cert;
268
Certificate c;
269
int ret;
270
271
memset(&c, 0, sizeof(c));
272
_hx509_query_clear(&q);
273
274
*signer_cert = NULL;
275
276
switch (client->element) {
277
case choice_CMSIdentifier_issuerAndSerialNumber:
278
q.serial = &client->u.issuerAndSerialNumber.serialNumber;
279
q.issuer_name = &client->u.issuerAndSerialNumber.issuer;
280
q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
281
break;
282
case choice_CMSIdentifier_subjectKeyIdentifier:
283
q.subject_id = &client->u.subjectKeyIdentifier;
284
q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
285
break;
286
default:
287
hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE,
288
"unknown CMS identifier element");
289
return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
290
}
291
292
q.match |= match;
293
294
q.match |= HX509_QUERY_MATCH_TIME;
295
if (time_now)
296
q.timenow = time_now;
297
else
298
q.timenow = time(NULL);
299
300
ret = hx509_certs_find(context, certs, &q, &cert);
301
if (ret == HX509_CERT_NOT_FOUND) {
302
char *str;
303
304
ret = unparse_CMSIdentifier(context, client, &str);
305
if (ret == 0) {
306
hx509_set_error_string(context, 0,
307
HX509_CMS_NO_RECIPIENT_CERTIFICATE,
308
"Failed to find %s", str);
309
} else
310
hx509_clear_error_string(context);
311
return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
312
} else if (ret) {
313
hx509_set_error_string(context, HX509_ERROR_APPEND,
314
HX509_CMS_NO_RECIPIENT_CERTIFICATE,
315
"Failed to find CMS id in cert store");
316
return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
317
}
318
319
*signer_cert = cert;
320
321
return 0;
322
}
323
324
/**
325
* Decode and unencrypt EnvelopedData.
326
*
327
* Extract data and parameteres from from the EnvelopedData. Also
328
* supports using detached EnvelopedData.
329
*
330
* @param context A hx509 context.
331
* @param certs Certificate that can decrypt the EnvelopedData
332
* encryption key.
333
* @param flags HX509_CMS_UE flags to control the behavior.
334
* @param data pointer the structure the contains the DER/BER encoded
335
* EnvelopedData stucture.
336
* @param length length of the data that data point to.
337
* @param encryptedContent in case of detached signature, this
338
* contains the actual encrypted data, othersize its should be NULL.
339
* @param time_now set the current time, if zero the library uses now as the date.
340
* @param contentType output type oid, should be freed with der_free_oid().
341
* @param content the data, free with der_free_octet_string().
342
*
343
* @ingroup hx509_cms
344
*/
345
346
int
347
hx509_cms_unenvelope(hx509_context context,
348
hx509_certs certs,
349
int flags,
350
const void *data,
351
size_t length,
352
const heim_octet_string *encryptedContent,
353
time_t time_now,
354
heim_oid *contentType,
355
heim_octet_string *content)
356
{
357
heim_octet_string key;
358
EnvelopedData ed;
359
hx509_cert cert;
360
AlgorithmIdentifier *ai;
361
const heim_octet_string *enccontent;
362
heim_octet_string *params, params_data;
363
heim_octet_string ivec;
364
size_t size;
365
int ret, matched = 0, findflags = 0;
366
size_t i;
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 (flags & HX509_CMS_UE_ALLOW_WEAK)
478
hx509_crypto_allow_weak(crypto);
479
480
if (params) {
481
ret = hx509_crypto_set_params(context, crypto, params, &ivec);
482
if (ret) {
483
hx509_crypto_destroy(crypto);
484
goto out;
485
}
486
}
487
488
ret = hx509_crypto_set_key_data(crypto, key.data, key.length);
489
if (ret) {
490
hx509_crypto_destroy(crypto);
491
hx509_set_error_string(context, 0, ret,
492
"Failed to set key for decryption "
493
"of EnvelopedData");
494
goto out;
495
}
496
497
ret = hx509_crypto_decrypt(crypto,
498
enccontent->data,
499
enccontent->length,
500
ivec.length ? &ivec : NULL,
501
content);
502
hx509_crypto_destroy(crypto);
503
if (ret) {
504
hx509_set_error_string(context, 0, ret,
505
"Failed to decrypt EnvelopedData");
506
goto out;
507
}
508
}
509
510
out:
511
512
free_EnvelopedData(&ed);
513
der_free_octet_string(&key);
514
if (ivec.length)
515
der_free_octet_string(&ivec);
516
if (ret) {
517
der_free_oid(contentType);
518
der_free_octet_string(content);
519
}
520
521
return ret;
522
}
523
524
/**
525
* Encrypt end encode EnvelopedData.
526
*
527
* Encrypt and encode EnvelopedData. The data is encrypted with a
528
* random key and the the random key is encrypted with the
529
* certificates private key. This limits what private key type can be
530
* used to RSA.
531
*
532
* @param context A hx509 context.
533
* @param flags flags to control the behavior.
534
* - HX509_CMS_EV_NO_KU_CHECK - Dont check KU on certificate
535
* - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo
536
* - HX509_CMS_EV_ID_NAME - prefer issuer name and serial number
537
* @param cert Certificate to encrypt the EnvelopedData encryption key
538
* with.
539
* @param data pointer the data to encrypt.
540
* @param length length of the data that data point to.
541
* @param encryption_type Encryption cipher to use for the bulk data,
542
* use NULL to get default.
543
* @param contentType type of the data that is encrypted
544
* @param content the output of the function,
545
* free with der_free_octet_string().
546
*
547
* @ingroup hx509_cms
548
*/
549
550
int
551
hx509_cms_envelope_1(hx509_context context,
552
int flags,
553
hx509_cert cert,
554
const void *data,
555
size_t length,
556
const heim_oid *encryption_type,
557
const heim_oid *contentType,
558
heim_octet_string *content)
559
{
560
KeyTransRecipientInfo *ri;
561
heim_octet_string ivec;
562
heim_octet_string key;
563
hx509_crypto crypto = NULL;
564
int ret, cmsidflag;
565
EnvelopedData ed;
566
size_t size;
567
568
memset(&ivec, 0, sizeof(ivec));
569
memset(&key, 0, sizeof(key));
570
memset(&ed, 0, sizeof(ed));
571
memset(content, 0, sizeof(*content));
572
573
if (encryption_type == NULL)
574
encryption_type = &asn1_oid_id_aes_256_cbc;
575
576
if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) {
577
ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE);
578
if (ret)
579
goto out;
580
}
581
582
ret = hx509_crypto_init(context, NULL, encryption_type, &crypto);
583
if (ret)
584
goto out;
585
586
if (flags & HX509_CMS_EV_ALLOW_WEAK)
587
hx509_crypto_allow_weak(crypto);
588
589
ret = hx509_crypto_set_random_key(crypto, &key);
590
if (ret) {
591
hx509_set_error_string(context, 0, ret,
592
"Create random key for EnvelopedData content");
593
goto out;
594
}
595
596
ret = hx509_crypto_random_iv(crypto, &ivec);
597
if (ret) {
598
hx509_set_error_string(context, 0, ret,
599
"Failed to create a random iv");
600
goto out;
601
}
602
603
ret = hx509_crypto_encrypt(crypto,
604
data,
605
length,
606
&ivec,
607
&ed.encryptedContentInfo.encryptedContent);
608
if (ret) {
609
hx509_set_error_string(context, 0, ret,
610
"Failed to encrypt EnvelopedData content");
611
goto out;
612
}
613
614
{
615
AlgorithmIdentifier *enc_alg;
616
enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
617
ret = der_copy_oid(encryption_type, &enc_alg->algorithm);
618
if (ret) {
619
hx509_set_error_string(context, 0, ret,
620
"Failed to set crypto oid "
621
"for EnvelopedData");
622
goto out;
623
}
624
ALLOC(enc_alg->parameters, 1);
625
if (enc_alg->parameters == NULL) {
626
ret = ENOMEM;
627
hx509_set_error_string(context, 0, ret,
628
"Failed to allocate crypto paramaters "
629
"for EnvelopedData");
630
goto out;
631
}
632
633
ret = hx509_crypto_get_params(context,
634
crypto,
635
&ivec,
636
enc_alg->parameters);
637
if (ret) {
638
goto out;
639
}
640
}
641
642
ALLOC_SEQ(&ed.recipientInfos, 1);
643
if (ed.recipientInfos.val == NULL) {
644
ret = ENOMEM;
645
hx509_set_error_string(context, 0, ret,
646
"Failed to allocate recipients info "
647
"for EnvelopedData");
648
goto out;
649
}
650
651
ri = &ed.recipientInfos.val[0];
652
653
if (flags & HX509_CMS_EV_ID_NAME) {
654
ri->version = 0;
655
cmsidflag = CMS_ID_NAME;
656
} else {
657
ri->version = 2;
658
cmsidflag = CMS_ID_SKI;
659
}
660
661
ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid);
662
if (ret) {
663
hx509_set_error_string(context, 0, ret,
664
"Failed to set CMS identifier info "
665
"for EnvelopedData");
666
goto out;
667
}
668
669
ret = hx509_cert_public_encrypt(context,
670
&key, cert,
671
&ri->keyEncryptionAlgorithm.algorithm,
672
&ri->encryptedKey);
673
if (ret) {
674
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
675
"Failed to encrypt transport key for "
676
"EnvelopedData");
677
goto out;
678
}
679
680
/*
681
*
682
*/
683
684
ed.version = 0;
685
ed.originatorInfo = NULL;
686
687
ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType);
688
if (ret) {
689
hx509_set_error_string(context, 0, ret,
690
"Failed to copy content oid for "
691
"EnvelopedData");
692
goto out;
693
}
694
695
ed.unprotectedAttrs = NULL;
696
697
ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length,
698
&ed, &size, ret);
699
if (ret) {
700
hx509_set_error_string(context, 0, ret,
701
"Failed to encode EnvelopedData");
702
goto out;
703
}
704
if (size != content->length)
705
_hx509_abort("internal ASN.1 encoder error");
706
707
out:
708
if (crypto)
709
hx509_crypto_destroy(crypto);
710
if (ret)
711
der_free_octet_string(content);
712
der_free_octet_string(&key);
713
der_free_octet_string(&ivec);
714
free_EnvelopedData(&ed);
715
716
return ret;
717
}
718
719
static int
720
any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
721
{
722
int ret;
723
size_t i;
724
725
if (sd->certificates == NULL)
726
return 0;
727
728
for (i = 0; i < sd->certificates->len; i++) {
729
hx509_cert c;
730
731
ret = hx509_cert_init_data(context,
732
sd->certificates->val[i].data,
733
sd->certificates->val[i].length,
734
&c);
735
if (ret)
736
return ret;
737
ret = hx509_certs_add(context, certs, c);
738
hx509_cert_free(c);
739
if (ret)
740
return ret;
741
}
742
743
return 0;
744
}
745
746
static const Attribute *
747
find_attribute(const CMSAttributes *attr, const heim_oid *oid)
748
{
749
size_t i;
750
for (i = 0; i < attr->len; i++)
751
if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0)
752
return &attr->val[i];
753
return NULL;
754
}
755
756
/**
757
* Decode SignedData and verify that the signature is correct.
758
*
759
* @param context A hx509 context.
760
* @param ctx a hx509 verify context.
761
* @param flags to control the behaivor of the function.
762
* - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage
763
* - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch
764
* - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below.
765
* @param data pointer to CMS SignedData encoded data.
766
* @param length length of the data that data point to.
767
* @param signedContent external data used for signature.
768
* @param pool certificate pool to build certificates paths.
769
* @param contentType free with der_free_oid().
770
* @param content the output of the function, free with
771
* der_free_octet_string().
772
* @param signer_certs list of the cerficates used to sign this
773
* request, free with hx509_certs_free().
774
*
775
* @ingroup hx509_cms
776
*/
777
778
int
779
hx509_cms_verify_signed(hx509_context context,
780
hx509_verify_ctx ctx,
781
unsigned int flags,
782
const void *data,
783
size_t length,
784
const heim_octet_string *signedContent,
785
hx509_certs pool,
786
heim_oid *contentType,
787
heim_octet_string *content,
788
hx509_certs *signer_certs)
789
{
790
SignerInfo *signer_info;
791
hx509_cert cert = NULL;
792
hx509_certs certs = NULL;
793
SignedData sd;
794
size_t size;
795
int ret, found_valid_sig;
796
size_t i;
797
798
*signer_certs = NULL;
799
content->data = NULL;
800
content->length = 0;
801
contentType->length = 0;
802
contentType->components = NULL;
803
804
memset(&sd, 0, sizeof(sd));
805
806
ret = decode_SignedData(data, length, &sd, &size);
807
if (ret) {
808
hx509_set_error_string(context, 0, ret,
809
"Failed to decode SignedData");
810
goto out;
811
}
812
813
if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) {
814
ret = HX509_CMS_NO_DATA_AVAILABLE;
815
hx509_set_error_string(context, 0, ret,
816
"No content data in SignedData");
817
goto out;
818
}
819
if (sd.encapContentInfo.eContent && signedContent) {
820
ret = HX509_CMS_NO_DATA_AVAILABLE;
821
hx509_set_error_string(context, 0, ret,
822
"Both external and internal SignedData");
823
goto out;
824
}
825
826
if (sd.encapContentInfo.eContent)
827
ret = der_copy_octet_string(sd.encapContentInfo.eContent, content);
828
else
829
ret = der_copy_octet_string(signedContent, content);
830
if (ret) {
831
hx509_set_error_string(context, 0, ret, "malloc: out of memory");
832
goto out;
833
}
834
835
ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer",
836
0, NULL, &certs);
837
if (ret)
838
goto out;
839
840
ret = hx509_certs_init(context, "MEMORY:cms-signer-certs",
841
0, NULL, signer_certs);
842
if (ret)
843
goto out;
844
845
/* XXX Check CMS version */
846
847
ret = any_to_certs(context, &sd, certs);
848
if (ret)
849
goto out;
850
851
if (pool) {
852
ret = hx509_certs_merge(context, certs, pool);
853
if (ret)
854
goto out;
855
}
856
857
for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) {
858
heim_octet_string signed_data;
859
const heim_oid *match_oid;
860
heim_oid decode_oid;
861
862
signer_info = &sd.signerInfos.val[i];
863
match_oid = NULL;
864
865
if (signer_info->signature.length == 0) {
866
ret = HX509_CMS_MISSING_SIGNER_DATA;
867
hx509_set_error_string(context, 0, ret,
868
"SignerInfo %d in SignedData "
869
"missing sigature", i);
870
continue;
871
}
872
873
ret = find_CMSIdentifier(context, &signer_info->sid, certs,
874
_hx509_verify_get_time(ctx), &cert,
875
HX509_QUERY_KU_DIGITALSIGNATURE);
876
if (ret) {
877
/**
878
* If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal
879
* search for matching certificates by not considering
880
* KeyUsage bits on the certificates.
881
*/
882
if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0)
883
continue;
884
885
ret = find_CMSIdentifier(context, &signer_info->sid, certs,
886
_hx509_verify_get_time(ctx), &cert,
887
0);
888
if (ret)
889
continue;
890
891
}
892
893
if (signer_info->signedAttrs) {
894
const Attribute *attr;
895
896
CMSAttributes sa;
897
heim_octet_string os;
898
899
sa.val = signer_info->signedAttrs->val;
900
sa.len = signer_info->signedAttrs->len;
901
902
/* verify that sigature exists */
903
attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest);
904
if (attr == NULL) {
905
ret = HX509_CRYPTO_SIGNATURE_MISSING;
906
hx509_set_error_string(context, 0, ret,
907
"SignerInfo have signed attributes "
908
"but messageDigest (signature) "
909
"is missing");
910
goto next_sigature;
911
}
912
if (attr->value.len != 1) {
913
ret = HX509_CRYPTO_SIGNATURE_MISSING;
914
hx509_set_error_string(context, 0, ret,
915
"SignerInfo have more then one "
916
"messageDigest (signature)");
917
goto next_sigature;
918
}
919
920
ret = decode_MessageDigest(attr->value.val[0].data,
921
attr->value.val[0].length,
922
&os,
923
&size);
924
if (ret) {
925
hx509_set_error_string(context, 0, ret,
926
"Failed to decode "
927
"messageDigest (signature)");
928
goto next_sigature;
929
}
930
931
ret = _hx509_verify_signature(context,
932
NULL,
933
&signer_info->digestAlgorithm,
934
content,
935
&os);
936
der_free_octet_string(&os);
937
if (ret) {
938
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
939
"Failed to verify messageDigest");
940
goto next_sigature;
941
}
942
943
/*
944
* Fetch content oid inside signedAttrs or set it to
945
* id-pkcs7-data.
946
*/
947
attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType);
948
if (attr == NULL) {
949
match_oid = &asn1_oid_id_pkcs7_data;
950
} else {
951
if (attr->value.len != 1) {
952
ret = HX509_CMS_DATA_OID_MISMATCH;
953
hx509_set_error_string(context, 0, ret,
954
"More then one oid in signedAttrs");
955
goto next_sigature;
956
957
}
958
ret = decode_ContentType(attr->value.val[0].data,
959
attr->value.val[0].length,
960
&decode_oid,
961
&size);
962
if (ret) {
963
hx509_set_error_string(context, 0, ret,
964
"Failed to decode "
965
"oid in signedAttrs");
966
goto next_sigature;
967
}
968
match_oid = &decode_oid;
969
}
970
971
ASN1_MALLOC_ENCODE(CMSAttributes,
972
signed_data.data,
973
signed_data.length,
974
&sa,
975
&size, ret);
976
if (ret) {
977
if (match_oid == &decode_oid)
978
der_free_oid(&decode_oid);
979
hx509_clear_error_string(context);
980
goto next_sigature;
981
}
982
if (size != signed_data.length)
983
_hx509_abort("internal ASN.1 encoder error");
984
985
} else {
986
signed_data.data = content->data;
987
signed_data.length = content->length;
988
match_oid = &asn1_oid_id_pkcs7_data;
989
}
990
991
/**
992
* If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow
993
* encapContentInfo mismatch with the oid in signedAttributes
994
* (or if no signedAttributes where use, pkcs7-data oid).
995
* This is only needed to work with broken CMS implementations
996
* that doesn't follow CMS signedAttributes rules.
997
*/
998
999
if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) &&
1000
(flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) {
1001
ret = HX509_CMS_DATA_OID_MISMATCH;
1002
hx509_set_error_string(context, 0, ret,
1003
"Oid in message mismatch from the expected");
1004
}
1005
if (match_oid == &decode_oid)
1006
der_free_oid(&decode_oid);
1007
1008
if (ret == 0) {
1009
ret = hx509_verify_signature(context,
1010
cert,
1011
&signer_info->signatureAlgorithm,
1012
&signed_data,
1013
&signer_info->signature);
1014
if (ret)
1015
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1016
"Failed to verify signature in "
1017
"CMS SignedData");
1018
}
1019
if (signer_info->signedAttrs)
1020
free(signed_data.data);
1021
if (ret)
1022
goto next_sigature;
1023
1024
/**
1025
* If HX509_CMS_VS_NO_VALIDATE flags is set, do not verify the
1026
* signing certificates and leave that up to the caller.
1027
*/
1028
1029
if ((flags & HX509_CMS_VS_NO_VALIDATE) == 0) {
1030
ret = hx509_verify_path(context, ctx, cert, certs);
1031
if (ret)
1032
goto next_sigature;
1033
}
1034
1035
ret = hx509_certs_add(context, *signer_certs, cert);
1036
if (ret)
1037
goto next_sigature;
1038
1039
found_valid_sig++;
1040
1041
next_sigature:
1042
if (cert)
1043
hx509_cert_free(cert);
1044
cert = NULL;
1045
}
1046
/**
1047
* If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty
1048
* SignerInfo (no signatures). If SignedData have no signatures,
1049
* the function will return 0 with signer_certs set to NULL. Zero
1050
* signers is allowed by the standard, but since its only useful
1051
* in corner cases, it make into a flag that the caller have to
1052
* turn on.
1053
*/
1054
if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) {
1055
if (*signer_certs)
1056
hx509_certs_free(signer_certs);
1057
} else if (found_valid_sig == 0) {
1058
if (ret == 0) {
1059
ret = HX509_CMS_SIGNER_NOT_FOUND;
1060
hx509_set_error_string(context, 0, ret,
1061
"No signers where found");
1062
}
1063
goto out;
1064
}
1065
1066
ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType);
1067
if (ret) {
1068
hx509_clear_error_string(context);
1069
goto out;
1070
}
1071
1072
out:
1073
free_SignedData(&sd);
1074
if (certs)
1075
hx509_certs_free(&certs);
1076
if (ret) {
1077
if (content->data)
1078
der_free_octet_string(content);
1079
if (*signer_certs)
1080
hx509_certs_free(signer_certs);
1081
der_free_oid(contentType);
1082
der_free_octet_string(content);
1083
}
1084
1085
return ret;
1086
}
1087
1088
static int
1089
add_one_attribute(Attribute **attr,
1090
unsigned int *len,
1091
const heim_oid *oid,
1092
heim_octet_string *data)
1093
{
1094
void *d;
1095
int ret;
1096
1097
d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1));
1098
if (d == NULL)
1099
return ENOMEM;
1100
(*attr) = d;
1101
1102
ret = der_copy_oid(oid, &(*attr)[*len].type);
1103
if (ret)
1104
return ret;
1105
1106
ALLOC_SEQ(&(*attr)[*len].value, 1);
1107
if ((*attr)[*len].value.val == NULL) {
1108
der_free_oid(&(*attr)[*len].type);
1109
return ENOMEM;
1110
}
1111
1112
(*attr)[*len].value.val[0].data = data->data;
1113
(*attr)[*len].value.val[0].length = data->length;
1114
1115
*len += 1;
1116
1117
return 0;
1118
}
1119
1120
/**
1121
* Decode SignedData and verify that the signature is correct.
1122
*
1123
* @param context A hx509 context.
1124
* @param flags
1125
* @param eContentType the type of the data.
1126
* @param data data to sign
1127
* @param length length of the data that data point to.
1128
* @param digest_alg digest algorithm to use, use NULL to get the
1129
* default or the peer determined algorithm.
1130
* @param cert certificate to use for sign the data.
1131
* @param peer info about the peer the message to send the message to,
1132
* like what digest algorithm to use.
1133
* @param anchors trust anchors that the client will use, used to
1134
* polulate the certificates included in the message
1135
* @param pool certificates to use in try to build the path to the
1136
* trust anchors.
1137
* @param signed_data the output of the function, free with
1138
* der_free_octet_string().
1139
*
1140
* @ingroup hx509_cms
1141
*/
1142
1143
int
1144
hx509_cms_create_signed_1(hx509_context context,
1145
int flags,
1146
const heim_oid *eContentType,
1147
const void *data, size_t length,
1148
const AlgorithmIdentifier *digest_alg,
1149
hx509_cert cert,
1150
hx509_peer_info peer,
1151
hx509_certs anchors,
1152
hx509_certs pool,
1153
heim_octet_string *signed_data)
1154
{
1155
hx509_certs certs;
1156
int ret = 0;
1157
1158
signed_data->data = NULL;
1159
signed_data->length = 0;
1160
1161
ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs);
1162
if (ret)
1163
return ret;
1164
ret = hx509_certs_add(context, certs, cert);
1165
if (ret)
1166
goto out;
1167
1168
ret = hx509_cms_create_signed(context, flags, eContentType, data, length,
1169
digest_alg, certs, peer, anchors, pool,
1170
signed_data);
1171
1172
out:
1173
hx509_certs_free(&certs);
1174
return ret;
1175
}
1176
1177
struct sigctx {
1178
SignedData sd;
1179
const AlgorithmIdentifier *digest_alg;
1180
const heim_oid *eContentType;
1181
heim_octet_string content;
1182
hx509_peer_info peer;
1183
int cmsidflag;
1184
int leafonly;
1185
hx509_certs certs;
1186
hx509_certs anchors;
1187
hx509_certs pool;
1188
};
1189
1190
static int
1191
sig_process(hx509_context context, void *ctx, hx509_cert cert)
1192
{
1193
struct sigctx *sigctx = ctx;
1194
heim_octet_string buf, sigdata = { 0, NULL };
1195
SignerInfo *signer_info = NULL;
1196
AlgorithmIdentifier digest;
1197
size_t size;
1198
void *ptr;
1199
int ret;
1200
SignedData *sd = &sigctx->sd;
1201
hx509_path path;
1202
1203
memset(&digest, 0, sizeof(digest));
1204
memset(&path, 0, sizeof(path));
1205
1206
if (_hx509_cert_private_key(cert) == NULL) {
1207
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1208
"Private key missing for signing");
1209
return HX509_PRIVATE_KEY_MISSING;
1210
}
1211
1212
if (sigctx->digest_alg) {
1213
ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest);
1214
if (ret)
1215
hx509_clear_error_string(context);
1216
} else {
1217
ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
1218
_hx509_cert_private_key(cert),
1219
sigctx->peer, &digest);
1220
}
1221
if (ret)
1222
goto out;
1223
1224
/*
1225
* Allocate on more signerInfo and do the signature processing
1226
*/
1227
1228
ptr = realloc(sd->signerInfos.val,
1229
(sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0]));
1230
if (ptr == NULL) {
1231
ret = ENOMEM;
1232
goto out;
1233
}
1234
sd->signerInfos.val = ptr;
1235
1236
signer_info = &sd->signerInfos.val[sd->signerInfos.len];
1237
1238
memset(signer_info, 0, sizeof(*signer_info));
1239
1240
signer_info->version = 1;
1241
1242
ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid);
1243
if (ret) {
1244
hx509_clear_error_string(context);
1245
goto out;
1246
}
1247
1248
signer_info->signedAttrs = NULL;
1249
signer_info->unsignedAttrs = NULL;
1250
1251
ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
1252
if (ret) {
1253
hx509_clear_error_string(context);
1254
goto out;
1255
}
1256
1257
/*
1258
* If it isn't pkcs7-data send signedAttributes
1259
*/
1260
1261
if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) {
1262
CMSAttributes sa;
1263
heim_octet_string sig;
1264
1265
ALLOC(signer_info->signedAttrs, 1);
1266
if (signer_info->signedAttrs == NULL) {
1267
ret = ENOMEM;
1268
goto out;
1269
}
1270
1271
ret = _hx509_create_signature(context,
1272
NULL,
1273
&digest,
1274
&sigctx->content,
1275
NULL,
1276
&sig);
1277
if (ret)
1278
goto out;
1279
1280
ASN1_MALLOC_ENCODE(MessageDigest,
1281
buf.data,
1282
buf.length,
1283
&sig,
1284
&size,
1285
ret);
1286
der_free_octet_string(&sig);
1287
if (ret) {
1288
hx509_clear_error_string(context);
1289
goto out;
1290
}
1291
if (size != buf.length)
1292
_hx509_abort("internal ASN.1 encoder error");
1293
1294
ret = add_one_attribute(&signer_info->signedAttrs->val,
1295
&signer_info->signedAttrs->len,
1296
&asn1_oid_id_pkcs9_messageDigest,
1297
&buf);
1298
if (ret) {
1299
free(buf.data);
1300
hx509_clear_error_string(context);
1301
goto out;
1302
}
1303
1304
1305
ASN1_MALLOC_ENCODE(ContentType,
1306
buf.data,
1307
buf.length,
1308
sigctx->eContentType,
1309
&size,
1310
ret);
1311
if (ret)
1312
goto out;
1313
if (size != buf.length)
1314
_hx509_abort("internal ASN.1 encoder error");
1315
1316
ret = add_one_attribute(&signer_info->signedAttrs->val,
1317
&signer_info->signedAttrs->len,
1318
&asn1_oid_id_pkcs9_contentType,
1319
&buf);
1320
if (ret) {
1321
free(buf.data);
1322
hx509_clear_error_string(context);
1323
goto out;
1324
}
1325
1326
sa.val = signer_info->signedAttrs->val;
1327
sa.len = signer_info->signedAttrs->len;
1328
1329
ASN1_MALLOC_ENCODE(CMSAttributes,
1330
sigdata.data,
1331
sigdata.length,
1332
&sa,
1333
&size,
1334
ret);
1335
if (ret) {
1336
hx509_clear_error_string(context);
1337
goto out;
1338
}
1339
if (size != sigdata.length)
1340
_hx509_abort("internal ASN.1 encoder error");
1341
} else {
1342
sigdata.data = sigctx->content.data;
1343
sigdata.length = sigctx->content.length;
1344
}
1345
1346
{
1347
AlgorithmIdentifier sigalg;
1348
1349
ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
1350
_hx509_cert_private_key(cert), sigctx->peer,
1351
&sigalg);
1352
if (ret)
1353
goto out;
1354
1355
ret = _hx509_create_signature(context,
1356
_hx509_cert_private_key(cert),
1357
&sigalg,
1358
&sigdata,
1359
&signer_info->signatureAlgorithm,
1360
&signer_info->signature);
1361
free_AlgorithmIdentifier(&sigalg);
1362
if (ret)
1363
goto out;
1364
}
1365
1366
sigctx->sd.signerInfos.len++;
1367
signer_info = NULL;
1368
1369
/*
1370
* Provide best effort path
1371
*/
1372
if (sigctx->certs) {
1373
unsigned int i;
1374
1375
if (sigctx->pool && sigctx->leafonly == 0) {
1376
_hx509_calculate_path(context,
1377
HX509_CALCULATE_PATH_NO_ANCHOR,
1378
time(NULL),
1379
sigctx->anchors,
1380
0,
1381
cert,
1382
sigctx->pool,
1383
&path);
1384
} else
1385
_hx509_path_append(context, &path, cert);
1386
1387
for (i = 0; i < path.len; i++) {
1388
/* XXX remove dups */
1389
ret = hx509_certs_add(context, sigctx->certs, path.val[i]);
1390
if (ret) {
1391
hx509_clear_error_string(context);
1392
goto out;
1393
}
1394
}
1395
}
1396
1397
out:
1398
if (signer_info)
1399
free_SignerInfo(signer_info);
1400
if (sigdata.data != sigctx->content.data)
1401
der_free_octet_string(&sigdata);
1402
_hx509_path_free(&path);
1403
free_AlgorithmIdentifier(&digest);
1404
1405
return ret;
1406
}
1407
1408
static int
1409
cert_process(hx509_context context, void *ctx, hx509_cert cert)
1410
{
1411
struct sigctx *sigctx = ctx;
1412
const unsigned int i = sigctx->sd.certificates->len;
1413
void *ptr;
1414
int ret;
1415
1416
ptr = realloc(sigctx->sd.certificates->val,
1417
(i + 1) * sizeof(sigctx->sd.certificates->val[0]));
1418
if (ptr == NULL)
1419
return ENOMEM;
1420
sigctx->sd.certificates->val = ptr;
1421
1422
ret = hx509_cert_binary(context, cert,
1423
&sigctx->sd.certificates->val[i]);
1424
if (ret == 0)
1425
sigctx->sd.certificates->len++;
1426
1427
return ret;
1428
}
1429
1430
static int
1431
cmp_AlgorithmIdentifier(const AlgorithmIdentifier *p, const AlgorithmIdentifier *q)
1432
{
1433
return der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1434
}
1435
1436
int
1437
hx509_cms_create_signed(hx509_context context,
1438
int flags,
1439
const heim_oid *eContentType,
1440
const void *data, size_t length,
1441
const AlgorithmIdentifier *digest_alg,
1442
hx509_certs certs,
1443
hx509_peer_info peer,
1444
hx509_certs anchors,
1445
hx509_certs pool,
1446
heim_octet_string *signed_data)
1447
{
1448
unsigned int i, j;
1449
hx509_name name;
1450
int ret;
1451
size_t size;
1452
struct sigctx sigctx;
1453
1454
memset(&sigctx, 0, sizeof(sigctx));
1455
memset(&name, 0, sizeof(name));
1456
1457
if (eContentType == NULL)
1458
eContentType = &asn1_oid_id_pkcs7_data;
1459
1460
sigctx.digest_alg = digest_alg;
1461
sigctx.content.data = rk_UNCONST(data);
1462
sigctx.content.length = length;
1463
sigctx.eContentType = eContentType;
1464
sigctx.peer = peer;
1465
/**
1466
* Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name
1467
* and serial number if possible. Otherwise subject key identifier
1468
* will preferred.
1469
*/
1470
if (flags & HX509_CMS_SIGNATURE_ID_NAME)
1471
sigctx.cmsidflag = CMS_ID_NAME;
1472
else
1473
sigctx.cmsidflag = CMS_ID_SKI;
1474
1475
/**
1476
* Use HX509_CMS_SIGNATURE_LEAF_ONLY to only request leaf
1477
* certificates to be added to the SignedData.
1478
*/
1479
sigctx.leafonly = (flags & HX509_CMS_SIGNATURE_LEAF_ONLY) ? 1 : 0;
1480
1481
/**
1482
* Use HX509_CMS_NO_CERTS to make the SignedData contain no
1483
* certificates, overrides HX509_CMS_SIGNATURE_LEAF_ONLY.
1484
*/
1485
1486
if ((flags & HX509_CMS_SIGNATURE_NO_CERTS) == 0) {
1487
ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs);
1488
if (ret)
1489
return ret;
1490
}
1491
1492
sigctx.anchors = anchors;
1493
sigctx.pool = pool;
1494
1495
sigctx.sd.version = CMSVersion_v3;
1496
1497
der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType);
1498
1499
/**
1500
* Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures.
1501
*/
1502
if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) {
1503
ALLOC(sigctx.sd.encapContentInfo.eContent, 1);
1504
if (sigctx.sd.encapContentInfo.eContent == NULL) {
1505
hx509_clear_error_string(context);
1506
ret = ENOMEM;
1507
goto out;
1508
}
1509
1510
sigctx.sd.encapContentInfo.eContent->data = malloc(length);
1511
if (sigctx.sd.encapContentInfo.eContent->data == NULL) {
1512
hx509_clear_error_string(context);
1513
ret = ENOMEM;
1514
goto out;
1515
}
1516
memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length);
1517
sigctx.sd.encapContentInfo.eContent->length = length;
1518
}
1519
1520
/**
1521
* Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no
1522
* signatures).
1523
*/
1524
if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) {
1525
ret = hx509_certs_iter_f(context, certs, sig_process, &sigctx);
1526
if (ret)
1527
goto out;
1528
}
1529
1530
if (sigctx.sd.signerInfos.len) {
1531
1532
/*
1533
* For each signerInfo, collect all different digest types.
1534
*/
1535
for (i = 0; i < sigctx.sd.signerInfos.len; i++) {
1536
AlgorithmIdentifier *di =
1537
&sigctx.sd.signerInfos.val[i].digestAlgorithm;
1538
1539
for (j = 0; j < sigctx.sd.digestAlgorithms.len; j++)
1540
if (cmp_AlgorithmIdentifier(di, &sigctx.sd.digestAlgorithms.val[j]) == 0)
1541
break;
1542
if (j == sigctx.sd.digestAlgorithms.len) {
1543
ret = add_DigestAlgorithmIdentifiers(&sigctx.sd.digestAlgorithms, di);
1544
if (ret) {
1545
hx509_clear_error_string(context);
1546
goto out;
1547
}
1548
}
1549
}
1550
}
1551
1552
/*
1553
* Add certs we think are needed, build as part of sig_process
1554
*/
1555
if (sigctx.certs) {
1556
ALLOC(sigctx.sd.certificates, 1);
1557
if (sigctx.sd.certificates == NULL) {
1558
hx509_clear_error_string(context);
1559
ret = ENOMEM;
1560
goto out;
1561
}
1562
1563
ret = hx509_certs_iter_f(context, sigctx.certs, cert_process, &sigctx);
1564
if (ret)
1565
goto out;
1566
}
1567
1568
ASN1_MALLOC_ENCODE(SignedData,
1569
signed_data->data, signed_data->length,
1570
&sigctx.sd, &size, ret);
1571
if (ret) {
1572
hx509_clear_error_string(context);
1573
goto out;
1574
}
1575
if (signed_data->length != size)
1576
_hx509_abort("internal ASN.1 encoder error");
1577
1578
out:
1579
hx509_certs_free(&sigctx.certs);
1580
free_SignedData(&sigctx.sd);
1581
1582
return ret;
1583
}
1584
1585
int
1586
hx509_cms_decrypt_encrypted(hx509_context context,
1587
hx509_lock lock,
1588
const void *data,
1589
size_t length,
1590
heim_oid *contentType,
1591
heim_octet_string *content)
1592
{
1593
heim_octet_string cont;
1594
CMSEncryptedData ed;
1595
AlgorithmIdentifier *ai;
1596
int ret;
1597
1598
memset(content, 0, sizeof(*content));
1599
memset(&cont, 0, sizeof(cont));
1600
1601
ret = decode_CMSEncryptedData(data, length, &ed, NULL);
1602
if (ret) {
1603
hx509_set_error_string(context, 0, ret,
1604
"Failed to decode CMSEncryptedData");
1605
return ret;
1606
}
1607
1608
if (ed.encryptedContentInfo.encryptedContent == NULL) {
1609
ret = HX509_CMS_NO_DATA_AVAILABLE;
1610
hx509_set_error_string(context, 0, ret,
1611
"No content in EncryptedData");
1612
goto out;
1613
}
1614
1615
ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);
1616
if (ret) {
1617
hx509_clear_error_string(context);
1618
goto out;
1619
}
1620
1621
ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
1622
if (ai->parameters == NULL) {
1623
ret = HX509_ALG_NOT_SUPP;
1624
hx509_clear_error_string(context);
1625
goto out;
1626
}
1627
1628
ret = _hx509_pbe_decrypt(context,
1629
lock,
1630
ai,
1631
ed.encryptedContentInfo.encryptedContent,
1632
&cont);
1633
if (ret)
1634
goto out;
1635
1636
*content = cont;
1637
1638
out:
1639
if (ret) {
1640
if (cont.data)
1641
free(cont.data);
1642
}
1643
free_CMSEncryptedData(&ed);
1644
return ret;
1645
}
1646
1647