Coverage Report

Created: 2025-03-18 06:55

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