Coverage Report

Created: 2026-11-12 07:00

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