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