Coverage Report

Created: 2023-11-19 07:41

/src/gnutls/lib/x509/pkcs7.c
Line
Count
Source (jump to first uncovered line)
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.40k
{
51
3.40k
  asn1_node c2;
52
3.40k
  int len, result;
53
3.40k
  gnutls_datum_t tmp = { NULL, 0 };
54
55
3.40k
  len = MAX_OID_SIZE - 1;
56
3.40k
  result = asn1_read_value(pkcs7->pkcs7, "contentType",
57
3.40k
         pkcs7->encap_data_oid, &len);
58
3.40k
  if (result != ASN1_SUCCESS) {
59
13
    gnutls_assert();
60
13
    return _gnutls_asn2err(result);
61
13
  }
62
63
3.39k
  if (strcmp(pkcs7->encap_data_oid, SIGNED_DATA_OID) != 0) {
64
70
    gnutls_assert();
65
70
    _gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n",
66
70
          pkcs7->encap_data_oid);
67
70
    return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
68
70
  }
69
70
3.32k
  if ((result = asn1_create_element(_gnutls_get_pkix(),
71
3.32k
            "PKIX1.pkcs-7-SignedData", &c2)) !=
72
3.32k
      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.32k
  result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
81
3.32k
  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.32k
  result = asn1_der_decoding(&c2, tmp.data, tmp.size, NULL);
90
3.32k
  if (result != ASN1_SUCCESS) {
91
1.58k
    gnutls_assert();
92
1.58k
    result = _gnutls_asn2err(result);
93
1.58k
    goto cleanup;
94
1.58k
  }
95
96
  /* read the encapsulated content */
97
1.74k
  len = MAX_OID_SIZE - 1;
98
1.74k
  result = asn1_read_value(c2, "encapContentInfo.eContentType",
99
1.74k
         pkcs7->encap_data_oid, &len);
100
1.74k
  if (result != ASN1_SUCCESS) {
101
70
    gnutls_assert();
102
70
    result = _gnutls_asn2err(result);
103
70
    goto cleanup;
104
70
  }
105
106
1.67k
  if (strcmp(pkcs7->encap_data_oid, DATA_OID) != 0 &&
107
1.67k
      strcmp(pkcs7->encap_data_oid, DIGESTED_DATA_OID) != 0) {
108
1.66k
    _gnutls_debug_log(
109
1.66k
      "Unknown PKCS#7 Encapsulated Content OID '%s'; treating as raw data\n",
110
1.66k
      pkcs7->encap_data_oid);
111
1.66k
  }
112
113
  /* Try reading as octet string according to rfc5652. If that fails, attempt
114
   * a raw read according to rfc2315 */
115
1.67k
  result = _gnutls_x509_read_string(c2, "encapContentInfo.eContent",
116
1.67k
            &pkcs7->der_signed_data,
117
1.67k
            ASN1_ETYPE_OCTET_STRING, 1);
118
1.67k
  if (result < 0) {
119
1.62k
    result = _gnutls_x509_read_value(c2,
120
1.62k
             "encapContentInfo.eContent",
121
1.62k
             &pkcs7->der_signed_data);
122
1.62k
    if (result < 0) {
123
1.45k
      pkcs7->der_signed_data.data = NULL;
124
1.45k
      pkcs7->der_signed_data.size = 0;
125
1.45k
    } else {
126
167
      int tag_len, len_len;
127
167
      unsigned char cls;
128
167
      unsigned long tag;
129
130
      /* we skip the embedded element's tag and length - uncharted territorry - used by MICROSOFT_CERT_TRUST_LIST */
131
167
      result = asn1_get_tag_der(pkcs7->der_signed_data.data,
132
167
              pkcs7->der_signed_data.size,
133
167
              &cls, &tag_len, &tag);
134
167
      if (result != ASN1_SUCCESS) {
135
0
        gnutls_assert();
136
0
        result = _gnutls_asn2err(result);
137
0
        goto cleanup;
138
0
      }
139
140
167
      result = asn1_get_length_ber(
141
167
        pkcs7->der_signed_data.data + tag_len,
142
167
        pkcs7->der_signed_data.size - tag_len,
143
167
        &len_len);
144
167
      if (result < 0) {
145
0
        gnutls_assert();
146
0
        result = GNUTLS_E_ASN1_DER_ERROR;
147
0
        goto cleanup;
148
0
      }
149
150
167
      tag_len += len_len;
151
167
      memmove(pkcs7->der_signed_data.data,
152
167
        &pkcs7->der_signed_data.data[tag_len],
153
167
        pkcs7->der_signed_data.size - tag_len);
154
167
      pkcs7->der_signed_data.size -= tag_len;
155
167
    }
156
1.62k
  }
157
158
1.67k
  if (pkcs7->signed_data)
159
0
    asn1_delete_structure(&pkcs7->signed_data);
160
1.67k
  pkcs7->signed_data = c2;
161
1.67k
  gnutls_free(tmp.data);
162
163
1.67k
  return 0;
164
165
1.65k
cleanup:
166
1.65k
  gnutls_free(tmp.data);
167
1.65k
  if (c2)
168
70
    asn1_delete_structure(&c2);
169
1.65k
  return result;
170
1.67k
}
171
172
static int pkcs7_reinit(gnutls_pkcs7_t pkcs7)
173
5.27k
{
174
5.27k
  int result;
175
176
5.27k
  asn1_delete_structure(&pkcs7->pkcs7);
177
178
5.27k
  result = asn1_create_element(_gnutls_get_pkix(),
179
5.27k
             "PKIX1.pkcs-7-ContentInfo", &pkcs7->pkcs7);
180
5.27k
  if (result != ASN1_SUCCESS) {
181
0
    result = _gnutls_asn2err(result);
182
0
    gnutls_assert();
183
0
    return result;
184
0
  }
185
186
5.27k
  return 0;
187
5.27k
}
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.27k
{
202
5.27k
  *pkcs7 = gnutls_calloc(1, sizeof(gnutls_pkcs7_int));
203
204
5.27k
  if (*pkcs7) {
205
5.27k
    int result = pkcs7_reinit(*pkcs7);
206
5.27k
    if (result < 0) {
207
0
      gnutls_assert();
208
0
      gnutls_free(*pkcs7);
209
0
      return result;
210
0
    }
211
5.27k
    return 0; /* success */
212
5.27k
  }
213
0
  return GNUTLS_E_MEMORY_ERROR;
214
5.27k
}
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.27k
{
224
5.27k
  if (!pkcs7)
225
0
    return;
226
227
5.27k
  if (pkcs7->pkcs7)
228
3.40k
    asn1_delete_structure(&pkcs7->pkcs7);
229
230
5.27k
  if (pkcs7->signed_data)
231
1.67k
    asn1_delete_structure(&pkcs7->signed_data);
232
233
5.27k
  _gnutls_free_datum(&pkcs7->der_signed_data);
234
235
5.27k
  gnutls_free(pkcs7);
236
5.27k
}
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.27k
{
258
5.27k
  int result = 0, need_free = 0;
259
5.27k
  gnutls_datum_t _data;
260
261
5.27k
  if (pkcs7 == NULL)
262
0
    return GNUTLS_E_INVALID_REQUEST;
263
264
5.27k
  _data.data = data->data;
265
5.27k
  _data.size = data->size;
266
267
  /* If the PKCS7 is in PEM format then decode it
268
   */
269
5.27k
  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.27k
  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.27k
  pkcs7->expanded = 1;
289
290
5.27k
  result = asn1_der_decoding(&pkcs7->pkcs7, _data.data, _data.size, NULL);
291
5.27k
  if (result != ASN1_SUCCESS) {
292
1.87k
    result = _gnutls_asn2err(result);
293
1.87k
    gnutls_assert();
294
1.87k
    goto cleanup;
295
1.87k
  }
296
297
  /* Decode the signed data.
298
   */
299
3.40k
  result = _decode_pkcs7_signed_data(pkcs7);
300
3.40k
  if (result < 0) {
301
1.73k
    gnutls_assert();
302
1.73k
    goto cleanup;
303
1.73k
  }
304
305
1.67k
  result = 0;
306
307
5.27k
cleanup:
308
5.27k
  if (need_free)
309
0
    _gnutls_free_datum(&_data);
310
5.27k
  return result;
311
1.67k
}
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
167k
{
335
167k
  int result, len;
336
167k
  char root2[MAX_NAME_SIZE];
337
167k
  char oid[MAX_OID_SIZE];
338
167k
  gnutls_datum_t tmp = { NULL, 0 };
339
340
167k
  if (pkcs7 == NULL)
341
0
    return GNUTLS_E_INVALID_REQUEST;
342
343
  /* Step 2. Parse the CertificateSet
344
   */
345
167k
  snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
346
347
167k
  len = sizeof(oid) - 1;
348
349
167k
  result = asn1_read_value(pkcs7->signed_data, root2, oid, &len);
350
351
167k
  if (result == ASN1_VALUE_NOT_FOUND) {
352
0
    result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
353
0
    goto cleanup;
354
0
  }
355
356
167k
  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
167k
  if (strcmp(oid, "certificate") == 0) {
365
167k
    int start, end;
366
367
167k
    result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
368
167k
    if (result < 0) {
369
0
      gnutls_assert();
370
0
      goto cleanup;
371
0
    }
372
373
167k
    result = asn1_der_decoding_startEnd(pkcs7->signed_data,
374
167k
                tmp.data, tmp.size, root2,
375
167k
                &start, &end);
376
377
167k
    if (result != ASN1_SUCCESS) {
378
0
      gnutls_assert();
379
0
      result = _gnutls_asn2err(result);
380
0
      goto cleanup;
381
0
    }
382
383
167k
    end = end - start + 1;
384
385
167k
    result = _gnutls_set_datum(cert, &tmp.data[start], end);
386
167k
  } else {
387
0
    result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
388
0
  }
389
390
167k
cleanup:
391
167k
  _gnutls_free_datum(&tmp);
392
167k
  return result;
393
167k
}
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.67k
{
451
1.67k
  int result, count;
452
453
1.67k
  if (pkcs7 == NULL)
454
0
    return GNUTLS_E_INVALID_REQUEST;
455
456
  /* Step 2. Count the CertificateSet */
457
458
1.67k
  result = asn1_number_of_elements(pkcs7->signed_data, "certificates",
459
1.67k
           &count);
460
1.67k
  if (result != ASN1_SUCCESS) {
461
1.41k
    gnutls_assert();
462
1.41k
    return 0; /* no certificates */
463
1.41k
  }
464
465
251
  return count;
466
1.67k
}
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.29k
{
479
9.29k
  gnutls_free(info->sig.data);
480
9.29k
  gnutls_free(info->issuer_dn.data);
481
9.29k
  gnutls_free(info->signer_serial.data);
482
9.29k
  gnutls_free(info->issuer_keyid.data);
483
9.29k
  gnutls_pkcs7_attrs_deinit(info->signed_attrs);
484
9.29k
  gnutls_pkcs7_attrs_deinit(info->unsigned_attrs);
485
9.29k
  memset(info, 0, sizeof(*info));
486
9.29k
}
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
10.9k
{
571
10.9k
  int ret, count, len;
572
10.9k
  char root[256];
573
10.9k
  char oid[MAX_OID_SIZE];
574
10.9k
  gnutls_pk_algorithm_t pk;
575
10.9k
  gnutls_sign_algorithm_t sig;
576
10.9k
  gnutls_datum_t tmp = { NULL, 0 };
577
10.9k
  unsigned i;
578
579
10.9k
  if (pkcs7 == NULL)
580
0
    return GNUTLS_E_INVALID_REQUEST;
581
582
10.9k
  memset(info, 0, sizeof(*info));
583
10.9k
  info->signing_time = -1;
584
585
10.9k
  ret = asn1_number_of_elements(pkcs7->signed_data, "signerInfos",
586
10.9k
              &count);
587
10.9k
  if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
588
1.31k
    gnutls_assert();
589
1.31k
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
590
1.31k
  }
591
9.61k
  snprintf(root, sizeof(root),
592
9.61k
     "signerInfos.?%u.signatureAlgorithm.algorithm", idx + 1);
593
594
9.61k
  len = sizeof(oid) - 1;
595
9.61k
  ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
596
9.61k
  if (ret != ASN1_SUCCESS) {
597
43
    gnutls_assert();
598
43
    goto unsupp_algo;
599
43
  }
600
601
9.56k
  sig = gnutls_oid_to_sign(oid);
602
9.56k
  if (sig == GNUTLS_SIGN_UNKNOWN) {
603
    /* great PKCS #7 allows to only specify a public key algo */
604
2.59k
    pk = gnutls_oid_to_pk(oid);
605
2.59k
    if (pk == GNUTLS_PK_UNKNOWN) {
606
158
      gnutls_assert();
607
158
      goto unsupp_algo;
608
158
    }
609
610
    /* use the digests algorithm */
611
2.43k
    snprintf(root, sizeof(root),
612
2.43k
       "signerInfos.?%u.digestAlgorithm.algorithm", idx + 1);
613
614
2.43k
    len = sizeof(oid) - 1;
615
2.43k
    ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
616
2.43k
    if (ret != ASN1_SUCCESS) {
617
6
      gnutls_assert();
618
6
      goto unsupp_algo;
619
6
    }
620
621
2.43k
    ret = gnutls_oid_to_digest(oid);
622
2.43k
    if (ret == GNUTLS_DIG_UNKNOWN) {
623
92
      gnutls_assert();
624
92
      goto unsupp_algo;
625
92
    }
626
627
2.33k
    sig = gnutls_pk_to_sign(pk, ret);
628
2.33k
    if (sig == GNUTLS_SIGN_UNKNOWN) {
629
16
      gnutls_assert();
630
16
      goto unsupp_algo;
631
16
    }
632
2.33k
  }
633
634
9.29k
  info->algo = sig;
635
636
9.29k
  snprintf(root, sizeof(root), "signerInfos.?%u.signature", idx + 1);
637
  /* read the signature */
638
9.29k
  ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &info->sig);
639
9.29k
  if (ret < 0) {
640
29
    gnutls_assert();
641
29
    goto fail;
642
29
  }
643
644
  /* read the issuer info */
645
9.26k
  snprintf(root, sizeof(root),
646
9.26k
     "signerInfos.?%u.sid.issuerAndSerialNumber.issuer.rdnSequence",
647
9.26k
     idx + 1);
648
  /* read the signature */
649
9.26k
  ret = _gnutls_x509_get_raw_field(pkcs7->signed_data, root,
650
9.26k
           &info->issuer_dn);
651
9.26k
  if (ret >= 0) {
652
6.53k
    snprintf(
653
6.53k
      root, sizeof(root),
654
6.53k
      "signerInfos.?%u.sid.issuerAndSerialNumber.serialNumber",
655
6.53k
      idx + 1);
656
    /* read the signature */
657
6.53k
    ret = _gnutls_x509_read_value(pkcs7->signed_data, root,
658
6.53k
                &info->signer_serial);
659
6.53k
    if (ret < 0) {
660
1
      gnutls_assert();
661
1
      goto fail;
662
1
    }
663
6.53k
  } else { /* keyid */
664
2.73k
    snprintf(root, sizeof(root),
665
2.73k
       "signerInfos.?%u.sid.subjectKeyIdentifier", idx + 1);
666
    /* read the signature */
667
2.73k
    ret = _gnutls_x509_read_value(pkcs7->signed_data, root,
668
2.73k
                &info->issuer_keyid);
669
2.73k
    if (ret < 0) {
670
12
      gnutls_assert();
671
12
    }
672
2.73k
  }
673
674
9.26k
  if (info->issuer_keyid.data == NULL && info->issuer_dn.data == NULL) {
675
12
    ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
676
12
    goto fail;
677
12
  }
678
679
  /* read the signing time */
680
9.25k
  for (i = 0;; i++) {
681
9.25k
    snprintf(root, sizeof(root),
682
9.25k
       "signerInfos.?%u.signedAttrs.?%u.type", idx + 1,
683
9.25k
       i + 1);
684
9.25k
    len = sizeof(oid) - 1;
685
9.25k
    ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
686
9.25k
    if (ret != ASN1_SUCCESS) {
687
9.25k
      break;
688
9.25k
    }
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 (strcmp(oid, ATTR_SIGNING_TIME) == 0) {
711
0
      info->signing_time = parse_time(pkcs7, root);
712
0
    }
713
0
  }
714
715
  /* read the unsigned attrs */
716
9.25k
  for (i = 0;; i++) {
717
9.25k
    snprintf(root, sizeof(root),
718
9.25k
       "signerInfos.?%u.unsignedAttrs.?%u.type", idx + 1,
719
9.25k
       i + 1);
720
9.25k
    len = sizeof(oid) - 1;
721
9.25k
    ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
722
9.25k
    if (ret != ASN1_SUCCESS) {
723
9.25k
      break;
724
9.25k
    }
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.25k
  return 0;
749
42
fail:
750
42
  gnutls_free(tmp.data);
751
42
  gnutls_pkcs7_signature_info_deinit(info);
752
42
  return ret;
753
315
unsupp_algo:
754
315
  return GNUTLS_E_UNKNOWN_ALGORITHM;
755
9.25k
}
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 (strcmp(oid, ATTR_MESSAGE_DIGEST) == 0) {
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
          memcmp(hash_output, tmp2.data, tmp2.size) == 0) {
817
0
        msg_digest_ok = 1;
818
0
      } else {
819
0
        gnutls_assert();
820
0
      }
821
0
    } else if (strcmp(oid, ATTR_CONTENT_TYPE) == 0) {
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
          memcmp(tmp.data, tmp2.data, tmp2.size) != 0) {
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.67k
{
956
1.67k
  if (pkcs7 == NULL || pkcs7->encap_data_oid[0] == 0)
957
0
    return NULL;
958
959
1.67k
  return pkcs7->encap_data_oid;
960
1.67k
}
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
          memcmp(info->signer_serial.data, tmp, tmp_size) !=
1189
0
            0) {
1190
0
        _gnutls_cert_log("doesn't match serial", crt);
1191
0
        gnutls_assert();
1192
0
        goto skip;
1193
0
      }
1194
0
    } else if (info->issuer_keyid.size > 0) {
1195
0
      tmp_size = sizeof(tmp);
1196
0
      ret = gnutls_x509_crt_get_subject_key_id(
1197
0
        crt, tmp, &tmp_size, NULL);
1198
0
      if (ret < 0) {
1199
0
        gnutls_assert();
1200
0
        goto skip;
1201
0
      }
1202
1203
0
      if (tmp_size != info->issuer_keyid.size ||
1204
0
          memcmp(info->issuer_keyid.data, tmp, tmp_size) !=
1205
0
            0) {
1206
0
        _gnutls_cert_log("doesn't match key ID", crt);
1207
0
        gnutls_assert();
1208
0
      skip:
1209
0
        gnutls_x509_crt_deinit(crt);
1210
0
        crt = NULL;
1211
0
        gnutls_free(tmpdata.data);
1212
0
        continue;
1213
0
      }
1214
0
    } else {
1215
0
      gnutls_assert();
1216
0
      crt = NULL;
1217
0
      goto fail;
1218
0
    }
1219
1220
0
    _gnutls_cert_log("signer is", crt);
1221
1222
    /* we found the child with the given serial or key ID */
1223
0
    break;
1224
0
  }
1225
1226
0
  if (crt == NULL) {
1227
0
    gnutls_assert();
1228
0
    return NULL;
1229
0
  }
1230
1231
0
  goto cleanup;
1232
0
fail:
1233
0
  if (crt) {
1234
0
    gnutls_x509_crt_deinit(crt);
1235
0
    crt = NULL;
1236
0
  }
1237
1238
0
cleanup:
1239
0
  gnutls_free(tmpdata.data);
1240
1241
0
  return crt;
1242
0
}
1243
1244
static gnutls_x509_crt_t find_signer(gnutls_pkcs7_t pkcs7,
1245
             gnutls_x509_trust_list_t tl,
1246
             gnutls_typed_vdata_st *vdata,
1247
             unsigned vdata_size, unsigned vflags,
1248
             gnutls_pkcs7_signature_info_st *info)
1249
0
{
1250
0
  gnutls_x509_crt_t issuer = NULL;
1251
0
  gnutls_x509_crt_t signer = NULL;
1252
0
  int ret;
1253
0
  gnutls_datum_t tmp = { NULL, 0 };
1254
0
  unsigned i, vtmp;
1255
0
  const char *purpose = NULL;
1256
1257
0
  if (info->issuer_keyid.data) {
1258
0
    ret = gnutls_x509_trust_list_get_issuer_by_subject_key_id(
1259
0
      tl, NULL, &info->issuer_keyid, &signer, 0);
1260
0
    if (ret < 0) {
1261
0
      gnutls_assert();
1262
0
      signer = NULL;
1263
0
    }
1264
0
  }
1265
1266
  /* get key purpose */
1267
0
  for (i = 0; i < vdata_size; i++) {
1268
0
    if (vdata[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
1269
0
      purpose = (char *)vdata[i].data;
1270
0
      break;
1271
0
    }
1272
0
  }
1273
1274
  /* this will give us the issuer of the signer (wtf) */
1275
0
  if (info->issuer_dn.data && signer == NULL) {
1276
0
    ret = gnutls_x509_trust_list_get_issuer_by_dn(
1277
0
      tl, &info->issuer_dn, &issuer, 0);
1278
0
    if (ret < 0) {
1279
0
      gnutls_assert();
1280
0
      signer = NULL;
1281
0
    }
1282
1283
0
    if (issuer) {
1284
      /* try to find the actual signer in the list of
1285
       * certificates */
1286
0
      signer = find_child_of_with_serial(pkcs7, issuer,
1287
0
                 purpose, info);
1288
0
      if (signer == NULL) {
1289
0
        gnutls_assert();
1290
0
        goto fail;
1291
0
      }
1292
1293
0
      gnutls_x509_crt_deinit(issuer);
1294
0
      issuer = NULL;
1295
0
    }
1296
0
  }
1297
1298
0
  if (signer == NULL) {
1299
    /* get the signer from the pkcs7 list; the one that matches serial
1300
     * or key ID */
1301
0
    signer = find_child_of_with_serial(pkcs7, NULL, purpose, info);
1302
0
    if (signer == NULL) {
1303
0
      gnutls_assert();
1304
0
      goto fail;
1305
0
    }
1306
1307
    /* if the signer cannot be verified from our trust list, make a chain of certificates
1308
     * starting from the identified signer, to a root we know. */
1309
0
    ret = gnutls_x509_trust_list_verify_crt2(
1310
0
      tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1311
0
    if (ret < 0 || vtmp != 0) {
1312
0
      gnutls_x509_crt_t prev = NULL;
1313
1314
0
      issuer = signer;
1315
      /* construct a chain */
1316
0
      do {
1317
0
        if (prev && prev != signer) {
1318
0
          gnutls_x509_crt_deinit(prev);
1319
0
        }
1320
0
        prev = issuer;
1321
1322
0
        issuer = find_verified_issuer_of(
1323
0
          pkcs7, issuer, purpose, vflags);
1324
1325
0
        if (issuer != NULL &&
1326
0
            gnutls_x509_crt_check_issuer(issuer,
1327
0
                 issuer)) {
1328
0
          if (prev && prev != signer)
1329
0
            gnutls_x509_crt_deinit(prev);
1330
0
          prev = issuer;
1331
0
          break;
1332
0
        }
1333
0
      } while (issuer != NULL);
1334
1335
0
      issuer = prev; /* the last we have seen */
1336
1337
0
      if (issuer == NULL) {
1338
0
        gnutls_assert();
1339
0
        goto fail;
1340
0
      }
1341
1342
0
      ret = gnutls_x509_trust_list_verify_crt2(
1343
0
        tl, &issuer, 1, vdata, vdata_size, vflags,
1344
0
        &vtmp, NULL);
1345
0
      if (ret < 0 || vtmp != 0) {
1346
        /* could not construct a valid chain */
1347
0
        _gnutls_reason_log(
1348
0
          "signer's chain failed trust list verification",
1349
0
          vtmp);
1350
0
        gnutls_assert();
1351
0
        goto fail;
1352
0
      }
1353
0
    }
1354
0
  } else {
1355
    /* verify that the signer we got is trusted */
1356
0
    ret = gnutls_x509_trust_list_verify_crt2(
1357
0
      tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
1358
0
    if (ret < 0 || vtmp != 0) {
1359
      /* could not construct a valid chain */
1360
0
      _gnutls_reason_log(
1361
0
        "signer failed trust list verification", vtmp);
1362
0
      gnutls_assert();
1363
0
      goto fail;
1364
0
    }
1365
0
  }
1366
1367
0
  if (signer == NULL) {
1368
0
    gnutls_assert();
1369
0
    goto fail;
1370
0
  }
1371
1372
0
  goto cleanup;
1373
1374
0
fail:
1375
0
  if (signer != NULL) {
1376
0
    if (issuer == signer)
1377
0
      issuer = NULL;
1378
0
    gnutls_x509_crt_deinit(signer);
1379
0
    signer = NULL;
1380
0
  }
1381
1382
0
cleanup:
1383
0
  if (issuer != NULL) {
1384
0
    gnutls_x509_crt_deinit(issuer);
1385
0
    issuer = NULL;
1386
0
  }
1387
0
  gnutls_free(tmp.data);
1388
1389
0
  return signer;
1390
0
}
1391
1392
/**
1393
 * gnutls_pkcs7_verify:
1394
 * @pkcs7: should contain a #gnutls_pkcs7_t type
1395
 * @tl: A list of trusted certificates
1396
 * @vdata: an array of typed data
1397
 * @vdata_size: the number of data elements
1398
 * @idx: the index of the signature info to check
1399
 * @data: The data to be verified or %NULL
1400
 * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
1401
 *
1402
 * This function will verify the provided data against the signature
1403
 * present in the SignedData of the PKCS #7 structure. If the data
1404
 * provided are NULL then the data in the encapsulatedContent field
1405
 * will be used instead.
1406
 *
1407
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1408
 *   negative error value. A verification error results to a
1409
 *   %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
1410
 *   to verify to a %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
1411
 *
1412
 * Since: 3.4.2
1413
 **/
1414
int gnutls_pkcs7_verify(gnutls_pkcs7_t pkcs7, gnutls_x509_trust_list_t tl,
1415
      gnutls_typed_vdata_st *vdata, unsigned int vdata_size,
1416
      unsigned idx, const gnutls_datum_t *data,
1417
      unsigned flags)
1418
0
{
1419
0
  int count, ret;
1420
0
  gnutls_datum_t tmpdata = { NULL, 0 };
1421
0
  gnutls_pkcs7_signature_info_st info;
1422
0
  gnutls_x509_crt_t signer;
1423
0
  gnutls_datum_t sigdata = { NULL, 0 };
1424
0
  char root[128];
1425
1426
0
  memset(&info, 0, sizeof(info));
1427
1428
0
  if (pkcs7 == NULL)
1429
0
    return GNUTLS_E_INVALID_REQUEST;
1430
1431
0
  ret = asn1_number_of_elements(pkcs7->signed_data, "signerInfos",
1432
0
              &count);
1433
0
  if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
1434
0
    gnutls_assert();
1435
0
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1436
0
  }
1437
1438
  /* read data */
1439
0
  ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
1440
0
  if (ret < 0) {
1441
0
    gnutls_assert();
1442
0
    goto cleanup;
1443
0
  }
1444
1445
0
  snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
1446
0
  ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
1447
0
  if (ret < 0) {
1448
0
    gnutls_assert();
1449
0
    goto cleanup;
1450
0
  }
1451
1452
0
  signer = find_signer(pkcs7, tl, vdata, vdata_size, flags, &info);
1453
0
  if (signer) {
1454
0
    ret = gnutls_x509_crt_verify_data3(signer, info.algo, vdata,
1455
0
               vdata_size, &sigdata,
1456
0
               &info.sig, flags);
1457
0
    if (ret < 0) {
1458
0
      _gnutls_cert_log("failed struct verification with",
1459
0
           signer);
1460
0
      gnutls_assert();
1461
0
    }
1462
0
    gnutls_x509_crt_deinit(signer);
1463
0
  } else {
1464
0
    gnutls_assert();
1465
0
    ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
1466
0
  }
1467
1468
0
cleanup:
1469
0
  gnutls_free(tmpdata.data);
1470
0
  gnutls_free(sigdata.data);
1471
0
  gnutls_pkcs7_signature_info_deinit(&info);
1472
1473
0
  return ret;
1474
0
}
1475
1476
static void disable_opt_fields(gnutls_pkcs7_t pkcs7)
1477
0
{
1478
0
  int result;
1479
0
  int count;
1480
1481
  /* disable the optional fields */
1482
0
  result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1483
0
  if (result != ASN1_SUCCESS || count == 0) {
1484
0
    (void)asn1_write_value(pkcs7->signed_data, "crls", NULL, 0);
1485
0
  }
1486
1487
0
  result = asn1_number_of_elements(pkcs7->signed_data, "certificates",
1488
0
           &count);
1489
0
  if (result != ASN1_SUCCESS || count == 0) {
1490
0
    (void)asn1_write_value(pkcs7->signed_data, "certificates", NULL,
1491
0
               0);
1492
0
  }
1493
1494
0
  return;
1495
0
}
1496
1497
static int reencode(gnutls_pkcs7_t pkcs7)
1498
0
{
1499
0
  int result;
1500
1501
0
  if (pkcs7->signed_data != NULL) {
1502
0
    disable_opt_fields(pkcs7);
1503
1504
    /* Replace the old content with the new
1505
     */
1506
0
    result = _gnutls_x509_der_encode_and_copy(
1507
0
      pkcs7->signed_data, "", pkcs7->pkcs7, "content", 0);
1508
0
    if (result < 0) {
1509
0
      return gnutls_assert_val(result);
1510
0
    }
1511
1512
    /* Write the content type of the signed data
1513
     */
1514
0
    result = asn1_write_value(pkcs7->pkcs7, "contentType",
1515
0
            SIGNED_DATA_OID, 1);
1516
0
    if (result != ASN1_SUCCESS) {
1517
0
      gnutls_assert();
1518
0
      return _gnutls_asn2err(result);
1519
0
    }
1520
0
  }
1521
0
  return 0;
1522
0
}
1523
1524
/**
1525
 * gnutls_pkcs7_export:
1526
 * @pkcs7: The pkcs7 type
1527
 * @format: the format of output params. One of PEM or DER.
1528
 * @output_data: will contain a structure PEM or DER encoded
1529
 * @output_data_size: holds the size of output_data (and will be
1530
 *   replaced by the actual size of parameters)
1531
 *
1532
 * This function will export the pkcs7 structure to DER or PEM format.
1533
 *
1534
 * If the buffer provided is not long enough to hold the output, then
1535
 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1536
 * will be returned.
1537
 *
1538
 * If the structure is PEM encoded, it will have a header
1539
 * of "BEGIN PKCS7".
1540
 *
1541
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1542
 *   negative error value.
1543
 **/
1544
int gnutls_pkcs7_export(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_fmt_t format,
1545
      void *output_data, size_t *output_data_size)
1546
0
{
1547
0
  int ret;
1548
0
  if (pkcs7 == NULL)
1549
0
    return GNUTLS_E_INVALID_REQUEST;
1550
1551
0
  if ((ret = reencode(pkcs7)) < 0)
1552
0
    return gnutls_assert_val(ret);
1553
1554
0
  return _gnutls_x509_export_int(pkcs7->pkcs7, format, PEM_PKCS7,
1555
0
               output_data, output_data_size);
1556
0
}
1557
1558
/**
1559
 * gnutls_pkcs7_export2:
1560
 * @pkcs7: The pkcs7 type
1561
 * @format: the format of output params. One of PEM or DER.
1562
 * @out: will contain a structure PEM or DER encoded
1563
 *
1564
 * This function will export the pkcs7 structure to DER or PEM format.
1565
 *
1566
 * The output buffer is allocated using gnutls_malloc().
1567
 *
1568
 * If the structure is PEM encoded, it will have a header
1569
 * of "BEGIN PKCS7".
1570
 *
1571
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1572
 *   negative error value.
1573
 *
1574
 * Since: 3.1.3
1575
 **/
1576
int gnutls_pkcs7_export2(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_fmt_t format,
1577
       gnutls_datum_t *out)
1578
0
{
1579
0
  int ret;
1580
0
  if (pkcs7 == NULL)
1581
0
    return GNUTLS_E_INVALID_REQUEST;
1582
1583
0
  if ((ret = reencode(pkcs7)) < 0)
1584
0
    return gnutls_assert_val(ret);
1585
1586
0
  return _gnutls_x509_export_int2(pkcs7->pkcs7, format, PEM_PKCS7, out);
1587
0
}
1588
1589
/* Creates an empty signed data structure in the pkcs7
1590
 * structure and returns a handle to the signed data.
1591
 */
1592
static int create_empty_signed_data(asn1_node pkcs7, asn1_node *sdata)
1593
0
{
1594
0
  int result;
1595
1596
0
  *sdata = NULL;
1597
1598
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
1599
0
            "PKIX1.pkcs-7-SignedData", sdata)) !=
1600
0
      ASN1_SUCCESS) {
1601
0
    gnutls_assert();
1602
0
    result = _gnutls_asn2err(result);
1603
0
    goto cleanup;
1604
0
  }
1605
1606
  /* Use version 1
1607
   */
1608
0
  result = asn1_write_value(*sdata, "version", &one, 1);
1609
0
  if (result != ASN1_SUCCESS) {
1610
0
    gnutls_assert();
1611
0
    result = _gnutls_asn2err(result);
1612
0
    goto cleanup;
1613
0
  }
1614
1615
  /* Use no digest algorithms
1616
   */
1617
1618
  /* id-data */
1619
0
  result = asn1_write_value(*sdata, "encapContentInfo.eContentType",
1620
0
          DIGESTED_DATA_OID, 1);
1621
0
  if (result != ASN1_SUCCESS) {
1622
0
    gnutls_assert();
1623
0
    result = _gnutls_asn2err(result);
1624
0
    goto cleanup;
1625
0
  }
1626
1627
0
  result = asn1_write_value(*sdata, "encapContentInfo.eContent", NULL, 0);
1628
0
  if (result != ASN1_SUCCESS) {
1629
0
    gnutls_assert();
1630
0
    result = _gnutls_asn2err(result);
1631
0
    goto cleanup;
1632
0
  }
1633
1634
  /* Add no certificates.
1635
   */
1636
1637
  /* Add no crls.
1638
   */
1639
1640
  /* Add no signerInfos.
1641
   */
1642
1643
0
  return 0;
1644
1645
0
cleanup:
1646
0
  asn1_delete_structure(sdata);
1647
0
  return result;
1648
0
}
1649
1650
/**
1651
 * gnutls_pkcs7_set_crt_raw:
1652
 * @pkcs7: The pkcs7 type
1653
 * @crt: the DER encoded certificate to be added
1654
 *
1655
 * This function will add a certificate to the PKCS7 or RFC2630
1656
 * certificate set.
1657
 *
1658
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1659
 *   negative error value.
1660
 **/
1661
int gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t *crt)
1662
0
{
1663
0
  int result;
1664
1665
0
  if (pkcs7 == NULL)
1666
0
    return GNUTLS_E_INVALID_REQUEST;
1667
1668
  /* If the signed data are uninitialized
1669
   * then create them.
1670
   */
1671
0
  if (pkcs7->signed_data == NULL) {
1672
    /* The pkcs7 structure is new, so create the
1673
     * signedData.
1674
     */
1675
0
    result = create_empty_signed_data(pkcs7->pkcs7,
1676
0
              &pkcs7->signed_data);
1677
0
    if (result < 0) {
1678
0
      gnutls_assert();
1679
0
      return result;
1680
0
    }
1681
0
  }
1682
1683
  /* Step 2. Append the new certificate.
1684
   */
1685
1686
0
  result = asn1_write_value(pkcs7->signed_data, "certificates", "NEW", 1);
1687
0
  if (result != ASN1_SUCCESS) {
1688
0
    gnutls_assert();
1689
0
    result = _gnutls_asn2err(result);
1690
0
    goto cleanup;
1691
0
  }
1692
1693
0
  result = asn1_write_value(pkcs7->signed_data, "certificates.?LAST",
1694
0
          "certificate", 1);
1695
0
  if (result != ASN1_SUCCESS) {
1696
0
    gnutls_assert();
1697
0
    result = _gnutls_asn2err(result);
1698
0
    goto cleanup;
1699
0
  }
1700
1701
0
  result = asn1_write_value(pkcs7->signed_data,
1702
0
          "certificates.?LAST.certificate", crt->data,
1703
0
          crt->size);
1704
0
  if (result != ASN1_SUCCESS) {
1705
0
    gnutls_assert();
1706
0
    result = _gnutls_asn2err(result);
1707
0
    goto cleanup;
1708
0
  }
1709
1710
0
  result = 0;
1711
1712
0
cleanup:
1713
0
  return result;
1714
0
}
1715
1716
/**
1717
 * gnutls_pkcs7_set_crt:
1718
 * @pkcs7: The pkcs7 type
1719
 * @crt: the certificate to be copied.
1720
 *
1721
 * This function will add a parsed certificate to the PKCS7 or
1722
 * RFC2630 certificate set.  This is a wrapper function over
1723
 * gnutls_pkcs7_set_crt_raw() .
1724
 *
1725
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1726
 *   negative error value.
1727
 **/
1728
int gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
1729
0
{
1730
0
  int ret;
1731
0
  gnutls_datum_t data;
1732
1733
0
  if (pkcs7 == NULL)
1734
0
    return GNUTLS_E_INVALID_REQUEST;
1735
1736
0
  ret = _gnutls_x509_der_encode(crt->cert, "", &data, 0);
1737
0
  if (ret < 0) {
1738
0
    gnutls_assert();
1739
0
    return ret;
1740
0
  }
1741
1742
0
  ret = gnutls_pkcs7_set_crt_raw(pkcs7, &data);
1743
1744
0
  _gnutls_free_datum(&data);
1745
1746
0
  if (ret < 0) {
1747
0
    gnutls_assert();
1748
0
    return ret;
1749
0
  }
1750
1751
0
  return 0;
1752
0
}
1753
1754
/**
1755
 * gnutls_pkcs7_delete_crt:
1756
 * @pkcs7: The pkcs7 type
1757
 * @indx: the index of the certificate to delete
1758
 *
1759
 * This function will delete a certificate from a PKCS7 or RFC2630
1760
 * certificate set.  Index starts from 0. Returns 0 on success.
1761
 *
1762
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1763
 *   negative error value.
1764
 **/
1765
int gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7, int indx)
1766
0
{
1767
0
  int result;
1768
0
  char root2[MAX_NAME_SIZE];
1769
1770
0
  if (pkcs7 == NULL)
1771
0
    return GNUTLS_E_INVALID_REQUEST;
1772
1773
  /* Step 2. Delete the certificate.
1774
   */
1775
1776
0
  snprintf(root2, sizeof(root2), "certificates.?%d", indx + 1);
1777
1778
0
  result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
1779
0
  if (result != ASN1_SUCCESS) {
1780
0
    gnutls_assert();
1781
0
    result = _gnutls_asn2err(result);
1782
0
    goto cleanup;
1783
0
  }
1784
1785
0
  return 0;
1786
1787
0
cleanup:
1788
0
  return result;
1789
0
}
1790
1791
/* Read and write CRLs
1792
 */
1793
1794
/**
1795
 * gnutls_pkcs7_get_crl_raw2:
1796
 * @pkcs7: The pkcs7 type
1797
 * @indx: contains the index of the crl to extract
1798
 * @crl: will contain the contents of the CRL in an allocated buffer
1799
 *
1800
 * This function will return a DER encoded CRL of the PKCS7 or RFC2630 crl set.
1801
 *
1802
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1803
 *   negative error value.  After the last crl has been read
1804
 *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1805
 *
1806
 * Since: 3.4.2
1807
 **/
1808
int gnutls_pkcs7_get_crl_raw2(gnutls_pkcs7_t pkcs7, unsigned indx,
1809
            gnutls_datum_t *crl)
1810
72.3k
{
1811
72.3k
  int result;
1812
72.3k
  char root2[MAX_NAME_SIZE];
1813
72.3k
  gnutls_datum_t tmp = { NULL, 0 };
1814
72.3k
  int start, end;
1815
1816
72.3k
  if (pkcs7 == NULL || crl == NULL)
1817
0
    return GNUTLS_E_INVALID_REQUEST;
1818
1819
72.3k
  result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
1820
72.3k
  if (result < 0) {
1821
0
    gnutls_assert();
1822
0
    goto cleanup;
1823
0
  }
1824
1825
  /* Step 2. Parse the CertificateSet
1826
   */
1827
1828
72.3k
  snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
1829
1830
  /* Get the raw CRL
1831
   */
1832
72.3k
  result = asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data,
1833
72.3k
              tmp.size, root2, &start, &end);
1834
1835
72.3k
  if (result != ASN1_SUCCESS) {
1836
0
    gnutls_assert();
1837
0
    result = _gnutls_asn2err(result);
1838
0
    goto cleanup;
1839
0
  }
1840
1841
72.3k
  end = end - start + 1;
1842
1843
72.3k
  result = _gnutls_set_datum(crl, &tmp.data[start], end);
1844
1845
72.3k
cleanup:
1846
72.3k
  _gnutls_free_datum(&tmp);
1847
72.3k
  return result;
1848
72.3k
}
1849
1850
/**
1851
 * gnutls_pkcs7_get_crl_raw:
1852
 * @pkcs7: The pkcs7 type
1853
 * @indx: contains the index of the crl to extract
1854
 * @crl: the contents of the crl will be copied there (may be null)
1855
 * @crl_size: should hold the size of the crl
1856
 *
1857
 * This function will return a crl of the PKCS7 or RFC2630 crl set.
1858
 *
1859
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1860
 *   negative error value.  If the provided buffer is not long enough,
1861
 *   then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
1862
 *   returned.  After the last crl has been read
1863
 *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1864
 **/
1865
int gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7, unsigned indx, void *crl,
1866
           size_t *crl_size)
1867
0
{
1868
0
  int ret;
1869
0
  gnutls_datum_t tmp = { NULL, 0 };
1870
1871
0
  ret = gnutls_pkcs7_get_crl_raw2(pkcs7, indx, &tmp);
1872
0
  if (ret < 0)
1873
0
    return gnutls_assert_val(ret);
1874
1875
0
  if ((unsigned)tmp.size > *crl_size) {
1876
0
    *crl_size = tmp.size;
1877
0
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
1878
0
    goto cleanup;
1879
0
  }
1880
1881
0
  assert(tmp.data != NULL);
1882
1883
0
  *crl_size = tmp.size;
1884
0
  if (crl)
1885
0
    memcpy(crl, tmp.data, tmp.size);
1886
1887
0
cleanup:
1888
0
  _gnutls_free_datum(&tmp);
1889
0
  return ret;
1890
0
}
1891
1892
/**
1893
 * gnutls_pkcs7_get_crl_count:
1894
 * @pkcs7: The pkcs7 type
1895
 *
1896
 * This function will return the number of certificates in the PKCS7
1897
 * or RFC2630 crl set.
1898
 *
1899
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1900
 *   negative error value.
1901
 **/
1902
int gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7)
1903
1.67k
{
1904
1.67k
  int result, count;
1905
1906
1.67k
  if (pkcs7 == NULL)
1907
0
    return GNUTLS_E_INVALID_REQUEST;
1908
1909
  /* Step 2. Count the CertificateSet */
1910
1911
1.67k
  result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
1912
1.67k
  if (result != ASN1_SUCCESS) {
1913
1.52k
    gnutls_assert();
1914
1.52k
    return 0; /* no crls */
1915
1.52k
  }
1916
1917
150
  return count;
1918
1.67k
}
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
int gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t *crl)
1931
0
{
1932
0
  int result;
1933
1934
0
  if (pkcs7 == NULL)
1935
0
    return GNUTLS_E_INVALID_REQUEST;
1936
1937
  /* If the signed data are uninitialized
1938
   * then create them.
1939
   */
1940
0
  if (pkcs7->signed_data == NULL) {
1941
    /* The pkcs7 structure is new, so create the
1942
     * signedData.
1943
     */
1944
0
    result = create_empty_signed_data(pkcs7->pkcs7,
1945
0
              &pkcs7->signed_data);
1946
0
    if (result < 0) {
1947
0
      gnutls_assert();
1948
0
      return result;
1949
0
    }
1950
0
  }
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
0
  }
1961
1962
0
  result = asn1_write_value(pkcs7->signed_data, "crls.?LAST", crl->data,
1963
0
          crl->size);
1964
0
  if (result != ASN1_SUCCESS) {
1965
0
    gnutls_assert();
1966
0
    result = _gnutls_asn2err(result);
1967
0
    goto cleanup;
1968
0
  }
1969
1970
0
  result = 0;
1971
1972
0
cleanup:
1973
0
  return result;
1974
0
}
1975
1976
/**
1977
 * gnutls_pkcs7_set_crl:
1978
 * @pkcs7: The pkcs7 type
1979
 * @crl: the DER encoded crl to be added
1980
 *
1981
 * This function will add a parsed CRL to the PKCS7 or RFC2630 crl
1982
 * set.
1983
 *
1984
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1985
 *   negative error value.
1986
 **/
1987
int gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
1988
0
{
1989
0
  int ret;
1990
0
  gnutls_datum_t data;
1991
1992
0
  if (pkcs7 == NULL)
1993
0
    return GNUTLS_E_INVALID_REQUEST;
1994
1995
0
  ret = _gnutls_x509_der_encode(crl->crl, "", &data, 0);
1996
0
  if (ret < 0) {
1997
0
    gnutls_assert();
1998
0
    return ret;
1999
0
  }
2000
2001
0
  ret = gnutls_pkcs7_set_crl_raw(pkcs7, &data);
2002
2003
0
  _gnutls_free_datum(&data);
2004
2005
0
  if (ret < 0) {
2006
0
    gnutls_assert();
2007
0
    return ret;
2008
0
  }
2009
2010
0
  return 0;
2011
0
}
2012
2013
/**
2014
 * gnutls_pkcs7_delete_crl:
2015
 * @pkcs7: The pkcs7 type
2016
 * @indx: the index of the crl to delete
2017
 *
2018
 * This function will delete a crl from a PKCS7 or RFC2630 crl set.
2019
 * Index starts from 0. Returns 0 on success.
2020
 *
2021
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2022
 *   negative error value.
2023
 **/
2024
int gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7, int indx)
2025
0
{
2026
0
  int result;
2027
0
  char root2[MAX_NAME_SIZE];
2028
2029
0
  if (pkcs7 == NULL)
2030
0
    return GNUTLS_E_INVALID_REQUEST;
2031
2032
  /* Delete the crl.
2033
   */
2034
2035
0
  snprintf(root2, sizeof(root2), "crls.?%d", indx + 1);
2036
2037
0
  result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
2038
0
  if (result != ASN1_SUCCESS) {
2039
0
    gnutls_assert();
2040
0
    result = _gnutls_asn2err(result);
2041
0
    goto cleanup;
2042
0
  }
2043
2044
0
  return 0;
2045
2046
0
cleanup:
2047
0
  return result;
2048
0
}
2049
2050
static int write_signer_id(asn1_node c2, const char *root,
2051
         gnutls_x509_crt_t signer, unsigned flags)
2052
0
{
2053
0
  int result;
2054
0
  size_t serial_size;
2055
0
  uint8_t serial[128];
2056
0
  char name[256];
2057
2058
0
  if (flags & GNUTLS_PKCS7_WRITE_SPKI) {
2059
0
    const uint8_t ver = 3;
2060
2061
0
    snprintf(name, sizeof(name), "%s.version", root);
2062
0
    result = asn1_write_value(c2, name, &ver, 1);
2063
0
    if (result != ASN1_SUCCESS) {
2064
0
      gnutls_assert();
2065
0
      return _gnutls_asn2err(result);
2066
0
    }
2067
2068
0
    snprintf(name, sizeof(name), "%s.sid", root);
2069
0
    result = asn1_write_value(c2, name, "subjectKeyIdentifier", 1);
2070
0
    if (result != ASN1_SUCCESS) {
2071
0
      gnutls_assert();
2072
0
      return _gnutls_asn2err(result);
2073
0
    }
2074
2075
0
    serial_size = sizeof(serial);
2076
0
    result = gnutls_x509_crt_get_subject_key_id(signer, serial,
2077
0
                  &serial_size, NULL);
2078
0
    if (result < 0)
2079
0
      return gnutls_assert_val(result);
2080
2081
0
    snprintf(name, sizeof(name), "%s.subjectKeyIdentifier", root);
2082
0
    result = asn1_write_value(c2, name, serial, serial_size);
2083
0
    if (result != ASN1_SUCCESS) {
2084
0
      gnutls_assert();
2085
0
      return _gnutls_asn2err(result);
2086
0
    }
2087
0
  } else {
2088
0
    serial_size = sizeof(serial);
2089
0
    result = gnutls_x509_crt_get_serial(signer, serial,
2090
0
                &serial_size);
2091
0
    if (result < 0)
2092
0
      return gnutls_assert_val(result);
2093
2094
0
    snprintf(name, sizeof(name), "%s.sid", root);
2095
0
    result = asn1_write_value(c2, name, "issuerAndSerialNumber", 1);
2096
0
    if (result != ASN1_SUCCESS) {
2097
0
      gnutls_assert();
2098
0
      return _gnutls_asn2err(result);
2099
0
    }
2100
2101
0
    snprintf(name, sizeof(name),
2102
0
       "%s.sid.issuerAndSerialNumber.serialNumber", root);
2103
0
    result = asn1_write_value(c2, name, serial, serial_size);
2104
0
    if (result != ASN1_SUCCESS) {
2105
0
      gnutls_assert();
2106
0
      return _gnutls_asn2err(result);
2107
0
    }
2108
2109
0
    snprintf(name, sizeof(name),
2110
0
       "%s.sid.issuerAndSerialNumber.issuer", root);
2111
0
    result = asn1_copy_node(c2, name, signer->cert,
2112
0
          "tbsCertificate.issuer");
2113
0
    if (result != ASN1_SUCCESS) {
2114
0
      gnutls_assert();
2115
0
      return _gnutls_asn2err(result);
2116
0
    }
2117
0
  }
2118
2119
0
  return 0;
2120
0
}
2121
2122
static int add_attrs(asn1_node c2, const char *root, gnutls_pkcs7_attrs_t attrs,
2123
         unsigned already_set)
2124
0
{
2125
0
  char name[256];
2126
0
  gnutls_pkcs7_attrs_st *p = attrs;
2127
0
  int result;
2128
2129
0
  if (attrs == NULL) {
2130
    /* if there are no other attributes delete that field */
2131
0
    if (already_set == 0)
2132
0
      (void)asn1_write_value(c2, root, NULL, 0);
2133
0
  } else {
2134
0
    while (p != NULL) {
2135
0
      result = asn1_write_value(c2, root, "NEW", 1);
2136
0
      if (result != ASN1_SUCCESS) {
2137
0
        gnutls_assert();
2138
0
        return _gnutls_asn2err(result);
2139
0
      }
2140
2141
0
      snprintf(name, sizeof(name), "%s.?LAST.type", root);
2142
0
      result = asn1_write_value(c2, name, p->oid, 1);
2143
0
      if (result != ASN1_SUCCESS) {
2144
0
        gnutls_assert();
2145
0
        return _gnutls_asn2err(result);
2146
0
      }
2147
2148
0
      snprintf(name, sizeof(name), "%s.?LAST.values", root);
2149
0
      result = asn1_write_value(c2, name, "NEW", 1);
2150
0
      if (result != ASN1_SUCCESS) {
2151
0
        gnutls_assert();
2152
0
        return _gnutls_asn2err(result);
2153
0
      }
2154
2155
0
      snprintf(name, sizeof(name), "%s.?LAST.values.?1",
2156
0
         root);
2157
0
      result = asn1_write_value(c2, name, p->data.data,
2158
0
              p->data.size);
2159
0
      if (result != ASN1_SUCCESS) {
2160
0
        gnutls_assert();
2161
0
        return _gnutls_asn2err(result);
2162
0
      }
2163
2164
0
      p = p->next;
2165
0
    }
2166
0
  }
2167
2168
0
  return 0;
2169
0
}
2170
2171
static int write_attributes(asn1_node c2, const char *root,
2172
          const gnutls_datum_t *data, const mac_entry_st *me,
2173
          gnutls_pkcs7_attrs_t other_attrs, unsigned flags)
2174
0
{
2175
0
  char name[256];
2176
0
  int result, ret;
2177
0
  uint8_t digest[MAX_HASH_SIZE];
2178
0
  gnutls_datum_t tmp = { NULL, 0 };
2179
0
  unsigned digest_size;
2180
0
  unsigned already_set = 0;
2181
2182
0
  if (flags & GNUTLS_PKCS7_INCLUDE_TIME) {
2183
0
    if (data == NULL || data->data == NULL) {
2184
0
      gnutls_assert();
2185
0
      return GNUTLS_E_INVALID_REQUEST;
2186
0
    }
2187
2188
    /* Add time */
2189
0
    result = asn1_write_value(c2, root, "NEW", 1);
2190
0
    if (result != ASN1_SUCCESS) {
2191
0
      gnutls_assert();
2192
0
      ret = _gnutls_asn2err(result);
2193
0
      return ret;
2194
0
    }
2195
2196
0
    snprintf(name, sizeof(name), "%s.?LAST.type", root);
2197
0
    result = asn1_write_value(c2, name, ATTR_SIGNING_TIME, 1);
2198
0
    if (result != ASN1_SUCCESS) {
2199
0
      gnutls_assert();
2200
0
      ret = _gnutls_asn2err(result);
2201
0
      return ret;
2202
0
    }
2203
2204
0
    snprintf(name, sizeof(name), "%s.?LAST.values", root);
2205
0
    result = asn1_write_value(c2, name, "NEW", 1);
2206
0
    if (result != ASN1_SUCCESS) {
2207
0
      gnutls_assert();
2208
0
      ret = _gnutls_asn2err(result);
2209
0
      return ret;
2210
0
    }
2211
2212
0
    snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2213
0
    ret = _gnutls_x509_set_raw_time(c2, name, gnutls_time(0));
2214
0
    if (ret < 0) {
2215
0
      gnutls_assert();
2216
0
      return ret;
2217
0
    }
2218
2219
0
    already_set = 1;
2220
0
  }
2221
2222
0
  ret = add_attrs(c2, root, other_attrs, already_set);
2223
0
  if (ret < 0) {
2224
0
    gnutls_assert();
2225
0
    return ret;
2226
0
  }
2227
2228
0
  if (already_set != 0 || other_attrs != NULL) {
2229
    /* Add content type */
2230
0
    result = asn1_write_value(c2, root, "NEW", 1);
2231
0
    if (result != ASN1_SUCCESS) {
2232
0
      gnutls_assert();
2233
0
      ret = _gnutls_asn2err(result);
2234
0
      return ret;
2235
0
    }
2236
2237
0
    snprintf(name, sizeof(name), "%s.?LAST.type", root);
2238
0
    result = asn1_write_value(c2, name, ATTR_CONTENT_TYPE, 1);
2239
0
    if (result != ASN1_SUCCESS) {
2240
0
      gnutls_assert();
2241
0
      ret = _gnutls_asn2err(result);
2242
0
      return ret;
2243
0
    }
2244
2245
0
    snprintf(name, sizeof(name), "%s.?LAST.values", root);
2246
0
    result = asn1_write_value(c2, name, "NEW", 1);
2247
0
    if (result != ASN1_SUCCESS) {
2248
0
      gnutls_assert();
2249
0
      ret = _gnutls_asn2err(result);
2250
0
      return ret;
2251
0
    }
2252
2253
0
    ret = _gnutls_x509_get_raw_field(
2254
0
      c2, "encapContentInfo.eContentType", &tmp);
2255
0
    if (ret < 0) {
2256
0
      gnutls_assert();
2257
0
      return ret;
2258
0
    }
2259
2260
0
    snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
2261
0
    result = asn1_write_value(c2, name, tmp.data, tmp.size);
2262
0
    gnutls_free(tmp.data);
2263
2264
0
    if (result != ASN1_SUCCESS) {
2265
0
      gnutls_assert();
2266
0
      ret = _gnutls_asn2err(result);
2267
0
      return ret;
2268
0
    }
2269
2270
    /* If we add any attribute we should add them all */
2271
    /* Add hash */
2272
0
    digest_size = _gnutls_hash_get_algo_len(me);
2273
0
    ret = gnutls_hash_fast(MAC_TO_DIG(me->id), data->data,
2274
0
               data->size, digest);
2275
0
    if (ret < 0) {
2276
0
      gnutls_assert();
2277
0
      return ret;
2278
0
    }
2279
2280
0
    result = asn1_write_value(c2, root, "NEW", 1);
2281
0
    if (result != ASN1_SUCCESS) {
2282
0
      gnutls_assert();
2283
0
      ret = _gnutls_asn2err(result);
2284
0
      return ret;
2285
0
    }
2286
2287
0
    snprintf(name, sizeof(name), "%s.?LAST", root);
2288
0
    ret = _gnutls_x509_encode_and_write_attribute(
2289
0
      ATTR_MESSAGE_DIGEST, c2, name, digest, digest_size, 1);
2290
0
    if (ret < 0) {
2291
0
      gnutls_assert();
2292
0
      return ret;
2293
0
    }
2294
0
  }
2295
2296
0
  return 0;
2297
0
}
2298
2299
/**
2300
 * gnutls_pkcs7_sign:
2301
 * @pkcs7: should contain a #gnutls_pkcs7_t type
2302
 * @signer: the certificate to sign the structure
2303
 * @signer_key: the key to sign the structure
2304
 * @data: The data to be signed or %NULL if the data are already embedded
2305
 * @signed_attrs: Any additional attributes to be included in the signed ones (or %NULL)
2306
 * @unsigned_attrs: Any additional attributes to be included in the unsigned ones (or %NULL)
2307
 * @dig: The digest algorithm to use for signing
2308
 * @flags: Should be zero or one of %GNUTLS_PKCS7 flags
2309
 *
2310
 * This function will add a signature in the provided PKCS #7 structure
2311
 * for the provided data. Multiple signatures can be made with different
2312
 * signers.
2313
 *
2314
 * The available flags are:
2315
 *  %GNUTLS_PKCS7_EMBED_DATA, %GNUTLS_PKCS7_INCLUDE_TIME, %GNUTLS_PKCS7_INCLUDE_CERT,
2316
 *  and %GNUTLS_PKCS7_WRITE_SPKI. They are explained in the #gnutls_pkcs7_sign_flags
2317
 *  definition.
2318
 *
2319
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2320
 *   negative error value.
2321
 *
2322
 * Since: 3.4.2
2323
 **/
2324
int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t signer,
2325
          gnutls_privkey_t signer_key, const gnutls_datum_t *data,
2326
          gnutls_pkcs7_attrs_t signed_attrs,
2327
          gnutls_pkcs7_attrs_t unsigned_attrs,
2328
          gnutls_digest_algorithm_t dig, unsigned flags)
2329
0
{
2330
0
  int ret, result;
2331
0
  gnutls_datum_t sigdata = { NULL, 0 };
2332
0
  gnutls_datum_t signature = { NULL, 0 };
2333
0
  const mac_entry_st *me = hash_to_entry(dig);
2334
0
  unsigned pk, sigalgo;
2335
0
  gnutls_x509_spki_st key_params, params;
2336
0
  const gnutls_sign_entry_st *se;
2337
2338
0
  if (pkcs7 == NULL || me == NULL)
2339
0
    return GNUTLS_E_INVALID_REQUEST;
2340
2341
0
  if (pkcs7->signed_data == NULL) {
2342
0
    result = asn1_create_element(_gnutls_get_pkix(),
2343
0
               "PKIX1.pkcs-7-SignedData",
2344
0
               &pkcs7->signed_data);
2345
0
    if (result != ASN1_SUCCESS) {
2346
0
      gnutls_assert();
2347
0
      ret = _gnutls_asn2err(result);
2348
0
      goto cleanup;
2349
0
    }
2350
2351
0
    if (!(flags & GNUTLS_PKCS7_EMBED_DATA)) {
2352
0
      (void)asn1_write_value(pkcs7->signed_data,
2353
0
                 "encapContentInfo.eContent",
2354
0
                 NULL, 0);
2355
0
    }
2356
0
  }
2357
2358
0
  result = asn1_write_value(pkcs7->signed_data, "version", &one, 1);
2359
0
  if (result != ASN1_SUCCESS) {
2360
0
    ret = _gnutls_asn2err(result);
2361
0
    goto cleanup;
2362
0
  }
2363
2364
0
  result = asn1_write_value(pkcs7->signed_data,
2365
0
          "encapContentInfo.eContentType", DATA_OID, 0);
2366
0
  if (result != ASN1_SUCCESS) {
2367
0
    ret = _gnutls_asn2err(result);
2368
0
    goto cleanup;
2369
0
  }
2370
2371
0
  if ((flags & GNUTLS_PKCS7_EMBED_DATA) && data->data) { /* embed data */
2372
0
    ret = _gnutls_x509_write_string(pkcs7->signed_data,
2373
0
            "encapContentInfo.eContent",
2374
0
            data, ASN1_ETYPE_OCTET_STRING);
2375
0
    if (ret < 0) {
2376
0
      goto cleanup;
2377
0
    }
2378
0
  }
2379
2380
0
  if (flags & GNUTLS_PKCS7_INCLUDE_CERT) {
2381
0
    ret = gnutls_pkcs7_set_crt(pkcs7, signer);
2382
0
    if (ret < 0) {
2383
0
      gnutls_assert();
2384
0
      goto cleanup;
2385
0
    }
2386
0
  }
2387
2388
  /* append digest info algorithm */
2389
0
  result = asn1_write_value(pkcs7->signed_data, "digestAlgorithms", "NEW",
2390
0
          1);
2391
0
  if (result != ASN1_SUCCESS) {
2392
0
    gnutls_assert();
2393
0
    ret = _gnutls_asn2err(result);
2394
0
    goto cleanup;
2395
0
  }
2396
2397
0
  result = asn1_write_value(pkcs7->signed_data,
2398
0
          "digestAlgorithms.?LAST.algorithm",
2399
0
          _gnutls_x509_digest_to_oid(me), 1);
2400
0
  if (result != ASN1_SUCCESS) {
2401
0
    gnutls_assert();
2402
0
    ret = _gnutls_asn2err(result);
2403
0
    goto cleanup;
2404
0
  }
2405
2406
0
  (void)asn1_write_value(pkcs7->signed_data,
2407
0
             "digestAlgorithms.?LAST.parameters", NULL, 0);
2408
2409
  /* append signer's info */
2410
0
  result = asn1_write_value(pkcs7->signed_data, "signerInfos", "NEW", 1);
2411
0
  if (result != ASN1_SUCCESS) {
2412
0
    gnutls_assert();
2413
0
    ret = _gnutls_asn2err(result);
2414
0
    goto cleanup;
2415
0
  }
2416
2417
0
  result = asn1_write_value(pkcs7->signed_data,
2418
0
          "signerInfos.?LAST.version", &one, 1);
2419
0
  if (result != ASN1_SUCCESS) {
2420
0
    gnutls_assert();
2421
0
    ret = _gnutls_asn2err(result);
2422
0
    goto cleanup;
2423
0
  }
2424
2425
0
  result = asn1_write_value(pkcs7->signed_data,
2426
0
          "signerInfos.?LAST.digestAlgorithm.algorithm",
2427
0
          _gnutls_x509_digest_to_oid(me), 1);
2428
0
  if (result != ASN1_SUCCESS) {
2429
0
    gnutls_assert();
2430
0
    ret = _gnutls_asn2err(result);
2431
0
    goto cleanup;
2432
0
  }
2433
2434
0
  (void)asn1_write_value(pkcs7->signed_data,
2435
0
             "signerInfos.?LAST.digestAlgorithm.parameters",
2436
0
             NULL, 0);
2437
2438
0
  ret = write_signer_id(pkcs7->signed_data, "signerInfos.?LAST", signer,
2439
0
            flags);
2440
0
  if (ret < 0) {
2441
0
    gnutls_assert();
2442
0
    goto cleanup;
2443
0
  }
2444
2445
0
  ret = add_attrs(pkcs7->signed_data, "signerInfos.?LAST.unsignedAttrs",
2446
0
      unsigned_attrs, 0);
2447
0
  if (ret < 0) {
2448
0
    gnutls_assert();
2449
0
    goto cleanup;
2450
0
  }
2451
2452
0
  ret = write_attributes(pkcs7->signed_data,
2453
0
             "signerInfos.?LAST.signedAttrs", data, me,
2454
0
             signed_attrs, flags);
2455
0
  if (ret < 0) {
2456
0
    gnutls_assert();
2457
0
    goto cleanup;
2458
0
  }
2459
2460
0
  disable_opt_fields(pkcs7);
2461
2462
  /* write the signature algorithm */
2463
0
  pk = gnutls_x509_crt_get_pk_algorithm(signer, NULL);
2464
2465
0
  ret = _gnutls_privkey_get_spki_params(signer_key, &key_params);
2466
0
  if (ret < 0) {
2467
0
    gnutls_assert();
2468
0
    goto cleanup;
2469
0
  }
2470
2471
0
  ret = _gnutls_x509_crt_get_spki_params(signer, &key_params, &params);
2472
0
  if (ret < 0) {
2473
0
    gnutls_assert();
2474
0
    goto cleanup;
2475
0
  }
2476
2477
0
  ret = _gnutls_privkey_update_spki_params(signer_key, pk, dig, 0,
2478
0
             &params);
2479
0
  if (ret < 0) {
2480
0
    gnutls_assert();
2481
0
    goto cleanup;
2482
0
  }
2483
2484
0
  se = _gnutls_pk_to_sign_entry(params.pk, dig);
2485
0
  if (se == NULL) {
2486
0
    ret = gnutls_assert_val(
2487
0
      GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
2488
0
    goto cleanup;
2489
0
  }
2490
2491
  /* RFC5652 is silent on what the values would be and initially I assumed that
2492
   * typical signature algorithms should be set. However RFC2315 (PKCS#7) mentions
2493
   * that a generic RSA OID should be used. We switch to this "unexpected" value
2494
   * because some implementations cannot cope with the "expected" signature values.
2495
   */
2496
0
  params.legacy = 1;
2497
0
  ret = _gnutls_x509_write_sign_params(
2498
0
    pkcs7->signed_data, "signerInfos.?LAST.signatureAlgorithm", se,
2499
0
    &params);
2500
0
  if (ret < 0) {
2501
0
    gnutls_assert();
2502
0
    goto cleanup;
2503
0
  }
2504
2505
0
  sigalgo = se->id;
2506
2507
  /* sign the data */
2508
0
  ret = figure_pkcs7_sigdata(pkcs7, "signerInfos.?LAST", data, sigalgo,
2509
0
           &sigdata);
2510
0
  if (ret < 0) {
2511
0
    gnutls_assert();
2512
0
    goto cleanup;
2513
0
  }
2514
2515
0
  FIX_SIGN_PARAMS(params, flags, dig);
2516
2517
0
  ret = privkey_sign_and_hash_data(signer_key, se, &sigdata, &signature,
2518
0
           &params);
2519
0
  if (ret < 0) {
2520
0
    gnutls_assert();
2521
0
    goto cleanup;
2522
0
  }
2523
2524
0
  result = asn1_write_value(pkcs7->signed_data,
2525
0
          "signerInfos.?LAST.signature", signature.data,
2526
0
          signature.size);
2527
0
  if (result != ASN1_SUCCESS) {
2528
0
    gnutls_assert();
2529
0
    ret = _gnutls_asn2err(result);
2530
0
    goto cleanup;
2531
0
  }
2532
2533
0
  ret = 0;
2534
2535
0
cleanup:
2536
0
  gnutls_free(sigdata.data);
2537
0
  gnutls_free(signature.data);
2538
0
  return ret;
2539
0
}