1 /*
2 * Copyright (C) 2003-2014 Free Software Foundation, Inc.
3 * Copyright (C) 2014 Red Hat
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 /* Functions that relate on PKCS12 Bag packet parsing.
25 */
26
27 #include "gnutls_int.h"
28
29 #include <datum.h>
30 #include <global.h>
31 #include "errors.h"
32 #include <common.h>
33 #include "x509_int.h"
34 #include "pkcs7_int.h"
35
36 /**
37 * gnutls_pkcs12_bag_init:
38 * @bag: A pointer to the type to be initialized
39 *
40 * This function will initialize a PKCS12 bag structure. PKCS12 Bags
41 * usually contain private keys, lists of X.509 Certificates and X.509
42 * Certificate revocation lists.
43 *
44 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
45 * negative error value.
46 **/
gnutls_pkcs12_bag_init(gnutls_pkcs12_bag_t * bag)47 int gnutls_pkcs12_bag_init(gnutls_pkcs12_bag_t * bag)
48 {
49 *bag = gnutls_calloc(1, sizeof(gnutls_pkcs12_bag_int));
50
51 if (*bag) {
52 return 0; /* success */
53 }
54 return GNUTLS_E_MEMORY_ERROR;
55 }
56
_pkcs12_bag_free_data(gnutls_pkcs12_bag_t bag)57 static inline void _pkcs12_bag_free_data(gnutls_pkcs12_bag_t bag)
58 {
59 unsigned i;
60
61 for (i = 0; i < bag->bag_elements; i++) {
62 _gnutls_free_datum(&bag->element[i].data);
63 _gnutls_free_datum(&bag->element[i].local_key_id);
64 gnutls_free(bag->element[i].friendly_name);
65 bag->element[i].type = 0;
66 }
67
68 }
69
70
71 /**
72 * gnutls_pkcs12_bag_deinit:
73 * @bag: A pointer to the type to be initialized
74 *
75 * This function will deinitialize a PKCS12 Bag structure.
76 **/
gnutls_pkcs12_bag_deinit(gnutls_pkcs12_bag_t bag)77 void gnutls_pkcs12_bag_deinit(gnutls_pkcs12_bag_t bag)
78 {
79 if (!bag)
80 return;
81
82 _pkcs12_bag_free_data(bag);
83
84 gnutls_free(bag);
85 }
86
87 /**
88 * gnutls_pkcs12_bag_get_type:
89 * @bag: The bag
90 * @indx: The element of the bag to get the type
91 *
92 * This function will return the bag's type.
93 *
94 * Returns: On error a negative error value or one of the #gnutls_pkcs12_bag_type_t enumerations.
95 **/
96 int
gnutls_pkcs12_bag_get_type(gnutls_pkcs12_bag_t bag,unsigned indx)97 gnutls_pkcs12_bag_get_type(gnutls_pkcs12_bag_t bag, unsigned indx)
98 {
99 if (bag == NULL) {
100 gnutls_assert();
101 return GNUTLS_E_INVALID_REQUEST;
102 }
103
104 if (indx >= bag->bag_elements)
105 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
106 return bag->element[indx].type;
107 }
108
109 /**
110 * gnutls_pkcs12_bag_get_count:
111 * @bag: The bag
112 *
113 * This function will return the number of the elements within the bag.
114 *
115 * Returns: Number of elements in bag, or an negative error code on
116 * error.
117 **/
gnutls_pkcs12_bag_get_count(gnutls_pkcs12_bag_t bag)118 int gnutls_pkcs12_bag_get_count(gnutls_pkcs12_bag_t bag)
119 {
120 if (bag == NULL) {
121 gnutls_assert();
122 return GNUTLS_E_INVALID_REQUEST;
123 }
124
125 return bag->bag_elements;
126 }
127
128 /**
129 * gnutls_pkcs12_bag_get_data:
130 * @bag: The bag
131 * @indx: The element of the bag to get the data from
132 * @data: where the bag's data will be. Should be treated as constant.
133 *
134 * This function will return the bag's data. The data is a constant
135 * that is stored into the bag. Should not be accessed after the bag
136 * is deleted.
137 *
138 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
139 * negative error value.
140 **/
141 int
gnutls_pkcs12_bag_get_data(gnutls_pkcs12_bag_t bag,unsigned indx,gnutls_datum_t * data)142 gnutls_pkcs12_bag_get_data(gnutls_pkcs12_bag_t bag, unsigned indx,
143 gnutls_datum_t * data)
144 {
145 if (bag == NULL) {
146 gnutls_assert();
147 return GNUTLS_E_INVALID_REQUEST;
148 }
149
150 if (indx >= bag->bag_elements)
151 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
152
153 data->data = bag->element[indx].data.data;
154 data->size = bag->element[indx].data.size;
155
156 return 0;
157 }
158
159 #define X509_CERT_OID "1.2.840.113549.1.9.22.1"
160 #define X509_CRL_OID "1.2.840.113549.1.9.23.1"
161 #define RANDOM_NONCE_OID "1.2.840.113549.1.9.25.3"
162
163 int
_pkcs12_decode_crt_bag(gnutls_pkcs12_bag_type_t type,const gnutls_datum_t * in,gnutls_datum_t * out)164 _pkcs12_decode_crt_bag(gnutls_pkcs12_bag_type_t type,
165 const gnutls_datum_t * in, gnutls_datum_t * out)
166 {
167 int ret;
168 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
169
170 switch (type) {
171 case GNUTLS_BAG_CERTIFICATE:
172 if ((ret = asn1_create_element(_gnutls_get_pkix(),
173 "PKIX1.pkcs-12-CertBag",
174 &c2)) != ASN1_SUCCESS) {
175 gnutls_assert();
176 ret = _gnutls_asn2err(ret);
177 goto cleanup;
178 }
179
180 ret = asn1_der_decoding(&c2, in->data, in->size, NULL);
181 if (ret != ASN1_SUCCESS) {
182 gnutls_assert();
183 ret = _gnutls_asn2err(ret);
184 goto cleanup;
185 }
186
187 ret =
188 _gnutls_x509_read_string(c2, "certValue", out,
189 ASN1_ETYPE_OCTET_STRING, 1);
190 if (ret < 0) {
191 gnutls_assert();
192 goto cleanup;
193 }
194 break;
195
196 case GNUTLS_BAG_CRL:
197 if ((ret = asn1_create_element(_gnutls_get_pkix(),
198 "PKIX1.pkcs-12-CRLBag",
199 &c2)) != ASN1_SUCCESS) {
200 gnutls_assert();
201 ret = _gnutls_asn2err(ret);
202 goto cleanup;
203 }
204
205 ret = asn1_der_decoding(&c2, in->data, in->size, NULL);
206 if (ret != ASN1_SUCCESS) {
207 gnutls_assert();
208 ret = _gnutls_asn2err(ret);
209 goto cleanup;
210 }
211
212 ret =
213 _gnutls_x509_read_string(c2, "crlValue", out,
214 ASN1_ETYPE_OCTET_STRING, 1);
215 if (ret < 0) {
216 gnutls_assert();
217 goto cleanup;
218 }
219 break;
220
221 case GNUTLS_BAG_SECRET:
222 if ((ret = asn1_create_element(_gnutls_get_pkix(),
223 "PKIX1.pkcs-12-SecretBag",
224 &c2)) != ASN1_SUCCESS) {
225 gnutls_assert();
226 ret = _gnutls_asn2err(ret);
227 goto cleanup;
228 }
229
230 ret = asn1_der_decoding(&c2, in->data, in->size, NULL);
231 if (ret != ASN1_SUCCESS) {
232 gnutls_assert();
233 ret = _gnutls_asn2err(ret);
234 goto cleanup;
235 }
236
237 ret =
238 _gnutls_x509_read_string(c2, "secretValue", out,
239 ASN1_ETYPE_OCTET_STRING, 1);
240 if (ret < 0) {
241 gnutls_assert();
242 goto cleanup;
243 }
244 break;
245
246 default:
247 gnutls_assert();
248 asn1_delete_structure(&c2);
249 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
250 }
251
252 asn1_delete_structure(&c2);
253
254 return 0;
255
256
257 cleanup:
258
259 asn1_delete_structure(&c2);
260 return ret;
261 }
262
263
264 int
_pkcs12_encode_crt_bag(gnutls_pkcs12_bag_type_t type,const gnutls_datum_t * raw,gnutls_datum_t * out)265 _pkcs12_encode_crt_bag(gnutls_pkcs12_bag_type_t type,
266 const gnutls_datum_t * raw, gnutls_datum_t * out)
267 {
268 int ret;
269 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
270
271 switch (type) {
272 case GNUTLS_BAG_CERTIFICATE:
273 if ((ret = asn1_create_element(_gnutls_get_pkix(),
274 "PKIX1.pkcs-12-CertBag",
275 &c2)) != ASN1_SUCCESS) {
276 gnutls_assert();
277 ret = _gnutls_asn2err(ret);
278 goto cleanup;
279 }
280
281 ret = asn1_write_value(c2, "certId", X509_CERT_OID, 1);
282 if (ret != ASN1_SUCCESS) {
283 gnutls_assert();
284 ret = _gnutls_asn2err(ret);
285 goto cleanup;
286 }
287
288 ret =
289 _gnutls_x509_write_string(c2, "certValue", raw,
290 ASN1_ETYPE_OCTET_STRING);
291 if (ret < 0) {
292 gnutls_assert();
293 goto cleanup;
294 }
295 break;
296
297 case GNUTLS_BAG_CRL:
298 if ((ret = asn1_create_element(_gnutls_get_pkix(),
299 "PKIX1.pkcs-12-CRLBag",
300 &c2)) != ASN1_SUCCESS) {
301 gnutls_assert();
302 ret = _gnutls_asn2err(ret);
303 goto cleanup;
304 }
305
306 ret = asn1_write_value(c2, "crlId", X509_CRL_OID, 1);
307 if (ret != ASN1_SUCCESS) {
308 gnutls_assert();
309 ret = _gnutls_asn2err(ret);
310 goto cleanup;
311 }
312
313 ret =
314 _gnutls_x509_write_string(c2, "crlValue", raw,
315 ASN1_ETYPE_OCTET_STRING);
316 if (ret < 0) {
317 gnutls_assert();
318 goto cleanup;
319 }
320 break;
321
322 case GNUTLS_BAG_SECRET:
323 if ((ret = asn1_create_element(_gnutls_get_pkix(),
324 "PKIX1.pkcs-12-SecretBag",
325 &c2)) != ASN1_SUCCESS) {
326 gnutls_assert();
327 ret = _gnutls_asn2err(ret);
328 goto cleanup;
329 }
330
331 ret =
332 asn1_write_value(c2, "secretTypeId", RANDOM_NONCE_OID,
333 1);
334 if (ret != ASN1_SUCCESS) {
335 gnutls_assert();
336 ret = _gnutls_asn2err(ret);
337 goto cleanup;
338 }
339
340 ret =
341 _gnutls_x509_write_string(c2, "secretValue", raw,
342 ASN1_ETYPE_OCTET_STRING);
343 if (ret < 0) {
344 gnutls_assert();
345 goto cleanup;
346 }
347 break;
348
349 default:
350 gnutls_assert();
351 asn1_delete_structure(&c2);
352 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
353 }
354
355 ret = _gnutls_x509_der_encode(c2, "", out, 0);
356
357 if (ret < 0) {
358 gnutls_assert();
359 goto cleanup;
360 }
361
362 asn1_delete_structure(&c2);
363
364 return 0;
365
366
367 cleanup:
368
369 asn1_delete_structure(&c2);
370 return ret;
371 }
372
373
374 /**
375 * gnutls_pkcs12_bag_set_data:
376 * @bag: The bag
377 * @type: The data's type
378 * @data: the data to be copied.
379 *
380 * This function will insert the given data of the given type into
381 * the bag.
382 *
383 * Returns: the index of the added bag on success, or a negative
384 * value on error.
385 **/
386 int
gnutls_pkcs12_bag_set_data(gnutls_pkcs12_bag_t bag,gnutls_pkcs12_bag_type_t type,const gnutls_datum_t * data)387 gnutls_pkcs12_bag_set_data(gnutls_pkcs12_bag_t bag,
388 gnutls_pkcs12_bag_type_t type,
389 const gnutls_datum_t * data)
390 {
391 int ret;
392 if (bag == NULL) {
393 gnutls_assert();
394 return GNUTLS_E_INVALID_REQUEST;
395 }
396
397 if (bag->bag_elements == MAX_BAG_ELEMENTS - 1) {
398 gnutls_assert();
399 /* bag is full */
400 return GNUTLS_E_MEMORY_ERROR;
401 }
402
403 if (bag->bag_elements == 1) {
404 /* A bag with a key or an encrypted bag, must have
405 * only one element.
406 */
407
408 if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY ||
409 bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY
410 || bag->element[0].type == GNUTLS_BAG_ENCRYPTED) {
411 gnutls_assert();
412 return GNUTLS_E_INVALID_REQUEST;
413 }
414 }
415
416 ret =
417 _gnutls_set_datum(&bag->element[bag->bag_elements].data,
418 data->data, data->size);
419
420 if (ret < 0) {
421 gnutls_assert();
422 return ret;
423 }
424
425 bag->element[bag->bag_elements].type = type;
426
427 bag->bag_elements++;
428
429 return bag->bag_elements - 1;
430 }
431
432 /**
433 * gnutls_pkcs12_bag_set_crt:
434 * @bag: The bag
435 * @crt: the certificate to be copied.
436 *
437 * This function will insert the given certificate into the
438 * bag. This is just a wrapper over gnutls_pkcs12_bag_set_data().
439 *
440 * Returns: the index of the added bag on success, or a negative
441 * value on failure.
442 **/
443 int
gnutls_pkcs12_bag_set_crt(gnutls_pkcs12_bag_t bag,gnutls_x509_crt_t crt)444 gnutls_pkcs12_bag_set_crt(gnutls_pkcs12_bag_t bag, gnutls_x509_crt_t crt)
445 {
446 int ret;
447 gnutls_datum_t data;
448
449 if (bag == NULL) {
450 gnutls_assert();
451 return GNUTLS_E_INVALID_REQUEST;
452 }
453
454 ret = _gnutls_x509_der_encode(crt->cert, "", &data, 0);
455 if (ret < 0) {
456 gnutls_assert();
457 return ret;
458 }
459
460 ret =
461 gnutls_pkcs12_bag_set_data(bag, GNUTLS_BAG_CERTIFICATE, &data);
462
463 _gnutls_free_datum(&data);
464
465 return ret;
466 }
467
468 /**
469 * gnutls_pkcs12_bag_set_crl:
470 * @bag: The bag
471 * @crl: the CRL to be copied.
472 *
473 * This function will insert the given CRL into the
474 * bag. This is just a wrapper over gnutls_pkcs12_bag_set_data().
475 *
476 * Returns: the index of the added bag on success, or a negative error code
477 * on failure.
478 **/
479 int
gnutls_pkcs12_bag_set_crl(gnutls_pkcs12_bag_t bag,gnutls_x509_crl_t crl)480 gnutls_pkcs12_bag_set_crl(gnutls_pkcs12_bag_t bag, gnutls_x509_crl_t crl)
481 {
482 int ret;
483 gnutls_datum_t data;
484
485
486 if (bag == NULL) {
487 gnutls_assert();
488 return GNUTLS_E_INVALID_REQUEST;
489 }
490
491 ret = _gnutls_x509_der_encode(crl->crl, "", &data, 0);
492 if (ret < 0) {
493 gnutls_assert();
494 return ret;
495 }
496
497 ret = gnutls_pkcs12_bag_set_data(bag, GNUTLS_BAG_CRL, &data);
498
499 _gnutls_free_datum(&data);
500
501 return ret;
502 }
503
504 /**
505 * gnutls_pkcs12_bag_set_key_id:
506 * @bag: The bag
507 * @indx: The bag's element to add the id
508 * @id: the ID
509 *
510 * This function will add the given key ID, to the specified, by the
511 * index, bag element. The key ID will be encoded as a 'Local key
512 * identifier' bag attribute, which is usually used to distinguish
513 * the local private key and the certificate pair.
514 *
515 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
516 * negative error value. or a negative error code on error.
517 **/
518 int
gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag_t bag,unsigned indx,const gnutls_datum_t * id)519 gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag_t bag, unsigned indx,
520 const gnutls_datum_t * id)
521 {
522 int ret;
523
524
525 if (bag == NULL) {
526 gnutls_assert();
527 return GNUTLS_E_INVALID_REQUEST;
528 }
529
530 if (indx > bag->bag_elements - 1) {
531 gnutls_assert();
532 return GNUTLS_E_INVALID_REQUEST;
533 }
534
535 ret = _gnutls_set_datum(&bag->element[indx].local_key_id,
536 id->data, id->size);
537
538 if (ret < 0) {
539 gnutls_assert();
540 return ret;
541 }
542
543 return 0;
544 }
545
546 /**
547 * gnutls_pkcs12_bag_get_key_id:
548 * @bag: The bag
549 * @indx: The bag's element to add the id
550 * @id: where the ID will be copied (to be treated as const)
551 *
552 * This function will return the key ID, of the specified bag element.
553 * The key ID is usually used to distinguish the local private key and
554 * the certificate pair.
555 *
556 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
557 * negative error value. or a negative error code on error.
558 **/
559 int
gnutls_pkcs12_bag_get_key_id(gnutls_pkcs12_bag_t bag,unsigned indx,gnutls_datum_t * id)560 gnutls_pkcs12_bag_get_key_id(gnutls_pkcs12_bag_t bag, unsigned indx,
561 gnutls_datum_t * id)
562 {
563 if (bag == NULL) {
564 gnutls_assert();
565 return GNUTLS_E_INVALID_REQUEST;
566 }
567
568 if (indx > bag->bag_elements - 1) {
569 gnutls_assert();
570 return GNUTLS_E_INVALID_REQUEST;
571 }
572
573 id->data = bag->element[indx].local_key_id.data;
574 id->size = bag->element[indx].local_key_id.size;
575
576 return 0;
577 }
578
579 /**
580 * gnutls_pkcs12_bag_get_friendly_name:
581 * @bag: The bag
582 * @indx: The bag's element to add the id
583 * @name: will hold a pointer to the name (to be treated as const)
584 *
585 * This function will return the friendly name, of the specified bag
586 * element. The key ID is usually used to distinguish the local
587 * private key and the certificate pair.
588 *
589 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
590 * negative error value. or a negative error code on error.
591 **/
592 int
gnutls_pkcs12_bag_get_friendly_name(gnutls_pkcs12_bag_t bag,unsigned indx,char ** name)593 gnutls_pkcs12_bag_get_friendly_name(gnutls_pkcs12_bag_t bag, unsigned indx,
594 char **name)
595 {
596 if (bag == NULL) {
597 gnutls_assert();
598 return GNUTLS_E_INVALID_REQUEST;
599 }
600
601 if (indx > bag->bag_elements - 1) {
602 gnutls_assert();
603 return GNUTLS_E_INVALID_REQUEST;
604 }
605
606 *name = bag->element[indx].friendly_name;
607
608 return 0;
609 }
610
611
612 /**
613 * gnutls_pkcs12_bag_set_friendly_name:
614 * @bag: The bag
615 * @indx: The bag's element to add the id
616 * @name: the name
617 *
618 * This function will add the given key friendly name, to the
619 * specified, by the index, bag element. The name will be encoded as
620 * a 'Friendly name' bag attribute, which is usually used to set a
621 * user name to the local private key and the certificate pair.
622 *
623 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
624 * negative error value. or a negative error code on error.
625 **/
626 int
gnutls_pkcs12_bag_set_friendly_name(gnutls_pkcs12_bag_t bag,unsigned indx,const char * name)627 gnutls_pkcs12_bag_set_friendly_name(gnutls_pkcs12_bag_t bag, unsigned indx,
628 const char *name)
629 {
630 if (bag == NULL) {
631 gnutls_assert();
632 return GNUTLS_E_INVALID_REQUEST;
633 }
634
635 if (indx > bag->bag_elements - 1) {
636 gnutls_assert();
637 return GNUTLS_E_INVALID_REQUEST;
638 }
639
640 bag->element[indx].friendly_name = gnutls_strdup(name);
641
642 if (name == NULL) {
643 gnutls_assert();
644 return GNUTLS_E_MEMORY_ERROR;
645 }
646
647 return 0;
648 }
649
650
651 /**
652 * gnutls_pkcs12_bag_decrypt:
653 * @bag: The bag
654 * @pass: The password used for encryption, must be ASCII.
655 *
656 * This function will decrypt the given encrypted bag and return 0 on
657 * success.
658 *
659 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
660 * otherwise a negative error code is returned.
661 **/
gnutls_pkcs12_bag_decrypt(gnutls_pkcs12_bag_t bag,const char * pass)662 int gnutls_pkcs12_bag_decrypt(gnutls_pkcs12_bag_t bag, const char *pass)
663 {
664 int ret;
665 gnutls_datum_t dec;
666
667 if (bag == NULL) {
668 gnutls_assert();
669 return GNUTLS_E_INVALID_REQUEST;
670 }
671
672 if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) {
673 gnutls_assert();
674 return GNUTLS_E_INVALID_REQUEST;
675 }
676
677 ret =
678 _gnutls_pkcs7_decrypt_data(&bag->element[0].data, pass, &dec);
679
680 if (ret < 0) {
681 gnutls_assert();
682 return ret;
683 }
684
685 /* decryption succeeded. Now decode the SafeContents
686 * stuff, and parse it.
687 */
688
689 _gnutls_free_datum(&bag->element[0].data);
690
691 ret = _pkcs12_decode_safe_contents(&dec, bag);
692
693 _gnutls_free_datum(&dec);
694
695 if (ret < 0) {
696 gnutls_assert();
697 return ret;
698 }
699
700 return 0;
701 }
702
703 /**
704 * gnutls_pkcs12_bag_encrypt:
705 * @bag: The bag
706 * @pass: The password used for encryption, must be ASCII
707 * @flags: should be one of #gnutls_pkcs_encrypt_flags_t elements bitwise or'd
708 *
709 * This function will encrypt the given bag.
710 *
711 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
712 * otherwise a negative error code is returned.
713 **/
714 int
gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag_t bag,const char * pass,unsigned int flags)715 gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag_t bag, const char *pass,
716 unsigned int flags)
717 {
718 int ret;
719 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
720 gnutls_datum_t der = { NULL, 0 };
721 gnutls_datum_t enc = { NULL, 0 };
722 schema_id id;
723
724 if (bag == NULL) {
725 gnutls_assert();
726 return GNUTLS_E_INVALID_REQUEST;
727 }
728
729 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED) {
730 gnutls_assert();
731 return GNUTLS_E_INVALID_REQUEST;
732 }
733
734 /* Encode the whole bag to a safe contents
735 * structure.
736 */
737 ret = _pkcs12_encode_safe_contents(bag, &safe_cont, NULL);
738 if (ret < 0) {
739 gnutls_assert();
740 return ret;
741 }
742
743 /* DER encode the SafeContents.
744 */
745 ret = _gnutls_x509_der_encode(safe_cont, "", &der, 0);
746
747 asn1_delete_structure(&safe_cont);
748
749 if (ret < 0) {
750 gnutls_assert();
751 return ret;
752 }
753
754 if (flags & GNUTLS_PKCS_PLAIN) {
755 gnutls_assert();
756 return GNUTLS_E_INVALID_REQUEST;
757 }
758
759 id = _gnutls_pkcs_flags_to_schema(flags);
760
761 /* Now encrypt them.
762 */
763 ret = _gnutls_pkcs7_encrypt_data(id, &der, pass, &enc);
764
765 _gnutls_free_datum(&der);
766
767 if (ret < 0) {
768 gnutls_assert();
769 return ret;
770 }
771
772 /* encryption succeeded.
773 */
774
775 _pkcs12_bag_free_data(bag);
776
777 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
778 bag->element[0].data = enc;
779
780 bag->bag_elements = 1;
781
782
783 return 0;
784 }
785
786 /**
787 * gnutls_pkcs12_bag_enc_info:
788 * @bag: The bag
789 * @schema: indicate the schema as one of %gnutls_pkcs_encrypt_flags_t
790 * @cipher: the cipher used as %gnutls_cipher_algorithm_t
791 * @salt: PBKDF2 salt (if non-NULL then @salt_size initially holds its size)
792 * @salt_size: PBKDF2 salt size
793 * @iter_count: PBKDF2 iteration count
794 * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
795 *
796 * This function will provide information on the encryption algorithms used
797 * in an encrypted bag. If the structure algorithms
798 * are unknown the code %GNUTLS_E_UNKNOWN_CIPHER_TYPE will be returned,
799 * and only @oid, will be set. That is, @oid will be set on encrypted bags
800 * whether supported or not. It must be deinitialized using gnutls_free().
801 * The other variables are only set on supported structures.
802 *
803 * Returns: %GNUTLS_E_INVALID_REQUEST if the provided bag isn't encrypted,
804 * %GNUTLS_E_UNKNOWN_CIPHER_TYPE if the structure's encryption isn't supported, or
805 * another negative error code in case of a failure. Zero on success.
806 **/
807 int
gnutls_pkcs12_bag_enc_info(gnutls_pkcs12_bag_t bag,unsigned int * schema,unsigned int * cipher,void * salt,unsigned int * salt_size,unsigned int * iter_count,char ** oid)808 gnutls_pkcs12_bag_enc_info(gnutls_pkcs12_bag_t bag, unsigned int *schema, unsigned int *cipher,
809 void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid)
810 {
811 int ret;
812 struct pbkdf2_params kdf;
813 const struct pkcs_cipher_schema_st *p;
814
815 if (bag == NULL) {
816 gnutls_assert();
817 return GNUTLS_E_INVALID_REQUEST;
818 }
819
820 if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) {
821 gnutls_assert();
822 return GNUTLS_E_INVALID_REQUEST;
823 }
824
825 ret =
826 _gnutls_pkcs7_data_enc_info(&bag->element[0].data, &p, &kdf, oid);
827
828 if (ret < 0) {
829 gnutls_assert();
830 return ret;
831 }
832
833 if (schema)
834 *schema = p->flag;
835
836 if (cipher)
837 *cipher = p->cipher;
838
839 if (iter_count)
840 *iter_count = kdf.iter_count;
841
842 if (salt) {
843 if (*salt_size >= (unsigned)kdf.salt_size) {
844 memcpy(salt, kdf.salt, kdf.salt_size);
845 } else {
846 *salt_size = kdf.salt_size;
847 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
848 }
849 }
850
851 if (salt_size)
852 *salt_size = kdf.salt_size;
853
854
855 return 0;
856 }
857
858 /**
859 * gnutls_pkcs12_bag_set_privkey:
860 * @bag: The bag
861 * @privkey: the private key to be copied.
862 * @password: the password to protect the key with (may be %NULL)
863 * @flags: should be one of #gnutls_pkcs_encrypt_flags_t elements bitwise or'd
864 *
865 * This function will insert the given private key into the
866 * bag. This is just a wrapper over gnutls_pkcs12_bag_set_data().
867 *
868 * Returns: the index of the added bag on success, or a negative
869 * value on failure.
870 **/
871 int
gnutls_pkcs12_bag_set_privkey(gnutls_pkcs12_bag_t bag,gnutls_x509_privkey_t privkey,const char * password,unsigned flags)872 gnutls_pkcs12_bag_set_privkey(gnutls_pkcs12_bag_t bag, gnutls_x509_privkey_t privkey,
873 const char *password, unsigned flags)
874 {
875 int ret;
876 gnutls_datum_t data = {NULL, 0};
877
878 if (bag == NULL) {
879 gnutls_assert();
880 return GNUTLS_E_INVALID_REQUEST;
881 }
882
883 ret = gnutls_x509_privkey_export2_pkcs8(privkey, GNUTLS_X509_FMT_DER,
884 password, flags, &data);
885 if (ret < 0)
886 return gnutls_assert_val(ret);
887
888 if (password == NULL) {
889 ret = gnutls_pkcs12_bag_set_data(bag, GNUTLS_BAG_PKCS8_KEY, &data);
890 if (ret < 0) {
891 gnutls_assert();
892 goto cleanup;
893 }
894 } else {
895 ret = gnutls_pkcs12_bag_set_data(bag, GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &data);
896 if (ret < 0) {
897 gnutls_assert();
898 goto cleanup;
899 }
900 }
901
902 cleanup:
903 _gnutls_free_datum(&data);
904
905 return ret;
906 }
907