Coverage Report

Created: 2024-06-20 06:28

/src/gnutls/lib/x509/pkcs12.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2012 Nikos Mavrogiannopoulos
4
 * Copyright (C) 2017 Red Hat, Inc.
5
 *
6
 * Author: Nikos Mavrogiannopoulos
7
 *
8
 * This file is part of GnuTLS.
9
 *
10
 * The GnuTLS is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public License
12
 * as published by the Free Software Foundation; either version 2.1 of
13
 * the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
22
 *
23
 */
24
25
/* Functions that relate on PKCS12 packet parsing.
26
 */
27
28
#include "gnutls_int.h"
29
#include <libtasn1.h>
30
31
#include "datum.h"
32
#include "global.h"
33
#include "errors.h"
34
#include "num.h"
35
#include "common.h"
36
#include "x509_b64.h"
37
#include "x509_int.h"
38
#include "pkcs7_int.h"
39
#include "random.h"
40
#include "intprops.h"
41
42
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
43
 * which holds them. Returns an asn1_node of authenticatedSafe.
44
 */
45
static int _decode_pkcs12_auth_safe(asn1_node pkcs12, asn1_node *authen_safe,
46
            gnutls_datum_t *raw)
47
0
{
48
0
  char oid[MAX_OID_SIZE];
49
0
  asn1_node c2 = NULL;
50
0
  gnutls_datum_t auth_safe = { NULL, 0 };
51
0
  int len, result;
52
0
  char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
53
54
0
  len = sizeof(oid) - 1;
55
0
  result = asn1_read_value(pkcs12, "authSafe.contentType", oid, &len);
56
0
  if (result != ASN1_SUCCESS) {
57
0
    gnutls_assert();
58
0
    return _gnutls_asn2err(result);
59
0
  }
60
61
0
  if (strcmp(oid, DATA_OID) != 0) {
62
0
    gnutls_assert();
63
0
    _gnutls_debug_log("Unknown PKCS12 Content OID '%s'\n", oid);
64
0
    return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
65
0
  }
66
67
  /* Step 1. Read the content data
68
   */
69
70
0
  result = _gnutls_x509_read_string(pkcs12, "authSafe.content",
71
0
            &auth_safe, ASN1_ETYPE_OCTET_STRING,
72
0
            1);
73
0
  if (result < 0) {
74
0
    gnutls_assert();
75
0
    goto cleanup;
76
0
  }
77
78
  /* Step 2. Extract the authenticatedSafe.
79
   */
80
81
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
82
0
            "PKIX1.pkcs-12-AuthenticatedSafe",
83
0
            &c2)) != ASN1_SUCCESS) {
84
0
    gnutls_assert();
85
0
    result = _gnutls_asn2err(result);
86
0
    goto cleanup;
87
0
  }
88
89
0
  result = asn1_der_decoding(&c2, auth_safe.data, auth_safe.size,
90
0
           error_str);
91
0
  if (result != ASN1_SUCCESS) {
92
0
    gnutls_assert();
93
0
    _gnutls_debug_log("DER error: %s\n", error_str);
94
0
    result = _gnutls_asn2err(result);
95
0
    goto cleanup;
96
0
  }
97
98
0
  if (raw == NULL) {
99
0
    _gnutls_free_datum(&auth_safe);
100
0
  } else {
101
0
    raw->data = auth_safe.data;
102
0
    raw->size = auth_safe.size;
103
0
  }
104
105
0
  if (authen_safe)
106
0
    *authen_safe = c2;
107
0
  else
108
0
    asn1_delete_structure(&c2);
109
110
0
  return 0;
111
112
0
cleanup:
113
0
  if (c2)
114
0
    asn1_delete_structure(&c2);
115
0
  _gnutls_free_datum(&auth_safe);
116
0
  return result;
117
0
}
118
119
static int pkcs12_reinit(gnutls_pkcs12_t pkcs12)
120
0
{
121
0
  int result;
122
123
0
  if (pkcs12->pkcs12)
124
0
    asn1_delete_structure(&pkcs12->pkcs12);
125
126
0
  result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-12-PFX",
127
0
             &pkcs12->pkcs12);
128
0
  if (result != ASN1_SUCCESS) {
129
0
    gnutls_assert();
130
0
    return _gnutls_asn2err(result);
131
0
  }
132
133
0
  return 0;
134
0
}
135
136
/**
137
 * gnutls_pkcs12_init:
138
 * @pkcs12: A pointer to the type to be initialized
139
 *
140
 * This function will initialize a PKCS12 type. PKCS12 structures
141
 * usually contain lists of X.509 Certificates and X.509 Certificate
142
 * revocation lists.
143
 *
144
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
145
 *   negative error value.
146
 **/
147
int gnutls_pkcs12_init(gnutls_pkcs12_t *pkcs12)
148
0
{
149
0
  *pkcs12 = gnutls_calloc(1, sizeof(gnutls_pkcs12_int));
150
151
0
  if (*pkcs12) {
152
0
    int result = pkcs12_reinit(*pkcs12);
153
0
    if (result < 0) {
154
0
      gnutls_assert();
155
0
      gnutls_free(*pkcs12);
156
0
      return result;
157
0
    }
158
0
    return 0; /* success */
159
0
  }
160
0
  return GNUTLS_E_MEMORY_ERROR;
161
0
}
162
163
/**
164
 * gnutls_pkcs12_deinit:
165
 * @pkcs12: The type to be initialized
166
 *
167
 * This function will deinitialize a PKCS12 type.
168
 **/
169
void gnutls_pkcs12_deinit(gnutls_pkcs12_t pkcs12)
170
0
{
171
0
  if (!pkcs12)
172
0
    return;
173
174
0
  if (pkcs12->pkcs12)
175
0
    asn1_delete_structure(&pkcs12->pkcs12);
176
177
0
  gnutls_free(pkcs12);
178
0
}
179
180
/**
181
 * gnutls_pkcs12_import:
182
 * @pkcs12: The data to store the parsed PKCS12.
183
 * @data: The DER or PEM encoded PKCS12.
184
 * @format: One of DER or PEM
185
 * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
186
 *
187
 * This function will convert the given DER or PEM encoded PKCS12
188
 * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
189
 *
190
 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
191
 *
192
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
193
 *   negative error value.
194
 **/
195
int gnutls_pkcs12_import(gnutls_pkcs12_t pkcs12, const gnutls_datum_t *data,
196
       gnutls_x509_crt_fmt_t format, unsigned int flags)
197
0
{
198
0
  int result = 0, need_free = 0;
199
0
  gnutls_datum_t _data;
200
0
  char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
201
202
0
  _data.data = data->data;
203
0
  _data.size = data->size;
204
205
0
  if (pkcs12 == NULL) {
206
0
    gnutls_assert();
207
0
    return GNUTLS_E_INVALID_REQUEST;
208
0
  }
209
210
  /* If the PKCS12 is in PEM format then decode it
211
   */
212
0
  if (format == GNUTLS_X509_FMT_PEM) {
213
0
    result = _gnutls_fbase64_decode(PEM_PKCS12, data->data,
214
0
            data->size, &_data);
215
216
0
    if (result < 0) {
217
0
      gnutls_assert();
218
0
      return result;
219
0
    }
220
221
0
    need_free = 1;
222
0
  }
223
224
0
  if (pkcs12->expanded) {
225
0
    result = pkcs12_reinit(pkcs12);
226
0
    if (result < 0) {
227
0
      gnutls_assert();
228
0
      goto cleanup;
229
0
    }
230
0
  }
231
0
  pkcs12->expanded = 1;
232
233
0
  result = asn1_der_decoding(&pkcs12->pkcs12, _data.data, _data.size,
234
0
           error_str);
235
0
  if (result != ASN1_SUCCESS) {
236
0
    result = _gnutls_asn2err(result);
237
0
    _gnutls_debug_log("DER error: %s\n", error_str);
238
0
    gnutls_assert();
239
0
    goto cleanup;
240
0
  }
241
242
0
  if (need_free)
243
0
    _gnutls_free_datum(&_data);
244
245
0
  return 0;
246
247
0
cleanup:
248
0
  if (need_free)
249
0
    _gnutls_free_datum(&_data);
250
0
  return result;
251
0
}
252
253
/**
254
 * gnutls_pkcs12_export:
255
 * @pkcs12: A pkcs12 type
256
 * @format: the format of output params. One of PEM or DER.
257
 * @output_data: will contain a structure PEM or DER encoded
258
 * @output_data_size: holds the size of output_data (and will be
259
 *   replaced by the actual size of parameters)
260
 *
261
 * This function will export the pkcs12 structure to DER or PEM format.
262
 *
263
 * If the buffer provided is not long enough to hold the output, then
264
 * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
265
 * will be returned.
266
 *
267
 * If the structure is PEM encoded, it will have a header
268
 * of "BEGIN PKCS12".
269
 *
270
 * Returns: In case of failure a negative error code will be
271
 *   returned, and 0 on success.
272
 **/
273
int gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12, gnutls_x509_crt_fmt_t format,
274
       void *output_data, size_t *output_data_size)
275
0
{
276
0
  int ret;
277
278
0
  if (pkcs12 == NULL) {
279
0
    gnutls_assert();
280
0
    return GNUTLS_E_INVALID_REQUEST;
281
0
  }
282
283
0
  ret = _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
284
0
              output_data, output_data_size);
285
286
0
  if (ret < 0) {
287
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
288
0
  } else {
289
    /* PKCS#12 export is always non-approved, because the MAC
290
     * calculation involves non-approved KDF (PKCS#12 KDF) and
291
     * without MAC the protection is insufficient.
292
     */
293
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
294
0
  }
295
0
  return ret;
296
0
}
297
298
/**
299
 * gnutls_pkcs12_export2:
300
 * @pkcs12: A pkcs12 type
301
 * @format: the format of output params. One of PEM or DER.
302
 * @out: will contain a structure PEM or DER encoded
303
 *
304
 * This function will export the pkcs12 structure to DER or PEM format.
305
 *
306
 * The output buffer is allocated using gnutls_malloc().
307
 *
308
 * If the structure is PEM encoded, it will have a header
309
 * of "BEGIN PKCS12".
310
 *
311
 * Returns: In case of failure a negative error code will be
312
 *   returned, and 0 on success.
313
 *
314
 * Since: 3.1.3
315
 **/
316
int gnutls_pkcs12_export2(gnutls_pkcs12_t pkcs12, gnutls_x509_crt_fmt_t format,
317
        gnutls_datum_t *out)
318
0
{
319
0
  int ret;
320
321
0
  if (pkcs12 == NULL) {
322
0
    gnutls_assert();
323
0
    return GNUTLS_E_INVALID_REQUEST;
324
0
  }
325
326
0
  ret = _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12, out);
327
0
  if (ret < 0) {
328
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
329
0
  } else {
330
    /* PKCS#12 export is always non-approved, because the MAC
331
     * calculation involves non-approved KDF (PKCS#12 KDF) and
332
     * without MAC the protection is insufficient.
333
     */
334
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
335
0
  }
336
0
  return ret;
337
0
}
338
339
static int oid2bag(const char *oid)
340
0
{
341
0
  if (strcmp(oid, BAG_PKCS8_KEY) == 0)
342
0
    return GNUTLS_BAG_PKCS8_KEY;
343
0
  if (strcmp(oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
344
0
    return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
345
0
  if (strcmp(oid, BAG_CERTIFICATE) == 0)
346
0
    return GNUTLS_BAG_CERTIFICATE;
347
0
  if (strcmp(oid, BAG_CRL) == 0)
348
0
    return GNUTLS_BAG_CRL;
349
0
  if (strcmp(oid, BAG_SECRET) == 0)
350
0
    return GNUTLS_BAG_SECRET;
351
352
0
  return GNUTLS_BAG_UNKNOWN;
353
0
}
354
355
static const char *bag_to_oid(int bag)
356
0
{
357
0
  switch (bag) {
358
0
  case GNUTLS_BAG_PKCS8_KEY:
359
0
    return BAG_PKCS8_KEY;
360
0
  case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
361
0
    return BAG_PKCS8_ENCRYPTED_KEY;
362
0
  case GNUTLS_BAG_CERTIFICATE:
363
0
    return BAG_CERTIFICATE;
364
0
  case GNUTLS_BAG_CRL:
365
0
    return BAG_CRL;
366
0
  case GNUTLS_BAG_SECRET:
367
0
    return BAG_SECRET;
368
0
  }
369
0
  return NULL;
370
0
}
371
372
/* Decodes the SafeContents, and puts the output in
373
 * the given bag. 
374
 */
375
int _pkcs12_decode_safe_contents(const gnutls_datum_t *content,
376
         gnutls_pkcs12_bag_t bag)
377
0
{
378
0
  char oid[MAX_OID_SIZE], root[MAX_NAME_SIZE];
379
0
  asn1_node c2 = NULL;
380
0
  int len, result;
381
0
  int bag_type;
382
0
  gnutls_datum_t attr_val;
383
0
  gnutls_datum_t t;
384
0
  int count = 0, attributes, j;
385
0
  unsigned i;
386
387
  /* Step 1. Extract the SEQUENCE.
388
   */
389
390
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
391
0
            "PKIX1.pkcs-12-SafeContents", &c2)) !=
392
0
      ASN1_SUCCESS) {
393
0
    gnutls_assert();
394
0
    result = _gnutls_asn2err(result);
395
0
    goto cleanup;
396
0
  }
397
398
0
  result = asn1_der_decoding(&c2, content->data, content->size, NULL);
399
0
  if (result != ASN1_SUCCESS) {
400
0
    gnutls_assert();
401
0
    result = _gnutls_asn2err(result);
402
0
    goto cleanup;
403
0
  }
404
405
  /* Count the number of bags
406
   */
407
0
  result = asn1_number_of_elements(c2, "", &count);
408
0
  if (result != ASN1_SUCCESS) {
409
0
    gnutls_assert();
410
0
    result = _gnutls_asn2err(result);
411
0
    goto cleanup;
412
0
  }
413
414
0
  bag->bag_elements = MIN(MAX_BAG_ELEMENTS, count);
415
416
0
  for (i = 0; i < bag->bag_elements; i++) {
417
0
    snprintf(root, sizeof(root), "?%u.bagId", i + 1);
418
419
0
    len = sizeof(oid);
420
0
    result = asn1_read_value(c2, root, oid, &len);
421
0
    if (result != ASN1_SUCCESS) {
422
0
      gnutls_assert();
423
0
      result = _gnutls_asn2err(result);
424
0
      goto cleanup;
425
0
    }
426
427
    /* Read the Bag type
428
     */
429
0
    bag_type = oid2bag(oid);
430
431
0
    if (bag_type < 0) {
432
0
      gnutls_assert();
433
0
      goto cleanup;
434
0
    }
435
436
    /* Read the Bag Value
437
     */
438
439
0
    snprintf(root, sizeof(root), "?%u.bagValue", i + 1);
440
441
0
    result = _gnutls_x509_read_value(c2, root,
442
0
             &bag->element[i].data);
443
0
    if (result < 0) {
444
0
      gnutls_assert();
445
0
      goto cleanup;
446
0
    }
447
448
0
    if (bag_type == GNUTLS_BAG_CERTIFICATE ||
449
0
        bag_type == GNUTLS_BAG_CRL ||
450
0
        bag_type == GNUTLS_BAG_SECRET) {
451
0
      gnutls_datum_t tmp = bag->element[i].data;
452
0
      bag->element[i].data.data = NULL;
453
0
      bag->element[i].data.size = 0;
454
455
0
      result = _pkcs12_decode_crt_bag(bag_type, &tmp,
456
0
              &bag->element[i].data);
457
0
      _gnutls_free_datum(&tmp);
458
0
      if (result < 0) {
459
0
        gnutls_assert();
460
0
        goto cleanup;
461
0
      }
462
0
    }
463
464
    /* read the bag attributes
465
     */
466
0
    snprintf(root, sizeof(root), "?%u.bagAttributes", i + 1);
467
468
0
    result = asn1_number_of_elements(c2, root, &attributes);
469
0
    if (result != ASN1_SUCCESS &&
470
0
        result != ASN1_ELEMENT_NOT_FOUND) {
471
0
      gnutls_assert();
472
0
      result = _gnutls_asn2err(result);
473
0
      goto cleanup;
474
0
    }
475
476
0
    if (attributes < 0)
477
0
      attributes = 1;
478
479
0
    if (result != ASN1_ELEMENT_NOT_FOUND)
480
0
      for (j = 0; j < attributes; j++) {
481
0
        snprintf(root, sizeof(root),
482
0
           "?%u.bagAttributes.?%d", i + 1, j + 1);
483
484
0
        result = _gnutls_x509_decode_and_read_attribute(
485
0
          c2, root, oid, sizeof(oid), &attr_val,
486
0
          1, 0);
487
488
0
        if (result < 0) {
489
0
          gnutls_assert();
490
0
          continue; /* continue in case we find some known attributes */
491
0
        }
492
493
0
        if (strcmp(oid, KEY_ID_OID) == 0) {
494
0
          result = _gnutls_x509_decode_string(
495
0
            ASN1_ETYPE_OCTET_STRING,
496
0
            attr_val.data, attr_val.size,
497
0
            &t, 1);
498
499
0
          _gnutls_free_datum(&attr_val);
500
0
          if (result < 0) {
501
0
            gnutls_assert();
502
0
            _gnutls_debug_log(
503
0
              "Error decoding PKCS12 Bag Attribute OID '%s'\n",
504
0
              oid);
505
0
            continue;
506
0
          }
507
508
0
          _gnutls_free_datum(
509
0
            &bag->element[i].local_key_id);
510
0
          bag->element[i].local_key_id.data =
511
0
            t.data;
512
0
          bag->element[i].local_key_id.size =
513
0
            t.size;
514
0
        } else if (strcmp(oid, FRIENDLY_NAME_OID) ==
515
0
               0 &&
516
0
             bag->element[i].friendly_name ==
517
0
               NULL) {
518
0
          result = _gnutls_x509_decode_string(
519
0
            ASN1_ETYPE_BMP_STRING,
520
0
            attr_val.data, attr_val.size,
521
0
            &t, 1);
522
523
0
          _gnutls_free_datum(&attr_val);
524
0
          if (result < 0) {
525
0
            gnutls_assert();
526
0
            _gnutls_debug_log(
527
0
              "Error decoding PKCS12 Bag Attribute OID '%s'\n",
528
0
              oid);
529
0
            continue;
530
0
          }
531
532
0
          gnutls_free(
533
0
            bag->element[i].friendly_name);
534
0
          bag->element[i].friendly_name =
535
0
            (char *)t.data;
536
0
        } else {
537
0
          _gnutls_free_datum(&attr_val);
538
0
          _gnutls_debug_log(
539
0
            "Unknown PKCS12 Bag Attribute OID '%s'\n",
540
0
            oid);
541
0
        }
542
0
      }
543
544
0
    bag->element[i].type = bag_type;
545
0
  }
546
547
0
  result = 0;
548
549
0
cleanup:
550
0
  if (c2)
551
0
    asn1_delete_structure(&c2);
552
0
  return result;
553
0
}
554
555
static int _parse_safe_contents(asn1_node sc, const char *sc_name,
556
        gnutls_pkcs12_bag_t bag)
557
0
{
558
0
  gnutls_datum_t content = { NULL, 0 };
559
0
  int result;
560
561
  /* Step 1. Extract the content.
562
   */
563
564
0
  result = _gnutls_x509_read_string(sc, sc_name, &content,
565
0
            ASN1_ETYPE_OCTET_STRING, 1);
566
0
  if (result < 0) {
567
0
    gnutls_assert();
568
0
    goto cleanup;
569
0
  }
570
571
0
  result = _pkcs12_decode_safe_contents(&content, bag);
572
0
  if (result < 0) {
573
0
    gnutls_assert();
574
0
    goto cleanup;
575
0
  }
576
577
0
  _gnutls_free_datum(&content);
578
579
0
  return 0;
580
581
0
cleanup:
582
0
  _gnutls_free_datum(&content);
583
0
  return result;
584
0
}
585
586
/**
587
 * gnutls_pkcs12_get_bag:
588
 * @pkcs12: A pkcs12 type
589
 * @indx: contains the index of the bag to extract
590
 * @bag: An initialized bag, where the contents of the bag will be copied
591
 *
592
 * This function will return a Bag from the PKCS12 structure.
593
 *
594
 * After the last Bag has been read
595
 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
596
 *
597
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
598
 *   negative error value.
599
 **/
600
int gnutls_pkcs12_get_bag(gnutls_pkcs12_t pkcs12, int indx,
601
        gnutls_pkcs12_bag_t bag)
602
0
{
603
0
  asn1_node c2 = NULL;
604
0
  int result, len;
605
0
  char root2[MAX_NAME_SIZE];
606
0
  char oid[MAX_OID_SIZE];
607
608
0
  if (pkcs12 == NULL) {
609
0
    gnutls_assert();
610
0
    return GNUTLS_E_INVALID_REQUEST;
611
0
  }
612
613
  /* Step 1. decode the data.
614
   */
615
0
  result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL);
616
0
  if (result < 0) {
617
0
    gnutls_assert();
618
0
    return result;
619
0
  }
620
621
  /* Step 2. Parse the AuthenticatedSafe
622
   */
623
624
0
  snprintf(root2, sizeof(root2), "?%d.contentType", indx + 1);
625
626
0
  len = sizeof(oid) - 1;
627
0
  result = asn1_read_value(c2, root2, oid, &len);
628
629
0
  if (result == ASN1_ELEMENT_NOT_FOUND) {
630
0
    result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
631
0
    goto cleanup;
632
0
  }
633
634
0
  if (result != ASN1_SUCCESS) {
635
0
    gnutls_assert();
636
0
    result = _gnutls_asn2err(result);
637
0
    goto cleanup;
638
0
  }
639
640
  /* Not encrypted Bag
641
   */
642
643
0
  snprintf(root2, sizeof(root2), "?%d.content", indx + 1);
644
645
0
  if (strcmp(oid, DATA_OID) == 0) {
646
0
    result = _parse_safe_contents(c2, root2, bag);
647
0
    goto cleanup;
648
0
  }
649
650
  /* ENC_DATA_OID needs decryption */
651
652
0
  result = _gnutls_x509_read_value(c2, root2, &bag->element[0].data);
653
0
  if (result < 0) {
654
0
    gnutls_assert();
655
0
    goto cleanup;
656
0
  }
657
658
0
  bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
659
0
  bag->bag_elements = 1;
660
661
0
  result = 0;
662
663
0
cleanup:
664
0
  if (c2)
665
0
    asn1_delete_structure(&c2);
666
0
  return result;
667
0
}
668
669
/* Creates an empty PFX structure for the PKCS12 structure.
670
 */
671
static int create_empty_pfx(asn1_node pkcs12)
672
0
{
673
0
  uint8_t three = 3;
674
0
  int result;
675
0
  asn1_node c2 = NULL;
676
677
  /* Use version 3
678
   */
679
0
  result = asn1_write_value(pkcs12, "version", &three, 1);
680
0
  if (result != ASN1_SUCCESS) {
681
0
    gnutls_assert();
682
0
    result = _gnutls_asn2err(result);
683
0
    goto cleanup;
684
0
  }
685
686
  /* Write the content type of the data
687
   */
688
0
  result = asn1_write_value(pkcs12, "authSafe.contentType", DATA_OID, 1);
689
0
  if (result != ASN1_SUCCESS) {
690
0
    gnutls_assert();
691
0
    result = _gnutls_asn2err(result);
692
0
    goto cleanup;
693
0
  }
694
695
  /* Check if the authenticatedSafe content is empty, and encode a
696
   * null one in that case.
697
   */
698
699
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
700
0
            "PKIX1.pkcs-12-AuthenticatedSafe",
701
0
            &c2)) != ASN1_SUCCESS) {
702
0
    gnutls_assert();
703
0
    result = _gnutls_asn2err(result);
704
0
    goto cleanup;
705
0
  }
706
707
0
  result = _gnutls_x509_der_encode_and_copy(c2, "", pkcs12,
708
0
              "authSafe.content", 1);
709
0
  if (result < 0) {
710
0
    gnutls_assert();
711
0
    goto cleanup;
712
0
  }
713
0
  asn1_delete_structure(&c2);
714
715
0
  return 0;
716
717
0
cleanup:
718
0
  asn1_delete_structure(&c2);
719
0
  return result;
720
0
}
721
722
/**
723
 * gnutls_pkcs12_set_bag:
724
 * @pkcs12: should contain a gnutls_pkcs12_t type
725
 * @bag: An initialized bag
726
 *
727
 * This function will insert a Bag into the PKCS12 structure.
728
 *
729
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
730
 *   negative error value.
731
 **/
732
int gnutls_pkcs12_set_bag(gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
733
0
{
734
0
  asn1_node c2 = NULL;
735
0
  asn1_node safe_cont = NULL;
736
0
  int result;
737
0
  int enc = 0, dum = 1;
738
0
  char null;
739
740
0
  if (pkcs12 == NULL) {
741
0
    gnutls_assert();
742
0
    return GNUTLS_E_INVALID_REQUEST;
743
0
  }
744
745
  /* Step 1. Check if the pkcs12 structure is empty. In that
746
   * case generate an empty PFX.
747
   */
748
0
  result = asn1_read_value(pkcs12->pkcs12, "authSafe.content", &null,
749
0
         &dum);
750
0
  if (result == ASN1_VALUE_NOT_FOUND) {
751
0
    result = create_empty_pfx(pkcs12->pkcs12);
752
0
    if (result < 0) {
753
0
      gnutls_assert();
754
0
      return result;
755
0
    }
756
0
  }
757
758
  /* Step 2. decode the authenticatedSafe.
759
   */
760
0
  result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL);
761
0
  if (result < 0) {
762
0
    gnutls_assert();
763
0
    return result;
764
0
  }
765
766
  /* Step 3. Encode the bag elements into a SafeContents 
767
   * structure.
768
   */
769
0
  result = _pkcs12_encode_safe_contents(bag, &safe_cont, &enc);
770
0
  if (result < 0) {
771
0
    gnutls_assert();
772
0
    return result;
773
0
  }
774
775
  /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
776
   * structure.
777
   */
778
0
  result = asn1_write_value(c2, "", "NEW", 1);
779
0
  if (result != ASN1_SUCCESS) {
780
0
    gnutls_assert();
781
0
    result = _gnutls_asn2err(result);
782
0
    goto cleanup;
783
0
  }
784
785
0
  if (enc)
786
0
    result = asn1_write_value(c2, "?LAST.contentType", ENC_DATA_OID,
787
0
            1);
788
0
  else
789
0
    result = asn1_write_value(c2, "?LAST.contentType", DATA_OID, 1);
790
0
  if (result != ASN1_SUCCESS) {
791
0
    gnutls_assert();
792
0
    result = _gnutls_asn2err(result);
793
0
    goto cleanup;
794
0
  }
795
796
0
  if (enc) {
797
    /* Encrypted packets are written directly.
798
     */
799
0
    result = asn1_write_value(c2, "?LAST.content",
800
0
            bag->element[0].data.data,
801
0
            bag->element[0].data.size);
802
0
    if (result != ASN1_SUCCESS) {
803
0
      gnutls_assert();
804
0
      result = _gnutls_asn2err(result);
805
0
      goto cleanup;
806
0
    }
807
0
  } else {
808
0
    result = _gnutls_x509_der_encode_and_copy(safe_cont, "", c2,
809
0
                "?LAST.content", 1);
810
0
    if (result < 0) {
811
0
      gnutls_assert();
812
0
      goto cleanup;
813
0
    }
814
0
  }
815
816
0
  asn1_delete_structure(&safe_cont);
817
818
  /* Step 5. Re-encode and copy the AuthenticatedSafe into the pkcs12
819
   * structure.
820
   */
821
0
  result = _gnutls_x509_der_encode_and_copy(c2, "", pkcs12->pkcs12,
822
0
              "authSafe.content", 1);
823
0
  if (result < 0) {
824
0
    gnutls_assert();
825
0
    goto cleanup;
826
0
  }
827
828
0
  asn1_delete_structure(&c2);
829
830
0
  return 0;
831
832
0
cleanup:
833
0
  asn1_delete_structure(&c2);
834
0
  asn1_delete_structure(&safe_cont);
835
0
  return result;
836
0
}
837
838
#if ENABLE_GOST
839
/*
840
 * Russian differs from PKCS#12 here. It described proprietary way
841
 * to obtain MAC key instead of using standard mechanism.
842
 *
843
 * See https://wwwold.tc26.ru/standard/rs/%D0%A0%2050.1.112-2016.pdf
844
 * section 5.
845
 */
846
static int
847
_gnutls_pkcs12_gost_string_to_key(gnutls_mac_algorithm_t algo,
848
          const uint8_t *salt, unsigned int salt_size,
849
          unsigned int iter, const char *pass,
850
          unsigned int req_keylen, uint8_t *keybuf)
851
0
{
852
0
  uint8_t temp[96];
853
0
  size_t temp_len = sizeof(temp);
854
0
  gnutls_datum_t key;
855
0
  gnutls_datum_t _salt;
856
0
  int ret;
857
858
0
  if (iter == 0)
859
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
860
861
0
  key.data = (void *)pass;
862
0
  key.size = pass ? strlen(pass) : 0;
863
864
0
  _salt.data = (void *)salt;
865
0
  _salt.size = salt_size;
866
867
0
  ret = gnutls_pbkdf2(algo, &key, &_salt, iter, temp, temp_len);
868
0
  if (ret < 0)
869
0
    return gnutls_assert_val(ret);
870
871
0
  memcpy(keybuf, temp + temp_len - req_keylen, req_keylen);
872
873
0
  return 0;
874
0
}
875
#endif
876
877
/**
878
 * gnutls_pkcs12_generate_mac2:
879
 * @pkcs12: A pkcs12 type
880
 * @mac: the MAC algorithm to use
881
 * @pass: The password for the MAC
882
 *
883
 * This function will generate a MAC for the PKCS12 structure.
884
 *
885
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
886
 *   negative error value.
887
 **/
888
int gnutls_pkcs12_generate_mac2(gnutls_pkcs12_t pkcs12,
889
        gnutls_mac_algorithm_t mac, const char *pass)
890
0
{
891
0
  uint8_t salt[8], key[MAX_HASH_SIZE];
892
0
  int result;
893
0
  const int iter = PKCS12_ITER_COUNT;
894
0
  mac_hd_st td1;
895
0
  gnutls_datum_t tmp = { NULL, 0 };
896
0
  unsigned mac_size, key_len;
897
0
  uint8_t mac_out[MAX_HASH_SIZE];
898
0
  const mac_entry_st *me = mac_to_entry(mac);
899
900
0
  if (pkcs12 == NULL || me == NULL)
901
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
902
903
0
  if (me->oid == NULL)
904
0
    return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
905
906
0
  mac_size = _gnutls_mac_get_algo_len(me);
907
0
  key_len = mac_size;
908
909
  /* Generate the salt.
910
   */
911
0
  result = gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt));
912
0
  if (result < 0) {
913
0
    gnutls_assert();
914
0
    return result;
915
0
  }
916
917
  /* Write the salt into the structure.
918
   */
919
0
  result = asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt,
920
0
          sizeof(salt));
921
0
  if (result != ASN1_SUCCESS) {
922
0
    gnutls_assert();
923
0
    result = _gnutls_asn2err(result);
924
0
    goto cleanup;
925
0
  }
926
927
  /* write the iterations
928
   */
929
930
0
  if (iter > 1) {
931
0
    result = _gnutls_x509_write_uint32(pkcs12->pkcs12,
932
0
               "macData.iterations", iter);
933
0
    if (result < 0) {
934
0
      gnutls_assert();
935
0
      goto cleanup;
936
0
    }
937
0
  }
938
939
  /* Generate the key.
940
   */
941
0
#if ENABLE_GOST
942
0
  if (me->id == GNUTLS_MAC_GOSTR_94 ||
943
0
      me->id == GNUTLS_MAC_STREEBOG_256 ||
944
0
      me->id == GNUTLS_MAC_STREEBOG_512) {
945
0
    key_len = 32;
946
0
    result = _gnutls_pkcs12_gost_string_to_key(
947
0
      me->id, salt, sizeof(salt), iter, pass, key_len, key);
948
0
  } else
949
0
#endif
950
0
    result = _gnutls_pkcs12_string_to_key(me, 3 /*MAC*/, salt,
951
0
                  sizeof(salt), iter, pass,
952
0
                  mac_size, key);
953
0
  if (result < 0) {
954
0
    gnutls_assert();
955
0
    goto cleanup;
956
0
  }
957
958
  /* Get the data to be MACed
959
   */
960
0
  result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
961
0
  if (result < 0) {
962
0
    gnutls_assert();
963
0
    goto cleanup;
964
0
  }
965
966
  /* MAC the data
967
   */
968
0
  result = _gnutls_mac_init(&td1, me, key, key_len);
969
0
  if (result < 0) {
970
0
    gnutls_assert();
971
0
    goto cleanup;
972
0
  }
973
974
0
  _gnutls_mac(&td1, tmp.data, tmp.size);
975
0
  _gnutls_free_datum(&tmp);
976
977
0
  _gnutls_mac_deinit(&td1, mac_out);
978
979
0
  result = asn1_write_value(pkcs12->pkcs12, "macData.mac.digest", mac_out,
980
0
          mac_size);
981
0
  if (result != ASN1_SUCCESS) {
982
0
    gnutls_assert();
983
0
    result = _gnutls_asn2err(result);
984
0
    goto cleanup;
985
0
  }
986
987
0
  result = asn1_write_value(pkcs12->pkcs12,
988
0
          "macData.mac.digestAlgorithm.parameters",
989
0
          NULL, 0);
990
0
  if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
991
0
    gnutls_assert();
992
0
    result = _gnutls_asn2err(result);
993
0
    goto cleanup;
994
0
  }
995
996
0
  result = asn1_write_value(pkcs12->pkcs12,
997
0
          "macData.mac.digestAlgorithm.algorithm",
998
0
          me->oid, 1);
999
0
  if (result != ASN1_SUCCESS) {
1000
0
    gnutls_assert();
1001
0
    result = _gnutls_asn2err(result);
1002
0
    goto cleanup;
1003
0
  }
1004
1005
  /* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
1006
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
1007
0
  return 0;
1008
1009
0
cleanup:
1010
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1011
0
  _gnutls_free_datum(&tmp);
1012
0
  return result;
1013
0
}
1014
1015
/**
1016
 * gnutls_pkcs12_generate_mac:
1017
 * @pkcs12: A pkcs12 type
1018
 * @pass: The password for the MAC
1019
 *
1020
 * This function will generate a MAC for the PKCS12 structure.
1021
 *
1022
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1023
 *   negative error value.
1024
 **/
1025
int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
1026
0
{
1027
0
  return gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA256, pass);
1028
0
}
1029
1030
/**
1031
 * gnutls_pkcs12_verify_mac:
1032
 * @pkcs12: should contain a gnutls_pkcs12_t type
1033
 * @pass: The password for the MAC
1034
 *
1035
 * This function will verify the MAC for the PKCS12 structure.
1036
 *
1037
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1038
 *   negative error value.
1039
 **/
1040
int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
1041
0
{
1042
0
  uint8_t key[MAX_HASH_SIZE];
1043
0
  char oid[MAX_OID_SIZE];
1044
0
  int result;
1045
0
  unsigned int iter;
1046
0
  int len;
1047
0
  mac_hd_st td1;
1048
0
  gnutls_datum_t tmp = { NULL, 0 }, salt = { NULL, 0 };
1049
0
  uint8_t mac_output[MAX_HASH_SIZE];
1050
0
  uint8_t mac_output_orig[MAX_HASH_SIZE];
1051
0
  gnutls_mac_algorithm_t algo;
1052
0
  unsigned mac_len, key_len;
1053
0
  const mac_entry_st *entry;
1054
0
#if ENABLE_GOST
1055
0
  int gost_retry = 0;
1056
0
#endif
1057
1058
0
  if (pkcs12 == NULL) {
1059
0
    gnutls_assert();
1060
0
    return GNUTLS_E_INVALID_REQUEST;
1061
0
  }
1062
1063
  /* read the iterations
1064
   */
1065
0
  result = _gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
1066
0
          &iter);
1067
0
  if (result < 0) {
1068
0
    iter = 1; /* the default */
1069
0
  }
1070
1071
0
  len = sizeof(oid);
1072
0
  result = asn1_read_value(pkcs12->pkcs12,
1073
0
         "macData.mac.digestAlgorithm.algorithm", oid,
1074
0
         &len);
1075
0
  if (result != ASN1_SUCCESS) {
1076
0
    gnutls_assert();
1077
0
    return _gnutls_asn2err(result);
1078
0
  }
1079
1080
0
  algo = DIG_TO_MAC(gnutls_oid_to_digest(oid));
1081
0
  if (algo == GNUTLS_MAC_UNKNOWN) {
1082
0
  unknown_mac:
1083
0
    gnutls_assert();
1084
0
    return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
1085
0
  }
1086
1087
0
  entry = mac_to_entry(algo);
1088
0
  if (entry == NULL)
1089
0
    goto unknown_mac;
1090
1091
0
  mac_len = _gnutls_mac_get_algo_len(entry);
1092
0
  key_len = mac_len;
1093
1094
  /* Read the salt from the structure.
1095
   */
1096
0
  result = _gnutls_x509_read_null_value(pkcs12->pkcs12, "macData.macSalt",
1097
0
                &salt);
1098
0
  if (result < 0) {
1099
0
    gnutls_assert();
1100
0
    goto cleanup;
1101
0
  }
1102
1103
  /* Generate the key.
1104
   */
1105
0
  result = _gnutls_pkcs12_string_to_key(entry, 3 /*MAC*/, salt.data,
1106
0
                salt.size, iter, pass, key_len,
1107
0
                key);
1108
0
  if (result < 0) {
1109
0
    gnutls_assert();
1110
0
    goto cleanup;
1111
0
  }
1112
1113
  /* Get the data to be MACed
1114
   */
1115
0
  result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
1116
0
  if (result < 0) {
1117
0
    gnutls_assert();
1118
0
    goto cleanup;
1119
0
  }
1120
0
#if ENABLE_GOST
1121
  /* GOST PKCS#12 files use either PKCS#12 scheme or proprietary
1122
   * HMAC-based scheme to generate MAC key. */
1123
0
pkcs12_try_gost:
1124
0
#endif
1125
1126
  /* MAC the data
1127
   */
1128
0
  result = _gnutls_mac_init(&td1, entry, key, key_len);
1129
0
  if (result < 0) {
1130
0
    gnutls_assert();
1131
0
    goto cleanup;
1132
0
  }
1133
1134
0
  _gnutls_mac(&td1, tmp.data, tmp.size);
1135
1136
0
  _gnutls_mac_deinit(&td1, mac_output);
1137
1138
0
  len = sizeof(mac_output_orig);
1139
0
  result = asn1_read_value(pkcs12->pkcs12, "macData.mac.digest",
1140
0
         mac_output_orig, &len);
1141
0
  if (result != ASN1_SUCCESS) {
1142
0
    gnutls_assert();
1143
0
    result = _gnutls_asn2err(result);
1144
0
    goto cleanup;
1145
0
  }
1146
1147
0
  if ((unsigned)len != mac_len ||
1148
0
      memcmp(mac_output_orig, mac_output, len) != 0) {
1149
0
#if ENABLE_GOST
1150
    /* It is possible that GOST files use proprietary
1151
     * key generation scheme */
1152
0
    if (!gost_retry && (algo == GNUTLS_MAC_GOSTR_94 ||
1153
0
            algo == GNUTLS_MAC_STREEBOG_256 ||
1154
0
            algo == GNUTLS_MAC_STREEBOG_512)) {
1155
0
      gost_retry = 1;
1156
0
      key_len = 32;
1157
0
      result = _gnutls_pkcs12_gost_string_to_key(
1158
0
        algo, salt.data, salt.size, iter, pass, key_len,
1159
0
        key);
1160
0
      if (result < 0) {
1161
0
        gnutls_assert();
1162
0
        goto cleanup;
1163
0
      }
1164
1165
0
      goto pkcs12_try_gost;
1166
0
    }
1167
0
#endif
1168
1169
0
    gnutls_assert();
1170
0
    result = GNUTLS_E_MAC_VERIFY_FAILED;
1171
0
    goto cleanup;
1172
0
  }
1173
1174
  /* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
1175
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
1176
0
  result = 0;
1177
0
cleanup:
1178
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1179
0
  _gnutls_free_datum(&tmp);
1180
0
  _gnutls_free_datum(&salt);
1181
0
  return result;
1182
0
}
1183
1184
static int write_attributes(gnutls_pkcs12_bag_t bag, int elem, asn1_node c2,
1185
          const char *where)
1186
0
{
1187
0
  int result;
1188
0
  char root[128];
1189
1190
  /* If the bag attributes are empty, then write
1191
   * nothing to the attribute field.
1192
   */
1193
0
  if (bag->element[elem].friendly_name == NULL &&
1194
0
      bag->element[elem].local_key_id.data == NULL) {
1195
    /* no attributes
1196
     */
1197
0
    result = asn1_write_value(c2, where, NULL, 0);
1198
0
    if (result != ASN1_SUCCESS) {
1199
0
      gnutls_assert();
1200
0
      return _gnutls_asn2err(result);
1201
0
    }
1202
1203
0
    return 0;
1204
0
  }
1205
1206
0
  if (bag->element[elem].local_key_id.data != NULL) {
1207
    /* Add a new Attribute
1208
     */
1209
0
    result = asn1_write_value(c2, where, "NEW", 1);
1210
0
    if (result != ASN1_SUCCESS) {
1211
0
      gnutls_assert();
1212
0
      return _gnutls_asn2err(result);
1213
0
    }
1214
1215
0
    _gnutls_str_cpy(root, sizeof(root), where);
1216
0
    _gnutls_str_cat(root, sizeof(root), ".?LAST");
1217
1218
0
    result = _gnutls_x509_encode_and_write_attribute(
1219
0
      KEY_ID_OID, c2, root,
1220
0
      bag->element[elem].local_key_id.data,
1221
0
      bag->element[elem].local_key_id.size, 1);
1222
0
    if (result < 0) {
1223
0
      gnutls_assert();
1224
0
      return result;
1225
0
    }
1226
0
  }
1227
1228
0
  if (bag->element[elem].friendly_name != NULL) {
1229
0
    uint8_t *name;
1230
0
    int size, i;
1231
0
    const char *p;
1232
1233
    /* Add a new Attribute
1234
     */
1235
0
    result = asn1_write_value(c2, where, "NEW", 1);
1236
0
    if (result != ASN1_SUCCESS) {
1237
0
      gnutls_assert();
1238
0
      return _gnutls_asn2err(result);
1239
0
    }
1240
1241
    /* convert name to BMPString
1242
     */
1243
0
    size = strlen(bag->element[elem].friendly_name) * 2;
1244
0
    name = gnutls_malloc(size);
1245
1246
0
    if (name == NULL) {
1247
0
      gnutls_assert();
1248
0
      return GNUTLS_E_MEMORY_ERROR;
1249
0
    }
1250
1251
0
    p = bag->element[elem].friendly_name;
1252
0
    for (i = 0; i < size; i += 2) {
1253
0
      name[i] = 0;
1254
0
      name[i + 1] = *p;
1255
0
      p++;
1256
0
    }
1257
1258
0
    _gnutls_str_cpy(root, sizeof(root), where);
1259
0
    _gnutls_str_cat(root, sizeof(root), ".?LAST");
1260
1261
0
    result = _gnutls_x509_encode_and_write_attribute(
1262
0
      FRIENDLY_NAME_OID, c2, root, name, size, 1);
1263
1264
0
    gnutls_free(name);
1265
1266
0
    if (result < 0) {
1267
0
      gnutls_assert();
1268
0
      return result;
1269
0
    }
1270
0
  }
1271
1272
0
  return 0;
1273
0
}
1274
1275
/* Encodes the bag into a SafeContents structure, and puts the output in
1276
 * the given datum. Enc is set to non-zero if the data are encrypted;
1277
 */
1278
int _pkcs12_encode_safe_contents(gnutls_pkcs12_bag_t bag, asn1_node *contents,
1279
         int *enc)
1280
0
{
1281
0
  asn1_node c2 = NULL;
1282
0
  int result;
1283
0
  unsigned i;
1284
0
  const char *oid;
1285
1286
0
  if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) {
1287
0
    *enc = 1;
1288
0
    return 0; /* ENCRYPTED BAG, do nothing. */
1289
0
  } else if (enc)
1290
0
    *enc = 0;
1291
1292
  /* Step 1. Create the SEQUENCE.
1293
   */
1294
1295
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
1296
0
            "PKIX1.pkcs-12-SafeContents", &c2)) !=
1297
0
      ASN1_SUCCESS) {
1298
0
    gnutls_assert();
1299
0
    result = _gnutls_asn2err(result);
1300
0
    goto cleanup;
1301
0
  }
1302
1303
0
  for (i = 0; i < bag->bag_elements; i++) {
1304
0
    oid = bag_to_oid(bag->element[i].type);
1305
0
    if (oid == NULL) {
1306
0
      gnutls_assert();
1307
0
      continue;
1308
0
    }
1309
1310
0
    result = asn1_write_value(c2, "", "NEW", 1);
1311
0
    if (result != ASN1_SUCCESS) {
1312
0
      gnutls_assert();
1313
0
      result = _gnutls_asn2err(result);
1314
0
      goto cleanup;
1315
0
    }
1316
1317
    /* Copy the bag type.
1318
     */
1319
0
    result = asn1_write_value(c2, "?LAST.bagId", oid, 1);
1320
0
    if (result != ASN1_SUCCESS) {
1321
0
      gnutls_assert();
1322
0
      result = _gnutls_asn2err(result);
1323
0
      goto cleanup;
1324
0
    }
1325
1326
    /* Set empty attributes
1327
     */
1328
0
    result = write_attributes(bag, i, c2, "?LAST.bagAttributes");
1329
0
    if (result < 0) {
1330
0
      gnutls_assert();
1331
0
      goto cleanup;
1332
0
    }
1333
1334
    /* Copy the Bag Value
1335
     */
1336
1337
0
    if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1338
0
        bag->element[i].type == GNUTLS_BAG_SECRET ||
1339
0
        bag->element[i].type == GNUTLS_BAG_CRL) {
1340
0
      gnutls_datum_t tmp;
1341
1342
      /* in that case encode it to a CertBag or
1343
       * a CrlBag.
1344
       */
1345
1346
0
      result = _pkcs12_encode_crt_bag(bag->element[i].type,
1347
0
              &bag->element[i].data,
1348
0
              &tmp);
1349
1350
0
      if (result < 0) {
1351
0
        gnutls_assert();
1352
0
        goto cleanup;
1353
0
      }
1354
1355
0
      result = _gnutls_x509_write_value(c2, "?LAST.bagValue",
1356
0
                &tmp);
1357
1358
0
      _gnutls_free_datum(&tmp);
1359
1360
0
    } else {
1361
0
      result = _gnutls_x509_write_value(
1362
0
        c2, "?LAST.bagValue", &bag->element[i].data);
1363
0
    }
1364
1365
0
    if (result < 0) {
1366
0
      gnutls_assert();
1367
0
      goto cleanup;
1368
0
    }
1369
0
  }
1370
1371
  /* Encode the data and copy them into the datum
1372
   */
1373
0
  *contents = c2;
1374
1375
0
  return 0;
1376
1377
0
cleanup:
1378
0
  if (c2)
1379
0
    asn1_delete_structure(&c2);
1380
0
  return result;
1381
0
}
1382
1383
/* Checks if the extra_certs contain certificates that may form a chain
1384
 * with the first certificate in chain (it is expected that chain_len==1)
1385
 * and appends those in the chain.
1386
 */
1387
static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
1388
          gnutls_x509_crt_t **extra_certs,
1389
          unsigned int *extra_certs_len, unsigned int flags)
1390
0
{
1391
0
  unsigned int i;
1392
1393
0
  if (*chain_len != 1)
1394
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1395
1396
0
  i = 0;
1397
0
  while (i < *extra_certs_len) {
1398
    /* if it is an issuer but not a self-signed one */
1399
0
    if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1],
1400
0
             (*extra_certs)[i]) != 0) {
1401
0
      if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) &&
1402
0
          gnutls_x509_crt_check_issuer(
1403
0
            (*extra_certs)[i], (*extra_certs)[i]) != 0)
1404
0
        goto skip;
1405
1406
0
      if (unlikely(INT_ADD_OVERFLOW(*chain_len, 1))) {
1407
0
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1408
0
      }
1409
1410
0
      *chain = _gnutls_reallocarray_fast(
1411
0
        *chain, ++(*chain_len), sizeof((*chain)[0]));
1412
0
      if (*chain == NULL) {
1413
0
        gnutls_assert();
1414
0
        return GNUTLS_E_MEMORY_ERROR;
1415
0
      }
1416
0
      (*chain)[*chain_len - 1] = (*extra_certs)[i];
1417
1418
0
      (*extra_certs)[i] =
1419
0
        (*extra_certs)[*extra_certs_len - 1];
1420
0
      (*extra_certs_len)--;
1421
1422
0
      i = 0;
1423
0
      continue;
1424
0
    }
1425
1426
0
  skip:
1427
0
    i++;
1428
0
  }
1429
0
  return 0;
1430
0
}
1431
1432
/**
1433
 * gnutls_pkcs12_simple_parse:
1434
 * @p12: A pkcs12 type
1435
 * @password: optional password used to decrypt the structure, bags and keys.
1436
 * @key: a structure to store the parsed private key.
1437
 * @chain: the corresponding to key certificate chain (may be %NULL)
1438
 * @chain_len: will be updated with the number of additional (may be %NULL)
1439
 * @extra_certs: optional pointer to receive an array of additional
1440
 *         certificates found in the PKCS12 structure (may be %NULL).
1441
 * @extra_certs_len: will be updated with the number of additional
1442
 *       certs (may be %NULL).
1443
 * @crl: an optional structure to store the parsed CRL (may be %NULL).
1444
 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
1445
 *
1446
 * This function parses a PKCS12 structure in @pkcs12 and extracts the
1447
 * private key, the corresponding certificate chain, any additional
1448
 * certificates and a CRL. The structures in @key, @chain @crl, and @extra_certs
1449
 * must not be initialized.
1450
 *
1451
 * The @extra_certs and @extra_certs_len parameters are optional
1452
 * and both may be set to %NULL. If either is non-%NULL, then both must
1453
 * be set. The value for @extra_certs is allocated
1454
 * using gnutls_malloc().
1455
 * 
1456
 * Encrypted PKCS12 bags and PKCS8 private keys are supported, but
1457
 * only with password based security and the same password for all
1458
 * operations.
1459
 *
1460
 * Note that a PKCS12 structure may contain many keys and/or certificates,
1461
 * and there is no way to identify which key/certificate pair you want.
1462
 * For this reason this function is useful for PKCS12 files that contain 
1463
 * only one key/certificate pair and/or one CRL.
1464
 *
1465
 * If the provided structure has encrypted fields but no password
1466
 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
1467
 *
1468
 * Note that normally the chain constructed does not include self signed
1469
 * certificates, to comply with TLS' requirements. If, however, the flag 
1470
 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
1471
 * self signed certificates will be included in the chain.
1472
 *
1473
 * Prior to using this function the PKCS #12 structure integrity must
1474
 * be verified using gnutls_pkcs12_verify_mac().
1475
 *
1476
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1477
 *   negative error value.
1478
 *
1479
 * Since: 3.1.0
1480
 **/
1481
int gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, const char *password,
1482
             gnutls_x509_privkey_t *key,
1483
             gnutls_x509_crt_t **chain,
1484
             unsigned int *chain_len,
1485
             gnutls_x509_crt_t **extra_certs,
1486
             unsigned int *extra_certs_len,
1487
             gnutls_x509_crl_t *crl, unsigned int flags)
1488
0
{
1489
0
  gnutls_pkcs12_bag_t bag = NULL;
1490
0
  gnutls_x509_crt_t *_extra_certs = NULL;
1491
0
  unsigned int _extra_certs_len = 0;
1492
0
  gnutls_x509_crt_t *_chain = NULL;
1493
0
  unsigned int _chain_len = 0;
1494
0
  int idx = 0;
1495
0
  int ret;
1496
0
  size_t cert_id_size = 0;
1497
0
  size_t key_id_size = 0;
1498
0
  uint8_t cert_id[20];
1499
0
  uint8_t key_id[20];
1500
0
  int privkey_ok = 0;
1501
0
  unsigned int i;
1502
0
  int elements_in_bag;
1503
1504
0
  *key = NULL;
1505
1506
0
  if (crl)
1507
0
    *crl = NULL;
1508
1509
  /* find the first private key */
1510
0
  for (;;) {
1511
0
    ret = gnutls_pkcs12_bag_init(&bag);
1512
0
    if (ret < 0) {
1513
0
      bag = NULL;
1514
0
      gnutls_assert();
1515
0
      goto done;
1516
0
    }
1517
1518
0
    ret = gnutls_pkcs12_get_bag(p12, idx, bag);
1519
0
    if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1520
0
      gnutls_pkcs12_bag_deinit(bag);
1521
0
      bag = NULL;
1522
0
      break;
1523
0
    }
1524
0
    if (ret < 0) {
1525
0
      gnutls_assert();
1526
0
      goto done;
1527
0
    }
1528
1529
0
    ret = gnutls_pkcs12_bag_get_type(bag, 0);
1530
0
    if (ret < 0) {
1531
0
      gnutls_assert();
1532
0
      goto done;
1533
0
    }
1534
1535
0
    if (ret == GNUTLS_BAG_ENCRYPTED) {
1536
0
      if (password == NULL) {
1537
0
        ret = gnutls_assert_val(
1538
0
          GNUTLS_E_DECRYPTION_FAILED);
1539
0
        goto done;
1540
0
      }
1541
1542
0
      ret = gnutls_pkcs12_bag_decrypt(bag, password);
1543
0
      if (ret < 0) {
1544
0
        gnutls_assert();
1545
0
        goto done;
1546
0
      }
1547
0
    }
1548
1549
0
    elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
1550
0
    if (elements_in_bag < 0) {
1551
0
      gnutls_assert();
1552
0
      goto done;
1553
0
    }
1554
1555
0
    for (i = 0; i < (unsigned)elements_in_bag; i++) {
1556
0
      int type;
1557
0
      gnutls_datum_t data;
1558
1559
0
      type = gnutls_pkcs12_bag_get_type(bag, i);
1560
0
      if (type < 0) {
1561
0
        gnutls_assert();
1562
0
        goto done;
1563
0
      }
1564
1565
0
      ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
1566
0
      if (ret < 0) {
1567
0
        gnutls_assert();
1568
0
        goto done;
1569
0
      }
1570
1571
0
      switch (type) {
1572
0
      case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
1573
0
        if (password == NULL) {
1574
0
          ret = gnutls_assert_val(
1575
0
            GNUTLS_E_DECRYPTION_FAILED);
1576
0
          goto done;
1577
0
        }
1578
1579
0
        FALLTHROUGH;
1580
0
      case GNUTLS_BAG_PKCS8_KEY:
1581
0
        if (*key != NULL) { /* too simple to continue */
1582
0
          gnutls_assert();
1583
0
          break;
1584
0
        }
1585
1586
0
        ret = gnutls_x509_privkey_init(key);
1587
0
        if (ret < 0) {
1588
0
          gnutls_assert();
1589
0
          goto done;
1590
0
        }
1591
1592
0
        ret = gnutls_x509_privkey_import_pkcs8(
1593
0
          *key, &data, GNUTLS_X509_FMT_DER,
1594
0
          password,
1595
0
          type == GNUTLS_BAG_PKCS8_KEY ?
1596
0
            GNUTLS_PKCS_PLAIN :
1597
0
            0);
1598
0
        if (ret < 0) {
1599
0
          gnutls_assert();
1600
0
          goto done;
1601
0
        }
1602
1603
0
        key_id_size = sizeof(key_id);
1604
0
        ret = gnutls_x509_privkey_get_key_id(
1605
0
          *key, 0, key_id, &key_id_size);
1606
0
        if (ret < 0) {
1607
0
          gnutls_assert();
1608
0
          goto done;
1609
0
        }
1610
1611
0
        privkey_ok = 1; /* break */
1612
0
        break;
1613
0
      default:
1614
0
        break;
1615
0
      }
1616
0
    }
1617
1618
0
    idx++;
1619
0
    gnutls_pkcs12_bag_deinit(bag);
1620
0
    bag = NULL;
1621
1622
0
    if (privkey_ok != 0) /* private key was found */
1623
0
      break;
1624
0
  }
1625
1626
0
  if (privkey_ok == 0) { /* no private key */
1627
0
    gnutls_assert();
1628
0
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1629
0
  }
1630
1631
  /* now find the corresponding certificate 
1632
   */
1633
0
  idx = 0;
1634
0
  bag = NULL;
1635
0
  for (;;) {
1636
0
    ret = gnutls_pkcs12_bag_init(&bag);
1637
0
    if (ret < 0) {
1638
0
      bag = NULL;
1639
0
      gnutls_assert();
1640
0
      goto done;
1641
0
    }
1642
1643
0
    ret = gnutls_pkcs12_get_bag(p12, idx, bag);
1644
0
    if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1645
0
      gnutls_pkcs12_bag_deinit(bag);
1646
0
      bag = NULL;
1647
0
      break;
1648
0
    }
1649
0
    if (ret < 0) {
1650
0
      gnutls_assert();
1651
0
      goto done;
1652
0
    }
1653
1654
0
    ret = gnutls_pkcs12_bag_get_type(bag, 0);
1655
0
    if (ret < 0) {
1656
0
      gnutls_assert();
1657
0
      goto done;
1658
0
    }
1659
1660
0
    if (ret == GNUTLS_BAG_ENCRYPTED) {
1661
0
      ret = gnutls_pkcs12_bag_decrypt(bag, password);
1662
0
      if (ret < 0) {
1663
0
        gnutls_assert();
1664
0
        goto done;
1665
0
      }
1666
0
    }
1667
1668
0
    elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
1669
0
    if (elements_in_bag < 0) {
1670
0
      gnutls_assert();
1671
0
      goto done;
1672
0
    }
1673
1674
0
    for (i = 0; i < (unsigned)elements_in_bag; i++) {
1675
0
      int type;
1676
0
      gnutls_datum_t data;
1677
0
      gnutls_x509_crt_t this_cert;
1678
1679
0
      type = gnutls_pkcs12_bag_get_type(bag, i);
1680
0
      if (type < 0) {
1681
0
        gnutls_assert();
1682
0
        goto done;
1683
0
      }
1684
1685
0
      ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
1686
0
      if (ret < 0) {
1687
0
        gnutls_assert();
1688
0
        goto done;
1689
0
      }
1690
1691
0
      switch (type) {
1692
0
      case GNUTLS_BAG_CERTIFICATE:
1693
0
        ret = gnutls_x509_crt_init(&this_cert);
1694
0
        if (ret < 0) {
1695
0
          gnutls_assert();
1696
0
          goto done;
1697
0
        }
1698
1699
0
        ret = gnutls_x509_crt_import(
1700
0
          this_cert, &data, GNUTLS_X509_FMT_DER);
1701
0
        if (ret < 0) {
1702
0
          gnutls_assert();
1703
0
          gnutls_x509_crt_deinit(this_cert);
1704
0
          this_cert = NULL;
1705
0
          goto done;
1706
0
        }
1707
1708
        /* check if the key id match */
1709
0
        cert_id_size = sizeof(cert_id);
1710
0
        ret = gnutls_x509_crt_get_key_id(
1711
0
          this_cert, 0, cert_id, &cert_id_size);
1712
0
        if (ret < 0) {
1713
0
          gnutls_assert();
1714
0
          gnutls_x509_crt_deinit(this_cert);
1715
0
          this_cert = NULL;
1716
0
          goto done;
1717
0
        }
1718
1719
0
        if (memcmp(cert_id, key_id, cert_id_size) !=
1720
0
            0) { /* they don't match - skip the certificate */
1721
0
          if (unlikely(INT_ADD_OVERFLOW(
1722
0
                _extra_certs_len, 1))) {
1723
0
            ret = gnutls_assert_val(
1724
0
              GNUTLS_E_MEMORY_ERROR);
1725
0
            goto done;
1726
0
          }
1727
1728
0
          _extra_certs = _gnutls_reallocarray_fast(
1729
0
            _extra_certs,
1730
0
            ++_extra_certs_len,
1731
0
            sizeof(_extra_certs[0]));
1732
0
          if (!_extra_certs) {
1733
0
            gnutls_assert();
1734
0
            ret = GNUTLS_E_MEMORY_ERROR;
1735
0
            goto done;
1736
0
          }
1737
0
          _extra_certs[_extra_certs_len - 1] =
1738
0
            this_cert;
1739
0
          this_cert = NULL;
1740
0
        } else {
1741
0
          if (chain && _chain_len == 0) {
1742
0
            _chain = gnutls_malloc(
1743
0
              sizeof(_chain[0]) *
1744
0
              (++_chain_len));
1745
0
            if (!_chain) {
1746
0
              gnutls_assert();
1747
0
              ret = GNUTLS_E_MEMORY_ERROR;
1748
0
              goto done;
1749
0
            }
1750
0
            _chain[_chain_len - 1] =
1751
0
              this_cert;
1752
0
            this_cert = NULL;
1753
0
          } else {
1754
0
            gnutls_x509_crt_deinit(
1755
0
              this_cert);
1756
0
            this_cert = NULL;
1757
0
          }
1758
0
        }
1759
0
        break;
1760
1761
0
      case GNUTLS_BAG_CRL:
1762
0
        if (crl == NULL || *crl != NULL) {
1763
0
          gnutls_assert();
1764
0
          break;
1765
0
        }
1766
1767
0
        ret = gnutls_x509_crl_init(crl);
1768
0
        if (ret < 0) {
1769
0
          gnutls_assert();
1770
0
          goto done;
1771
0
        }
1772
1773
0
        ret = gnutls_x509_crl_import(
1774
0
          *crl, &data, GNUTLS_X509_FMT_DER);
1775
0
        if (ret < 0) {
1776
0
          gnutls_assert();
1777
0
          gnutls_x509_crl_deinit(*crl);
1778
0
          *crl = NULL;
1779
0
          goto done;
1780
0
        }
1781
0
        break;
1782
1783
0
      case GNUTLS_BAG_ENCRYPTED:
1784
        /* XXX Bother to recurse one level down?  Unlikely to
1785
           use the same password anyway. */
1786
0
      case GNUTLS_BAG_EMPTY:
1787
0
      default:
1788
0
        break;
1789
0
      }
1790
0
    }
1791
1792
0
    idx++;
1793
0
    gnutls_pkcs12_bag_deinit(bag);
1794
0
    bag = NULL;
1795
0
  }
1796
1797
0
  if (chain != NULL) {
1798
0
    if (_chain_len != 1) {
1799
0
      ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1800
0
      goto done;
1801
0
    }
1802
1803
0
    ret = make_chain(&_chain, &_chain_len, &_extra_certs,
1804
0
         &_extra_certs_len, flags);
1805
0
    if (ret < 0) {
1806
0
      gnutls_assert();
1807
0
      goto done;
1808
0
    }
1809
0
  }
1810
1811
0
  ret = 0;
1812
1813
0
done:
1814
0
  if (bag)
1815
0
    gnutls_pkcs12_bag_deinit(bag);
1816
1817
0
  if (ret < 0) {
1818
0
    if (*key) {
1819
0
      gnutls_x509_privkey_deinit(*key);
1820
0
      *key = NULL;
1821
0
    }
1822
0
    if (crl != NULL && *crl != NULL) {
1823
0
      gnutls_x509_crl_deinit(*crl);
1824
0
      *crl = NULL;
1825
0
    }
1826
0
    if (_extra_certs_len && _extra_certs != NULL) {
1827
0
      for (i = 0; i < _extra_certs_len; i++)
1828
0
        gnutls_x509_crt_deinit(_extra_certs[i]);
1829
0
      gnutls_free(_extra_certs);
1830
0
    }
1831
0
    if (_chain_len && _chain != NULL) {
1832
0
      for (i = 0; i < _chain_len; i++)
1833
0
        gnutls_x509_crt_deinit(_chain[i]);
1834
0
      gnutls_free(_chain);
1835
0
    }
1836
1837
0
    return ret;
1838
0
  }
1839
1840
0
  if (extra_certs && _extra_certs_len > 0) {
1841
0
    *extra_certs = _extra_certs;
1842
0
    *extra_certs_len = _extra_certs_len;
1843
0
  } else {
1844
0
    if (extra_certs) {
1845
0
      *extra_certs = NULL;
1846
0
      *extra_certs_len = 0;
1847
0
    }
1848
0
    for (i = 0; i < _extra_certs_len; i++)
1849
0
      gnutls_x509_crt_deinit(_extra_certs[i]);
1850
0
    gnutls_free(_extra_certs);
1851
0
  }
1852
1853
0
  if (chain != NULL) {
1854
0
    *chain = _chain;
1855
0
    *chain_len = _chain_len;
1856
0
  }
1857
1858
0
  return ret;
1859
0
}
1860
1861
/**
1862
 * gnutls_pkcs12_mac_info:
1863
 * @pkcs12: A pkcs12 type
1864
 * @mac: the MAC algorithm used as %gnutls_mac_algorithm_t
1865
 * @salt: the salt used for string to key (if non-NULL then @salt_size initially holds its size)
1866
 * @salt_size: string to key salt size
1867
 * @iter_count: string to key iteration count
1868
 * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
1869
 *
1870
 * This function will provide information on the MAC algorithm used
1871
 * in a PKCS #12 structure. If the structure algorithms
1872
 * are unknown the code %GNUTLS_E_UNKNOWN_HASH_ALGORITHM will be returned,
1873
 * and only @oid, will be set. That is, @oid will be set on structures
1874
 * with a MAC whether supported or not. It must be deinitialized using gnutls_free().
1875
 * The other variables are only set on supported structures.
1876
 *
1877
 * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure doesn't contain a MAC,
1878
 *  %GNUTLS_E_UNKNOWN_HASH_ALGORITHM if the structure's MAC isn't supported, or
1879
 *  another negative error code in case of a failure. Zero on success.
1880
 **/
1881
int gnutls_pkcs12_mac_info(gnutls_pkcs12_t pkcs12, unsigned int *mac,
1882
         void *salt, unsigned int *salt_size,
1883
         unsigned int *iter_count, char **oid)
1884
0
{
1885
0
  int ret;
1886
0
  gnutls_datum_t tmp = { NULL, 0 }, dsalt = { NULL, 0 };
1887
0
  gnutls_mac_algorithm_t algo;
1888
1889
0
  if (oid)
1890
0
    *oid = NULL;
1891
1892
0
  if (pkcs12 == NULL) {
1893
0
    gnutls_assert();
1894
0
    return GNUTLS_E_INVALID_REQUEST;
1895
0
  }
1896
1897
0
  ret = _gnutls_x509_read_value(
1898
0
    pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm", &tmp);
1899
0
  if (ret < 0) {
1900
0
    gnutls_assert();
1901
0
    return GNUTLS_E_INVALID_REQUEST;
1902
0
  }
1903
1904
0
  if (oid) {
1905
0
    *oid = (char *)tmp.data;
1906
0
  }
1907
1908
0
  algo = DIG_TO_MAC(gnutls_oid_to_digest((char *)tmp.data));
1909
0
  if (algo == GNUTLS_MAC_UNKNOWN || mac_to_entry(algo) == NULL) {
1910
0
    gnutls_assert();
1911
0
    return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
1912
0
  }
1913
1914
0
  if (oid) {
1915
0
    tmp.data = NULL;
1916
0
  }
1917
1918
0
  if (mac) {
1919
0
    *mac = algo;
1920
0
  }
1921
1922
0
  if (iter_count) {
1923
0
    ret = _gnutls_x509_read_uint(pkcs12->pkcs12,
1924
0
               "macData.iterations", iter_count);
1925
0
    if (ret < 0) {
1926
0
      *iter_count = 1; /* the default */
1927
0
    }
1928
0
  }
1929
1930
0
  if (salt) {
1931
    /* Read the salt from the structure.
1932
     */
1933
0
    ret = _gnutls_x509_read_null_value(pkcs12->pkcs12,
1934
0
               "macData.macSalt", &dsalt);
1935
0
    if (ret < 0) {
1936
0
      gnutls_assert();
1937
0
      goto cleanup;
1938
0
    }
1939
1940
0
    if (*salt_size >= (unsigned)dsalt.size) {
1941
0
      *salt_size = dsalt.size;
1942
0
      if (dsalt.size > 0)
1943
0
        memcpy(salt, dsalt.data, dsalt.size);
1944
0
    } else {
1945
0
      *salt_size = dsalt.size;
1946
0
      ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1947
0
      goto cleanup;
1948
0
    }
1949
0
  }
1950
1951
0
  ret = 0;
1952
0
cleanup:
1953
0
  _gnutls_free_datum(&tmp);
1954
0
  _gnutls_free_datum(&dsalt);
1955
0
  return ret;
1956
0
}