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