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, &params);
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 						  &params);
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, &params);
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, &params);
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