Line data Source code
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 : */
49 203 : static int _decode_pkcs7_signed_data(gnutls_pkcs7_t pkcs7)
50 : {
51 203 : ASN1_TYPE c2;
52 203 : int len, result;
53 203 : gnutls_datum_t tmp = {NULL, 0};
54 :
55 203 : len = MAX_OID_SIZE - 1;
56 203 : result = asn1_read_value(pkcs7->pkcs7, "contentType", pkcs7->encap_data_oid, &len);
57 203 : if (result != ASN1_SUCCESS) {
58 1 : gnutls_assert();
59 1 : return _gnutls_asn2err(result);
60 : }
61 :
62 202 : if (strcmp(pkcs7->encap_data_oid, SIGNED_DATA_OID) != 0) {
63 11 : gnutls_assert();
64 11 : _gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n", pkcs7->encap_data_oid);
65 11 : return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
66 : }
67 :
68 191 : if ((result = asn1_create_element
69 : (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
70 : &c2)) != ASN1_SUCCESS) {
71 0 : gnutls_assert();
72 0 : return _gnutls_asn2err(result);
73 : }
74 :
75 : /* the Signed-data has been created, so
76 : * decode them.
77 : */
78 191 : result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
79 191 : if (result < 0) {
80 0 : gnutls_assert();
81 0 : goto cleanup;
82 : }
83 :
84 : /* Step 1. In case of a signed structure extract certificate set.
85 : */
86 :
87 191 : result = asn1_der_decoding(&c2, tmp.data, tmp.size, NULL);
88 191 : if (result != ASN1_SUCCESS) {
89 1 : gnutls_assert();
90 1 : result = _gnutls_asn2err(result);
91 1 : goto cleanup;
92 : }
93 :
94 : /* read the encapsulated content */
95 190 : len = MAX_OID_SIZE - 1;
96 190 : result =
97 190 : asn1_read_value(c2, "encapContentInfo.eContentType", pkcs7->encap_data_oid, &len);
98 190 : if (result != ASN1_SUCCESS) {
99 1 : gnutls_assert();
100 1 : result = _gnutls_asn2err(result);
101 1 : goto cleanup;
102 : }
103 :
104 189 : if (strcmp(pkcs7->encap_data_oid, DATA_OID) != 0
105 129 : && strcmp(pkcs7->encap_data_oid, DIGESTED_DATA_OID) != 0) {
106 128 : _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 189 : result = _gnutls_x509_read_string(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data, ASN1_ETYPE_OCTET_STRING, 1);
115 189 : if (result < 0) {
116 141 : result = _gnutls_x509_read_value(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data);
117 141 : if (result < 0) {
118 78 : pkcs7->der_signed_data.data = NULL;
119 78 : pkcs7->der_signed_data.size = 0;
120 : } else {
121 63 : int tag_len, len_len;
122 63 : unsigned char cls;
123 63 : unsigned long tag;
124 :
125 : /* we skip the embedded element's tag and length - uncharted territorry - used by MICROSOFT_CERT_TRUST_LIST */
126 63 : result = asn1_get_tag_der(pkcs7->der_signed_data.data, pkcs7->der_signed_data.size, &cls, &tag_len, &tag);
127 63 : if (result != ASN1_SUCCESS) {
128 0 : gnutls_assert();
129 0 : result = _gnutls_asn2err(result);
130 0 : goto cleanup;
131 : }
132 :
133 63 : result = asn1_get_length_ber(pkcs7->der_signed_data.data+tag_len, pkcs7->der_signed_data.size-tag_len, &len_len);
134 63 : if (result < 0) {
135 0 : gnutls_assert();
136 0 : result = GNUTLS_E_ASN1_DER_ERROR;
137 0 : goto cleanup;
138 : }
139 :
140 63 : tag_len += len_len;
141 63 : memmove(pkcs7->der_signed_data.data, &pkcs7->der_signed_data.data[tag_len], pkcs7->der_signed_data.size-tag_len);
142 63 : pkcs7->der_signed_data.size-=tag_len;
143 : }
144 : }
145 :
146 189 : pkcs7->signed_data = c2;
147 189 : gnutls_free(tmp.data);
148 :
149 189 : return 0;
150 :
151 2 : cleanup:
152 2 : gnutls_free(tmp.data);
153 2 : if (c2)
154 1 : asn1_delete_structure(&c2);
155 : return result;
156 : }
157 :
158 218 : static int pkcs7_reinit(gnutls_pkcs7_t pkcs7)
159 : {
160 218 : int result;
161 :
162 218 : asn1_delete_structure(&pkcs7->pkcs7);
163 :
164 218 : result = asn1_create_element(_gnutls_get_pkix(),
165 : "PKIX1.pkcs-7-ContentInfo", &pkcs7->pkcs7);
166 218 : if (result != ASN1_SUCCESS) {
167 0 : result = _gnutls_asn2err(result);
168 0 : gnutls_assert();
169 0 : 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 : **/
186 218 : int gnutls_pkcs7_init(gnutls_pkcs7_t * pkcs7)
187 : {
188 218 : *pkcs7 = gnutls_calloc(1, sizeof(gnutls_pkcs7_int));
189 :
190 218 : if (*pkcs7) {
191 218 : int result = pkcs7_reinit(*pkcs7);
192 218 : if (result < 0) {
193 0 : gnutls_assert();
194 0 : gnutls_free(*pkcs7);
195 0 : 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 : **/
208 218 : void gnutls_pkcs7_deinit(gnutls_pkcs7_t pkcs7)
209 : {
210 218 : if (!pkcs7)
211 : return;
212 :
213 218 : if (pkcs7->pkcs7)
214 217 : asn1_delete_structure(&pkcs7->pkcs7);
215 :
216 218 : if (pkcs7->signed_data)
217 203 : asn1_delete_structure(&pkcs7->signed_data);
218 :
219 218 : _gnutls_free_datum(&pkcs7->der_signed_data);
220 :
221 218 : 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
240 204 : gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data,
241 : gnutls_x509_crt_fmt_t format)
242 : {
243 204 : int result = 0, need_free = 0;
244 204 : gnutls_datum_t _data;
245 :
246 204 : if (pkcs7 == NULL)
247 : return GNUTLS_E_INVALID_REQUEST;
248 :
249 204 : _data.data = data->data;
250 204 : _data.size = data->size;
251 :
252 : /* If the PKCS7 is in PEM format then decode it
253 : */
254 204 : if (format == GNUTLS_X509_FMT_PEM) {
255 32 : result =
256 64 : _gnutls_fbase64_decode(PEM_PKCS7, data->data,
257 32 : data->size, &_data);
258 :
259 32 : if (result < 0) {
260 0 : gnutls_assert();
261 0 : return result;
262 : }
263 :
264 : need_free = 1;
265 : }
266 :
267 204 : if (pkcs7->expanded) {
268 0 : result = pkcs7_reinit(pkcs7);
269 0 : if (result < 0) {
270 0 : gnutls_assert();
271 0 : goto cleanup;
272 : }
273 : }
274 204 : pkcs7->expanded = 1;
275 :
276 204 : result = asn1_der_decoding(&pkcs7->pkcs7, _data.data, _data.size, NULL);
277 204 : if (result != ASN1_SUCCESS) {
278 1 : result = _gnutls_asn2err(result);
279 1 : gnutls_assert();
280 1 : goto cleanup;
281 : }
282 :
283 : /* Decode the signed data.
284 : */
285 203 : result = _decode_pkcs7_signed_data(pkcs7);
286 203 : if (result < 0) {
287 14 : gnutls_assert();
288 14 : goto cleanup;
289 : }
290 :
291 : result = 0;
292 :
293 204 : cleanup:
294 204 : if (need_free)
295 32 : _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
319 11358 : gnutls_pkcs7_get_crt_raw2(gnutls_pkcs7_t pkcs7,
320 : unsigned indx, gnutls_datum_t * cert)
321 : {
322 11358 : int result, len;
323 11358 : char root2[MAX_NAME_SIZE];
324 11358 : char oid[MAX_OID_SIZE];
325 11358 : gnutls_datum_t tmp = { NULL, 0 };
326 :
327 11358 : if (pkcs7 == NULL)
328 : return GNUTLS_E_INVALID_REQUEST;
329 :
330 : /* Step 2. Parse the CertificateSet
331 : */
332 11358 : snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
333 :
334 11358 : len = sizeof(oid) - 1;
335 :
336 11358 : result = asn1_read_value(pkcs7->signed_data, root2, oid, &len);
337 :
338 11358 : if (result == ASN1_VALUE_NOT_FOUND) {
339 0 : result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
340 0 : goto cleanup;
341 : }
342 :
343 11358 : if (result != ASN1_SUCCESS) {
344 0 : gnutls_assert();
345 0 : result = _gnutls_asn2err(result);
346 0 : goto cleanup;
347 : }
348 :
349 : /* if 'Certificate' is the choice found:
350 : */
351 11358 : if (strcmp(oid, "certificate") == 0) {
352 11358 : int start, end;
353 :
354 11358 : result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
355 11358 : if (result < 0) {
356 0 : gnutls_assert();
357 0 : goto cleanup;
358 : }
359 :
360 11358 : result =
361 22716 : asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data,
362 11358 : tmp.size, root2, &start, &end);
363 :
364 11358 : if (result != ASN1_SUCCESS) {
365 0 : gnutls_assert();
366 0 : result = _gnutls_asn2err(result);
367 0 : goto cleanup;
368 : }
369 :
370 11358 : end = end - start + 1;
371 :
372 11358 : result = _gnutls_set_datum(cert, &tmp.data[start], end);
373 : } else {
374 : result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
375 : }
376 :
377 11358 : cleanup:
378 11358 : _gnutls_free_datum(&tmp);
379 11358 : 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
402 0 : gnutls_pkcs7_get_crt_raw(gnutls_pkcs7_t pkcs7,
403 : unsigned indx, void *certificate,
404 : size_t * certificate_size)
405 : {
406 0 : int ret;
407 0 : gnutls_datum_t tmp = { NULL, 0 };
408 :
409 0 : ret = gnutls_pkcs7_get_crt_raw2(pkcs7, indx, &tmp);
410 0 : if (ret < 0)
411 0 : return gnutls_assert_val(ret);
412 :
413 0 : if ((unsigned)tmp.size > *certificate_size) {
414 0 : *certificate_size = tmp.size;
415 0 : ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
416 0 : goto cleanup;
417 : }
418 :
419 0 : *certificate_size = tmp.size;
420 0 : if (certificate)
421 0 : memcpy(certificate, tmp.data, tmp.size);
422 :
423 0 : cleanup:
424 0 : _gnutls_free_datum(&tmp);
425 0 : 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 : **/
438 170 : int gnutls_pkcs7_get_crt_count(gnutls_pkcs7_t pkcs7)
439 : {
440 170 : int result, count;
441 :
442 170 : if (pkcs7 == NULL)
443 : return GNUTLS_E_INVALID_REQUEST;
444 :
445 : /* Step 2. Count the CertificateSet */
446 :
447 170 : result =
448 170 : asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
449 170 : if (result != ASN1_SUCCESS) {
450 91 : gnutls_assert();
451 91 : return 0; /* no certificates */
452 : }
453 :
454 79 : 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 : **/
466 1587 : void gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st * info)
467 : {
468 1587 : gnutls_free(info->sig.data);
469 1587 : gnutls_free(info->issuer_dn.data);
470 1587 : gnutls_free(info->signer_serial.data);
471 1587 : gnutls_free(info->issuer_keyid.data);
472 1587 : gnutls_pkcs7_attrs_deinit(info->signed_attrs);
473 1587 : gnutls_pkcs7_attrs_deinit(info->unsigned_attrs);
474 1587 : memset(info, 0, sizeof(*info));
475 1587 : }
476 :
477 46 : static time_t parse_time(gnutls_pkcs7_t pkcs7, const char *root)
478 : {
479 46 : char tval[128];
480 46 : ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
481 46 : time_t ret;
482 46 : int result, len;
483 :
484 46 : result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Time", &c2);
485 46 : if (result != ASN1_SUCCESS) {
486 0 : ret = -1;
487 0 : gnutls_assert();
488 0 : goto cleanup;
489 : }
490 :
491 46 : len = sizeof(tval);
492 46 : result = asn1_read_value(pkcs7->signed_data, root, tval, &len);
493 46 : if (result != ASN1_SUCCESS) {
494 0 : ret = -1;
495 0 : gnutls_assert();
496 0 : goto cleanup;
497 : }
498 :
499 46 : result = _asn1_strict_der_decode(&c2, tval, len, NULL);
500 46 : if (result != ASN1_SUCCESS) {
501 0 : ret = -1;
502 0 : gnutls_assert();
503 0 : goto cleanup;
504 : }
505 :
506 46 : ret = _gnutls_x509_get_time(c2, "", 0);
507 :
508 46 : cleanup:
509 46 : asn1_delete_structure(&c2);
510 46 : 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 : **/
525 0 : int gnutls_pkcs7_get_signature_count(gnutls_pkcs7_t pkcs7)
526 : {
527 0 : int ret, count;
528 :
529 0 : if (pkcs7 == NULL)
530 : return GNUTLS_E_INVALID_REQUEST;
531 :
532 0 : ret =
533 0 : asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
534 0 : if (ret != ASN1_SUCCESS) {
535 0 : gnutls_assert();
536 0 : return 0;
537 : }
538 :
539 0 : 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 : **/
557 1744 : int gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7, unsigned idx,
558 : gnutls_pkcs7_signature_info_st * info)
559 : {
560 1744 : int ret, count, len;
561 1744 : char root[256];
562 1744 : char oid[MAX_OID_SIZE];
563 1744 : gnutls_pk_algorithm_t pk;
564 1744 : gnutls_sign_algorithm_t sig;
565 1744 : gnutls_datum_t tmp = { NULL, 0 };
566 1744 : unsigned i;
567 :
568 1744 : if (pkcs7 == NULL)
569 : return GNUTLS_E_INVALID_REQUEST;
570 :
571 1744 : memset(info, 0, sizeof(*info));
572 1744 : info->signing_time = -1;
573 :
574 1744 : ret =
575 1744 : asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
576 1744 : if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
577 146 : gnutls_assert();
578 146 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
579 : }
580 1598 : snprintf(root, sizeof(root),
581 : "signerInfos.?%u.signatureAlgorithm.algorithm", idx + 1);
582 :
583 1598 : len = sizeof(oid) - 1;
584 1598 : ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
585 1598 : if (ret != ASN1_SUCCESS) {
586 3 : gnutls_assert();
587 3 : goto unsupp_algo;
588 : }
589 :
590 1595 : sig = gnutls_oid_to_sign(oid);
591 1595 : if (sig == GNUTLS_SIGN_UNKNOWN) {
592 : /* great PKCS #7 allows to only specify a public key algo */
593 857 : pk = gnutls_oid_to_pk(oid);
594 857 : if (pk == GNUTLS_PK_UNKNOWN) {
595 2 : gnutls_assert();
596 2 : goto unsupp_algo;
597 : }
598 :
599 : /* use the digests algorithm */
600 855 : snprintf(root, sizeof(root),
601 : "signerInfos.?%u.digestAlgorithm.algorithm", idx + 1);
602 :
603 855 : len = sizeof(oid) - 1;
604 855 : ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
605 855 : if (ret != ASN1_SUCCESS) {
606 4 : gnutls_assert();
607 4 : goto unsupp_algo;
608 : }
609 :
610 851 : ret = gnutls_oid_to_digest(oid);
611 851 : if (ret == GNUTLS_DIG_UNKNOWN) {
612 2 : gnutls_assert();
613 2 : goto unsupp_algo;
614 : }
615 :
616 849 : sig = gnutls_pk_to_sign(pk, ret);
617 849 : if (sig == GNUTLS_SIGN_UNKNOWN) {
618 0 : gnutls_assert();
619 0 : goto unsupp_algo;
620 : }
621 : }
622 :
623 1587 : info->algo = sig;
624 :
625 1587 : snprintf(root, sizeof(root), "signerInfos.?%u.signature", idx + 1);
626 : /* read the signature */
627 1587 : ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &info->sig);
628 1587 : if (ret < 0) {
629 19 : gnutls_assert();
630 19 : goto fail;
631 : }
632 :
633 : /* read the issuer info */
634 1568 : snprintf(root, sizeof(root),
635 : "signerInfos.?%u.sid.issuerAndSerialNumber.issuer.rdnSequence",
636 : idx + 1);
637 : /* read the signature */
638 1568 : ret =
639 1568 : _gnutls_x509_get_raw_field(pkcs7->signed_data, root,
640 : &info->issuer_dn);
641 1568 : if (ret >= 0) {
642 102 : snprintf(root, sizeof(root),
643 : "signerInfos.?%u.sid.issuerAndSerialNumber.serialNumber",
644 : idx + 1);
645 : /* read the signature */
646 102 : ret =
647 102 : _gnutls_x509_read_value(pkcs7->signed_data, root,
648 : &info->signer_serial);
649 102 : if (ret < 0) {
650 1 : gnutls_assert();
651 1 : goto fail;
652 : }
653 : } else { /* keyid */
654 1466 : snprintf(root, sizeof(root),
655 : "signerInfos.?%u.sid.subjectKeyIdentifier", idx + 1);
656 : /* read the signature */
657 1466 : ret =
658 1466 : _gnutls_x509_read_value(pkcs7->signed_data, root,
659 : &info->issuer_keyid);
660 1466 : if (ret < 0) {
661 7 : gnutls_assert();
662 : }
663 : }
664 :
665 1567 : if (info->issuer_keyid.data == NULL && info->issuer_dn.data == NULL) {
666 7 : ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
667 7 : goto fail;
668 : }
669 :
670 : /* read the signing time */
671 : for (i = 0;; i++) {
672 1776 : snprintf(root, sizeof(root),
673 : "signerInfos.?%u.signedAttrs.?%u.type", idx + 1,
674 : i + 1);
675 1776 : len = sizeof(oid) - 1;
676 1776 : ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
677 1776 : if (ret != ASN1_SUCCESS) {
678 : break;
679 : }
680 :
681 216 : snprintf(root, sizeof(root),
682 : "signerInfos.?%u.signedAttrs.?%u.values.?1", idx + 1,
683 : i + 1);
684 216 : ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
685 216 : if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
686 0 : tmp.data = NULL;
687 0 : tmp.size = 0;
688 216 : } else if (ret < 0) {
689 0 : gnutls_assert();
690 0 : goto fail;
691 : }
692 :
693 216 : ret = gnutls_pkcs7_add_attr(&info->signed_attrs, oid, &tmp, 0);
694 216 : gnutls_free(tmp.data);
695 :
696 216 : if (ret < 0) {
697 0 : gnutls_assert();
698 0 : goto fail;
699 : }
700 :
701 216 : if (strcmp(oid, ATTR_SIGNING_TIME) == 0) {
702 46 : info->signing_time = parse_time(pkcs7, root);
703 : }
704 : }
705 :
706 : /* read the unsigned attrs */
707 : for (i = 0;; i++) {
708 1569 : snprintf(root, sizeof(root),
709 : "signerInfos.?%u.unsignedAttrs.?%u.type", idx + 1,
710 : i + 1);
711 1569 : len = sizeof(oid) - 1;
712 1569 : ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
713 1569 : if (ret != ASN1_SUCCESS) {
714 : break;
715 : }
716 :
717 9 : snprintf(root, sizeof(root),
718 : "signerInfos.?%u.unsignedAttrs.?%u.values.?1", idx + 1,
719 : i + 1);
720 9 : ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
721 9 : if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
722 0 : tmp.data = NULL;
723 0 : tmp.size = 0;
724 9 : } else if (ret < 0) {
725 0 : gnutls_assert();
726 0 : goto fail;
727 : }
728 :
729 9 : ret =
730 9 : gnutls_pkcs7_add_attr(&info->unsigned_attrs, oid, &tmp, 0);
731 9 : gnutls_free(tmp.data);
732 :
733 9 : if (ret < 0) {
734 0 : gnutls_assert();
735 0 : goto fail;
736 : }
737 : }
738 :
739 : return 0;
740 27 : fail:
741 27 : gnutls_free(tmp.data);
742 27 : gnutls_pkcs7_signature_info_deinit(info);
743 27 : 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 */
750 26 : 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 26 : unsigned hash;
755 26 : gnutls_datum_t tmp = { NULL, 0 };
756 26 : gnutls_datum_t tmp2 = { NULL, 0 };
757 26 : uint8_t hash_output[MAX_HASH_SIZE];
758 26 : unsigned hash_size, i;
759 26 : char oid[MAX_OID_SIZE];
760 26 : char name[256];
761 26 : unsigned msg_digest_ok = 0;
762 26 : unsigned num_cont_types = 0;
763 26 : int ret;
764 :
765 26 : hash = gnutls_sign_get_hash_algorithm(algo);
766 :
767 : /* hash the data */
768 26 : if (hash == GNUTLS_DIG_UNKNOWN)
769 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
770 :
771 26 : hash_size = gnutls_hash_get_len(hash);
772 :
773 26 : if (data == NULL || data->data == NULL) {
774 19 : data = &pkcs7->der_signed_data;
775 : }
776 :
777 26 : if (data->size == 0) {
778 1 : return gnutls_assert_val(GNUTLS_E_NO_EMBEDDED_DATA);
779 : }
780 :
781 25 : ret = gnutls_hash_fast(hash, data->data, data->size, hash_output);
782 25 : if (ret < 0)
783 0 : return gnutls_assert_val(ret);
784 :
785 : /* now verify that hash matches */
786 96 : for (i = 0;; i++) {
787 121 : snprintf(name, sizeof(name), "%s.signedAttrs.?%u", root, i + 1);
788 :
789 121 : ret = _gnutls_x509_decode_and_read_attribute(pkcs7->signed_data,
790 : name, oid,
791 : sizeof(oid), &tmp,
792 : 1, 0);
793 121 : if (ret < 0) {
794 25 : if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
795 : break;
796 0 : return gnutls_assert_val(ret);
797 : }
798 :
799 96 : if (strcmp(oid, ATTR_MESSAGE_DIGEST) == 0) {
800 25 : ret =
801 50 : _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
802 25 : tmp.data, tmp.size,
803 : &tmp2, 0);
804 25 : if (ret < 0) {
805 0 : gnutls_assert();
806 0 : goto cleanup;
807 : }
808 :
809 25 : if (tmp2.size == hash_size
810 25 : && memcmp(hash_output, tmp2.data, tmp2.size) == 0) {
811 : msg_digest_ok = 1;
812 : } else {
813 0 : gnutls_assert();
814 : }
815 71 : } else if (strcmp(oid, ATTR_CONTENT_TYPE) == 0) {
816 25 : if (num_cont_types > 0) {
817 0 : gnutls_assert();
818 0 : ret = GNUTLS_E_PARSING_ERROR;
819 0 : goto cleanup;
820 : }
821 :
822 25 : num_cont_types++;
823 :
824 : /* check if it matches */
825 25 : ret =
826 25 : _gnutls_x509_get_raw_field(pkcs7->signed_data,
827 : "encapContentInfo.eContentType",
828 : &tmp2);
829 25 : if (ret < 0) {
830 0 : gnutls_assert();
831 0 : goto cleanup;
832 : }
833 :
834 25 : if (tmp2.size != tmp.size
835 25 : || memcmp(tmp.data, tmp2.data, tmp2.size) != 0) {
836 0 : gnutls_assert();
837 0 : ret = GNUTLS_E_PARSING_ERROR;
838 0 : goto cleanup;
839 : }
840 : }
841 :
842 96 : gnutls_free(tmp.data);
843 96 : gnutls_free(tmp2.data);
844 : }
845 :
846 25 : if (msg_digest_ok)
847 : ret = 0;
848 : else
849 0 : ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
850 :
851 25 : cleanup:
852 25 : gnutls_free(tmp.data);
853 25 : gnutls_free(tmp2.data);
854 25 : 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 : */
860 61 : 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 61 : int ret;
866 61 : char name[256];
867 :
868 61 : snprintf(name, sizeof(name), "%s.signedAttrs", root);
869 : /* read the signature */
870 61 : ret = _gnutls_x509_get_raw_field(pkcs7->signed_data, name, sigdata);
871 61 : if (ret == 0) {
872 : /* verify that hash matches */
873 26 : ret = verify_hash_attr(pkcs7, root, algo, data);
874 26 : if (ret < 0)
875 1 : return gnutls_assert_val(ret);
876 :
877 25 : if (sigdata->size > 0)
878 25 : sigdata->data[0] = 0x31;
879 :
880 25 : return 0;
881 : }
882 :
883 : /* We have no signedAttrs. Use the provided data, or the encapsulated */
884 35 : if (data == NULL || data->data == NULL) {
885 24 : return _gnutls_set_datum(sigdata, pkcs7->der_signed_data.data, pkcs7->der_signed_data.size);
886 : }
887 :
888 11 : 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
914 6 : gnutls_pkcs7_get_embedded_data(gnutls_pkcs7_t pkcs7, unsigned flags,
915 : gnutls_datum_t *data)
916 : {
917 6 : if (pkcs7 == NULL)
918 : return GNUTLS_E_INVALID_REQUEST;
919 :
920 6 : if (pkcs7->der_signed_data.size == 0)
921 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
922 :
923 6 : if (flags & GNUTLS_PKCS7_EDATA_GET_RAW) {
924 1 : if (pkcs7->signed_data == NULL)
925 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
926 :
927 1 : return _gnutls_x509_read_value(pkcs7->signed_data, "encapContentInfo.eContent", data);
928 : } else {
929 5 : 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 *
947 182 : gnutls_pkcs7_get_embedded_data_oid(gnutls_pkcs7_t pkcs7)
948 : {
949 182 : if (pkcs7 == NULL || pkcs7->encap_data_oid[0] == 0)
950 : return NULL;
951 :
952 182 : 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 : **/
983 23 : 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 23 : int count, ret;
989 23 : gnutls_datum_t tmpdata = { NULL, 0 };
990 23 : gnutls_pkcs7_signature_info_st info;
991 23 : gnutls_datum_t sigdata = { NULL, 0 };
992 23 : char root[128];
993 :
994 23 : memset(&info, 0, sizeof(info));
995 :
996 23 : if (pkcs7 == NULL)
997 : return GNUTLS_E_INVALID_REQUEST;
998 :
999 23 : ret =
1000 23 : asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
1001 23 : if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
1002 0 : gnutls_assert();
1003 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1004 : }
1005 :
1006 23 : ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
1007 23 : if (ret < 0) {
1008 0 : gnutls_assert();
1009 0 : goto cleanup;
1010 : }
1011 :
1012 23 : snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
1013 23 : ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
1014 23 : if (ret < 0) {
1015 0 : gnutls_assert();
1016 0 : goto cleanup;
1017 : }
1018 :
1019 23 : ret =
1020 23 : gnutls_x509_crt_verify_data2(signer, info.algo, flags, &sigdata,
1021 : &info.sig);
1022 23 : if (ret < 0) {
1023 6 : gnutls_assert();
1024 : }
1025 :
1026 23 : cleanup:
1027 23 : gnutls_free(tmpdata.data);
1028 23 : gnutls_free(sigdata.data);
1029 23 : gnutls_pkcs7_signature_info_deinit(&info);
1030 :
1031 23 : return ret;
1032 : }
1033 :
1034 : /* Finds the issuer of the given certificate (@cert) in the
1035 : * included in PKCS#7 list of certificates */
1036 9 : 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 9 : gnutls_x509_crt_t issuer = NULL;
1042 9 : int ret, count;
1043 9 : gnutls_datum_t tmp = { NULL, 0 };
1044 9 : unsigned i, vtmp;
1045 :
1046 9 : count = gnutls_pkcs7_get_crt_count(pkcs7);
1047 9 : if (count < 0) {
1048 0 : gnutls_assert();
1049 0 : return NULL;
1050 : }
1051 :
1052 23 : for (i = 0; i < (unsigned)count; i++) {
1053 : /* Try to find the signer in the appended list. */
1054 19 : ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmp);
1055 19 : if (ret < 0) {
1056 0 : gnutls_assert();
1057 0 : goto fail;
1058 : }
1059 :
1060 19 : ret = gnutls_x509_crt_init(&issuer);
1061 19 : if (ret < 0) {
1062 0 : gnutls_assert();
1063 0 : goto fail;
1064 : }
1065 :
1066 19 : ret = gnutls_x509_crt_import(issuer, &tmp, GNUTLS_X509_FMT_DER);
1067 19 : if (ret < 0) {
1068 0 : gnutls_assert();
1069 0 : goto fail;
1070 : }
1071 :
1072 19 : if (!gnutls_x509_crt_check_issuer(cert, issuer)) {
1073 14 : gnutls_assert();
1074 14 : goto skip;
1075 : }
1076 :
1077 5 : ret = gnutls_x509_crt_verify(cert, &issuer, 1, vflags|GNUTLS_VERIFY_DO_NOT_ALLOW_SAME, &vtmp);
1078 5 : if (ret < 0 || vtmp != 0 ||
1079 0 : (purpose != NULL && !_gnutls_check_key_purpose(issuer, purpose, 0))) {
1080 0 : gnutls_assert(); /* maybe next one is trusted */
1081 0 : _gnutls_cert_log("failed verification with", issuer);
1082 0 : skip:
1083 14 : gnutls_x509_crt_deinit(issuer);
1084 14 : issuer = NULL;
1085 14 : gnutls_free(tmp.data);
1086 14 : continue;
1087 : }
1088 :
1089 5 : _gnutls_cert_log("issued by", issuer);
1090 :
1091 : /* we found a signer we trust. let's return it */
1092 : break;
1093 : }
1094 :
1095 9 : if (issuer == NULL) {
1096 4 : gnutls_assert();
1097 4 : return NULL;
1098 : }
1099 5 : goto cleanup;
1100 :
1101 0 : fail:
1102 0 : if (issuer) {
1103 0 : gnutls_x509_crt_deinit(issuer);
1104 0 : issuer = NULL;
1105 : }
1106 :
1107 0 : cleanup:
1108 5 : gnutls_free(tmp.data);
1109 :
1110 5 : 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 : */
1116 24 : 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 24 : gnutls_x509_crt_t crt = NULL;
1122 24 : int ret, count;
1123 24 : uint8_t tmp[128];
1124 24 : size_t tmp_size;
1125 24 : gnutls_datum_t tmpdata = { NULL, 0 };
1126 24 : unsigned i;
1127 :
1128 24 : count = gnutls_pkcs7_get_crt_count(pkcs7);
1129 24 : if (count < 0) {
1130 0 : gnutls_assert();
1131 0 : return NULL;
1132 : }
1133 :
1134 37 : for (i = 0; i < (unsigned)count; i++) {
1135 : /* Try to find the crt in the appended list. */
1136 35 : ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmpdata);
1137 35 : if (ret < 0) {
1138 0 : gnutls_assert();
1139 0 : goto fail;
1140 : }
1141 :
1142 35 : ret = gnutls_x509_crt_init(&crt);
1143 35 : if (ret < 0) {
1144 0 : gnutls_assert();
1145 0 : goto fail;
1146 : }
1147 :
1148 35 : ret = gnutls_x509_crt_import(crt, &tmpdata, GNUTLS_X509_FMT_DER);
1149 35 : if (ret < 0) {
1150 0 : gnutls_assert();
1151 0 : goto fail;
1152 : }
1153 :
1154 35 : if (issuer != NULL) {
1155 19 : if (!gnutls_x509_crt_check_issuer(crt, issuer)) {
1156 0 : gnutls_assert();
1157 0 : goto skip;
1158 : }
1159 : }
1160 :
1161 35 : if (purpose) {
1162 14 : ret =
1163 7 : _gnutls_check_key_purpose(crt, purpose, 0);
1164 7 : if (ret == 0) {
1165 3 : _gnutls_cert_log("key purpose unacceptable", crt);
1166 3 : goto skip;
1167 : }
1168 : }
1169 :
1170 32 : if (info->signer_serial.size > 0) {
1171 24 : tmp_size = sizeof(tmp);
1172 24 : ret = gnutls_x509_crt_get_serial(crt, tmp, &tmp_size);
1173 24 : if (ret < 0) {
1174 0 : gnutls_assert();
1175 0 : goto skip;
1176 : }
1177 :
1178 24 : if (tmp_size != info->signer_serial.size
1179 24 : || memcmp(info->signer_serial.data, tmp,
1180 : tmp_size) != 0) {
1181 6 : _gnutls_cert_log("doesn't match serial", crt);
1182 6 : gnutls_assert();
1183 6 : goto skip;
1184 : }
1185 8 : } else if (info->issuer_keyid.size > 0) {
1186 8 : tmp_size = sizeof(tmp);
1187 8 : ret = gnutls_x509_crt_get_subject_key_id(crt, tmp, &tmp_size, NULL);
1188 8 : if (ret < 0) {
1189 0 : gnutls_assert();
1190 0 : goto skip;
1191 : }
1192 :
1193 8 : if (tmp_size != info->issuer_keyid.size
1194 8 : || memcmp(info->issuer_keyid.data, tmp,
1195 : tmp_size) != 0) {
1196 4 : _gnutls_cert_log("doesn't match key ID", crt);
1197 4 : gnutls_assert();
1198 4 : skip:
1199 13 : gnutls_x509_crt_deinit(crt);
1200 13 : crt = NULL;
1201 13 : gnutls_free(tmpdata.data);
1202 13 : continue;
1203 : }
1204 : } else {
1205 0 : gnutls_assert();
1206 0 : crt = NULL;
1207 0 : goto fail;
1208 : }
1209 :
1210 22 : _gnutls_cert_log("signer is", crt);
1211 :
1212 : /* we found the child with the given serial or key ID */
1213 : break;
1214 : }
1215 :
1216 24 : if (crt == NULL) {
1217 2 : gnutls_assert();
1218 2 : return NULL;
1219 : }
1220 :
1221 22 : goto cleanup;
1222 0 : fail:
1223 0 : if (crt) {
1224 0 : gnutls_x509_crt_deinit(crt);
1225 0 : crt = NULL;
1226 : }
1227 :
1228 0 : cleanup:
1229 22 : gnutls_free(tmpdata.data);
1230 :
1231 22 : return crt;
1232 : }
1233 :
1234 : static
1235 24 : 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 24 : gnutls_x509_crt_t issuer = NULL;
1242 24 : gnutls_x509_crt_t signer = NULL;
1243 24 : int ret;
1244 24 : gnutls_datum_t tmp = { NULL, 0 };
1245 24 : unsigned i, vtmp;
1246 24 : const char *purpose = NULL;
1247 :
1248 24 : if (info->issuer_keyid.data) {
1249 4 : ret =
1250 8 : gnutls_x509_trust_list_get_issuer_by_subject_key_id(tl,
1251 : NULL,
1252 4 : &info->
1253 : issuer_keyid,
1254 : &signer,
1255 : 0);
1256 4 : if (ret < 0) {
1257 4 : gnutls_assert();
1258 4 : signer = NULL;
1259 : }
1260 : }
1261 :
1262 : /* get key purpose */
1263 24 : for (i = 0; i < vdata_size; i++) {
1264 6 : if (vdata[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
1265 6 : purpose = (char *)vdata[i].data;
1266 6 : break;
1267 : }
1268 : }
1269 :
1270 : /* this will give us the issuer of the signer (wtf) */
1271 24 : if (info->issuer_dn.data && signer == NULL) {
1272 20 : ret =
1273 40 : gnutls_x509_trust_list_get_issuer_by_dn(tl,
1274 20 : &info->issuer_dn,
1275 : &issuer, 0);
1276 20 : if (ret < 0) {
1277 3 : gnutls_assert();
1278 3 : signer = NULL;
1279 : }
1280 :
1281 20 : if (issuer) {
1282 : /* try to find the actual signer in the list of
1283 : * certificates */
1284 17 : signer = find_child_of_with_serial(pkcs7, issuer, purpose, info);
1285 17 : if (signer == NULL) {
1286 2 : gnutls_assert();
1287 2 : goto fail;
1288 : }
1289 :
1290 15 : gnutls_x509_crt_deinit(issuer);
1291 15 : issuer = NULL;
1292 : }
1293 : }
1294 :
1295 22 : if (signer == NULL) {
1296 : /* get the signer from the pkcs7 list; the one that matches serial
1297 : * or key ID */
1298 7 : signer = find_child_of_with_serial(pkcs7, NULL, purpose, info);
1299 7 : if (signer == NULL) {
1300 0 : gnutls_assert();
1301 0 : 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 7 : ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1307 7 : if (ret < 0 || vtmp != 0) {
1308 6 : gnutls_x509_crt_t prev = NULL;
1309 :
1310 6 : issuer = signer;
1311 : /* construct a chain */
1312 9 : do {
1313 9 : if (prev && prev != signer) {
1314 0 : gnutls_x509_crt_deinit(prev);
1315 : }
1316 9 : prev = issuer;
1317 :
1318 9 : issuer = find_verified_issuer_of(pkcs7, issuer, purpose, vflags);
1319 :
1320 9 : if (issuer != NULL && gnutls_x509_crt_check_issuer(issuer, issuer)) {
1321 2 : if (prev) gnutls_x509_crt_deinit(prev);
1322 2 : prev = issuer;
1323 2 : break;
1324 : }
1325 7 : } while(issuer != NULL);
1326 :
1327 6 : issuer = prev; /* the last we have seen */
1328 :
1329 6 : if (issuer == NULL) {
1330 0 : gnutls_assert();
1331 0 : goto fail;
1332 : }
1333 :
1334 6 : ret = gnutls_x509_trust_list_verify_crt2(tl, &issuer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1335 6 : if (ret < 0 || vtmp != 0) {
1336 : /* could not construct a valid chain */
1337 3 : _gnutls_reason_log("signer's chain failed trust list verification", vtmp);
1338 3 : gnutls_assert();
1339 3 : goto fail;
1340 : }
1341 : }
1342 : } else {
1343 : /* verify that the signer we got is trusted */
1344 15 : ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1345 15 : if (ret < 0 || vtmp != 0) {
1346 : /* could not construct a valid chain */
1347 8 : _gnutls_reason_log("signer failed trust list verification", vtmp);
1348 8 : gnutls_assert();
1349 8 : goto fail;
1350 : }
1351 : }
1352 :
1353 11 : if (signer == NULL) {
1354 0 : gnutls_assert();
1355 0 : goto fail;
1356 : }
1357 :
1358 11 : goto cleanup;
1359 :
1360 13 : fail:
1361 13 : if (signer != NULL) {
1362 11 : if (issuer == signer)
1363 3 : issuer = NULL;
1364 11 : gnutls_x509_crt_deinit(signer);
1365 11 : signer = NULL;
1366 : }
1367 :
1368 2 : cleanup:
1369 24 : if (issuer != NULL) {
1370 5 : gnutls_x509_crt_deinit(issuer);
1371 5 : issuer = NULL;
1372 : }
1373 24 : gnutls_free(tmp.data);
1374 :
1375 24 : 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 : **/
1400 25 : 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 25 : int count, ret;
1408 25 : gnutls_datum_t tmpdata = { NULL, 0 };
1409 25 : gnutls_pkcs7_signature_info_st info;
1410 25 : gnutls_x509_crt_t signer;
1411 25 : gnutls_datum_t sigdata = { NULL, 0 };
1412 25 : char root[128];
1413 :
1414 25 : memset(&info, 0, sizeof(info));
1415 :
1416 25 : if (pkcs7 == NULL)
1417 : return GNUTLS_E_INVALID_REQUEST;
1418 :
1419 25 : ret =
1420 25 : asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
1421 25 : if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
1422 0 : gnutls_assert();
1423 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1424 : }
1425 :
1426 : /* read data */
1427 25 : ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
1428 25 : if (ret < 0) {
1429 0 : gnutls_assert();
1430 0 : goto cleanup;
1431 : }
1432 :
1433 25 : snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
1434 25 : ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
1435 25 : if (ret < 0) {
1436 1 : gnutls_assert();
1437 1 : goto cleanup;
1438 : }
1439 :
1440 24 : signer = find_signer(pkcs7, tl, vdata, vdata_size, flags, &info);
1441 24 : if (signer) {
1442 11 : ret =
1443 11 : gnutls_x509_crt_verify_data3(signer, info.algo, vdata, vdata_size,
1444 : &sigdata, &info.sig, flags);
1445 11 : if (ret < 0) {
1446 0 : _gnutls_cert_log("failed struct verification with", signer);
1447 0 : gnutls_assert();
1448 : }
1449 11 : gnutls_x509_crt_deinit(signer);
1450 : } else {
1451 13 : gnutls_assert();
1452 : ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
1453 : }
1454 :
1455 25 : cleanup:
1456 25 : gnutls_free(tmpdata.data);
1457 25 : gnutls_free(sigdata.data);
1458 25 : gnutls_pkcs7_signature_info_deinit(&info);
1459 :
1460 25 : return ret;
1461 : }
1462 :
1463 39 : static void disable_opt_fields(gnutls_pkcs7_t pkcs7)
1464 : {
1465 39 : int result;
1466 39 : int count;
1467 :
1468 : /* disable the optional fields */
1469 39 : result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1470 39 : if (result != ASN1_SUCCESS || count == 0) {
1471 39 : (void)asn1_write_value(pkcs7->signed_data, "crls", NULL, 0);
1472 : }
1473 :
1474 39 : result =
1475 39 : asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
1476 39 : if (result != ASN1_SUCCESS || count == 0) {
1477 3 : (void)asn1_write_value(pkcs7->signed_data, "certificates", NULL, 0);
1478 : }
1479 :
1480 39 : return;
1481 : }
1482 :
1483 26 : static int reencode(gnutls_pkcs7_t pkcs7)
1484 : {
1485 26 : int result;
1486 :
1487 26 : if (pkcs7->signed_data != ASN1_TYPE_EMPTY) {
1488 26 : disable_opt_fields(pkcs7);
1489 :
1490 : /* Replace the old content with the new
1491 : */
1492 26 : result =
1493 26 : _gnutls_x509_der_encode_and_copy(pkcs7->signed_data, "",
1494 : pkcs7->pkcs7, "content",
1495 : 0);
1496 26 : if (result < 0) {
1497 0 : return gnutls_assert_val(result);
1498 : }
1499 :
1500 : /* Write the content type of the signed data
1501 : */
1502 26 : result =
1503 26 : asn1_write_value(pkcs7->pkcs7, "contentType",
1504 : SIGNED_DATA_OID, 1);
1505 26 : if (result != ASN1_SUCCESS) {
1506 0 : gnutls_assert();
1507 0 : 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
1534 24 : 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 24 : int ret;
1539 24 : if (pkcs7 == NULL)
1540 : return GNUTLS_E_INVALID_REQUEST;
1541 :
1542 24 : if ((ret = reencode(pkcs7)) < 0)
1543 0 : return gnutls_assert_val(ret);
1544 :
1545 24 : 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
1568 2 : gnutls_pkcs7_export2(gnutls_pkcs7_t pkcs7,
1569 : gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
1570 : {
1571 2 : int ret;
1572 2 : if (pkcs7 == NULL)
1573 : return GNUTLS_E_INVALID_REQUEST;
1574 :
1575 2 : if ((ret = reencode(pkcs7)) < 0)
1576 0 : return gnutls_assert_val(ret);
1577 :
1578 2 : 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 : */
1584 1 : static int create_empty_signed_data(ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
1585 : {
1586 1 : int result;
1587 :
1588 1 : *sdata = ASN1_TYPE_EMPTY;
1589 :
1590 1 : if ((result = asn1_create_element
1591 : (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
1592 : sdata)) != ASN1_SUCCESS) {
1593 0 : gnutls_assert();
1594 0 : result = _gnutls_asn2err(result);
1595 0 : goto cleanup;
1596 : }
1597 :
1598 : /* Use version 1
1599 : */
1600 1 : result = asn1_write_value(*sdata, "version", &one, 1);
1601 1 : if (result != ASN1_SUCCESS) {
1602 0 : gnutls_assert();
1603 0 : result = _gnutls_asn2err(result);
1604 0 : goto cleanup;
1605 : }
1606 :
1607 : /* Use no digest algorithms
1608 : */
1609 :
1610 : /* id-data */
1611 1 : result =
1612 1 : asn1_write_value(*sdata, "encapContentInfo.eContentType",
1613 : DIGESTED_DATA_OID, 1);
1614 1 : if (result != ASN1_SUCCESS) {
1615 0 : gnutls_assert();
1616 0 : result = _gnutls_asn2err(result);
1617 0 : goto cleanup;
1618 : }
1619 :
1620 1 : result = asn1_write_value(*sdata, "encapContentInfo.eContent", NULL, 0);
1621 1 : if (result != ASN1_SUCCESS) {
1622 0 : gnutls_assert();
1623 0 : result = _gnutls_asn2err(result);
1624 0 : 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 0 : cleanup:
1639 0 : asn1_delete_structure(sdata);
1640 0 : 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 : **/
1655 19 : int gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt)
1656 : {
1657 19 : int result;
1658 :
1659 19 : if (pkcs7 == NULL)
1660 : return GNUTLS_E_INVALID_REQUEST;
1661 :
1662 : /* If the signed data are uninitialized
1663 : * then create them.
1664 : */
1665 19 : if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
1666 : /* The pkcs7 structure is new, so create the
1667 : * signedData.
1668 : */
1669 1 : result =
1670 1 : create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
1671 1 : if (result < 0) {
1672 0 : gnutls_assert();
1673 0 : return result;
1674 : }
1675 : }
1676 :
1677 : /* Step 2. Append the new certificate.
1678 : */
1679 :
1680 19 : result = asn1_write_value(pkcs7->signed_data, "certificates", "NEW", 1);
1681 19 : if (result != ASN1_SUCCESS) {
1682 0 : gnutls_assert();
1683 0 : result = _gnutls_asn2err(result);
1684 0 : goto cleanup;
1685 : }
1686 :
1687 19 : result =
1688 19 : asn1_write_value(pkcs7->signed_data, "certificates.?LAST",
1689 : "certificate", 1);
1690 19 : if (result != ASN1_SUCCESS) {
1691 0 : gnutls_assert();
1692 0 : result = _gnutls_asn2err(result);
1693 0 : goto cleanup;
1694 : }
1695 :
1696 19 : result =
1697 38 : asn1_write_value(pkcs7->signed_data,
1698 19 : "certificates.?LAST.certificate", crt->data,
1699 19 : crt->size);
1700 19 : if (result != ASN1_SUCCESS) {
1701 0 : gnutls_assert();
1702 0 : result = _gnutls_asn2err(result);
1703 0 : 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 : **/
1724 19 : int gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
1725 : {
1726 19 : int ret;
1727 19 : gnutls_datum_t data;
1728 :
1729 19 : if (pkcs7 == NULL)
1730 : return GNUTLS_E_INVALID_REQUEST;
1731 :
1732 19 : ret = _gnutls_x509_der_encode(crt->cert, "", &data, 0);
1733 19 : if (ret < 0) {
1734 0 : gnutls_assert();
1735 0 : return ret;
1736 : }
1737 :
1738 19 : ret = gnutls_pkcs7_set_crt_raw(pkcs7, &data);
1739 :
1740 19 : _gnutls_free_datum(&data);
1741 :
1742 19 : if (ret < 0) {
1743 0 : gnutls_assert();
1744 0 : 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 : **/
1761 0 : int gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7, int indx)
1762 : {
1763 0 : int result;
1764 0 : char root2[MAX_NAME_SIZE];
1765 :
1766 0 : if (pkcs7 == NULL)
1767 : return GNUTLS_E_INVALID_REQUEST;
1768 :
1769 : /* Step 2. Delete the certificate.
1770 : */
1771 :
1772 0 : snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
1773 :
1774 0 : result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
1775 0 : if (result != ASN1_SUCCESS) {
1776 0 : gnutls_assert();
1777 0 : result = _gnutls_asn2err(result);
1778 0 : goto cleanup;
1779 : }
1780 :
1781 : return 0;
1782 :
1783 0 : cleanup:
1784 0 : 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
1805 581 : gnutls_pkcs7_get_crl_raw2(gnutls_pkcs7_t pkcs7,
1806 : unsigned indx, gnutls_datum_t * crl)
1807 : {
1808 581 : int result;
1809 581 : char root2[MAX_NAME_SIZE];
1810 581 : gnutls_datum_t tmp = { NULL, 0 };
1811 581 : int start, end;
1812 :
1813 581 : if (pkcs7 == NULL || crl == NULL)
1814 : return GNUTLS_E_INVALID_REQUEST;
1815 :
1816 581 : result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
1817 581 : if (result < 0) {
1818 0 : gnutls_assert();
1819 0 : goto cleanup;
1820 : }
1821 :
1822 : /* Step 2. Parse the CertificateSet
1823 : */
1824 :
1825 581 : snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
1826 :
1827 : /* Get the raw CRL
1828 : */
1829 581 : result =
1830 581 : asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data, tmp.size,
1831 : root2, &start, &end);
1832 :
1833 581 : if (result != ASN1_SUCCESS) {
1834 0 : gnutls_assert();
1835 0 : result = _gnutls_asn2err(result);
1836 0 : goto cleanup;
1837 : }
1838 :
1839 581 : end = end - start + 1;
1840 :
1841 581 : result = _gnutls_set_datum(crl, &tmp.data[start], end);
1842 :
1843 581 : cleanup:
1844 581 : _gnutls_free_datum(&tmp);
1845 581 : 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
1864 0 : gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7,
1865 : unsigned indx, void *crl, size_t * crl_size)
1866 : {
1867 0 : int ret;
1868 0 : gnutls_datum_t tmp = { NULL, 0 };
1869 :
1870 0 : ret = gnutls_pkcs7_get_crl_raw2(pkcs7, indx, &tmp);
1871 0 : if (ret < 0)
1872 0 : return gnutls_assert_val(ret);
1873 :
1874 0 : if ((unsigned)tmp.size > *crl_size) {
1875 0 : *crl_size = tmp.size;
1876 0 : ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
1877 0 : goto cleanup;
1878 : }
1879 :
1880 0 : assert(tmp.data != NULL);
1881 :
1882 0 : *crl_size = tmp.size;
1883 0 : if (crl)
1884 0 : memcpy(crl, tmp.data, tmp.size);
1885 :
1886 0 : cleanup:
1887 0 : _gnutls_free_datum(&tmp);
1888 0 : 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 : **/
1901 137 : int gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7)
1902 : {
1903 137 : int result, count;
1904 :
1905 137 : if (pkcs7 == NULL)
1906 : return GNUTLS_E_INVALID_REQUEST;
1907 :
1908 : /* Step 2. Count the CertificateSet */
1909 :
1910 137 : result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1911 137 : if (result != ASN1_SUCCESS) {
1912 112 : gnutls_assert();
1913 112 : return 0; /* no crls */
1914 : }
1915 :
1916 25 : 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 : **/
1930 0 : int gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl)
1931 : {
1932 0 : int result;
1933 :
1934 0 : if (pkcs7 == NULL)
1935 : return GNUTLS_E_INVALID_REQUEST;
1936 :
1937 : /* If the signed data are uninitialized
1938 : * then create them.
1939 : */
1940 0 : if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
1941 : /* The pkcs7 structure is new, so create the
1942 : * signedData.
1943 : */
1944 0 : result =
1945 0 : create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
1946 0 : if (result < 0) {
1947 0 : gnutls_assert();
1948 0 : return result;
1949 : }
1950 : }
1951 :
1952 : /* Step 2. Append the new crl.
1953 : */
1954 :
1955 0 : result = asn1_write_value(pkcs7->signed_data, "crls", "NEW", 1);
1956 0 : if (result != ASN1_SUCCESS) {
1957 0 : gnutls_assert();
1958 0 : result = _gnutls_asn2err(result);
1959 0 : goto cleanup;
1960 : }
1961 :
1962 0 : result =
1963 0 : asn1_write_value(pkcs7->signed_data, "crls.?LAST", crl->data,
1964 0 : crl->size);
1965 0 : if (result != ASN1_SUCCESS) {
1966 0 : gnutls_assert();
1967 0 : result = _gnutls_asn2err(result);
1968 0 : 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 : **/
1988 0 : int gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
1989 : {
1990 0 : int ret;
1991 0 : gnutls_datum_t data;
1992 :
1993 0 : if (pkcs7 == NULL)
1994 : return GNUTLS_E_INVALID_REQUEST;
1995 :
1996 0 : ret = _gnutls_x509_der_encode(crl->crl, "", &data, 0);
1997 0 : if (ret < 0) {
1998 0 : gnutls_assert();
1999 0 : return ret;
2000 : }
2001 :
2002 0 : ret = gnutls_pkcs7_set_crl_raw(pkcs7, &data);
2003 :
2004 0 : _gnutls_free_datum(&data);
2005 :
2006 0 : if (ret < 0) {
2007 0 : gnutls_assert();
2008 0 : 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 : **/
2025 0 : int gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7, int indx)
2026 : {
2027 0 : int result;
2028 0 : char root2[MAX_NAME_SIZE];
2029 :
2030 0 : if (pkcs7 == NULL)
2031 : return GNUTLS_E_INVALID_REQUEST;
2032 :
2033 : /* Delete the crl.
2034 : */
2035 :
2036 0 : snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
2037 :
2038 0 : result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
2039 0 : if (result != ASN1_SUCCESS) {
2040 0 : gnutls_assert();
2041 0 : result = _gnutls_asn2err(result);
2042 0 : goto cleanup;
2043 : }
2044 :
2045 : return 0;
2046 :
2047 0 : cleanup:
2048 0 : return result;
2049 : }
2050 :
2051 13 : static int write_signer_id(ASN1_TYPE c2, const char *root,
2052 : gnutls_x509_crt_t signer, unsigned flags)
2053 : {
2054 13 : int result;
2055 13 : size_t serial_size;
2056 13 : uint8_t serial[128];
2057 13 : char name[256];
2058 :
2059 13 : if (flags & GNUTLS_PKCS7_WRITE_SPKI) {
2060 0 : const uint8_t ver = 3;
2061 :
2062 0 : snprintf(name, sizeof(name), "%s.version", root);
2063 0 : result = asn1_write_value(c2, name, &ver, 1);
2064 0 : if (result != ASN1_SUCCESS) {
2065 0 : gnutls_assert();
2066 0 : return _gnutls_asn2err(result);
2067 : }
2068 :
2069 0 : snprintf(name, sizeof(name), "%s.sid", root);
2070 0 : result = asn1_write_value(c2, name, "subjectKeyIdentifier", 1);
2071 0 : if (result != ASN1_SUCCESS) {
2072 0 : gnutls_assert();
2073 0 : return _gnutls_asn2err(result);
2074 : }
2075 :
2076 0 : serial_size = sizeof(serial);
2077 0 : result =
2078 0 : gnutls_x509_crt_get_subject_key_id(signer, serial,
2079 : &serial_size, NULL);
2080 0 : if (result < 0)
2081 0 : return gnutls_assert_val(result);
2082 :
2083 0 : snprintf(name, sizeof(name), "%s.subjectKeyIdentifier", root);
2084 0 : result = asn1_write_value(c2, name, serial, serial_size);
2085 0 : if (result != ASN1_SUCCESS) {
2086 0 : gnutls_assert();
2087 0 : return _gnutls_asn2err(result);
2088 : }
2089 : } else {
2090 13 : serial_size = sizeof(serial);
2091 13 : result =
2092 13 : gnutls_x509_crt_get_serial(signer, serial, &serial_size);
2093 13 : if (result < 0)
2094 0 : return gnutls_assert_val(result);
2095 :
2096 13 : snprintf(name, sizeof(name), "%s.sid", root);
2097 13 : result = asn1_write_value(c2, name, "issuerAndSerialNumber", 1);
2098 13 : if (result != ASN1_SUCCESS) {
2099 0 : gnutls_assert();
2100 0 : return _gnutls_asn2err(result);
2101 : }
2102 :
2103 13 : snprintf(name, sizeof(name),
2104 : "%s.sid.issuerAndSerialNumber.serialNumber", root);
2105 13 : result = asn1_write_value(c2, name, serial, serial_size);
2106 13 : if (result != ASN1_SUCCESS) {
2107 0 : gnutls_assert();
2108 0 : return _gnutls_asn2err(result);
2109 : }
2110 :
2111 13 : snprintf(name, sizeof(name),
2112 : "%s.sid.issuerAndSerialNumber.issuer", root);
2113 13 : result =
2114 13 : asn1_copy_node(c2, name, signer->cert,
2115 : "tbsCertificate.issuer");
2116 13 : if (result != ASN1_SUCCESS) {
2117 0 : gnutls_assert();
2118 0 : return _gnutls_asn2err(result);
2119 : }
2120 : }
2121 :
2122 : return 0;
2123 : }
2124 :
2125 26 : static int add_attrs(ASN1_TYPE c2, const char *root, gnutls_pkcs7_attrs_t attrs,
2126 : unsigned already_set)
2127 : {
2128 26 : char name[256];
2129 26 : gnutls_pkcs7_attrs_st *p = attrs;
2130 26 : int result;
2131 :
2132 26 : if (attrs == NULL) {
2133 : /* if there are no other attributes delete that field */
2134 24 : if (already_set == 0)
2135 22 : (void)asn1_write_value(c2, root, NULL, 0);
2136 : } else {
2137 5 : while (p != NULL) {
2138 3 : result = asn1_write_value(c2, root, "NEW", 1);
2139 3 : if (result != ASN1_SUCCESS) {
2140 0 : gnutls_assert();
2141 0 : return _gnutls_asn2err(result);
2142 : }
2143 :
2144 3 : snprintf(name, sizeof(name), "%s.?LAST.type", root);
2145 3 : result = asn1_write_value(c2, name, p->oid, 1);
2146 3 : if (result != ASN1_SUCCESS) {
2147 0 : gnutls_assert();
2148 0 : return _gnutls_asn2err(result);
2149 : }
2150 :
2151 3 : snprintf(name, sizeof(name), "%s.?LAST.values", root);
2152 3 : result = asn1_write_value(c2, name, "NEW", 1);
2153 3 : if (result != ASN1_SUCCESS) {
2154 0 : gnutls_assert();
2155 0 : return _gnutls_asn2err(result);
2156 : }
2157 :
2158 3 : snprintf(name, sizeof(name), "%s.?LAST.values.?1",
2159 : root);
2160 3 : result =
2161 6 : asn1_write_value(c2, name, p->data.data,
2162 3 : p->data.size);
2163 3 : if (result != ASN1_SUCCESS) {
2164 0 : gnutls_assert();
2165 0 : return _gnutls_asn2err(result);
2166 : }
2167 :
2168 3 : p = p->next;
2169 : }
2170 : }
2171 :
2172 : return 0;
2173 : }
2174 :
2175 13 : 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 13 : char name[256];
2181 13 : int result, ret;
2182 13 : uint8_t digest[MAX_HASH_SIZE];
2183 13 : gnutls_datum_t tmp = { NULL, 0 };
2184 13 : unsigned digest_size;
2185 13 : unsigned already_set = 0;
2186 :
2187 13 : if (flags & GNUTLS_PKCS7_INCLUDE_TIME) {
2188 2 : if (data == NULL || data->data == NULL) {
2189 0 : gnutls_assert();
2190 0 : return GNUTLS_E_INVALID_REQUEST;
2191 : }
2192 :
2193 : /* Add time */
2194 2 : result = asn1_write_value(c2, root, "NEW", 1);
2195 2 : if (result != ASN1_SUCCESS) {
2196 0 : gnutls_assert();
2197 0 : ret = _gnutls_asn2err(result);
2198 0 : return ret;
2199 : }
2200 :
2201 2 : snprintf(name, sizeof(name), "%s.?LAST.type", root);
2202 2 : result = asn1_write_value(c2, name, ATTR_SIGNING_TIME, 1);
2203 2 : if (result != ASN1_SUCCESS) {
2204 0 : gnutls_assert();
2205 0 : ret = _gnutls_asn2err(result);
2206 0 : return ret;
2207 : }
2208 :
2209 2 : snprintf(name, sizeof(name), "%s.?LAST.values", root);
2210 2 : result = asn1_write_value(c2, name, "NEW", 1);
2211 2 : if (result != ASN1_SUCCESS) {
2212 0 : gnutls_assert();
2213 0 : ret = _gnutls_asn2err(result);
2214 0 : return ret;
2215 : }
2216 :
2217 2 : snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2218 2 : ret = _gnutls_x509_set_raw_time(c2, name, gnutls_time(0));
2219 2 : if (ret < 0) {
2220 0 : gnutls_assert();
2221 0 : return ret;
2222 : }
2223 :
2224 : already_set = 1;
2225 : }
2226 :
2227 13 : ret = add_attrs(c2, root, other_attrs, already_set);
2228 13 : if (ret < 0) {
2229 0 : gnutls_assert();
2230 0 : return ret;
2231 : }
2232 :
2233 13 : if (already_set != 0 || other_attrs != NULL) {
2234 : /* Add content type */
2235 3 : result = asn1_write_value(c2, root, "NEW", 1);
2236 3 : if (result != ASN1_SUCCESS) {
2237 0 : gnutls_assert();
2238 0 : ret = _gnutls_asn2err(result);
2239 0 : return ret;
2240 : }
2241 :
2242 3 : snprintf(name, sizeof(name), "%s.?LAST.type", root);
2243 3 : result = asn1_write_value(c2, name, ATTR_CONTENT_TYPE, 1);
2244 3 : if (result != ASN1_SUCCESS) {
2245 0 : gnutls_assert();
2246 0 : ret = _gnutls_asn2err(result);
2247 0 : return ret;
2248 : }
2249 :
2250 3 : snprintf(name, sizeof(name), "%s.?LAST.values", root);
2251 3 : result = asn1_write_value(c2, name, "NEW", 1);
2252 3 : if (result != ASN1_SUCCESS) {
2253 0 : gnutls_assert();
2254 0 : ret = _gnutls_asn2err(result);
2255 0 : return ret;
2256 : }
2257 :
2258 3 : ret =
2259 3 : _gnutls_x509_get_raw_field(c2,
2260 : "encapContentInfo.eContentType",
2261 : &tmp);
2262 3 : if (ret < 0) {
2263 0 : gnutls_assert();
2264 0 : return ret;
2265 : }
2266 :
2267 3 : snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2268 3 : result = asn1_write_value(c2, name, tmp.data, tmp.size);
2269 3 : gnutls_free(tmp.data);
2270 :
2271 3 : if (result != ASN1_SUCCESS) {
2272 0 : gnutls_assert();
2273 0 : ret = _gnutls_asn2err(result);
2274 0 : return ret;
2275 : }
2276 :
2277 : /* If we add any attribute we should add them all */
2278 : /* Add hash */
2279 3 : digest_size = _gnutls_hash_get_algo_len(me);
2280 3 : ret = gnutls_hash_fast(MAC_TO_DIG(me->id), data->data, data->size, digest);
2281 3 : if (ret < 0) {
2282 0 : gnutls_assert();
2283 0 : return ret;
2284 : }
2285 :
2286 3 : result = asn1_write_value(c2, root, "NEW", 1);
2287 3 : if (result != ASN1_SUCCESS) {
2288 0 : gnutls_assert();
2289 0 : ret = _gnutls_asn2err(result);
2290 0 : return ret;
2291 : }
2292 :
2293 3 : snprintf(name, sizeof(name), "%s.?LAST", root);
2294 3 : ret =
2295 3 : _gnutls_x509_encode_and_write_attribute(ATTR_MESSAGE_DIGEST,
2296 : c2, name, digest,
2297 : digest_size, 1);
2298 3 : if (ret < 0) {
2299 0 : gnutls_assert();
2300 0 : 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 : **/
2332 13 : 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 13 : int ret, result;
2341 13 : gnutls_datum_t sigdata = { NULL, 0 };
2342 13 : gnutls_datum_t signature = { NULL, 0 };
2343 13 : const mac_entry_st *me = hash_to_entry(dig);
2344 13 : unsigned pk, sigalgo;
2345 13 : gnutls_x509_spki_st key_params, params;
2346 13 : const gnutls_sign_entry_st *se;
2347 :
2348 13 : if (pkcs7 == NULL || me == NULL)
2349 : return GNUTLS_E_INVALID_REQUEST;
2350 :
2351 13 : if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
2352 13 : result =
2353 13 : asn1_create_element(_gnutls_get_pkix(),
2354 : "PKIX1.pkcs-7-SignedData",
2355 : &pkcs7->signed_data);
2356 13 : if (result != ASN1_SUCCESS) {
2357 0 : gnutls_assert();
2358 0 : ret = _gnutls_asn2err(result);
2359 0 : goto cleanup;
2360 : }
2361 :
2362 13 : if (!(flags & GNUTLS_PKCS7_EMBED_DATA)) {
2363 4 : (void)asn1_write_value(pkcs7->signed_data,
2364 : "encapContentInfo.eContent", NULL, 0);
2365 : }
2366 : }
2367 :
2368 13 : result = asn1_write_value(pkcs7->signed_data, "version", &one, 1);
2369 13 : if (result != ASN1_SUCCESS) {
2370 0 : ret = _gnutls_asn2err(result);
2371 0 : goto cleanup;
2372 : }
2373 :
2374 13 : result =
2375 13 : asn1_write_value(pkcs7->signed_data,
2376 : "encapContentInfo.eContentType", DATA_OID,
2377 : 0);
2378 13 : if (result != ASN1_SUCCESS) {
2379 0 : ret = _gnutls_asn2err(result);
2380 0 : goto cleanup;
2381 : }
2382 :
2383 13 : if ((flags & GNUTLS_PKCS7_EMBED_DATA) && data->data) { /* embed data */
2384 9 : ret =
2385 9 : _gnutls_x509_write_string(pkcs7->signed_data,
2386 : "encapContentInfo.eContent", data,
2387 : ASN1_ETYPE_OCTET_STRING);
2388 9 : if (ret < 0) {
2389 0 : goto cleanup;
2390 : }
2391 : }
2392 :
2393 13 : if (flags & GNUTLS_PKCS7_INCLUDE_CERT) {
2394 12 : ret = gnutls_pkcs7_set_crt(pkcs7, signer);
2395 12 : if (ret < 0) {
2396 0 : gnutls_assert();
2397 0 : goto cleanup;
2398 : }
2399 : }
2400 :
2401 : /* append digest info algorithm */
2402 13 : result =
2403 13 : asn1_write_value(pkcs7->signed_data, "digestAlgorithms", "NEW", 1);
2404 13 : if (result != ASN1_SUCCESS) {
2405 0 : gnutls_assert();
2406 0 : ret = _gnutls_asn2err(result);
2407 0 : goto cleanup;
2408 : }
2409 :
2410 13 : result =
2411 26 : asn1_write_value(pkcs7->signed_data,
2412 : "digestAlgorithms.?LAST.algorithm",
2413 13 : _gnutls_x509_digest_to_oid(me), 1);
2414 13 : if (result != ASN1_SUCCESS) {
2415 0 : gnutls_assert();
2416 0 : ret = _gnutls_asn2err(result);
2417 0 : goto cleanup;
2418 : }
2419 :
2420 13 : (void)asn1_write_value(pkcs7->signed_data,
2421 : "digestAlgorithms.?LAST.parameters", NULL, 0);
2422 :
2423 : /* append signer's info */
2424 13 : result = asn1_write_value(pkcs7->signed_data, "signerInfos", "NEW", 1);
2425 13 : if (result != ASN1_SUCCESS) {
2426 0 : gnutls_assert();
2427 0 : ret = _gnutls_asn2err(result);
2428 0 : goto cleanup;
2429 : }
2430 :
2431 13 : result =
2432 13 : asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.version",
2433 : &one, 1);
2434 13 : if (result != ASN1_SUCCESS) {
2435 0 : gnutls_assert();
2436 0 : ret = _gnutls_asn2err(result);
2437 0 : goto cleanup;
2438 : }
2439 :
2440 13 : result =
2441 26 : asn1_write_value(pkcs7->signed_data,
2442 : "signerInfos.?LAST.digestAlgorithm.algorithm",
2443 13 : _gnutls_x509_digest_to_oid(me), 1);
2444 13 : if (result != ASN1_SUCCESS) {
2445 0 : gnutls_assert();
2446 0 : ret = _gnutls_asn2err(result);
2447 0 : goto cleanup;
2448 : }
2449 :
2450 13 : (void)asn1_write_value(pkcs7->signed_data,
2451 : "signerInfos.?LAST.digestAlgorithm.parameters", NULL,
2452 : 0);
2453 :
2454 13 : ret =
2455 13 : write_signer_id(pkcs7->signed_data, "signerInfos.?LAST", signer,
2456 : flags);
2457 13 : if (ret < 0) {
2458 0 : gnutls_assert();
2459 0 : goto cleanup;
2460 : }
2461 :
2462 13 : ret =
2463 13 : add_attrs(pkcs7->signed_data, "signerInfos.?LAST.unsignedAttrs",
2464 : unsigned_attrs, 0);
2465 13 : if (ret < 0) {
2466 0 : gnutls_assert();
2467 0 : goto cleanup;
2468 : }
2469 :
2470 13 : ret =
2471 13 : write_attributes(pkcs7->signed_data,
2472 : "signerInfos.?LAST.signedAttrs", data, me,
2473 : signed_attrs, flags);
2474 13 : if (ret < 0) {
2475 0 : gnutls_assert();
2476 0 : goto cleanup;
2477 : }
2478 :
2479 13 : disable_opt_fields(pkcs7);
2480 :
2481 : /* write the signature algorithm */
2482 13 : pk = gnutls_x509_crt_get_pk_algorithm(signer, NULL);
2483 :
2484 13 : ret = _gnutls_privkey_get_spki_params(signer_key, &key_params);
2485 13 : if (ret < 0) {
2486 0 : gnutls_assert();
2487 0 : goto cleanup;
2488 : }
2489 :
2490 13 : ret = _gnutls_x509_crt_get_spki_params(signer, &key_params, ¶ms);
2491 13 : if (ret < 0) {
2492 0 : gnutls_assert();
2493 0 : goto cleanup;
2494 : }
2495 :
2496 13 : ret = _gnutls_privkey_update_spki_params(signer_key, pk, dig, 0,
2497 : ¶ms);
2498 13 : if (ret < 0) {
2499 0 : gnutls_assert();
2500 0 : goto cleanup;
2501 : }
2502 :
2503 13 : se = _gnutls_pk_to_sign_entry(params.pk, dig);
2504 13 : if (se == NULL) {
2505 0 : ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
2506 0 : 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 13 : params.legacy = 1;
2515 13 : ret =
2516 13 : _gnutls_x509_write_sign_params(pkcs7->signed_data,
2517 : "signerInfos.?LAST.signatureAlgorithm",
2518 : se, ¶ms);
2519 13 : if (ret < 0) {
2520 0 : gnutls_assert();
2521 0 : goto cleanup;
2522 : }
2523 :
2524 13 : sigalgo = se->id;
2525 :
2526 : /* sign the data */
2527 13 : ret =
2528 13 : figure_pkcs7_sigdata(pkcs7, "signerInfos.?LAST", data, sigalgo,
2529 : &sigdata);
2530 13 : if (ret < 0) {
2531 0 : gnutls_assert();
2532 0 : goto cleanup;
2533 : }
2534 :
2535 13 : FIX_SIGN_PARAMS(params, flags, dig);
2536 :
2537 13 : ret = privkey_sign_and_hash_data(signer_key, se,
2538 : &sigdata, &signature, ¶ms);
2539 13 : if (ret < 0) {
2540 0 : gnutls_assert();
2541 0 : goto cleanup;
2542 : }
2543 :
2544 13 : result =
2545 26 : asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.signature",
2546 13 : signature.data, signature.size);
2547 13 : if (result != ASN1_SUCCESS) {
2548 0 : gnutls_assert();
2549 0 : ret = _gnutls_asn2err(result);
2550 0 : goto cleanup;
2551 : }
2552 :
2553 : ret = 0;
2554 :
2555 13 : cleanup:
2556 13 : gnutls_free(sigdata.data);
2557 13 : gnutls_free(signature.data);
2558 13 : return ret;
2559 : }
|