Coverage Report

Created: 2023-03-26 07:33

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