1 /*
2 * Copyright (C) 2003-2015 Free Software Foundation, Inc.
3 * Copyright (C) 2015 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 /* Functions that relate on PKCS7 certificate lists parsing.
25 */
26
27 #include "gnutls_int.h"
28 #include <libtasn1.h>
29
30 #include <datum.h>
31 #include <global.h>
32 #include "errors.h"
33 #include <common.h>
34 #include <x509_b64.h>
35 #include <pkcs7_int.h>
36 #include <gnutls/abstract.h>
37 #include <gnutls/pkcs7.h>
38
39 #define ATTR_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
40 #define ATTR_SIGNING_TIME "1.2.840.113549.1.9.5"
41 #define ATTR_CONTENT_TYPE "1.2.840.113549.1.9.3"
42
43 static const uint8_t one = 1;
44
45 /* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE,
46 * which holds them. If raw is non null then the raw decoded
47 * data are copied (they are locally allocated) there.
48 */
_decode_pkcs7_signed_data(gnutls_pkcs7_t pkcs7)49 static int _decode_pkcs7_signed_data(gnutls_pkcs7_t pkcs7)
50 {
51 ASN1_TYPE c2;
52 int len, result;
53 gnutls_datum_t tmp = {NULL, 0};
54
55 len = MAX_OID_SIZE - 1;
56 result = asn1_read_value(pkcs7->pkcs7, "contentType", pkcs7->encap_data_oid, &len);
57 if (result != ASN1_SUCCESS) {
58 gnutls_assert();
59 return _gnutls_asn2err(result);
60 }
61
62 if (strcmp(pkcs7->encap_data_oid, SIGNED_DATA_OID) != 0) {
63 gnutls_assert();
64 _gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n", pkcs7->encap_data_oid);
65 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
66 }
67
68 if ((result = asn1_create_element
69 (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
70 &c2)) != ASN1_SUCCESS) {
71 gnutls_assert();
72 return _gnutls_asn2err(result);
73 }
74
75 /* the Signed-data has been created, so
76 * decode them.
77 */
78 result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
79 if (result < 0) {
80 gnutls_assert();
81 goto cleanup;
82 }
83
84 /* Step 1. In case of a signed structure extract certificate set.
85 */
86
87 result = asn1_der_decoding(&c2, tmp.data, tmp.size, NULL);
88 if (result != ASN1_SUCCESS) {
89 gnutls_assert();
90 result = _gnutls_asn2err(result);
91 goto cleanup;
92 }
93
94 /* read the encapsulated content */
95 len = MAX_OID_SIZE - 1;
96 result =
97 asn1_read_value(c2, "encapContentInfo.eContentType", pkcs7->encap_data_oid, &len);
98 if (result != ASN1_SUCCESS) {
99 gnutls_assert();
100 result = _gnutls_asn2err(result);
101 goto cleanup;
102 }
103
104 if (strcmp(pkcs7->encap_data_oid, DATA_OID) != 0
105 && strcmp(pkcs7->encap_data_oid, DIGESTED_DATA_OID) != 0) {
106 _gnutls_debug_log
107 ("Unknown PKCS#7 Encapsulated Content OID '%s'; treating as raw data\n",
108 pkcs7->encap_data_oid);
109
110 }
111
112 /* Try reading as octet string according to rfc5652. If that fails, attempt
113 * a raw read according to rfc2315 */
114 result = _gnutls_x509_read_string(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data, ASN1_ETYPE_OCTET_STRING, 1);
115 if (result < 0) {
116 result = _gnutls_x509_read_value(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data);
117 if (result < 0) {
118 pkcs7->der_signed_data.data = NULL;
119 pkcs7->der_signed_data.size = 0;
120 } else {
121 int tag_len, len_len;
122 unsigned char cls;
123 unsigned long tag;
124
125 /* we skip the embedded element's tag and length - uncharted territorry - used by MICROSOFT_CERT_TRUST_LIST */
126 result = asn1_get_tag_der(pkcs7->der_signed_data.data, pkcs7->der_signed_data.size, &cls, &tag_len, &tag);
127 if (result != ASN1_SUCCESS) {
128 gnutls_assert();
129 result = _gnutls_asn2err(result);
130 goto cleanup;
131 }
132
133 result = asn1_get_length_ber(pkcs7->der_signed_data.data+tag_len, pkcs7->der_signed_data.size-tag_len, &len_len);
134 if (result < 0) {
135 gnutls_assert();
136 result = GNUTLS_E_ASN1_DER_ERROR;
137 goto cleanup;
138 }
139
140 tag_len += len_len;
141 memmove(pkcs7->der_signed_data.data, &pkcs7->der_signed_data.data[tag_len], pkcs7->der_signed_data.size-tag_len);
142 pkcs7->der_signed_data.size-=tag_len;
143 }
144 }
145
146 pkcs7->signed_data = c2;
147 gnutls_free(tmp.data);
148
149 return 0;
150
151 cleanup:
152 gnutls_free(tmp.data);
153 if (c2)
154 asn1_delete_structure(&c2);
155 return result;
156 }
157
pkcs7_reinit(gnutls_pkcs7_t pkcs7)158 static int pkcs7_reinit(gnutls_pkcs7_t pkcs7)
159 {
160 int result;
161
162 asn1_delete_structure(&pkcs7->pkcs7);
163
164 result = asn1_create_element(_gnutls_get_pkix(),
165 "PKIX1.pkcs-7-ContentInfo", &pkcs7->pkcs7);
166 if (result != ASN1_SUCCESS) {
167 result = _gnutls_asn2err(result);
168 gnutls_assert();
169 return result;
170 }
171
172 return 0;
173 }
174
175 /**
176 * gnutls_pkcs7_init:
177 * @pkcs7: A pointer to the type to be initialized
178 *
179 * This function will initialize a PKCS7 structure. PKCS7 structures
180 * usually contain lists of X.509 Certificates and X.509 Certificate
181 * revocation lists.
182 *
183 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
184 * negative error value.
185 **/
gnutls_pkcs7_init(gnutls_pkcs7_t * pkcs7)186 int gnutls_pkcs7_init(gnutls_pkcs7_t * pkcs7)
187 {
188 *pkcs7 = gnutls_calloc(1, sizeof(gnutls_pkcs7_int));
189
190 if (*pkcs7) {
191 int result = pkcs7_reinit(*pkcs7);
192 if (result < 0) {
193 gnutls_assert();
194 gnutls_free(*pkcs7);
195 return result;
196 }
197 return 0; /* success */
198 }
199 return GNUTLS_E_MEMORY_ERROR;
200 }
201
202 /**
203 * gnutls_pkcs7_deinit:
204 * @pkcs7: the type to be deinitialized
205 *
206 * This function will deinitialize a PKCS7 type.
207 **/
gnutls_pkcs7_deinit(gnutls_pkcs7_t pkcs7)208 void gnutls_pkcs7_deinit(gnutls_pkcs7_t pkcs7)
209 {
210 if (!pkcs7)
211 return;
212
213 if (pkcs7->pkcs7)
214 asn1_delete_structure(&pkcs7->pkcs7);
215
216 if (pkcs7->signed_data)
217 asn1_delete_structure(&pkcs7->signed_data);
218
219 _gnutls_free_datum(&pkcs7->der_signed_data);
220
221 gnutls_free(pkcs7);
222 }
223
224 /**
225 * gnutls_pkcs7_import:
226 * @pkcs7: The data to store the parsed PKCS7.
227 * @data: The DER or PEM encoded PKCS7.
228 * @format: One of DER or PEM
229 *
230 * This function will convert the given DER or PEM encoded PKCS7 to
231 * the native #gnutls_pkcs7_t format. The output will be stored in
232 * @pkcs7.
233 *
234 * If the PKCS7 is PEM encoded it should have a header of "PKCS7".
235 *
236 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
237 * negative error value.
238 **/
239 int
gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format)240 gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data,
241 gnutls_x509_crt_fmt_t format)
242 {
243 int result = 0, need_free = 0;
244 gnutls_datum_t _data;
245
246 if (pkcs7 == NULL)
247 return GNUTLS_E_INVALID_REQUEST;
248
249 _data.data = data->data;
250 _data.size = data->size;
251
252 /* If the PKCS7 is in PEM format then decode it
253 */
254 if (format == GNUTLS_X509_FMT_PEM) {
255 result =
256 _gnutls_fbase64_decode(PEM_PKCS7, data->data,
257 data->size, &_data);
258
259 if (result < 0) {
260 gnutls_assert();
261 return result;
262 }
263
264 need_free = 1;
265 }
266
267 if (pkcs7->expanded) {
268 result = pkcs7_reinit(pkcs7);
269 if (result < 0) {
270 gnutls_assert();
271 goto cleanup;
272 }
273 }
274 pkcs7->expanded = 1;
275
276 result = asn1_der_decoding(&pkcs7->pkcs7, _data.data, _data.size, NULL);
277 if (result != ASN1_SUCCESS) {
278 result = _gnutls_asn2err(result);
279 gnutls_assert();
280 goto cleanup;
281 }
282
283 /* Decode the signed data.
284 */
285 result = _decode_pkcs7_signed_data(pkcs7);
286 if (result < 0) {
287 gnutls_assert();
288 goto cleanup;
289 }
290
291 result = 0;
292
293 cleanup:
294 if (need_free)
295 _gnutls_free_datum(&_data);
296 return result;
297 }
298
299 /**
300 * gnutls_pkcs7_get_crt_raw2:
301 * @pkcs7: should contain a gnutls_pkcs7_t type
302 * @indx: contains the index of the certificate to extract
303 * @cert: will hold the contents of the certificate; must be deallocated with gnutls_free()
304 *
305 * This function will return a certificate of the PKCS7 or RFC2630
306 * certificate set.
307 *
308 * After the last certificate has been read
309 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
310 *
311 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
312 * negative error value. If the provided buffer is not long enough,
313 * then @certificate_size is updated and
314 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
315 *
316 * Since: 3.4.2
317 **/
318 int
gnutls_pkcs7_get_crt_raw2(gnutls_pkcs7_t pkcs7,unsigned indx,gnutls_datum_t * cert)319 gnutls_pkcs7_get_crt_raw2(gnutls_pkcs7_t pkcs7,
320 unsigned indx, gnutls_datum_t * cert)
321 {
322 int result, len;
323 char root2[MAX_NAME_SIZE];
324 char oid[MAX_OID_SIZE];
325 gnutls_datum_t tmp = { NULL, 0 };
326
327 if (pkcs7 == NULL)
328 return GNUTLS_E_INVALID_REQUEST;
329
330 /* Step 2. Parse the CertificateSet
331 */
332 snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
333
334 len = sizeof(oid) - 1;
335
336 result = asn1_read_value(pkcs7->signed_data, root2, oid, &len);
337
338 if (result == ASN1_VALUE_NOT_FOUND) {
339 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
340 goto cleanup;
341 }
342
343 if (result != ASN1_SUCCESS) {
344 gnutls_assert();
345 result = _gnutls_asn2err(result);
346 goto cleanup;
347 }
348
349 /* if 'Certificate' is the choice found:
350 */
351 if (strcmp(oid, "certificate") == 0) {
352 int start, end;
353
354 result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
355 if (result < 0) {
356 gnutls_assert();
357 goto cleanup;
358 }
359
360 result =
361 asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data,
362 tmp.size, root2, &start, &end);
363
364 if (result != ASN1_SUCCESS) {
365 gnutls_assert();
366 result = _gnutls_asn2err(result);
367 goto cleanup;
368 }
369
370 end = end - start + 1;
371
372 result = _gnutls_set_datum(cert, &tmp.data[start], end);
373 } else {
374 result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
375 }
376
377 cleanup:
378 _gnutls_free_datum(&tmp);
379 return result;
380 }
381
382 /**
383 * gnutls_pkcs7_get_crt_raw:
384 * @pkcs7: should contain a gnutls_pkcs7_t type
385 * @indx: contains the index of the certificate to extract
386 * @certificate: the contents of the certificate will be copied
387 * there (may be null)
388 * @certificate_size: should hold the size of the certificate
389 *
390 * This function will return a certificate of the PKCS7 or RFC2630
391 * certificate set.
392 *
393 * After the last certificate has been read
394 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
395 *
396 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
397 * negative error value. If the provided buffer is not long enough,
398 * then @certificate_size is updated and
399 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
400 **/
401 int
gnutls_pkcs7_get_crt_raw(gnutls_pkcs7_t pkcs7,unsigned indx,void * certificate,size_t * certificate_size)402 gnutls_pkcs7_get_crt_raw(gnutls_pkcs7_t pkcs7,
403 unsigned indx, void *certificate,
404 size_t * certificate_size)
405 {
406 int ret;
407 gnutls_datum_t tmp = { NULL, 0 };
408
409 ret = gnutls_pkcs7_get_crt_raw2(pkcs7, indx, &tmp);
410 if (ret < 0)
411 return gnutls_assert_val(ret);
412
413 if ((unsigned)tmp.size > *certificate_size) {
414 *certificate_size = tmp.size;
415 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
416 goto cleanup;
417 }
418
419 *certificate_size = tmp.size;
420 if (certificate)
421 memcpy(certificate, tmp.data, tmp.size);
422
423 cleanup:
424 _gnutls_free_datum(&tmp);
425 return ret;
426 }
427
428 /**
429 * gnutls_pkcs7_get_crt_count:
430 * @pkcs7: should contain a #gnutls_pkcs7_t type
431 *
432 * This function will return the number of certificates in the PKCS7
433 * or RFC2630 certificate set.
434 *
435 * Returns: On success, a positive number is returned, otherwise a
436 * negative error value.
437 **/
gnutls_pkcs7_get_crt_count(gnutls_pkcs7_t pkcs7)438 int gnutls_pkcs7_get_crt_count(gnutls_pkcs7_t pkcs7)
439 {
440 int result, count;
441
442 if (pkcs7 == NULL)
443 return GNUTLS_E_INVALID_REQUEST;
444
445 /* Step 2. Count the CertificateSet */
446
447 result =
448 asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
449 if (result != ASN1_SUCCESS) {
450 gnutls_assert();
451 return 0; /* no certificates */
452 }
453
454 return count;
455 }
456
457 /**
458 * gnutls_pkcs7_signature_info_deinit:
459 * @info: should point to a #gnutls_pkcs7_signature_info_st structure
460 *
461 * This function will deinitialize any allocated value in the
462 * provided #gnutls_pkcs7_signature_info_st.
463 *
464 * Since: 3.4.2
465 **/
gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st * info)466 void gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st * info)
467 {
468 gnutls_free(info->sig.data);
469 gnutls_free(info->issuer_dn.data);
470 gnutls_free(info->signer_serial.data);
471 gnutls_free(info->issuer_keyid.data);
472 gnutls_pkcs7_attrs_deinit(info->signed_attrs);
473 gnutls_pkcs7_attrs_deinit(info->unsigned_attrs);
474 memset(info, 0, sizeof(*info));
475 }
476
parse_time(gnutls_pkcs7_t pkcs7,const char * root)477 static time_t parse_time(gnutls_pkcs7_t pkcs7, const char *root)
478 {
479 char tval[128];
480 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
481 time_t ret;
482 int result, len;
483
484 result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Time", &c2);
485 if (result != ASN1_SUCCESS) {
486 ret = -1;
487 gnutls_assert();
488 goto cleanup;
489 }
490
491 len = sizeof(tval);
492 result = asn1_read_value(pkcs7->signed_data, root, tval, &len);
493 if (result != ASN1_SUCCESS) {
494 ret = -1;
495 gnutls_assert();
496 goto cleanup;
497 }
498
499 result = _asn1_strict_der_decode(&c2, tval, len, NULL);
500 if (result != ASN1_SUCCESS) {
501 ret = -1;
502 gnutls_assert();
503 goto cleanup;
504 }
505
506 ret = _gnutls_x509_get_time(c2, "", 0);
507
508 cleanup:
509 asn1_delete_structure(&c2);
510 return ret;
511 }
512
513 /**
514 * gnutls_pkcs7_get_signature_count:
515 * @pkcs7: should contain a #gnutls_pkcs7_t type
516 *
517 * This function will return the number of signatures in the PKCS7
518 * structure.
519 *
520 * Returns: On success, a positive number is returned, otherwise a
521 * negative error value.
522 *
523 * Since: 3.4.3
524 **/
gnutls_pkcs7_get_signature_count(gnutls_pkcs7_t pkcs7)525 int gnutls_pkcs7_get_signature_count(gnutls_pkcs7_t pkcs7)
526 {
527 int ret, count;
528
529 if (pkcs7 == NULL)
530 return GNUTLS_E_INVALID_REQUEST;
531
532 ret =
533 asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
534 if (ret != ASN1_SUCCESS) {
535 gnutls_assert();
536 return 0;
537 }
538
539 return count;
540 }
541
542 /**
543 * gnutls_pkcs7_get_signature_info:
544 * @pkcs7: should contain a #gnutls_pkcs7_t type
545 * @idx: the index of the signature info to check
546 * @info: will contain the output signature
547 *
548 * This function will return information about the signature identified
549 * by idx in the provided PKCS #7 structure. The information should be
550 * deinitialized using gnutls_pkcs7_signature_info_deinit().
551 *
552 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
553 * negative error value.
554 *
555 * Since: 3.4.2
556 **/
gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7,unsigned idx,gnutls_pkcs7_signature_info_st * info)557 int gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7, unsigned idx,
558 gnutls_pkcs7_signature_info_st * info)
559 {
560 int ret, count, len;
561 char root[256];
562 char oid[MAX_OID_SIZE];
563 gnutls_pk_algorithm_t pk;
564 gnutls_sign_algorithm_t sig;
565 gnutls_datum_t tmp = { NULL, 0 };
566 unsigned i;
567
568 if (pkcs7 == NULL)
569 return GNUTLS_E_INVALID_REQUEST;
570
571 memset(info, 0, sizeof(*info));
572 info->signing_time = -1;
573
574 ret =
575 asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
576 if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
577 gnutls_assert();
578 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
579 }
580 snprintf(root, sizeof(root),
581 "signerInfos.?%u.signatureAlgorithm.algorithm", idx + 1);
582
583 len = sizeof(oid) - 1;
584 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
585 if (ret != ASN1_SUCCESS) {
586 gnutls_assert();
587 goto unsupp_algo;
588 }
589
590 sig = gnutls_oid_to_sign(oid);
591 if (sig == GNUTLS_SIGN_UNKNOWN) {
592 /* great PKCS #7 allows to only specify a public key algo */
593 pk = gnutls_oid_to_pk(oid);
594 if (pk == GNUTLS_PK_UNKNOWN) {
595 gnutls_assert();
596 goto unsupp_algo;
597 }
598
599 /* use the digests algorithm */
600 snprintf(root, sizeof(root),
601 "signerInfos.?%u.digestAlgorithm.algorithm", idx + 1);
602
603 len = sizeof(oid) - 1;
604 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
605 if (ret != ASN1_SUCCESS) {
606 gnutls_assert();
607 goto unsupp_algo;
608 }
609
610 ret = gnutls_oid_to_digest(oid);
611 if (ret == GNUTLS_DIG_UNKNOWN) {
612 gnutls_assert();
613 goto unsupp_algo;
614 }
615
616 sig = gnutls_pk_to_sign(pk, ret);
617 if (sig == GNUTLS_SIGN_UNKNOWN) {
618 gnutls_assert();
619 goto unsupp_algo;
620 }
621 }
622
623 info->algo = sig;
624
625 snprintf(root, sizeof(root), "signerInfos.?%u.signature", idx + 1);
626 /* read the signature */
627 ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &info->sig);
628 if (ret < 0) {
629 gnutls_assert();
630 goto fail;
631 }
632
633 /* read the issuer info */
634 snprintf(root, sizeof(root),
635 "signerInfos.?%u.sid.issuerAndSerialNumber.issuer.rdnSequence",
636 idx + 1);
637 /* read the signature */
638 ret =
639 _gnutls_x509_get_raw_field(pkcs7->signed_data, root,
640 &info->issuer_dn);
641 if (ret >= 0) {
642 snprintf(root, sizeof(root),
643 "signerInfos.?%u.sid.issuerAndSerialNumber.serialNumber",
644 idx + 1);
645 /* read the signature */
646 ret =
647 _gnutls_x509_read_value(pkcs7->signed_data, root,
648 &info->signer_serial);
649 if (ret < 0) {
650 gnutls_assert();
651 goto fail;
652 }
653 } else { /* keyid */
654 snprintf(root, sizeof(root),
655 "signerInfos.?%u.sid.subjectKeyIdentifier", idx + 1);
656 /* read the signature */
657 ret =
658 _gnutls_x509_read_value(pkcs7->signed_data, root,
659 &info->issuer_keyid);
660 if (ret < 0) {
661 gnutls_assert();
662 }
663 }
664
665 if (info->issuer_keyid.data == NULL && info->issuer_dn.data == NULL) {
666 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
667 goto fail;
668 }
669
670 /* read the signing time */
671 for (i = 0;; i++) {
672 snprintf(root, sizeof(root),
673 "signerInfos.?%u.signedAttrs.?%u.type", idx + 1,
674 i + 1);
675 len = sizeof(oid) - 1;
676 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
677 if (ret != ASN1_SUCCESS) {
678 break;
679 }
680
681 snprintf(root, sizeof(root),
682 "signerInfos.?%u.signedAttrs.?%u.values.?1", idx + 1,
683 i + 1);
684 ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
685 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
686 tmp.data = NULL;
687 tmp.size = 0;
688 } else if (ret < 0) {
689 gnutls_assert();
690 goto fail;
691 }
692
693 ret = gnutls_pkcs7_add_attr(&info->signed_attrs, oid, &tmp, 0);
694 gnutls_free(tmp.data);
695
696 if (ret < 0) {
697 gnutls_assert();
698 goto fail;
699 }
700
701 if (strcmp(oid, ATTR_SIGNING_TIME) == 0) {
702 info->signing_time = parse_time(pkcs7, root);
703 }
704 }
705
706 /* read the unsigned attrs */
707 for (i = 0;; i++) {
708 snprintf(root, sizeof(root),
709 "signerInfos.?%u.unsignedAttrs.?%u.type", idx + 1,
710 i + 1);
711 len = sizeof(oid) - 1;
712 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
713 if (ret != ASN1_SUCCESS) {
714 break;
715 }
716
717 snprintf(root, sizeof(root),
718 "signerInfos.?%u.unsignedAttrs.?%u.values.?1", idx + 1,
719 i + 1);
720 ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
721 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
722 tmp.data = NULL;
723 tmp.size = 0;
724 } else if (ret < 0) {
725 gnutls_assert();
726 goto fail;
727 }
728
729 ret =
730 gnutls_pkcs7_add_attr(&info->unsigned_attrs, oid, &tmp, 0);
731 gnutls_free(tmp.data);
732
733 if (ret < 0) {
734 gnutls_assert();
735 goto fail;
736 }
737 }
738
739 return 0;
740 fail:
741 gnutls_free(tmp.data);
742 gnutls_pkcs7_signature_info_deinit(info);
743 return ret;
744 unsupp_algo:
745 return GNUTLS_E_UNKNOWN_ALGORITHM;
746 }
747
748 /* Verifies that the hash attribute ATTR_MESSAGE_DIGEST is present
749 * and matches our calculated hash */
verify_hash_attr(gnutls_pkcs7_t pkcs7,const char * root,gnutls_sign_algorithm_t algo,const gnutls_datum_t * data)750 static int verify_hash_attr(gnutls_pkcs7_t pkcs7, const char *root,
751 gnutls_sign_algorithm_t algo,
752 const gnutls_datum_t *data)
753 {
754 unsigned hash;
755 gnutls_datum_t tmp = { NULL, 0 };
756 gnutls_datum_t tmp2 = { NULL, 0 };
757 uint8_t hash_output[MAX_HASH_SIZE];
758 unsigned hash_size, i;
759 char oid[MAX_OID_SIZE];
760 char name[256];
761 unsigned msg_digest_ok = 0;
762 unsigned num_cont_types = 0;
763 int ret;
764
765 hash = gnutls_sign_get_hash_algorithm(algo);
766
767 /* hash the data */
768 if (hash == GNUTLS_DIG_UNKNOWN)
769 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
770
771 hash_size = gnutls_hash_get_len(hash);
772
773 if (data == NULL || data->data == NULL) {
774 data = &pkcs7->der_signed_data;
775 }
776
777 if (data->size == 0) {
778 return gnutls_assert_val(GNUTLS_E_NO_EMBEDDED_DATA);
779 }
780
781 ret = gnutls_hash_fast(hash, data->data, data->size, hash_output);
782 if (ret < 0)
783 return gnutls_assert_val(ret);
784
785 /* now verify that hash matches */
786 for (i = 0;; i++) {
787 snprintf(name, sizeof(name), "%s.signedAttrs.?%u", root, i + 1);
788
789 ret = _gnutls_x509_decode_and_read_attribute(pkcs7->signed_data,
790 name, oid,
791 sizeof(oid), &tmp,
792 1, 0);
793 if (ret < 0) {
794 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
795 break;
796 return gnutls_assert_val(ret);
797 }
798
799 if (strcmp(oid, ATTR_MESSAGE_DIGEST) == 0) {
800 ret =
801 _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
802 tmp.data, tmp.size,
803 &tmp2, 0);
804 if (ret < 0) {
805 gnutls_assert();
806 goto cleanup;
807 }
808
809 if (tmp2.size == hash_size
810 && memcmp(hash_output, tmp2.data, tmp2.size) == 0) {
811 msg_digest_ok = 1;
812 } else {
813 gnutls_assert();
814 }
815 } else if (strcmp(oid, ATTR_CONTENT_TYPE) == 0) {
816 if (num_cont_types > 0) {
817 gnutls_assert();
818 ret = GNUTLS_E_PARSING_ERROR;
819 goto cleanup;
820 }
821
822 num_cont_types++;
823
824 /* check if it matches */
825 ret =
826 _gnutls_x509_get_raw_field(pkcs7->signed_data,
827 "encapContentInfo.eContentType",
828 &tmp2);
829 if (ret < 0) {
830 gnutls_assert();
831 goto cleanup;
832 }
833
834 if (tmp2.size != tmp.size
835 || memcmp(tmp.data, tmp2.data, tmp2.size) != 0) {
836 gnutls_assert();
837 ret = GNUTLS_E_PARSING_ERROR;
838 goto cleanup;
839 }
840 }
841
842 gnutls_free(tmp.data);
843 gnutls_free(tmp2.data);
844 }
845
846 if (msg_digest_ok)
847 ret = 0;
848 else
849 ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
850
851 cleanup:
852 gnutls_free(tmp.data);
853 gnutls_free(tmp2.data);
854 return ret;
855 }
856
857 /* Returns the data to be used for signature verification. PKCS #7
858 * decided that this should not be an easy task.
859 */
figure_pkcs7_sigdata(gnutls_pkcs7_t pkcs7,const char * root,const gnutls_datum_t * data,gnutls_sign_algorithm_t algo,gnutls_datum_t * sigdata)860 static int figure_pkcs7_sigdata(gnutls_pkcs7_t pkcs7, const char *root,
861 const gnutls_datum_t * data,
862 gnutls_sign_algorithm_t algo,
863 gnutls_datum_t * sigdata)
864 {
865 int ret;
866 char name[256];
867
868 snprintf(name, sizeof(name), "%s.signedAttrs", root);
869 /* read the signature */
870 ret = _gnutls_x509_get_raw_field(pkcs7->signed_data, name, sigdata);
871 if (ret == 0) {
872 /* verify that hash matches */
873 ret = verify_hash_attr(pkcs7, root, algo, data);
874 if (ret < 0)
875 return gnutls_assert_val(ret);
876
877 if (sigdata->size > 0)
878 sigdata->data[0] = 0x31;
879
880 return 0;
881 }
882
883 /* We have no signedAttrs. Use the provided data, or the encapsulated */
884 if (data == NULL || data->data == NULL) {
885 return _gnutls_set_datum(sigdata, pkcs7->der_signed_data.data, pkcs7->der_signed_data.size);
886 }
887
888 return _gnutls_set_datum(sigdata, data->data, data->size);
889 }
890
891 /**
892 * gnutls_pkcs7_get_embedded_data:
893 * @pkcs7: should contain a gnutls_pkcs7_t type
894 * @flags: must be zero or %GNUTLS_PKCS7_EDATA_GET_RAW
895 * @data: will hold the embedded data in the provided structure
896 *
897 * This function will return the data embedded in the signature of
898 * the PKCS7 structure. If no data are available then
899 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
900 *
901 * The returned data must be de-allocated using gnutls_free().
902 *
903 * Note, that this function returns the exact same data that are
904 * authenticated. If the %GNUTLS_PKCS7_EDATA_GET_RAW flag is provided,
905 * the returned data will be including the wrapping tag/value as
906 * they are encoded in the structure.
907 *
908 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
909 * negative error value.
910 *
911 * Since: 3.4.8
912 **/
913 int
gnutls_pkcs7_get_embedded_data(gnutls_pkcs7_t pkcs7,unsigned flags,gnutls_datum_t * data)914 gnutls_pkcs7_get_embedded_data(gnutls_pkcs7_t pkcs7, unsigned flags,
915 gnutls_datum_t *data)
916 {
917 if (pkcs7 == NULL)
918 return GNUTLS_E_INVALID_REQUEST;
919
920 if (pkcs7->der_signed_data.size == 0)
921 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
922
923 if (flags & GNUTLS_PKCS7_EDATA_GET_RAW) {
924 if (pkcs7->signed_data == NULL)
925 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
926
927 return _gnutls_x509_read_value(pkcs7->signed_data, "encapContentInfo.eContent", data);
928 } else {
929 return _gnutls_set_datum(data, pkcs7->der_signed_data.data, pkcs7->der_signed_data.size);
930 }
931 }
932
933 /**
934 * gnutls_pkcs7_get_embedded_data_oid:
935 * @pkcs7: should contain a gnutls_pkcs7_t type
936 *
937 * This function will return the OID of the data embedded in the signature of
938 * the PKCS7 structure. If no data are available then %NULL will be
939 * returned. The returned value will be valid during the lifetime
940 * of the @pkcs7 structure.
941 *
942 * Returns: On success, a pointer to an OID string, %NULL on error.
943 *
944 * Since: 3.5.5
945 **/
946 const char *
gnutls_pkcs7_get_embedded_data_oid(gnutls_pkcs7_t pkcs7)947 gnutls_pkcs7_get_embedded_data_oid(gnutls_pkcs7_t pkcs7)
948 {
949 if (pkcs7 == NULL || pkcs7->encap_data_oid[0] == 0)
950 return NULL;
951
952 return pkcs7->encap_data_oid;
953 }
954
955 /**
956 * gnutls_pkcs7_verify_direct:
957 * @pkcs7: should contain a #gnutls_pkcs7_t type
958 * @signer: the certificate believed to have signed the structure
959 * @idx: the index of the signature info to check
960 * @data: The data to be verified or %NULL
961 * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
962 *
963 * This function will verify the provided data against the signature
964 * present in the SignedData of the PKCS #7 structure. If the data
965 * provided are NULL then the data in the encapsulatedContent field
966 * will be used instead.
967 *
968 * Note that, unlike gnutls_pkcs7_verify() this function does not
969 * verify the key purpose of the signer. It is expected for the caller
970 * to verify the intended purpose of the %signer -e.g., via gnutls_x509_crt_get_key_purpose_oid(),
971 * or gnutls_x509_crt_check_key_purpose().
972 *
973 * Note also, that since GnuTLS 3.5.6 this function introduces checks in the
974 * end certificate (@signer), including time checks and key usage checks.
975 *
976 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
977 * negative error value. A verification error results to a
978 * %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
979 * to verify to a %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
980 *
981 * Since: 3.4.2
982 **/
gnutls_pkcs7_verify_direct(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_t signer,unsigned idx,const gnutls_datum_t * data,unsigned flags)983 int gnutls_pkcs7_verify_direct(gnutls_pkcs7_t pkcs7,
984 gnutls_x509_crt_t signer,
985 unsigned idx,
986 const gnutls_datum_t *data, unsigned flags)
987 {
988 int count, ret;
989 gnutls_datum_t tmpdata = { NULL, 0 };
990 gnutls_pkcs7_signature_info_st info;
991 gnutls_datum_t sigdata = { NULL, 0 };
992 char root[128];
993
994 memset(&info, 0, sizeof(info));
995
996 if (pkcs7 == NULL)
997 return GNUTLS_E_INVALID_REQUEST;
998
999 ret =
1000 asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
1001 if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
1002 gnutls_assert();
1003 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1004 }
1005
1006 ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
1007 if (ret < 0) {
1008 gnutls_assert();
1009 goto cleanup;
1010 }
1011
1012 snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
1013 ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
1014 if (ret < 0) {
1015 gnutls_assert();
1016 goto cleanup;
1017 }
1018
1019 ret =
1020 gnutls_x509_crt_verify_data2(signer, info.algo, flags, &sigdata,
1021 &info.sig);
1022 if (ret < 0) {
1023 gnutls_assert();
1024 }
1025
1026 cleanup:
1027 gnutls_free(tmpdata.data);
1028 gnutls_free(sigdata.data);
1029 gnutls_pkcs7_signature_info_deinit(&info);
1030
1031 return ret;
1032 }
1033
1034 /* Finds the issuer of the given certificate (@cert) in the
1035 * included in PKCS#7 list of certificates */
find_verified_issuer_of(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_t cert,const char * purpose,unsigned vflags)1036 static gnutls_x509_crt_t find_verified_issuer_of(gnutls_pkcs7_t pkcs7,
1037 gnutls_x509_crt_t cert,
1038 const char *purpose,
1039 unsigned vflags)
1040 {
1041 gnutls_x509_crt_t issuer = NULL;
1042 int ret, count;
1043 gnutls_datum_t tmp = { NULL, 0 };
1044 unsigned i, vtmp;
1045
1046 count = gnutls_pkcs7_get_crt_count(pkcs7);
1047 if (count < 0) {
1048 gnutls_assert();
1049 return NULL;
1050 }
1051
1052 for (i = 0; i < (unsigned)count; i++) {
1053 /* Try to find the signer in the appended list. */
1054 ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmp);
1055 if (ret < 0) {
1056 gnutls_assert();
1057 goto fail;
1058 }
1059
1060 ret = gnutls_x509_crt_init(&issuer);
1061 if (ret < 0) {
1062 gnutls_assert();
1063 goto fail;
1064 }
1065
1066 ret = gnutls_x509_crt_import(issuer, &tmp, GNUTLS_X509_FMT_DER);
1067 if (ret < 0) {
1068 gnutls_assert();
1069 goto fail;
1070 }
1071
1072 if (!gnutls_x509_crt_check_issuer(cert, issuer)) {
1073 gnutls_assert();
1074 goto skip;
1075 }
1076
1077 ret = gnutls_x509_crt_verify(cert, &issuer, 1, vflags|GNUTLS_VERIFY_DO_NOT_ALLOW_SAME, &vtmp);
1078 if (ret < 0 || vtmp != 0 ||
1079 (purpose != NULL && !_gnutls_check_key_purpose(issuer, purpose, 0))) {
1080 gnutls_assert(); /* maybe next one is trusted */
1081 _gnutls_cert_log("failed verification with", issuer);
1082 skip:
1083 gnutls_x509_crt_deinit(issuer);
1084 issuer = NULL;
1085 gnutls_free(tmp.data);
1086 continue;
1087 }
1088
1089 _gnutls_cert_log("issued by", issuer);
1090
1091 /* we found a signer we trust. let's return it */
1092 break;
1093 }
1094
1095 if (issuer == NULL) {
1096 gnutls_assert();
1097 return NULL;
1098 }
1099 goto cleanup;
1100
1101 fail:
1102 if (issuer) {
1103 gnutls_x509_crt_deinit(issuer);
1104 issuer = NULL;
1105 }
1106
1107 cleanup:
1108 gnutls_free(tmp.data);
1109
1110 return issuer;
1111 }
1112
1113 /* Finds a certificate that is issued by @issuer -if given-, and matches
1114 * either the serial number or the key ID (both in @info) .
1115 */
find_child_of_with_serial(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_t issuer,const char * purpose,gnutls_pkcs7_signature_info_st * info)1116 static gnutls_x509_crt_t find_child_of_with_serial(gnutls_pkcs7_t pkcs7,
1117 gnutls_x509_crt_t issuer,
1118 const char *purpose,
1119 gnutls_pkcs7_signature_info_st *info)
1120 {
1121 gnutls_x509_crt_t crt = NULL;
1122 int ret, count;
1123 uint8_t tmp[128];
1124 size_t tmp_size;
1125 gnutls_datum_t tmpdata = { NULL, 0 };
1126 unsigned i;
1127
1128 count = gnutls_pkcs7_get_crt_count(pkcs7);
1129 if (count < 0) {
1130 gnutls_assert();
1131 return NULL;
1132 }
1133
1134 for (i = 0; i < (unsigned)count; i++) {
1135 /* Try to find the crt in the appended list. */
1136 ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmpdata);
1137 if (ret < 0) {
1138 gnutls_assert();
1139 goto fail;
1140 }
1141
1142 ret = gnutls_x509_crt_init(&crt);
1143 if (ret < 0) {
1144 gnutls_assert();
1145 goto fail;
1146 }
1147
1148 ret = gnutls_x509_crt_import(crt, &tmpdata, GNUTLS_X509_FMT_DER);
1149 if (ret < 0) {
1150 gnutls_assert();
1151 goto fail;
1152 }
1153
1154 if (issuer != NULL) {
1155 if (!gnutls_x509_crt_check_issuer(crt, issuer)) {
1156 gnutls_assert();
1157 goto skip;
1158 }
1159 }
1160
1161 if (purpose) {
1162 ret =
1163 _gnutls_check_key_purpose(crt, purpose, 0);
1164 if (ret == 0) {
1165 _gnutls_cert_log("key purpose unacceptable", crt);
1166 goto skip;
1167 }
1168 }
1169
1170 if (info->signer_serial.size > 0) {
1171 tmp_size = sizeof(tmp);
1172 ret = gnutls_x509_crt_get_serial(crt, tmp, &tmp_size);
1173 if (ret < 0) {
1174 gnutls_assert();
1175 goto skip;
1176 }
1177
1178 if (tmp_size != info->signer_serial.size
1179 || memcmp(info->signer_serial.data, tmp,
1180 tmp_size) != 0) {
1181 _gnutls_cert_log("doesn't match serial", crt);
1182 gnutls_assert();
1183 goto skip;
1184 }
1185 } else if (info->issuer_keyid.size > 0) {
1186 tmp_size = sizeof(tmp);
1187 ret = gnutls_x509_crt_get_subject_key_id(crt, tmp, &tmp_size, NULL);
1188 if (ret < 0) {
1189 gnutls_assert();
1190 goto skip;
1191 }
1192
1193 if (tmp_size != info->issuer_keyid.size
1194 || memcmp(info->issuer_keyid.data, tmp,
1195 tmp_size) != 0) {
1196 _gnutls_cert_log("doesn't match key ID", crt);
1197 gnutls_assert();
1198 skip:
1199 gnutls_x509_crt_deinit(crt);
1200 crt = NULL;
1201 gnutls_free(tmpdata.data);
1202 continue;
1203 }
1204 } else {
1205 gnutls_assert();
1206 crt = NULL;
1207 goto fail;
1208 }
1209
1210 _gnutls_cert_log("signer is", crt);
1211
1212 /* we found the child with the given serial or key ID */
1213 break;
1214 }
1215
1216 if (crt == NULL) {
1217 gnutls_assert();
1218 return NULL;
1219 }
1220
1221 goto cleanup;
1222 fail:
1223 if (crt) {
1224 gnutls_x509_crt_deinit(crt);
1225 crt = NULL;
1226 }
1227
1228 cleanup:
1229 gnutls_free(tmpdata.data);
1230
1231 return crt;
1232 }
1233
1234 static
find_signer(gnutls_pkcs7_t pkcs7,gnutls_x509_trust_list_t tl,gnutls_typed_vdata_st * vdata,unsigned vdata_size,unsigned vflags,gnutls_pkcs7_signature_info_st * info)1235 gnutls_x509_crt_t find_signer(gnutls_pkcs7_t pkcs7, gnutls_x509_trust_list_t tl,
1236 gnutls_typed_vdata_st * vdata,
1237 unsigned vdata_size,
1238 unsigned vflags,
1239 gnutls_pkcs7_signature_info_st * info)
1240 {
1241 gnutls_x509_crt_t issuer = NULL;
1242 gnutls_x509_crt_t signer = NULL;
1243 int ret;
1244 gnutls_datum_t tmp = { NULL, 0 };
1245 unsigned i, vtmp;
1246 const char *purpose = NULL;
1247
1248 if (info->issuer_keyid.data) {
1249 ret =
1250 gnutls_x509_trust_list_get_issuer_by_subject_key_id(tl,
1251 NULL,
1252 &info->
1253 issuer_keyid,
1254 &signer,
1255 0);
1256 if (ret < 0) {
1257 gnutls_assert();
1258 signer = NULL;
1259 }
1260 }
1261
1262 /* get key purpose */
1263 for (i = 0; i < vdata_size; i++) {
1264 if (vdata[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
1265 purpose = (char *)vdata[i].data;
1266 break;
1267 }
1268 }
1269
1270 /* this will give us the issuer of the signer (wtf) */
1271 if (info->issuer_dn.data && signer == NULL) {
1272 ret =
1273 gnutls_x509_trust_list_get_issuer_by_dn(tl,
1274 &info->issuer_dn,
1275 &issuer, 0);
1276 if (ret < 0) {
1277 gnutls_assert();
1278 signer = NULL;
1279 }
1280
1281 if (issuer) {
1282 /* try to find the actual signer in the list of
1283 * certificates */
1284 signer = find_child_of_with_serial(pkcs7, issuer, purpose, info);
1285 if (signer == NULL) {
1286 gnutls_assert();
1287 goto fail;
1288 }
1289
1290 gnutls_x509_crt_deinit(issuer);
1291 issuer = NULL;
1292 }
1293 }
1294
1295 if (signer == NULL) {
1296 /* get the signer from the pkcs7 list; the one that matches serial
1297 * or key ID */
1298 signer = find_child_of_with_serial(pkcs7, NULL, purpose, info);
1299 if (signer == NULL) {
1300 gnutls_assert();
1301 goto fail;
1302 }
1303
1304 /* if the signer cannot be verified from our trust list, make a chain of certificates
1305 * starting from the identified signer, to a root we know. */
1306 ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1307 if (ret < 0 || vtmp != 0) {
1308 gnutls_x509_crt_t prev = NULL;
1309
1310 issuer = signer;
1311 /* construct a chain */
1312 do {
1313 if (prev && prev != signer) {
1314 gnutls_x509_crt_deinit(prev);
1315 }
1316 prev = issuer;
1317
1318 issuer = find_verified_issuer_of(pkcs7, issuer, purpose, vflags);
1319
1320 if (issuer != NULL && gnutls_x509_crt_check_issuer(issuer, issuer)) {
1321 if (prev) gnutls_x509_crt_deinit(prev);
1322 prev = issuer;
1323 break;
1324 }
1325 } while(issuer != NULL);
1326
1327 issuer = prev; /* the last we have seen */
1328
1329 if (issuer == NULL) {
1330 gnutls_assert();
1331 goto fail;
1332 }
1333
1334 ret = gnutls_x509_trust_list_verify_crt2(tl, &issuer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1335 if (ret < 0 || vtmp != 0) {
1336 /* could not construct a valid chain */
1337 _gnutls_reason_log("signer's chain failed trust list verification", vtmp);
1338 gnutls_assert();
1339 goto fail;
1340 }
1341 }
1342 } else {
1343 /* verify that the signer we got is trusted */
1344 ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1345 if (ret < 0 || vtmp != 0) {
1346 /* could not construct a valid chain */
1347 _gnutls_reason_log("signer failed trust list verification", vtmp);
1348 gnutls_assert();
1349 goto fail;
1350 }
1351 }
1352
1353 if (signer == NULL) {
1354 gnutls_assert();
1355 goto fail;
1356 }
1357
1358 goto cleanup;
1359
1360 fail:
1361 if (signer != NULL) {
1362 if (issuer == signer)
1363 issuer = NULL;
1364 gnutls_x509_crt_deinit(signer);
1365 signer = NULL;
1366 }
1367
1368 cleanup:
1369 if (issuer != NULL) {
1370 gnutls_x509_crt_deinit(issuer);
1371 issuer = NULL;
1372 }
1373 gnutls_free(tmp.data);
1374
1375 return signer;
1376 }
1377
1378 /**
1379 * gnutls_pkcs7_verify:
1380 * @pkcs7: should contain a #gnutls_pkcs7_t type
1381 * @tl: A list of trusted certificates
1382 * @vdata: an array of typed data
1383 * @vdata_size: the number of data elements
1384 * @idx: the index of the signature info to check
1385 * @data: The data to be verified or %NULL
1386 * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
1387 *
1388 * This function will verify the provided data against the signature
1389 * present in the SignedData of the PKCS #7 structure. If the data
1390 * provided are NULL then the data in the encapsulatedContent field
1391 * will be used instead.
1392 *
1393 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1394 * negative error value. A verification error results to a
1395 * %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
1396 * to verify to a %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
1397 *
1398 * Since: 3.4.2
1399 **/
gnutls_pkcs7_verify(gnutls_pkcs7_t pkcs7,gnutls_x509_trust_list_t tl,gnutls_typed_vdata_st * vdata,unsigned int vdata_size,unsigned idx,const gnutls_datum_t * data,unsigned flags)1400 int gnutls_pkcs7_verify(gnutls_pkcs7_t pkcs7,
1401 gnutls_x509_trust_list_t tl,
1402 gnutls_typed_vdata_st *vdata,
1403 unsigned int vdata_size,
1404 unsigned idx,
1405 const gnutls_datum_t *data, unsigned flags)
1406 {
1407 int count, ret;
1408 gnutls_datum_t tmpdata = { NULL, 0 };
1409 gnutls_pkcs7_signature_info_st info;
1410 gnutls_x509_crt_t signer;
1411 gnutls_datum_t sigdata = { NULL, 0 };
1412 char root[128];
1413
1414 memset(&info, 0, sizeof(info));
1415
1416 if (pkcs7 == NULL)
1417 return GNUTLS_E_INVALID_REQUEST;
1418
1419 ret =
1420 asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
1421 if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
1422 gnutls_assert();
1423 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1424 }
1425
1426 /* read data */
1427 ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
1428 if (ret < 0) {
1429 gnutls_assert();
1430 goto cleanup;
1431 }
1432
1433 snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
1434 ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
1435 if (ret < 0) {
1436 gnutls_assert();
1437 goto cleanup;
1438 }
1439
1440 signer = find_signer(pkcs7, tl, vdata, vdata_size, flags, &info);
1441 if (signer) {
1442 ret =
1443 gnutls_x509_crt_verify_data3(signer, info.algo, vdata, vdata_size,
1444 &sigdata, &info.sig, flags);
1445 if (ret < 0) {
1446 _gnutls_cert_log("failed struct verification with", signer);
1447 gnutls_assert();
1448 }
1449 gnutls_x509_crt_deinit(signer);
1450 } else {
1451 gnutls_assert();
1452 ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
1453 }
1454
1455 cleanup:
1456 gnutls_free(tmpdata.data);
1457 gnutls_free(sigdata.data);
1458 gnutls_pkcs7_signature_info_deinit(&info);
1459
1460 return ret;
1461 }
1462
disable_opt_fields(gnutls_pkcs7_t pkcs7)1463 static void disable_opt_fields(gnutls_pkcs7_t pkcs7)
1464 {
1465 int result;
1466 int count;
1467
1468 /* disable the optional fields */
1469 result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1470 if (result != ASN1_SUCCESS || count == 0) {
1471 (void)asn1_write_value(pkcs7->signed_data, "crls", NULL, 0);
1472 }
1473
1474 result =
1475 asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
1476 if (result != ASN1_SUCCESS || count == 0) {
1477 (void)asn1_write_value(pkcs7->signed_data, "certificates", NULL, 0);
1478 }
1479
1480 return;
1481 }
1482
reencode(gnutls_pkcs7_t pkcs7)1483 static int reencode(gnutls_pkcs7_t pkcs7)
1484 {
1485 int result;
1486
1487 if (pkcs7->signed_data != ASN1_TYPE_EMPTY) {
1488 disable_opt_fields(pkcs7);
1489
1490 /* Replace the old content with the new
1491 */
1492 result =
1493 _gnutls_x509_der_encode_and_copy(pkcs7->signed_data, "",
1494 pkcs7->pkcs7, "content",
1495 0);
1496 if (result < 0) {
1497 return gnutls_assert_val(result);
1498 }
1499
1500 /* Write the content type of the signed data
1501 */
1502 result =
1503 asn1_write_value(pkcs7->pkcs7, "contentType",
1504 SIGNED_DATA_OID, 1);
1505 if (result != ASN1_SUCCESS) {
1506 gnutls_assert();
1507 return _gnutls_asn2err(result);
1508 }
1509 }
1510 return 0;
1511 }
1512
1513 /**
1514 * gnutls_pkcs7_export:
1515 * @pkcs7: The pkcs7 type
1516 * @format: the format of output params. One of PEM or DER.
1517 * @output_data: will contain a structure PEM or DER encoded
1518 * @output_data_size: holds the size of output_data (and will be
1519 * replaced by the actual size of parameters)
1520 *
1521 * This function will export the pkcs7 structure to DER or PEM format.
1522 *
1523 * If the buffer provided is not long enough to hold the output, then
1524 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1525 * will be returned.
1526 *
1527 * If the structure is PEM encoded, it will have a header
1528 * of "BEGIN PKCS7".
1529 *
1530 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1531 * negative error value.
1532 **/
1533 int
gnutls_pkcs7_export(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_fmt_t format,void * output_data,size_t * output_data_size)1534 gnutls_pkcs7_export(gnutls_pkcs7_t pkcs7,
1535 gnutls_x509_crt_fmt_t format, void *output_data,
1536 size_t * output_data_size)
1537 {
1538 int ret;
1539 if (pkcs7 == NULL)
1540 return GNUTLS_E_INVALID_REQUEST;
1541
1542 if ((ret = reencode(pkcs7)) < 0)
1543 return gnutls_assert_val(ret);
1544
1545 return _gnutls_x509_export_int(pkcs7->pkcs7, format, PEM_PKCS7,
1546 output_data, output_data_size);
1547 }
1548
1549 /**
1550 * gnutls_pkcs7_export2:
1551 * @pkcs7: The pkcs7 type
1552 * @format: the format of output params. One of PEM or DER.
1553 * @out: will contain a structure PEM or DER encoded
1554 *
1555 * This function will export the pkcs7 structure to DER or PEM format.
1556 *
1557 * The output buffer is allocated using gnutls_malloc().
1558 *
1559 * If the structure is PEM encoded, it will have a header
1560 * of "BEGIN PKCS7".
1561 *
1562 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1563 * negative error value.
1564 *
1565 * Since: 3.1.3
1566 **/
1567 int
gnutls_pkcs7_export2(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)1568 gnutls_pkcs7_export2(gnutls_pkcs7_t pkcs7,
1569 gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
1570 {
1571 int ret;
1572 if (pkcs7 == NULL)
1573 return GNUTLS_E_INVALID_REQUEST;
1574
1575 if ((ret = reencode(pkcs7)) < 0)
1576 return gnutls_assert_val(ret);
1577
1578 return _gnutls_x509_export_int2(pkcs7->pkcs7, format, PEM_PKCS7, out);
1579 }
1580
1581 /* Creates an empty signed data structure in the pkcs7
1582 * structure and returns a handle to the signed data.
1583 */
create_empty_signed_data(ASN1_TYPE pkcs7,ASN1_TYPE * sdata)1584 static int create_empty_signed_data(ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
1585 {
1586 int result;
1587
1588 *sdata = ASN1_TYPE_EMPTY;
1589
1590 if ((result = asn1_create_element
1591 (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
1592 sdata)) != ASN1_SUCCESS) {
1593 gnutls_assert();
1594 result = _gnutls_asn2err(result);
1595 goto cleanup;
1596 }
1597
1598 /* Use version 1
1599 */
1600 result = asn1_write_value(*sdata, "version", &one, 1);
1601 if (result != ASN1_SUCCESS) {
1602 gnutls_assert();
1603 result = _gnutls_asn2err(result);
1604 goto cleanup;
1605 }
1606
1607 /* Use no digest algorithms
1608 */
1609
1610 /* id-data */
1611 result =
1612 asn1_write_value(*sdata, "encapContentInfo.eContentType",
1613 DIGESTED_DATA_OID, 1);
1614 if (result != ASN1_SUCCESS) {
1615 gnutls_assert();
1616 result = _gnutls_asn2err(result);
1617 goto cleanup;
1618 }
1619
1620 result = asn1_write_value(*sdata, "encapContentInfo.eContent", NULL, 0);
1621 if (result != ASN1_SUCCESS) {
1622 gnutls_assert();
1623 result = _gnutls_asn2err(result);
1624 goto cleanup;
1625 }
1626
1627 /* Add no certificates.
1628 */
1629
1630 /* Add no crls.
1631 */
1632
1633 /* Add no signerInfos.
1634 */
1635
1636 return 0;
1637
1638 cleanup:
1639 asn1_delete_structure(sdata);
1640 return result;
1641
1642 }
1643
1644 /**
1645 * gnutls_pkcs7_set_crt_raw:
1646 * @pkcs7: The pkcs7 type
1647 * @crt: the DER encoded certificate to be added
1648 *
1649 * This function will add a certificate to the PKCS7 or RFC2630
1650 * certificate set.
1651 *
1652 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1653 * negative error value.
1654 **/
gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7,const gnutls_datum_t * crt)1655 int gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt)
1656 {
1657 int result;
1658
1659 if (pkcs7 == NULL)
1660 return GNUTLS_E_INVALID_REQUEST;
1661
1662 /* If the signed data are uninitialized
1663 * then create them.
1664 */
1665 if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
1666 /* The pkcs7 structure is new, so create the
1667 * signedData.
1668 */
1669 result =
1670 create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
1671 if (result < 0) {
1672 gnutls_assert();
1673 return result;
1674 }
1675 }
1676
1677 /* Step 2. Append the new certificate.
1678 */
1679
1680 result = asn1_write_value(pkcs7->signed_data, "certificates", "NEW", 1);
1681 if (result != ASN1_SUCCESS) {
1682 gnutls_assert();
1683 result = _gnutls_asn2err(result);
1684 goto cleanup;
1685 }
1686
1687 result =
1688 asn1_write_value(pkcs7->signed_data, "certificates.?LAST",
1689 "certificate", 1);
1690 if (result != ASN1_SUCCESS) {
1691 gnutls_assert();
1692 result = _gnutls_asn2err(result);
1693 goto cleanup;
1694 }
1695
1696 result =
1697 asn1_write_value(pkcs7->signed_data,
1698 "certificates.?LAST.certificate", crt->data,
1699 crt->size);
1700 if (result != ASN1_SUCCESS) {
1701 gnutls_assert();
1702 result = _gnutls_asn2err(result);
1703 goto cleanup;
1704 }
1705
1706 result = 0;
1707
1708 cleanup:
1709 return result;
1710 }
1711
1712 /**
1713 * gnutls_pkcs7_set_crt:
1714 * @pkcs7: The pkcs7 type
1715 * @crt: the certificate to be copied.
1716 *
1717 * This function will add a parsed certificate to the PKCS7 or
1718 * RFC2630 certificate set. This is a wrapper function over
1719 * gnutls_pkcs7_set_crt_raw() .
1720 *
1721 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1722 * negative error value.
1723 **/
gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_t crt)1724 int gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
1725 {
1726 int ret;
1727 gnutls_datum_t data;
1728
1729 if (pkcs7 == NULL)
1730 return GNUTLS_E_INVALID_REQUEST;
1731
1732 ret = _gnutls_x509_der_encode(crt->cert, "", &data, 0);
1733 if (ret < 0) {
1734 gnutls_assert();
1735 return ret;
1736 }
1737
1738 ret = gnutls_pkcs7_set_crt_raw(pkcs7, &data);
1739
1740 _gnutls_free_datum(&data);
1741
1742 if (ret < 0) {
1743 gnutls_assert();
1744 return ret;
1745 }
1746
1747 return 0;
1748 }
1749
1750 /**
1751 * gnutls_pkcs7_delete_crt:
1752 * @pkcs7: The pkcs7 type
1753 * @indx: the index of the certificate to delete
1754 *
1755 * This function will delete a certificate from a PKCS7 or RFC2630
1756 * certificate set. Index starts from 0. Returns 0 on success.
1757 *
1758 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1759 * negative error value.
1760 **/
gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7,int indx)1761 int gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7, int indx)
1762 {
1763 int result;
1764 char root2[MAX_NAME_SIZE];
1765
1766 if (pkcs7 == NULL)
1767 return GNUTLS_E_INVALID_REQUEST;
1768
1769 /* Step 2. Delete the certificate.
1770 */
1771
1772 snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
1773
1774 result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
1775 if (result != ASN1_SUCCESS) {
1776 gnutls_assert();
1777 result = _gnutls_asn2err(result);
1778 goto cleanup;
1779 }
1780
1781 return 0;
1782
1783 cleanup:
1784 return result;
1785 }
1786
1787 /* Read and write CRLs
1788 */
1789
1790 /**
1791 * gnutls_pkcs7_get_crl_raw2:
1792 * @pkcs7: The pkcs7 type
1793 * @indx: contains the index of the crl to extract
1794 * @crl: will contain the contents of the CRL in an allocated buffer
1795 *
1796 * This function will return a DER encoded CRL of the PKCS7 or RFC2630 crl set.
1797 *
1798 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1799 * negative error value. After the last crl has been read
1800 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1801 *
1802 * Since: 3.4.2
1803 **/
1804 int
gnutls_pkcs7_get_crl_raw2(gnutls_pkcs7_t pkcs7,unsigned indx,gnutls_datum_t * crl)1805 gnutls_pkcs7_get_crl_raw2(gnutls_pkcs7_t pkcs7,
1806 unsigned indx, gnutls_datum_t * crl)
1807 {
1808 int result;
1809 char root2[MAX_NAME_SIZE];
1810 gnutls_datum_t tmp = { NULL, 0 };
1811 int start, end;
1812
1813 if (pkcs7 == NULL || crl == NULL)
1814 return GNUTLS_E_INVALID_REQUEST;
1815
1816 result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
1817 if (result < 0) {
1818 gnutls_assert();
1819 goto cleanup;
1820 }
1821
1822 /* Step 2. Parse the CertificateSet
1823 */
1824
1825 snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
1826
1827 /* Get the raw CRL
1828 */
1829 result =
1830 asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data, tmp.size,
1831 root2, &start, &end);
1832
1833 if (result != ASN1_SUCCESS) {
1834 gnutls_assert();
1835 result = _gnutls_asn2err(result);
1836 goto cleanup;
1837 }
1838
1839 end = end - start + 1;
1840
1841 result = _gnutls_set_datum(crl, &tmp.data[start], end);
1842
1843 cleanup:
1844 _gnutls_free_datum(&tmp);
1845 return result;
1846 }
1847
1848 /**
1849 * gnutls_pkcs7_get_crl_raw:
1850 * @pkcs7: The pkcs7 type
1851 * @indx: contains the index of the crl to extract
1852 * @crl: the contents of the crl will be copied there (may be null)
1853 * @crl_size: should hold the size of the crl
1854 *
1855 * This function will return a crl of the PKCS7 or RFC2630 crl set.
1856 *
1857 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1858 * negative error value. If the provided buffer is not long enough,
1859 * then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
1860 * returned. After the last crl has been read
1861 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1862 **/
1863 int
gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7,unsigned indx,void * crl,size_t * crl_size)1864 gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7,
1865 unsigned indx, void *crl, size_t * crl_size)
1866 {
1867 int ret;
1868 gnutls_datum_t tmp = { NULL, 0 };
1869
1870 ret = gnutls_pkcs7_get_crl_raw2(pkcs7, indx, &tmp);
1871 if (ret < 0)
1872 return gnutls_assert_val(ret);
1873
1874 if ((unsigned)tmp.size > *crl_size) {
1875 *crl_size = tmp.size;
1876 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
1877 goto cleanup;
1878 }
1879
1880 assert(tmp.data != NULL);
1881
1882 *crl_size = tmp.size;
1883 if (crl)
1884 memcpy(crl, tmp.data, tmp.size);
1885
1886 cleanup:
1887 _gnutls_free_datum(&tmp);
1888 return ret;
1889 }
1890
1891 /**
1892 * gnutls_pkcs7_get_crl_count:
1893 * @pkcs7: The pkcs7 type
1894 *
1895 * This function will return the number of certificates in the PKCS7
1896 * or RFC2630 crl set.
1897 *
1898 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1899 * negative error value.
1900 **/
gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7)1901 int gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7)
1902 {
1903 int result, count;
1904
1905 if (pkcs7 == NULL)
1906 return GNUTLS_E_INVALID_REQUEST;
1907
1908 /* Step 2. Count the CertificateSet */
1909
1910 result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1911 if (result != ASN1_SUCCESS) {
1912 gnutls_assert();
1913 return 0; /* no crls */
1914 }
1915
1916 return count;
1917
1918 }
1919
1920 /**
1921 * gnutls_pkcs7_set_crl_raw:
1922 * @pkcs7: The pkcs7 type
1923 * @crl: the DER encoded crl to be added
1924 *
1925 * This function will add a crl to the PKCS7 or RFC2630 crl set.
1926 *
1927 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1928 * negative error value.
1929 **/
gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7,const gnutls_datum_t * crl)1930 int gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl)
1931 {
1932 int result;
1933
1934 if (pkcs7 == NULL)
1935 return GNUTLS_E_INVALID_REQUEST;
1936
1937 /* If the signed data are uninitialized
1938 * then create them.
1939 */
1940 if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
1941 /* The pkcs7 structure is new, so create the
1942 * signedData.
1943 */
1944 result =
1945 create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
1946 if (result < 0) {
1947 gnutls_assert();
1948 return result;
1949 }
1950 }
1951
1952 /* Step 2. Append the new crl.
1953 */
1954
1955 result = asn1_write_value(pkcs7->signed_data, "crls", "NEW", 1);
1956 if (result != ASN1_SUCCESS) {
1957 gnutls_assert();
1958 result = _gnutls_asn2err(result);
1959 goto cleanup;
1960 }
1961
1962 result =
1963 asn1_write_value(pkcs7->signed_data, "crls.?LAST", crl->data,
1964 crl->size);
1965 if (result != ASN1_SUCCESS) {
1966 gnutls_assert();
1967 result = _gnutls_asn2err(result);
1968 goto cleanup;
1969 }
1970
1971 result = 0;
1972
1973 cleanup:
1974 return result;
1975 }
1976
1977 /**
1978 * gnutls_pkcs7_set_crl:
1979 * @pkcs7: The pkcs7 type
1980 * @crl: the DER encoded crl to be added
1981 *
1982 * This function will add a parsed CRL to the PKCS7 or RFC2630 crl
1983 * set.
1984 *
1985 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1986 * negative error value.
1987 **/
gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7,gnutls_x509_crl_t crl)1988 int gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
1989 {
1990 int ret;
1991 gnutls_datum_t data;
1992
1993 if (pkcs7 == NULL)
1994 return GNUTLS_E_INVALID_REQUEST;
1995
1996 ret = _gnutls_x509_der_encode(crl->crl, "", &data, 0);
1997 if (ret < 0) {
1998 gnutls_assert();
1999 return ret;
2000 }
2001
2002 ret = gnutls_pkcs7_set_crl_raw(pkcs7, &data);
2003
2004 _gnutls_free_datum(&data);
2005
2006 if (ret < 0) {
2007 gnutls_assert();
2008 return ret;
2009 }
2010
2011 return 0;
2012 }
2013
2014 /**
2015 * gnutls_pkcs7_delete_crl:
2016 * @pkcs7: The pkcs7 type
2017 * @indx: the index of the crl to delete
2018 *
2019 * This function will delete a crl from a PKCS7 or RFC2630 crl set.
2020 * Index starts from 0. Returns 0 on success.
2021 *
2022 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2023 * negative error value.
2024 **/
gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7,int indx)2025 int gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7, int indx)
2026 {
2027 int result;
2028 char root2[MAX_NAME_SIZE];
2029
2030 if (pkcs7 == NULL)
2031 return GNUTLS_E_INVALID_REQUEST;
2032
2033 /* Delete the crl.
2034 */
2035
2036 snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
2037
2038 result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
2039 if (result != ASN1_SUCCESS) {
2040 gnutls_assert();
2041 result = _gnutls_asn2err(result);
2042 goto cleanup;
2043 }
2044
2045 return 0;
2046
2047 cleanup:
2048 return result;
2049 }
2050
write_signer_id(ASN1_TYPE c2,const char * root,gnutls_x509_crt_t signer,unsigned flags)2051 static int write_signer_id(ASN1_TYPE c2, const char *root,
2052 gnutls_x509_crt_t signer, unsigned flags)
2053 {
2054 int result;
2055 size_t serial_size;
2056 uint8_t serial[128];
2057 char name[256];
2058
2059 if (flags & GNUTLS_PKCS7_WRITE_SPKI) {
2060 const uint8_t ver = 3;
2061
2062 snprintf(name, sizeof(name), "%s.version", root);
2063 result = asn1_write_value(c2, name, &ver, 1);
2064 if (result != ASN1_SUCCESS) {
2065 gnutls_assert();
2066 return _gnutls_asn2err(result);
2067 }
2068
2069 snprintf(name, sizeof(name), "%s.sid", root);
2070 result = asn1_write_value(c2, name, "subjectKeyIdentifier", 1);
2071 if (result != ASN1_SUCCESS) {
2072 gnutls_assert();
2073 return _gnutls_asn2err(result);
2074 }
2075
2076 serial_size = sizeof(serial);
2077 result =
2078 gnutls_x509_crt_get_subject_key_id(signer, serial,
2079 &serial_size, NULL);
2080 if (result < 0)
2081 return gnutls_assert_val(result);
2082
2083 snprintf(name, sizeof(name), "%s.subjectKeyIdentifier", root);
2084 result = asn1_write_value(c2, name, serial, serial_size);
2085 if (result != ASN1_SUCCESS) {
2086 gnutls_assert();
2087 return _gnutls_asn2err(result);
2088 }
2089 } else {
2090 serial_size = sizeof(serial);
2091 result =
2092 gnutls_x509_crt_get_serial(signer, serial, &serial_size);
2093 if (result < 0)
2094 return gnutls_assert_val(result);
2095
2096 snprintf(name, sizeof(name), "%s.sid", root);
2097 result = asn1_write_value(c2, name, "issuerAndSerialNumber", 1);
2098 if (result != ASN1_SUCCESS) {
2099 gnutls_assert();
2100 return _gnutls_asn2err(result);
2101 }
2102
2103 snprintf(name, sizeof(name),
2104 "%s.sid.issuerAndSerialNumber.serialNumber", root);
2105 result = asn1_write_value(c2, name, serial, serial_size);
2106 if (result != ASN1_SUCCESS) {
2107 gnutls_assert();
2108 return _gnutls_asn2err(result);
2109 }
2110
2111 snprintf(name, sizeof(name),
2112 "%s.sid.issuerAndSerialNumber.issuer", root);
2113 result =
2114 asn1_copy_node(c2, name, signer->cert,
2115 "tbsCertificate.issuer");
2116 if (result != ASN1_SUCCESS) {
2117 gnutls_assert();
2118 return _gnutls_asn2err(result);
2119 }
2120 }
2121
2122 return 0;
2123 }
2124
add_attrs(ASN1_TYPE c2,const char * root,gnutls_pkcs7_attrs_t attrs,unsigned already_set)2125 static int add_attrs(ASN1_TYPE c2, const char *root, gnutls_pkcs7_attrs_t attrs,
2126 unsigned already_set)
2127 {
2128 char name[256];
2129 gnutls_pkcs7_attrs_st *p = attrs;
2130 int result;
2131
2132 if (attrs == NULL) {
2133 /* if there are no other attributes delete that field */
2134 if (already_set == 0)
2135 (void)asn1_write_value(c2, root, NULL, 0);
2136 } else {
2137 while (p != NULL) {
2138 result = asn1_write_value(c2, root, "NEW", 1);
2139 if (result != ASN1_SUCCESS) {
2140 gnutls_assert();
2141 return _gnutls_asn2err(result);
2142 }
2143
2144 snprintf(name, sizeof(name), "%s.?LAST.type", root);
2145 result = asn1_write_value(c2, name, p->oid, 1);
2146 if (result != ASN1_SUCCESS) {
2147 gnutls_assert();
2148 return _gnutls_asn2err(result);
2149 }
2150
2151 snprintf(name, sizeof(name), "%s.?LAST.values", root);
2152 result = asn1_write_value(c2, name, "NEW", 1);
2153 if (result != ASN1_SUCCESS) {
2154 gnutls_assert();
2155 return _gnutls_asn2err(result);
2156 }
2157
2158 snprintf(name, sizeof(name), "%s.?LAST.values.?1",
2159 root);
2160 result =
2161 asn1_write_value(c2, name, p->data.data,
2162 p->data.size);
2163 if (result != ASN1_SUCCESS) {
2164 gnutls_assert();
2165 return _gnutls_asn2err(result);
2166 }
2167
2168 p = p->next;
2169 }
2170 }
2171
2172 return 0;
2173 }
2174
write_attributes(ASN1_TYPE c2,const char * root,const gnutls_datum_t * data,const mac_entry_st * me,gnutls_pkcs7_attrs_t other_attrs,unsigned flags)2175 static int write_attributes(ASN1_TYPE c2, const char *root,
2176 const gnutls_datum_t * data,
2177 const mac_entry_st * me,
2178 gnutls_pkcs7_attrs_t other_attrs, unsigned flags)
2179 {
2180 char name[256];
2181 int result, ret;
2182 uint8_t digest[MAX_HASH_SIZE];
2183 gnutls_datum_t tmp = { NULL, 0 };
2184 unsigned digest_size;
2185 unsigned already_set = 0;
2186
2187 if (flags & GNUTLS_PKCS7_INCLUDE_TIME) {
2188 if (data == NULL || data->data == NULL) {
2189 gnutls_assert();
2190 return GNUTLS_E_INVALID_REQUEST;
2191 }
2192
2193 /* Add time */
2194 result = asn1_write_value(c2, root, "NEW", 1);
2195 if (result != ASN1_SUCCESS) {
2196 gnutls_assert();
2197 ret = _gnutls_asn2err(result);
2198 return ret;
2199 }
2200
2201 snprintf(name, sizeof(name), "%s.?LAST.type", root);
2202 result = asn1_write_value(c2, name, ATTR_SIGNING_TIME, 1);
2203 if (result != ASN1_SUCCESS) {
2204 gnutls_assert();
2205 ret = _gnutls_asn2err(result);
2206 return ret;
2207 }
2208
2209 snprintf(name, sizeof(name), "%s.?LAST.values", root);
2210 result = asn1_write_value(c2, name, "NEW", 1);
2211 if (result != ASN1_SUCCESS) {
2212 gnutls_assert();
2213 ret = _gnutls_asn2err(result);
2214 return ret;
2215 }
2216
2217 snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2218 ret = _gnutls_x509_set_raw_time(c2, name, gnutls_time(0));
2219 if (ret < 0) {
2220 gnutls_assert();
2221 return ret;
2222 }
2223
2224 already_set = 1;
2225 }
2226
2227 ret = add_attrs(c2, root, other_attrs, already_set);
2228 if (ret < 0) {
2229 gnutls_assert();
2230 return ret;
2231 }
2232
2233 if (already_set != 0 || other_attrs != NULL) {
2234 /* Add content type */
2235 result = asn1_write_value(c2, root, "NEW", 1);
2236 if (result != ASN1_SUCCESS) {
2237 gnutls_assert();
2238 ret = _gnutls_asn2err(result);
2239 return ret;
2240 }
2241
2242 snprintf(name, sizeof(name), "%s.?LAST.type", root);
2243 result = asn1_write_value(c2, name, ATTR_CONTENT_TYPE, 1);
2244 if (result != ASN1_SUCCESS) {
2245 gnutls_assert();
2246 ret = _gnutls_asn2err(result);
2247 return ret;
2248 }
2249
2250 snprintf(name, sizeof(name), "%s.?LAST.values", root);
2251 result = asn1_write_value(c2, name, "NEW", 1);
2252 if (result != ASN1_SUCCESS) {
2253 gnutls_assert();
2254 ret = _gnutls_asn2err(result);
2255 return ret;
2256 }
2257
2258 ret =
2259 _gnutls_x509_get_raw_field(c2,
2260 "encapContentInfo.eContentType",
2261 &tmp);
2262 if (ret < 0) {
2263 gnutls_assert();
2264 return ret;
2265 }
2266
2267 snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2268 result = asn1_write_value(c2, name, tmp.data, tmp.size);
2269 gnutls_free(tmp.data);
2270
2271 if (result != ASN1_SUCCESS) {
2272 gnutls_assert();
2273 ret = _gnutls_asn2err(result);
2274 return ret;
2275 }
2276
2277 /* If we add any attribute we should add them all */
2278 /* Add hash */
2279 digest_size = _gnutls_hash_get_algo_len(me);
2280 ret = gnutls_hash_fast(MAC_TO_DIG(me->id), data->data, data->size, digest);
2281 if (ret < 0) {
2282 gnutls_assert();
2283 return ret;
2284 }
2285
2286 result = asn1_write_value(c2, root, "NEW", 1);
2287 if (result != ASN1_SUCCESS) {
2288 gnutls_assert();
2289 ret = _gnutls_asn2err(result);
2290 return ret;
2291 }
2292
2293 snprintf(name, sizeof(name), "%s.?LAST", root);
2294 ret =
2295 _gnutls_x509_encode_and_write_attribute(ATTR_MESSAGE_DIGEST,
2296 c2, name, digest,
2297 digest_size, 1);
2298 if (ret < 0) {
2299 gnutls_assert();
2300 return ret;
2301 }
2302 }
2303
2304 return 0;
2305 }
2306
2307 /**
2308 * gnutls_pkcs7_sign:
2309 * @pkcs7: should contain a #gnutls_pkcs7_t type
2310 * @signer: the certificate to sign the structure
2311 * @signer_key: the key to sign the structure
2312 * @data: The data to be signed or %NULL if the data are already embedded
2313 * @signed_attrs: Any additional attributes to be included in the signed ones (or %NULL)
2314 * @unsigned_attrs: Any additional attributes to be included in the unsigned ones (or %NULL)
2315 * @dig: The digest algorithm to use for signing
2316 * @flags: Should be zero or one of %GNUTLS_PKCS7 flags
2317 *
2318 * This function will add a signature in the provided PKCS #7 structure
2319 * for the provided data. Multiple signatures can be made with different
2320 * signers.
2321 *
2322 * The available flags are:
2323 * %GNUTLS_PKCS7_EMBED_DATA, %GNUTLS_PKCS7_INCLUDE_TIME, %GNUTLS_PKCS7_INCLUDE_CERT,
2324 * and %GNUTLS_PKCS7_WRITE_SPKI. They are explained in the #gnutls_pkcs7_sign_flags
2325 * definition.
2326 *
2327 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2328 * negative error value.
2329 *
2330 * Since: 3.4.2
2331 **/
gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7,gnutls_x509_crt_t signer,gnutls_privkey_t signer_key,const gnutls_datum_t * data,gnutls_pkcs7_attrs_t signed_attrs,gnutls_pkcs7_attrs_t unsigned_attrs,gnutls_digest_algorithm_t dig,unsigned flags)2332 int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7,
2333 gnutls_x509_crt_t signer,
2334 gnutls_privkey_t signer_key,
2335 const gnutls_datum_t *data,
2336 gnutls_pkcs7_attrs_t signed_attrs,
2337 gnutls_pkcs7_attrs_t unsigned_attrs,
2338 gnutls_digest_algorithm_t dig, unsigned flags)
2339 {
2340 int ret, result;
2341 gnutls_datum_t sigdata = { NULL, 0 };
2342 gnutls_datum_t signature = { NULL, 0 };
2343 const mac_entry_st *me = hash_to_entry(dig);
2344 unsigned pk, sigalgo;
2345 gnutls_x509_spki_st key_params, params;
2346 const gnutls_sign_entry_st *se;
2347
2348 if (pkcs7 == NULL || me == NULL)
2349 return GNUTLS_E_INVALID_REQUEST;
2350
2351 if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
2352 result =
2353 asn1_create_element(_gnutls_get_pkix(),
2354 "PKIX1.pkcs-7-SignedData",
2355 &pkcs7->signed_data);
2356 if (result != ASN1_SUCCESS) {
2357 gnutls_assert();
2358 ret = _gnutls_asn2err(result);
2359 goto cleanup;
2360 }
2361
2362 if (!(flags & GNUTLS_PKCS7_EMBED_DATA)) {
2363 (void)asn1_write_value(pkcs7->signed_data,
2364 "encapContentInfo.eContent", NULL, 0);
2365 }
2366 }
2367
2368 result = asn1_write_value(pkcs7->signed_data, "version", &one, 1);
2369 if (result != ASN1_SUCCESS) {
2370 ret = _gnutls_asn2err(result);
2371 goto cleanup;
2372 }
2373
2374 result =
2375 asn1_write_value(pkcs7->signed_data,
2376 "encapContentInfo.eContentType", DATA_OID,
2377 0);
2378 if (result != ASN1_SUCCESS) {
2379 ret = _gnutls_asn2err(result);
2380 goto cleanup;
2381 }
2382
2383 if ((flags & GNUTLS_PKCS7_EMBED_DATA) && data->data) { /* embed data */
2384 ret =
2385 _gnutls_x509_write_string(pkcs7->signed_data,
2386 "encapContentInfo.eContent", data,
2387 ASN1_ETYPE_OCTET_STRING);
2388 if (ret < 0) {
2389 goto cleanup;
2390 }
2391 }
2392
2393 if (flags & GNUTLS_PKCS7_INCLUDE_CERT) {
2394 ret = gnutls_pkcs7_set_crt(pkcs7, signer);
2395 if (ret < 0) {
2396 gnutls_assert();
2397 goto cleanup;
2398 }
2399 }
2400
2401 /* append digest info algorithm */
2402 result =
2403 asn1_write_value(pkcs7->signed_data, "digestAlgorithms", "NEW", 1);
2404 if (result != ASN1_SUCCESS) {
2405 gnutls_assert();
2406 ret = _gnutls_asn2err(result);
2407 goto cleanup;
2408 }
2409
2410 result =
2411 asn1_write_value(pkcs7->signed_data,
2412 "digestAlgorithms.?LAST.algorithm",
2413 _gnutls_x509_digest_to_oid(me), 1);
2414 if (result != ASN1_SUCCESS) {
2415 gnutls_assert();
2416 ret = _gnutls_asn2err(result);
2417 goto cleanup;
2418 }
2419
2420 (void)asn1_write_value(pkcs7->signed_data,
2421 "digestAlgorithms.?LAST.parameters", NULL, 0);
2422
2423 /* append signer's info */
2424 result = asn1_write_value(pkcs7->signed_data, "signerInfos", "NEW", 1);
2425 if (result != ASN1_SUCCESS) {
2426 gnutls_assert();
2427 ret = _gnutls_asn2err(result);
2428 goto cleanup;
2429 }
2430
2431 result =
2432 asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.version",
2433 &one, 1);
2434 if (result != ASN1_SUCCESS) {
2435 gnutls_assert();
2436 ret = _gnutls_asn2err(result);
2437 goto cleanup;
2438 }
2439
2440 result =
2441 asn1_write_value(pkcs7->signed_data,
2442 "signerInfos.?LAST.digestAlgorithm.algorithm",
2443 _gnutls_x509_digest_to_oid(me), 1);
2444 if (result != ASN1_SUCCESS) {
2445 gnutls_assert();
2446 ret = _gnutls_asn2err(result);
2447 goto cleanup;
2448 }
2449
2450 (void)asn1_write_value(pkcs7->signed_data,
2451 "signerInfos.?LAST.digestAlgorithm.parameters", NULL,
2452 0);
2453
2454 ret =
2455 write_signer_id(pkcs7->signed_data, "signerInfos.?LAST", signer,
2456 flags);
2457 if (ret < 0) {
2458 gnutls_assert();
2459 goto cleanup;
2460 }
2461
2462 ret =
2463 add_attrs(pkcs7->signed_data, "signerInfos.?LAST.unsignedAttrs",
2464 unsigned_attrs, 0);
2465 if (ret < 0) {
2466 gnutls_assert();
2467 goto cleanup;
2468 }
2469
2470 ret =
2471 write_attributes(pkcs7->signed_data,
2472 "signerInfos.?LAST.signedAttrs", data, me,
2473 signed_attrs, flags);
2474 if (ret < 0) {
2475 gnutls_assert();
2476 goto cleanup;
2477 }
2478
2479 disable_opt_fields(pkcs7);
2480
2481 /* write the signature algorithm */
2482 pk = gnutls_x509_crt_get_pk_algorithm(signer, NULL);
2483
2484 ret = _gnutls_privkey_get_spki_params(signer_key, &key_params);
2485 if (ret < 0) {
2486 gnutls_assert();
2487 goto cleanup;
2488 }
2489
2490 ret = _gnutls_x509_crt_get_spki_params(signer, &key_params, ¶ms);
2491 if (ret < 0) {
2492 gnutls_assert();
2493 goto cleanup;
2494 }
2495
2496 ret = _gnutls_privkey_update_spki_params(signer_key, pk, dig, 0,
2497 ¶ms);
2498 if (ret < 0) {
2499 gnutls_assert();
2500 goto cleanup;
2501 }
2502
2503 se = _gnutls_pk_to_sign_entry(params.pk, dig);
2504 if (se == NULL) {
2505 ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
2506 goto cleanup;
2507 }
2508
2509 /* RFC5652 is silent on what the values would be and initially I assumed that
2510 * typical signature algorithms should be set. However RFC2315 (PKCS#7) mentions
2511 * that a generic RSA OID should be used. We switch to this "unexpected" value
2512 * because some implementations cannot cope with the "expected" signature values.
2513 */
2514 params.legacy = 1;
2515 ret =
2516 _gnutls_x509_write_sign_params(pkcs7->signed_data,
2517 "signerInfos.?LAST.signatureAlgorithm",
2518 se, ¶ms);
2519 if (ret < 0) {
2520 gnutls_assert();
2521 goto cleanup;
2522 }
2523
2524 sigalgo = se->id;
2525
2526 /* sign the data */
2527 ret =
2528 figure_pkcs7_sigdata(pkcs7, "signerInfos.?LAST", data, sigalgo,
2529 &sigdata);
2530 if (ret < 0) {
2531 gnutls_assert();
2532 goto cleanup;
2533 }
2534
2535 FIX_SIGN_PARAMS(params, flags, dig);
2536
2537 ret = privkey_sign_and_hash_data(signer_key, se,
2538 &sigdata, &signature, ¶ms);
2539 if (ret < 0) {
2540 gnutls_assert();
2541 goto cleanup;
2542 }
2543
2544 result =
2545 asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.signature",
2546 signature.data, signature.size);
2547 if (result != ASN1_SUCCESS) {
2548 gnutls_assert();
2549 ret = _gnutls_asn2err(result);
2550 goto cleanup;
2551 }
2552
2553 ret = 0;
2554
2555 cleanup:
2556 gnutls_free(sigdata.data);
2557 gnutls_free(signature.data);
2558 return ret;
2559 }
2560