Coverage Report

Created: 2023-03-26 08:33

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