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