Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/x509/privkey_pkcs8.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2014-2017 Red Hat
4
 * Copyright (C) 2014-2016 Nikos Mavrogiannopoulos
5
 *
6
 * Author: Nikos Mavrogiannopoulos
7
 *
8
 * This file is part of GnuTLS.
9
 *
10
 * The GnuTLS is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public License
12
 * as published by the Free Software Foundation; either version 2.1 of
13
 * the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
22
 *
23
 */
24
25
#include "gnutls_int.h"
26
27
#include "datum.h"
28
#include "global.h"
29
#include "errors.h"
30
#include "common.h"
31
#include "x509.h"
32
#include "x509_b64.h"
33
#include "x509_int.h"
34
#include "pkcs7_int.h"
35
#include "algorithms.h"
36
#include "num.h"
37
#include "random.h"
38
#include "pk.h"
39
#include "attributes.h"
40
#include "prov-seed.h"
41
#include "intprops.h"
42
43
static int _decode_pkcs8_ecc_key(asn1_node pkcs8_asn,
44
         gnutls_x509_privkey_t pkey);
45
static int pkcs8_key_info(const gnutls_datum_t *raw_key,
46
        const struct pkcs_cipher_schema_st **p,
47
        struct pbkdf2_params *kdf_params, char **oid);
48
49
static int decode_private_key_info(const gnutls_datum_t *der,
50
           gnutls_x509_privkey_t pkey);
51
52
0
#define PEM_PKCS8 "ENCRYPTED PRIVATE KEY"
53
0
#define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY"
54
55
/* Returns a negative error code if the encryption schema in
56
 * the OID is not supported. The schema ID is returned.
57
 */
58
/* Encodes a private key to the raw format PKCS #8 needs.
59
 * For RSA it is a PKCS #1 DER private key and for DSA it is
60
 * an ASN.1 INTEGER of the x value.
61
 */
62
inline static int _encode_privkey(gnutls_x509_privkey_t pkey,
63
          gnutls_datum_t *raw)
64
0
{
65
0
  int ret;
66
0
  asn1_node spk = NULL;
67
68
0
  switch (pkey->params.algo) {
69
0
  case GNUTLS_PK_EDDSA_ED25519:
70
0
  case GNUTLS_PK_EDDSA_ED448:
71
0
  case GNUTLS_PK_ECDH_X25519:
72
0
  case GNUTLS_PK_ECDH_X448:
73
    /* we encode as octet string (which is going to be stored inside
74
     * another octet string). No comments. */
75
0
    ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
76
0
             pkey->params.raw_priv.data,
77
0
             pkey->params.raw_priv.size,
78
0
             raw);
79
0
    if (ret < 0)
80
0
      gnutls_assert();
81
0
    return ret;
82
0
  case GNUTLS_PK_MLDSA44:
83
0
  case GNUTLS_PK_MLDSA65:
84
0
  case GNUTLS_PK_MLDSA87: {
85
0
    gnutls_datum_t concatenated_key = { NULL, 0 };
86
0
    size_t concatenated_key_size = 0;
87
88
0
    if (!INT_ADD_OK(pkey->params.raw_priv.size,
89
0
        pkey->params.raw_pub.size,
90
0
        &concatenated_key_size))
91
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
92
0
    ret = _gnutls_set_datum(&concatenated_key,
93
0
          pkey->params.raw_priv.data,
94
0
          pkey->params.raw_priv.size);
95
0
    if (ret < 0)
96
0
      return gnutls_assert_val(ret);
97
0
    concatenated_key.data = gnutls_realloc_fast(
98
0
      concatenated_key.data, concatenated_key_size);
99
0
    if (!concatenated_key.data)
100
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
101
0
    concatenated_key.size = concatenated_key_size;
102
0
    memcpy(&concatenated_key.data[pkey->params.raw_priv.size],
103
0
           pkey->params.raw_pub.data, pkey->params.raw_pub.size);
104
0
    ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
105
0
             concatenated_key.data,
106
0
             concatenated_key.size, raw);
107
0
    _gnutls_free_key_datum(&concatenated_key);
108
0
    if (ret < 0)
109
0
      gnutls_assert();
110
0
    return ret;
111
0
  }
112
0
  case GNUTLS_PK_GOST_01:
113
0
  case GNUTLS_PK_GOST_12_256:
114
0
  case GNUTLS_PK_GOST_12_512:
115
0
    if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
116
0
                 "GNUTLS.GOSTPrivateKey",
117
0
                 &spk)) != ASN1_SUCCESS) {
118
0
      gnutls_assert();
119
0
      ret = _gnutls_asn2err(ret);
120
0
      goto error;
121
0
    }
122
123
0
    ret = _gnutls_x509_write_key_int_le(
124
0
      spk, "", pkey->params.params[GOST_K]);
125
0
    if (ret < 0) {
126
0
      gnutls_assert();
127
0
      goto error;
128
0
    }
129
130
0
    ret = _gnutls_x509_der_encode(spk, "", raw, 0);
131
0
    if (ret < 0) {
132
0
      gnutls_assert();
133
0
      goto error;
134
0
    }
135
136
0
    asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE);
137
0
    break;
138
139
0
  case GNUTLS_PK_RSA:
140
0
  case GNUTLS_PK_RSA_PSS:
141
0
  case GNUTLS_PK_RSA_OAEP:
142
0
  case GNUTLS_PK_ECDSA:
143
0
    ret = _gnutls_x509_export_int2(pkey->key, GNUTLS_X509_FMT_DER,
144
0
                 "", raw);
145
0
    if (ret < 0) {
146
0
      gnutls_assert();
147
0
      goto error;
148
0
    }
149
150
0
    break;
151
0
  case GNUTLS_PK_DSA:
152
    /* DSAPublicKey == INTEGER */
153
0
    if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
154
0
                 "GNUTLS.DSAPublicKey", &spk)) !=
155
0
        ASN1_SUCCESS) {
156
0
      gnutls_assert();
157
0
      return _gnutls_asn2err(ret);
158
0
    }
159
160
0
    ret = _gnutls_x509_write_int(spk, "", pkey->params.params[4],
161
0
               1);
162
0
    if (ret < 0) {
163
0
      gnutls_assert();
164
0
      goto error;
165
0
    }
166
0
    ret = _gnutls_x509_der_encode(spk, "", raw, 0);
167
0
    if (ret < 0) {
168
0
      gnutls_assert();
169
0
      goto error;
170
0
    }
171
172
0
    asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE);
173
0
    break;
174
175
0
  default:
176
0
    gnutls_assert();
177
0
    return GNUTLS_E_INVALID_REQUEST;
178
0
  }
179
180
0
  return 0;
181
182
0
error:
183
0
  asn1_delete_structure2(&spk, ASN1_DELETE_FLAG_ZEROIZE);
184
0
  asn1_delete_structure(&spk);
185
0
  return ret;
186
0
}
187
188
/* 
189
 * Encodes a PKCS #1 private key to a PKCS #8 private key
190
 * info. The output will be allocated and stored into der. Also
191
 * the asn1_node of private key info will be returned.
192
 */
193
static int encode_to_private_key_info(gnutls_x509_privkey_t pkey,
194
              gnutls_datum_t *der, asn1_node *pkey_info)
195
0
{
196
0
  int result, len;
197
0
  uint8_t null = 0;
198
0
  const char *oid;
199
0
  gnutls_datum_t algo_params = { NULL, 0 };
200
0
  gnutls_datum_t algo_privkey = { NULL, 0 };
201
202
0
  oid = gnutls_pk_get_oid(pkey->params.algo);
203
0
  if (oid == NULL) {
204
0
    gnutls_assert();
205
0
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
206
0
  }
207
208
0
  result = _gnutls_x509_write_pubkey_params(&pkey->params, &algo_params);
209
0
  if (result < 0) {
210
0
    gnutls_assert();
211
0
    return result;
212
0
  }
213
214
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
215
0
            "PKIX1.pkcs-8-PrivateKeyInfo",
216
0
            pkey_info)) != ASN1_SUCCESS) {
217
0
    gnutls_assert();
218
0
    result = _gnutls_asn2err(result);
219
0
    goto error;
220
0
  }
221
222
  /* Write the version.
223
   */
224
0
  result = asn1_write_value(*pkey_info, "version", &null, 1);
225
0
  if (result != ASN1_SUCCESS) {
226
0
    gnutls_assert();
227
0
    result = _gnutls_asn2err(result);
228
0
    goto error;
229
0
  }
230
231
  /* write the privateKeyAlgorithm
232
   * fields. (OID+NULL data)
233
   */
234
0
  result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.algorithm",
235
0
          oid, 1);
236
0
  if (result != ASN1_SUCCESS) {
237
0
    gnutls_assert();
238
0
    result = _gnutls_asn2err(result);
239
0
    goto error;
240
0
  }
241
242
0
  result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.parameters",
243
0
          algo_params.data, algo_params.size);
244
0
  _gnutls_free_key_datum(&algo_params);
245
246
0
  if (result != ASN1_SUCCESS) {
247
0
    gnutls_assert();
248
0
    result = _gnutls_asn2err(result);
249
0
    goto error;
250
0
  }
251
252
  /* Write the raw private key
253
   */
254
0
  result = _encode_privkey(pkey, &algo_privkey);
255
0
  if (result < 0) {
256
0
    gnutls_assert();
257
0
    goto error;
258
0
  }
259
260
0
  result = asn1_write_value(*pkey_info, "privateKey", algo_privkey.data,
261
0
          algo_privkey.size);
262
0
  _gnutls_free_key_datum(&algo_privkey);
263
264
0
  if (result != ASN1_SUCCESS) {
265
0
    gnutls_assert();
266
0
    result = _gnutls_asn2err(result);
267
0
    goto error;
268
0
  }
269
270
0
  if ((pkey->params.pkflags & GNUTLS_PK_FLAG_PROVABLE) &&
271
0
      pkey->params.seed_size > 0) {
272
0
    gnutls_datum_t seed_info;
273
    /* rfc8479 attribute encoding */
274
275
0
    result = _x509_encode_provable_seed(pkey, &seed_info);
276
0
    if (result < 0) {
277
0
      gnutls_assert();
278
0
      goto error;
279
0
    }
280
281
0
    result = _x509_set_attribute(*pkey_info, "attributes",
282
0
               OID_ATTR_PROV_SEED, &seed_info);
283
0
    gnutls_free(seed_info.data);
284
0
    if (result < 0) {
285
0
      gnutls_assert();
286
0
      goto error;
287
0
    }
288
0
  } else {
289
    /* Append an empty Attributes field.
290
     */
291
0
    result = asn1_write_value(*pkey_info, "attributes", NULL, 0);
292
0
    if (result != ASN1_SUCCESS) {
293
0
      gnutls_assert();
294
0
      result = _gnutls_asn2err(result);
295
0
      goto error;
296
0
    }
297
0
  }
298
299
  /* DER Encode the generated private key info.
300
   */
301
0
  len = 0;
302
0
  result = asn1_der_coding(*pkey_info, "", NULL, &len, NULL);
303
0
  if (result != ASN1_MEM_ERROR) {
304
0
    gnutls_assert();
305
0
    result = _gnutls_asn2err(result);
306
0
    goto error;
307
0
  }
308
309
  /* allocate data for the der
310
   */
311
0
  der->size = len;
312
0
  der->data = gnutls_malloc(len);
313
0
  if (der->data == NULL) {
314
0
    gnutls_assert();
315
0
    return GNUTLS_E_MEMORY_ERROR;
316
0
  }
317
318
0
  result = asn1_der_coding(*pkey_info, "", der->data, &len, NULL);
319
0
  if (result != ASN1_SUCCESS) {
320
0
    gnutls_assert();
321
0
    result = _gnutls_asn2err(result);
322
0
    goto error;
323
0
  }
324
325
0
  return 0;
326
327
0
error:
328
0
  asn1_delete_structure2(pkey_info, ASN1_DELETE_FLAG_ZEROIZE);
329
0
  _gnutls_free_datum(&algo_params);
330
0
  _gnutls_free_key_datum(&algo_privkey);
331
0
  return result;
332
0
}
333
334
/* Converts a PKCS #8 private key info to
335
 * a PKCS #8 EncryptedPrivateKeyInfo.
336
 */
337
static int encode_to_pkcs8_key(schema_id schema, const gnutls_datum_t *der_key,
338
             const char *password, asn1_node *out)
339
0
{
340
0
  int result;
341
0
  gnutls_datum_t key = { NULL, 0 };
342
0
  gnutls_datum_t tmp = { NULL, 0 };
343
0
  asn1_node pkcs8_asn = NULL;
344
0
  struct pbkdf2_params kdf_params;
345
0
  struct pbe_enc_params enc_params;
346
0
  const struct pkcs_cipher_schema_st *s;
347
348
0
  s = _gnutls_pkcs_schema_get(schema);
349
0
  if (s == NULL || s->decrypt_only) {
350
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
351
0
  }
352
353
0
  if ((result = asn1_create_element(
354
0
         _gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
355
0
         &pkcs8_asn)) != ASN1_SUCCESS) {
356
0
    gnutls_assert();
357
0
    return _gnutls_asn2err(result);
358
0
  }
359
360
  /* Write the encryption schema OID
361
   */
362
0
  result = asn1_write_value(pkcs8_asn, "encryptionAlgorithm.algorithm",
363
0
          s->write_oid, 1);
364
365
0
  if (result != ASN1_SUCCESS) {
366
0
    gnutls_assert();
367
0
    result = _gnutls_asn2err(result);
368
0
    goto error;
369
0
  }
370
371
  /* Generate a symmetric key.
372
   */
373
374
0
  result = _gnutls_pkcs_generate_key(schema, password, &kdf_params,
375
0
             &enc_params, &key);
376
0
  if (result < 0) {
377
0
    gnutls_assert();
378
0
    goto error;
379
0
  }
380
381
0
  result = _gnutls_pkcs_write_schema_params(
382
0
    schema, pkcs8_asn, "encryptionAlgorithm.parameters",
383
0
    &kdf_params, &enc_params);
384
0
  if (result < 0) {
385
0
    gnutls_assert();
386
0
    goto error;
387
0
  }
388
389
  /* Parameters have been encoded. Now
390
   * encrypt the Data.
391
   */
392
0
  result =
393
0
    _gnutls_pkcs_raw_encrypt_data(der_key, &enc_params, &key, &tmp);
394
0
  if (result < 0) {
395
0
    gnutls_assert();
396
0
    goto error;
397
0
  }
398
399
  /* write the encrypted data.
400
   */
401
0
  result = asn1_write_value(pkcs8_asn, "encryptedData", tmp.data,
402
0
          tmp.size);
403
0
  if (result != ASN1_SUCCESS) {
404
0
    gnutls_assert();
405
0
    result = _gnutls_asn2err(result);
406
0
    goto error;
407
0
  }
408
409
0
  _gnutls_free_datum(&tmp);
410
0
  _gnutls_free_key_datum(&key);
411
412
0
  *out = pkcs8_asn;
413
414
0
  return 0;
415
416
0
error:
417
0
  _gnutls_free_key_datum(&key);
418
0
  _gnutls_free_datum(&tmp);
419
0
  asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
420
0
  return result;
421
0
}
422
423
/**
424
 * gnutls_x509_privkey_export_pkcs8:
425
 * @key: Holds the key
426
 * @format: the format of output params. One of PEM or DER.
427
 * @password: the password that will be used to encrypt the key.
428
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
429
 * @output_data: will contain a private key PEM or DER encoded
430
 * @output_data_size: holds the size of output_data (and will be
431
 *   replaced by the actual size of parameters)
432
 *
433
 * This function will export the private key to a PKCS8 structure.
434
 * Both RSA and DSA keys can be exported. For DSA keys we use
435
 * PKCS #11 definitions. If the flags do not specify the encryption
436
 * cipher, then the default 3DES (PBES2) will be used.
437
 *
438
 * The @password can be either ASCII or UTF-8 in the default PBES2
439
 * encryption schemas, or ASCII for the PKCS12 schemas.
440
 *
441
 * If the buffer provided is not long enough to hold the output, then
442
 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
443
 * be returned.
444
 *
445
 * If the structure is PEM encoded, it will have a header
446
 * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if
447
 * encryption is not used.
448
 *
449
 * Returns: In case of failure a negative error code will be
450
 *   returned, and 0 on success.
451
 **/
452
int gnutls_x509_privkey_export_pkcs8(gnutls_x509_privkey_t key,
453
             gnutls_x509_crt_fmt_t format,
454
             const char *password, unsigned int flags,
455
             void *output_data,
456
             size_t *output_data_size)
457
0
{
458
0
  asn1_node pkcs8_asn = NULL, pkey_info;
459
0
  int ret;
460
0
  gnutls_datum_t tmp = { NULL, 0 };
461
0
  schema_id schema;
462
463
0
  if (key == NULL) {
464
0
    gnutls_assert();
465
0
    return GNUTLS_E_INVALID_REQUEST;
466
0
  }
467
468
  /* Get the private key info
469
   * tmp holds the DER encoding.
470
   */
471
0
  ret = encode_to_private_key_info(key, &tmp, &pkey_info);
472
0
  if (ret < 0) {
473
0
    gnutls_assert();
474
0
    return ret;
475
0
  }
476
477
0
  schema = _gnutls_pkcs_flags_to_schema(flags);
478
479
0
  if (((flags & GNUTLS_PKCS_PLAIN) || password == NULL) &&
480
0
      !(flags & GNUTLS_PKCS_NULL_PASSWORD)) {
481
0
    _gnutls_free_datum(&tmp);
482
483
0
    ret = _gnutls_x509_export_int(pkey_info, format,
484
0
                PEM_UNENCRYPTED_PKCS8,
485
0
                output_data, output_data_size);
486
487
0
    asn1_delete_structure2(&pkey_info, ASN1_DELETE_FLAG_ZEROIZE);
488
0
  } else {
489
0
    asn1_delete_structure2(
490
0
      &pkey_info,
491
0
      ASN1_DELETE_FLAG_ZEROIZE); /* we don't need it */
492
493
0
    ret = encode_to_pkcs8_key(schema, &tmp, password, &pkcs8_asn);
494
0
    _gnutls_free_key_datum(&tmp);
495
496
0
    if (ret < 0) {
497
0
      gnutls_assert();
498
0
      return ret;
499
0
    }
500
501
0
    ret = _gnutls_x509_export_int(pkcs8_asn, format, PEM_PKCS8,
502
0
                output_data, output_data_size);
503
504
0
    asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
505
0
  }
506
507
0
  return ret;
508
0
}
509
510
/**
511
 * gnutls_pkcs8_info:
512
 * @data: Holds the PKCS #8 data
513
 * @format: the format of the PKCS #8 data
514
 * @schema: indicate the schema as one of %gnutls_pkcs_encrypt_flags_t
515
 * @cipher: the cipher used as %gnutls_cipher_algorithm_t
516
 * @salt: PBKDF2 salt (if non-NULL then @salt_size initially holds its size)
517
 * @salt_size: PBKDF2 salt size
518
 * @iter_count: PBKDF2 iteration count
519
 * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
520
 *
521
 * This function will provide information on the algorithms used
522
 * in a particular PKCS #8 structure. If the structure algorithms
523
 * are unknown the code %GNUTLS_E_UNKNOWN_CIPHER_TYPE will be returned,
524
 * and only @oid, will be set. That is, @oid will be set on encrypted PKCS #8
525
 * structures whether supported or not. It must be deinitialized using gnutls_free().
526
 * The other variables are only set on supported structures.
527
 *
528
 * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure isn't an encrypted key,
529
 *  %GNUTLS_E_UNKNOWN_CIPHER_TYPE if the structure's encryption isn't supported, or
530
 *  another negative error code in case of a failure. Zero on success.
531
 *
532
 * Since: 3.4.0
533
 **/
534
int gnutls_pkcs8_info(const gnutls_datum_t *data, gnutls_x509_crt_fmt_t format,
535
          unsigned int *schema, unsigned int *cipher, void *salt,
536
          unsigned int *salt_size, unsigned int *iter_count,
537
          char **oid)
538
0
{
539
0
  int ret = 0, need_free = 0;
540
0
  gnutls_datum_t _data;
541
0
  const struct pkcs_cipher_schema_st *p = NULL;
542
0
  struct pbkdf2_params kdf;
543
544
0
  memset(&kdf, 0, sizeof(kdf));
545
546
0
  if (oid)
547
0
    *oid = NULL;
548
549
0
  _data.data = data->data;
550
0
  _data.size = data->size;
551
552
  /* If the Certificate is in PEM format then decode it
553
   */
554
0
  if (format == GNUTLS_X509_FMT_PEM) {
555
    /* Try the first header 
556
     */
557
0
    ret = _gnutls_fbase64_decode(PEM_UNENCRYPTED_PKCS8, data->data,
558
0
               data->size, &_data);
559
560
0
    if (ret < 0) { /* Try the encrypted header 
561
         */
562
0
      ret = _gnutls_fbase64_decode(PEM_PKCS8, data->data,
563
0
                 data->size, &_data);
564
565
0
      if (ret < 0) {
566
0
        gnutls_assert();
567
0
        return ret;
568
0
      }
569
0
    }
570
571
0
    need_free = 1;
572
0
  }
573
574
0
  ret = pkcs8_key_info(&_data, &p, &kdf, oid);
575
0
  if (ret == GNUTLS_E_DECRYPTION_FAILED)
576
0
    ret = GNUTLS_E_INVALID_REQUEST;
577
0
  if (ret < 0) {
578
0
    gnutls_assert();
579
0
    goto cleanup;
580
0
  }
581
582
0
  assert(p != NULL);
583
584
0
  if (need_free)
585
0
    _gnutls_free_datum(&_data);
586
587
0
  if (schema)
588
0
    *schema = p->flag;
589
590
0
  if (cipher)
591
0
    *cipher = p->cipher;
592
593
0
  if (iter_count)
594
0
    *iter_count = kdf.iter_count;
595
596
0
  if (salt) {
597
0
    if (*salt_size >= (unsigned)kdf.salt_size) {
598
0
      memcpy(salt, kdf.salt, kdf.salt_size);
599
0
    } else {
600
0
      *salt_size = kdf.salt_size;
601
0
      ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
602
0
      goto cleanup;
603
0
    }
604
0
  }
605
606
0
  if (salt_size)
607
0
    *salt_size = kdf.salt_size;
608
609
0
  return 0;
610
611
0
cleanup:
612
0
  if (ret != GNUTLS_E_UNKNOWN_CIPHER_TYPE && oid) {
613
0
    gnutls_free(*oid);
614
0
  }
615
0
  if (need_free)
616
0
    _gnutls_free_datum(&_data);
617
0
  return ret;
618
0
}
619
620
/**
621
 * gnutls_x509_privkey_export2_pkcs8:
622
 * @key: Holds the key
623
 * @format: the format of output params. One of PEM or DER.
624
 * @password: the password that will be used to encrypt the key.
625
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
626
 * @out: will contain a private key PEM or DER encoded
627
 *
628
 * This function will export the private key to a PKCS8 structure.
629
 * Both RSA and DSA keys can be exported. For DSA keys we use
630
 * PKCS #11 definitions. If the flags do not specify the encryption
631
 * cipher, then the default 3DES (PBES2) will be used.
632
 *
633
 * The @password can be either ASCII or UTF-8 in the default PBES2
634
 * encryption schemas, or ASCII for the PKCS12 schemas.
635
 *
636
 * The output buffer is allocated using gnutls_malloc().
637
 *
638
 * If the structure is PEM encoded, it will have a header
639
 * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if
640
 * encryption is not used.
641
 *
642
 * Returns: In case of failure a negative error code will be
643
 *   returned, and 0 on success.
644
 *
645
 * Since 3.1.3
646
 **/
647
int gnutls_x509_privkey_export2_pkcs8(gnutls_x509_privkey_t key,
648
              gnutls_x509_crt_fmt_t format,
649
              const char *password, unsigned int flags,
650
              gnutls_datum_t *out)
651
0
{
652
0
  asn1_node pkcs8_asn = NULL, pkey_info;
653
0
  int ret;
654
0
  gnutls_datum_t tmp = { NULL, 0 };
655
0
  schema_id schema;
656
657
0
  if (key == NULL) {
658
0
    gnutls_assert();
659
0
    return GNUTLS_E_INVALID_REQUEST;
660
0
  }
661
662
  /* Get the private key info
663
   * tmp holds the DER encoding.
664
   */
665
0
  ret = encode_to_private_key_info(key, &tmp, &pkey_info);
666
0
  if (ret < 0) {
667
0
    gnutls_assert();
668
0
    return ret;
669
0
  }
670
671
0
  schema = _gnutls_pkcs_flags_to_schema(flags);
672
673
0
  if (((flags & GNUTLS_PKCS_PLAIN) || password == NULL) &&
674
0
      !(flags & GNUTLS_PKCS_NULL_PASSWORD)) {
675
0
    _gnutls_free_key_datum(&tmp);
676
677
0
    ret = _gnutls_x509_export_int2(pkey_info, format,
678
0
                 PEM_UNENCRYPTED_PKCS8, out);
679
680
0
    asn1_delete_structure2(&pkey_info, ASN1_DELETE_FLAG_ZEROIZE);
681
0
  } else {
682
0
    asn1_delete_structure2(
683
0
      &pkey_info,
684
0
      ASN1_DELETE_FLAG_ZEROIZE); /* we don't need it */
685
686
0
    ret = encode_to_pkcs8_key(schema, &tmp, password, &pkcs8_asn);
687
0
    _gnutls_free_key_datum(&tmp);
688
689
0
    if (ret < 0) {
690
0
      gnutls_assert();
691
0
      return ret;
692
0
    }
693
694
0
    ret = _gnutls_x509_export_int2(pkcs8_asn, format, PEM_PKCS8,
695
0
                 out);
696
697
0
    asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
698
0
  }
699
700
0
  return ret;
701
0
}
702
703
/* We've gotten this far. In the real world it's almost certain
704
   * that we're dealing with a good file, but wrong password.
705
   * Sadly like 90% of random data is somehow valid DER for the
706
   * a first small number of bytes, so no easy way to guarantee. */
707
#define CHECK_ERR_FOR_ENCRYPTED(result)                     \
708
0
  if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND ||    \
709
0
      result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND || \
710
0
      result == GNUTLS_E_ASN1_DER_ERROR ||            \
711
0
      result == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||      \
712
0
      result == GNUTLS_E_ASN1_GENERIC_ERROR ||        \
713
0
      result == GNUTLS_E_ASN1_VALUE_NOT_VALID ||      \
714
0
      result == GNUTLS_E_ASN1_TAG_ERROR ||            \
715
0
      result == GNUTLS_E_ASN1_TAG_IMPLICIT ||         \
716
0
      result == GNUTLS_E_ASN1_TYPE_ANY_ERROR ||       \
717
0
      result == GNUTLS_E_ASN1_SYNTAX_ERROR ||         \
718
0
      result == GNUTLS_E_ASN1_DER_OVERFLOW) {         \
719
0
    result = GNUTLS_E_DECRYPTION_FAILED;        \
720
0
  }
721
722
static int pkcs8_key_decrypt(const gnutls_datum_t *raw_key, asn1_node pkcs8_asn,
723
           const char *password, gnutls_x509_privkey_t pkey)
724
0
{
725
0
  int result, len;
726
0
  char enc_oid[MAX_OID_SIZE];
727
0
  gnutls_datum_t tmp = { NULL, 0 };
728
0
  int params_start, params_end, params_len;
729
0
  struct pbkdf2_params kdf_params;
730
0
  struct pbe_enc_params enc_params;
731
0
  schema_id schema;
732
733
  /* Check the encryption schema OID
734
   */
735
0
  len = sizeof(enc_oid);
736
0
  result = asn1_read_value(pkcs8_asn, "encryptionAlgorithm.algorithm",
737
0
         enc_oid, &len);
738
0
  if (result != ASN1_SUCCESS) {
739
0
    gnutls_assert();
740
0
    goto error;
741
0
  }
742
743
0
  if ((result = _gnutls_check_pkcs_cipher_schema(enc_oid)) < 0) {
744
0
    gnutls_assert();
745
0
    goto error;
746
0
  }
747
748
0
  schema = result;
749
750
  /* Get the DER encoding of the parameters.
751
   */
752
0
  result = asn1_der_decoding_startEnd(pkcs8_asn, raw_key->data,
753
0
              raw_key->size,
754
0
              "encryptionAlgorithm.parameters",
755
0
              &params_start, &params_end);
756
0
  if (result != ASN1_SUCCESS) {
757
0
    gnutls_assert();
758
0
    result = _gnutls_asn2err(result);
759
0
    goto error;
760
0
  }
761
0
  params_len = params_end - params_start + 1;
762
763
0
  result = _gnutls_read_pkcs_schema_params(&schema, password,
764
0
             &raw_key->data[params_start],
765
0
             params_len, &kdf_params,
766
0
             &enc_params);
767
768
0
  if (result < 0) {
769
0
    gnutls_assert();
770
0
    goto error;
771
0
  }
772
773
  /* Parameters have been decoded. Now
774
   * decrypt the EncryptedData.
775
   */
776
0
  result = _gnutls_pkcs_raw_decrypt_data(schema, pkcs8_asn,
777
0
                 "encryptedData", password,
778
0
                 &kdf_params, &enc_params, &tmp);
779
0
  if (result < 0) {
780
0
    gnutls_assert();
781
0
    result = GNUTLS_E_DECRYPTION_FAILED;
782
0
    goto error;
783
0
  }
784
785
0
  result = decode_private_key_info(&tmp, pkey);
786
0
  _gnutls_free_key_datum(&tmp);
787
788
0
  CHECK_ERR_FOR_ENCRYPTED(result);
789
0
  if (result < 0) {
790
0
    gnutls_assert();
791
0
    goto error;
792
0
  }
793
794
0
  return 0;
795
796
0
error:
797
0
  return result;
798
0
}
799
800
static int check_for_decrypted(const gnutls_datum_t *der)
801
0
{
802
0
  int result;
803
0
  asn1_node pkcs8_asn = NULL;
804
805
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
806
0
            "PKIX1.pkcs-8-PrivateKeyInfo",
807
0
            &pkcs8_asn)) != ASN1_SUCCESS) {
808
0
    gnutls_assert();
809
0
    return _gnutls_asn2err(result);
810
0
  }
811
812
0
  result =
813
0
    _asn1_strict_der_decode(&pkcs8_asn, der->data, der->size, NULL);
814
0
  if (result != ASN1_SUCCESS) {
815
0
    gnutls_assert();
816
0
    result = _gnutls_asn2err(result);
817
0
    goto error;
818
0
  }
819
820
0
  result = 0;
821
0
error:
822
0
  asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
823
0
  return result;
824
0
}
825
826
static int pkcs8_key_info(const gnutls_datum_t *raw_key,
827
        const struct pkcs_cipher_schema_st **p,
828
        struct pbkdf2_params *kdf_params, char **oid)
829
0
{
830
0
  int result, len;
831
0
  char enc_oid[MAX_OID_SIZE * 2];
832
0
  int params_start, params_end, params_len;
833
0
  struct pbe_enc_params enc_params;
834
0
  schema_id schema;
835
0
  asn1_node pkcs8_asn = NULL;
836
837
0
  memset(&enc_params, 0, sizeof(enc_params));
838
839
0
  result = check_for_decrypted(raw_key);
840
0
  if (result == 0)
841
0
    return GNUTLS_E_INVALID_REQUEST;
842
843
0
  if ((result = asn1_create_element(
844
0
         _gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
845
0
         &pkcs8_asn)) != ASN1_SUCCESS) {
846
0
    gnutls_assert();
847
0
    result = _gnutls_asn2err(result);
848
0
    goto error;
849
0
  }
850
851
0
  result = _asn1_strict_der_decode(&pkcs8_asn, raw_key->data,
852
0
           raw_key->size, NULL);
853
0
  if (result != ASN1_SUCCESS) {
854
0
    gnutls_assert();
855
0
    result = _gnutls_asn2err(result);
856
0
    goto error;
857
0
  }
858
859
  /* Check the encryption schema OID
860
   */
861
0
  len = sizeof(enc_oid);
862
0
  result = asn1_read_value(pkcs8_asn, "encryptionAlgorithm.algorithm",
863
0
         enc_oid, &len);
864
0
  if (result != ASN1_SUCCESS) {
865
0
    gnutls_assert();
866
0
    goto error;
867
0
  }
868
869
0
  if (oid) {
870
0
    *oid = gnutls_strdup(enc_oid);
871
0
  }
872
873
0
  if ((result = _gnutls_check_pkcs_cipher_schema(enc_oid)) < 0) {
874
0
    gnutls_assert();
875
0
    goto error;
876
0
  }
877
878
0
  schema = result;
879
880
  /* Get the DER encoding of the parameters.
881
   */
882
0
  result = asn1_der_decoding_startEnd(pkcs8_asn, raw_key->data,
883
0
              raw_key->size,
884
0
              "encryptionAlgorithm.parameters",
885
0
              &params_start, &params_end);
886
0
  if (result != ASN1_SUCCESS) {
887
0
    gnutls_assert();
888
0
    result = _gnutls_asn2err(result);
889
0
    goto error;
890
0
  }
891
0
  params_len = params_end - params_start + 1;
892
893
0
  result = _gnutls_read_pkcs_schema_params(&schema, NULL,
894
0
             &raw_key->data[params_start],
895
0
             params_len, kdf_params,
896
0
             &enc_params);
897
898
0
  if (result < 0) {
899
0
    gnutls_assert();
900
0
    if (oid && enc_params.pbes2_oid[0] != 0) {
901
0
      snprintf(enc_oid, sizeof(enc_oid), "%s/%s", *oid,
902
0
         enc_params.pbes2_oid);
903
0
      gnutls_free(*oid);
904
0
      *oid = gnutls_strdup(enc_oid);
905
0
    }
906
0
    goto error;
907
0
  }
908
909
0
  *p = _gnutls_pkcs_schema_get(schema);
910
0
  if (*p == NULL) {
911
0
    gnutls_assert();
912
0
    result = GNUTLS_E_UNKNOWN_CIPHER_TYPE;
913
0
    goto error;
914
0
  }
915
916
0
  result = 0;
917
918
0
error:
919
0
  asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
920
0
  return result;
921
0
}
922
923
/* Converts a PKCS #8 key to
924
 * an internal structure (gnutls_private_key)
925
 * (normally a PKCS #1 encoded RSA key)
926
 */
927
static int pkcs8_key_decode(const gnutls_datum_t *raw_key, const char *password,
928
          gnutls_x509_privkey_t pkey, unsigned int decrypt)
929
0
{
930
0
  int result;
931
0
  asn1_node pkcs8_asn = NULL;
932
933
0
  if ((result = asn1_create_element(
934
0
         _gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
935
0
         &pkcs8_asn)) != ASN1_SUCCESS) {
936
0
    gnutls_assert();
937
0
    result = _gnutls_asn2err(result);
938
0
    goto error;
939
0
  }
940
941
0
  result = _asn1_strict_der_decode(&pkcs8_asn, raw_key->data,
942
0
           raw_key->size, NULL);
943
0
  if (result != ASN1_SUCCESS) {
944
0
    gnutls_assert();
945
0
    result = _gnutls_asn2err(result);
946
0
    goto error;
947
0
  }
948
949
0
  if (decrypt)
950
0
    result = pkcs8_key_decrypt(raw_key, pkcs8_asn, password, pkey);
951
0
  else
952
0
    result = 0;
953
954
0
error:
955
0
  asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
956
0
  return result;
957
0
}
958
959
/* Decodes an RSA privateKey from a PKCS8 structure.
960
 */
961
static int _decode_pkcs8_rsa_key(asn1_node pkcs8_asn,
962
         gnutls_x509_privkey_t pkey)
963
0
{
964
0
  int ret;
965
0
  gnutls_datum_t tmp = { NULL, 0 };
966
967
0
  ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
968
0
  if (ret < 0) {
969
0
    gnutls_assert();
970
0
    goto error;
971
0
  }
972
973
0
  pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key(&tmp, pkey);
974
0
  _gnutls_free_key_datum(&tmp);
975
976
0
  if (pkey->key == NULL) {
977
0
    ret = GNUTLS_E_PK_INVALID_PRIVKEY;
978
0
    gnutls_assert();
979
0
    goto error;
980
0
  }
981
982
0
  ret = 0;
983
984
0
error:
985
0
  return ret;
986
0
}
987
988
/* Decodes an RSA-PSS privateKey from a PKCS8 structure.
989
 */
990
static int _decode_pkcs8_rsa_pss_key(asn1_node pkcs8_asn,
991
             gnutls_x509_privkey_t pkey)
992
0
{
993
0
  int ret;
994
0
  gnutls_datum_t tmp = { NULL, 0 };
995
0
  gnutls_x509_spki_st params;
996
997
0
  memset(&params, 0, sizeof(params));
998
999
0
  ret = _gnutls_x509_read_value(pkcs8_asn,
1000
0
              "privateKeyAlgorithm.parameters", &tmp);
1001
0
  if (ret < 0) {
1002
0
    if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||
1003
0
        ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1004
0
      goto skip_params;
1005
1006
0
    gnutls_assert();
1007
0
    goto error;
1008
0
  }
1009
1010
0
  ret = _gnutls_x509_read_rsa_pss_params(tmp.data, tmp.size, &params);
1011
0
  _gnutls_free_key_datum(&tmp);
1012
1013
0
  if (ret < 0) {
1014
0
    gnutls_assert();
1015
0
    goto error;
1016
0
  }
1017
1018
0
skip_params:
1019
0
  ret = _decode_pkcs8_rsa_key(pkcs8_asn, pkey);
1020
0
  if (ret < 0) {
1021
0
    gnutls_assert();
1022
0
    goto error;
1023
0
  }
1024
1025
0
  pkey->params.algo = GNUTLS_PK_RSA_PSS;
1026
0
  ret = _gnutls_x509_spki_copy(&pkey->params.spki, &params);
1027
0
  if (ret < 0) {
1028
0
    gnutls_assert();
1029
0
    goto error;
1030
0
  }
1031
1032
0
  ret = 0;
1033
1034
0
error:
1035
0
  return ret;
1036
0
}
1037
1038
/* Decodes an RSA-OAEP privateKey from a PKCS8 structure.
1039
 */
1040
static int _decode_pkcs8_rsa_oaep_key(asn1_node pkcs8_asn,
1041
              gnutls_x509_privkey_t pkey)
1042
0
{
1043
0
  int ret;
1044
0
  gnutls_datum_t tmp = { NULL, 0 };
1045
0
  gnutls_x509_spki_st params;
1046
1047
0
  memset(&params, 0, sizeof(params));
1048
1049
0
  ret = _gnutls_x509_read_value(pkcs8_asn,
1050
0
              "privateKeyAlgorithm.parameters", &tmp);
1051
0
  if (ret < 0) {
1052
0
    if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||
1053
0
        ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1054
0
      goto skip_params;
1055
1056
0
    gnutls_assert();
1057
0
    goto error;
1058
0
  }
1059
1060
0
  ret = _gnutls_x509_read_rsa_oaep_params(tmp.data, tmp.size, &params);
1061
0
  _gnutls_free_key_datum(&tmp);
1062
1063
0
  if (ret < 0) {
1064
0
    gnutls_assert();
1065
0
    goto error;
1066
0
  }
1067
1068
0
skip_params:
1069
0
  ret = _decode_pkcs8_rsa_key(pkcs8_asn, pkey);
1070
0
  if (ret < 0) {
1071
0
    gnutls_assert();
1072
0
    goto error;
1073
0
  }
1074
1075
0
  pkey->params.algo = GNUTLS_PK_RSA_OAEP;
1076
  /* Take ownership of allocated members of params */
1077
0
  pkey->params.spki = params;
1078
1079
0
  ret = 0;
1080
1081
0
error:
1082
0
  return ret;
1083
0
}
1084
1085
/* Decodes an ECC privateKey from a PKCS8 structure.
1086
 */
1087
static int _decode_pkcs8_ecc_key(asn1_node pkcs8_asn,
1088
         gnutls_x509_privkey_t pkey)
1089
0
{
1090
0
  int ret;
1091
0
  gnutls_datum_t tmp = { NULL, 0 };
1092
0
  unsigned char oid[MAX_OID_SIZE];
1093
0
  unsigned curve = GNUTLS_ECC_CURVE_INVALID;
1094
0
  int len, result;
1095
1096
  /* openssl PKCS #8 files with ECC keys place the curve in
1097
   * privateKeyAlgorithm.parameters instead of the ECPrivateKey.parameters.
1098
   */
1099
0
  len = sizeof(oid);
1100
0
  result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters",
1101
0
         oid, &len);
1102
0
  if (result == ASN1_SUCCESS) {
1103
0
    ret = _gnutls_x509_read_ecc_params(oid, len, &curve);
1104
0
    if (ret < 0) {
1105
0
      _gnutls_debug_log("PKCS#8: unknown curve OID %s\n",
1106
0
            oid);
1107
0
      curve = GNUTLS_ECC_CURVE_INVALID;
1108
0
    }
1109
0
  }
1110
1111
0
  ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
1112
0
  if (ret < 0) {
1113
0
    gnutls_assert();
1114
0
    goto error;
1115
0
  }
1116
1117
0
  ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey, curve);
1118
0
  _gnutls_free_key_datum(&tmp);
1119
1120
0
  if (ret < 0) {
1121
0
    gnutls_assert();
1122
0
    goto error;
1123
0
  }
1124
1125
0
  ret = 0;
1126
1127
0
error:
1128
0
  return ret;
1129
0
}
1130
1131
static int _decode_pkcs8_eddsa_key(asn1_node pkcs8_asn,
1132
           gnutls_x509_privkey_t pkey, const char *oid)
1133
0
{
1134
0
  int ret;
1135
0
  gnutls_datum_t tmp;
1136
0
  gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID;
1137
0
  const gnutls_ecc_curve_entry_st *ce;
1138
1139
0
  gnutls_pk_params_init(&pkey->params);
1140
1141
0
  curve = gnutls_oid_to_ecc_curve(oid);
1142
0
  if (curve == GNUTLS_ECC_CURVE_INVALID) {
1143
0
    _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid);
1144
0
    return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1145
0
  }
1146
1147
0
  ce = _gnutls_ecc_curve_get_params(curve);
1148
0
  if (_curve_is_eddsa(ce)) {
1149
0
    ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp,
1150
0
                 ASN1_ETYPE_OCTET_STRING, 1);
1151
0
    if (ret < 0) {
1152
0
      gnutls_assert();
1153
0
      return gnutls_assert_val(ret);
1154
0
    }
1155
1156
0
    if (tmp.size != ce->size) {
1157
0
      gnutls_free(tmp.data);
1158
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
1159
0
    }
1160
0
    gnutls_free(pkey->params.raw_priv.data);
1161
0
    switch (curve) {
1162
0
    case GNUTLS_ECC_CURVE_ED25519:
1163
0
      pkey->params.algo = GNUTLS_PK_EDDSA_ED25519;
1164
0
      break;
1165
0
    case GNUTLS_ECC_CURVE_ED448:
1166
0
      pkey->params.algo = GNUTLS_PK_EDDSA_ED448;
1167
0
      break;
1168
0
    default:
1169
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1170
0
    }
1171
0
    pkey->params.raw_priv.data = tmp.data;
1172
0
    pkey->params.raw_priv.size = tmp.size;
1173
0
    pkey->params.curve = curve;
1174
1175
0
    tmp.data = NULL;
1176
0
    return 0;
1177
0
  } else {
1178
0
    return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1179
0
  }
1180
0
}
1181
1182
static int _decode_pkcs8_modern_ecdh_key(asn1_node pkcs8_asn,
1183
           gnutls_x509_privkey_t pkey,
1184
           const char *oid)
1185
0
{
1186
0
  int ret;
1187
0
  gnutls_datum_t tmp;
1188
0
  gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID;
1189
0
  const gnutls_ecc_curve_entry_st *ce;
1190
1191
0
  gnutls_pk_params_init(&pkey->params);
1192
1193
0
  curve = gnutls_oid_to_ecc_curve(oid);
1194
0
  if (curve == GNUTLS_ECC_CURVE_INVALID) {
1195
0
    _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid);
1196
0
    return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1197
0
  }
1198
1199
0
  ce = _gnutls_ecc_curve_get_params(curve);
1200
0
  if (_curve_is_modern_ecdh(ce)) {
1201
0
    ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp,
1202
0
                 ASN1_ETYPE_OCTET_STRING, 1);
1203
0
    if (ret < 0) {
1204
0
      gnutls_assert();
1205
0
      return gnutls_assert_val(ret);
1206
0
    }
1207
1208
0
    if (tmp.size != ce->size) {
1209
0
      gnutls_free(tmp.data);
1210
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
1211
0
    }
1212
0
    gnutls_free(pkey->params.raw_priv.data);
1213
0
    switch (curve) {
1214
0
    case GNUTLS_ECC_CURVE_X25519:
1215
0
      pkey->params.algo = GNUTLS_PK_ECDH_X25519;
1216
0
      break;
1217
0
    case GNUTLS_ECC_CURVE_X448:
1218
0
      pkey->params.algo = GNUTLS_PK_ECDH_X448;
1219
0
      break;
1220
0
    default:
1221
0
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1222
0
    }
1223
0
    pkey->params.raw_priv.data = tmp.data;
1224
0
    pkey->params.raw_priv.size = tmp.size;
1225
0
    pkey->params.curve = curve;
1226
1227
0
    tmp.data = NULL;
1228
0
    return 0;
1229
0
  } else {
1230
0
    return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1231
0
  }
1232
0
}
1233
1234
/* Converts a GOST key to
1235
 * an internal structure (gnutls_private_key)
1236
 */
1237
static int _privkey_decode_gost_key(const gnutls_datum_t *raw_key,
1238
            gnutls_x509_privkey_t pkey)
1239
0
{
1240
0
  int ret;
1241
0
  int ecc_size = gnutls_ecc_curve_get_size(pkey->params.curve);
1242
1243
  /* Just to be sure here */
1244
0
  if (ecc_size <= 0) {
1245
0
    gnutls_assert();
1246
0
    ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
1247
0
    goto error;
1248
0
  }
1249
1250
  /* Private key form described in R 50.1.112-2016.
1251
   * Private key can come up as masked value concatenated with several masks.
1252
   * each part is of ecc_size bytes. Key will be unmasked in pk_fixup */
1253
0
  if (raw_key->size % ecc_size == 0) {
1254
0
    ret = _gnutls_mpi_init_scan_le(&pkey->params.params[GOST_K],
1255
0
                 raw_key->data, raw_key->size);
1256
0
    if (ret < 0) {
1257
0
      gnutls_assert();
1258
0
      goto error;
1259
0
    }
1260
0
  } else if (raw_key->data[0] == ASN1_TAG_INTEGER) {
1261
0
    asn1_node pkey_asn;
1262
1263
    /* Very old format: INTEGER packed in OCTET STRING */
1264
0
    if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
1265
0
                 "GNUTLS.GOSTPrivateKeyOld",
1266
0
                 &pkey_asn)) != ASN1_SUCCESS) {
1267
0
      gnutls_assert();
1268
0
      ret = _gnutls_asn2err(ret);
1269
0
      goto error;
1270
0
    }
1271
1272
0
    ret = _asn1_strict_der_decode(&pkey_asn, raw_key->data,
1273
0
                raw_key->size, NULL);
1274
0
    if (ret != ASN1_SUCCESS) {
1275
0
      gnutls_assert();
1276
0
      ret = _gnutls_asn2err(ret);
1277
0
      asn1_delete_structure2(&pkey_asn,
1278
0
                 ASN1_DELETE_FLAG_ZEROIZE);
1279
0
      goto error;
1280
0
    }
1281
1282
0
    ret = _gnutls_x509_read_key_int(pkey_asn, "",
1283
0
            &pkey->params.params[GOST_K]);
1284
0
    if (ret < 0) {
1285
0
      gnutls_assert();
1286
0
      asn1_delete_structure2(&pkey_asn,
1287
0
                 ASN1_DELETE_FLAG_ZEROIZE);
1288
0
      goto error;
1289
0
    }
1290
0
    asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
1291
0
  } else if (raw_key->data[0] == ASN1_TAG_OCTET_STRING) {
1292
0
    asn1_node pkey_asn;
1293
1294
    /* format: OCTET STRING packed in OCTET STRING */
1295
0
    if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
1296
0
                 "GNUTLS.GOSTPrivateKey",
1297
0
                 &pkey_asn)) != ASN1_SUCCESS) {
1298
0
      gnutls_assert();
1299
0
      ret = _gnutls_asn2err(ret);
1300
0
      goto error;
1301
0
    }
1302
1303
0
    ret = _asn1_strict_der_decode(&pkey_asn, raw_key->data,
1304
0
                raw_key->size, NULL);
1305
0
    if (ret != ASN1_SUCCESS) {
1306
0
      gnutls_assert();
1307
0
      ret = _gnutls_asn2err(ret);
1308
0
      asn1_delete_structure2(&pkey_asn,
1309
0
                 ASN1_DELETE_FLAG_ZEROIZE);
1310
0
      goto error;
1311
0
    }
1312
1313
0
    ret = _gnutls_x509_read_key_int_le(
1314
0
      pkey_asn, "", &pkey->params.params[GOST_K]);
1315
0
    if (ret < 0) {
1316
0
      gnutls_assert();
1317
0
      asn1_delete_structure2(&pkey_asn,
1318
0
                 ASN1_DELETE_FLAG_ZEROIZE);
1319
0
      goto error;
1320
0
    }
1321
0
    asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
1322
0
  } else {
1323
0
    gnutls_assert();
1324
0
    ret = GNUTLS_E_PARSING_ERROR;
1325
0
    goto error;
1326
0
  }
1327
1328
0
  pkey->params.params_nr++;
1329
1330
0
  return 0;
1331
1332
0
error:
1333
0
  return ret;
1334
0
}
1335
1336
/* Decodes a GOST privateKey from a PKCS8 structure.
1337
 */
1338
static int _decode_pkcs8_gost_key(asn1_node pkcs8_asn,
1339
          gnutls_x509_privkey_t pkey,
1340
          gnutls_pk_algorithm_t algo)
1341
0
{
1342
0
  int ret;
1343
0
  gnutls_datum_t tmp;
1344
0
  unsigned char
1345
0
    oid[3 *
1346
0
        MAX_OID_SIZE]; /* GOST parameters can have 3 OIDs at most */
1347
0
  int len, result;
1348
1349
0
  gnutls_pk_params_init(&pkey->params);
1350
1351
0
  len = sizeof(oid);
1352
0
  result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters",
1353
0
         oid, &len);
1354
0
  if (result != ASN1_SUCCESS) {
1355
0
    gnutls_assert();
1356
0
    ret = GNUTLS_E_PARSING_ERROR;
1357
0
    goto error;
1358
0
  } else {
1359
0
    ret = _gnutls_x509_read_gost_params(oid, len, &pkey->params,
1360
0
                algo);
1361
0
    if (ret < 0) {
1362
0
      gnutls_assert();
1363
0
      goto error;
1364
0
    }
1365
0
  }
1366
1367
  /* Will be fixed later by pk_fixup */
1368
0
  ret = _gnutls_mpi_init(&pkey->params.params[GOST_X]);
1369
0
  if (ret < 0) {
1370
0
    gnutls_assert();
1371
0
    goto error;
1372
0
  }
1373
0
  pkey->params.params_nr++;
1374
1375
0
  ret = _gnutls_mpi_init(&pkey->params.params[GOST_Y]);
1376
0
  if (ret < 0) {
1377
0
    gnutls_assert();
1378
0
    goto error;
1379
0
  }
1380
0
  pkey->params.params_nr++;
1381
1382
0
  _gnutls_mpi_set_ui(pkey->params.params[GOST_X], 0);
1383
0
  _gnutls_mpi_set_ui(pkey->params.params[GOST_Y], 0);
1384
1385
0
  ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
1386
0
  if (ret < 0) {
1387
0
    gnutls_assert();
1388
0
    goto error;
1389
0
  }
1390
1391
0
  ret = _privkey_decode_gost_key(&tmp, pkey);
1392
0
  _gnutls_free_key_datum(&tmp);
1393
1394
0
  if (ret < 0) {
1395
0
    gnutls_assert();
1396
0
    goto error;
1397
0
  }
1398
1399
0
  pkey->params.algo = algo;
1400
1401
0
  return 0;
1402
1403
0
error:
1404
0
  gnutls_pk_params_clear(&pkey->params);
1405
0
  gnutls_pk_params_release(&pkey->params);
1406
1407
0
  return ret;
1408
0
}
1409
1410
/* Decodes an DSA privateKey and params from a PKCS8 structure.
1411
 */
1412
static int _decode_pkcs8_dsa_key(asn1_node pkcs8_asn,
1413
         gnutls_x509_privkey_t pkey)
1414
0
{
1415
0
  int ret;
1416
0
  gnutls_datum_t tmp = { NULL, 0 };
1417
1418
0
  gnutls_pk_params_init(&pkey->params);
1419
1420
0
  ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
1421
0
  if (ret < 0) {
1422
0
    gnutls_assert();
1423
0
    goto error;
1424
0
  }
1425
1426
0
  ret = _gnutls_x509_read_der_int(tmp.data, tmp.size,
1427
0
          &pkey->params.params[4]);
1428
0
  _gnutls_free_key_datum(&tmp);
1429
1430
0
  if (ret < 0) {
1431
0
    gnutls_assert();
1432
0
    goto error;
1433
0
  }
1434
1435
0
  ret = _gnutls_x509_read_value(pkcs8_asn,
1436
0
              "privateKeyAlgorithm.parameters", &tmp);
1437
0
  if (ret < 0) {
1438
0
    gnutls_assert();
1439
0
    goto error;
1440
0
  }
1441
1442
0
  ret = _gnutls_x509_read_pubkey_params(GNUTLS_PK_DSA, tmp.data, tmp.size,
1443
0
                &pkey->params);
1444
0
  _gnutls_free_datum(&tmp);
1445
0
  if (ret < 0) {
1446
0
    gnutls_assert();
1447
0
    goto error;
1448
0
  }
1449
1450
0
  if (_gnutls_mpi_cmp_ui(pkey->params.params[0], 0) == 0) {
1451
0
    gnutls_assert();
1452
0
    ret = GNUTLS_E_ILLEGAL_PARAMETER;
1453
0
    goto error;
1454
0
  }
1455
1456
  /* the public key can be generated as g^x mod p */
1457
0
  ret = _gnutls_mpi_init(&pkey->params.params[3]);
1458
0
  if (ret < 0) {
1459
0
    gnutls_assert();
1460
0
    goto error;
1461
0
  }
1462
1463
0
  ret = _gnutls_mpi_powm(pkey->params.params[3], pkey->params.params[2],
1464
0
             pkey->params.params[4], pkey->params.params[0]);
1465
0
  if (ret < 0) {
1466
0
    gnutls_assert();
1467
0
    goto error;
1468
0
  }
1469
1470
0
  pkey->params.algo = GNUTLS_PK_DSA;
1471
0
  pkey->params.params_nr = DSA_PRIVATE_PARAMS;
1472
1473
0
  ret = _gnutls_asn1_encode_privkey(&pkey->key, &pkey->params);
1474
0
  if (ret < 0) {
1475
0
    gnutls_assert();
1476
0
    goto error;
1477
0
  }
1478
1479
0
  return 0;
1480
1481
0
error:
1482
0
  if (pkey->params.params_nr != DSA_PRIVATE_PARAMS)
1483
0
    _gnutls_mpi_release(&pkey->params.params[4]);
1484
0
  return ret;
1485
0
}
1486
1487
static int _decode_pkcs8_ml_dsa_key(asn1_node pkcs8_asn,
1488
            gnutls_x509_privkey_t pkey,
1489
            gnutls_pk_algorithm_t algo)
1490
0
{
1491
0
  int ret;
1492
0
  size_t raw_pub_size, raw_priv_size;
1493
1494
0
  switch (algo) {
1495
0
  case GNUTLS_PK_MLDSA44:
1496
0
    raw_priv_size = MLDSA44_PRIVKEY_SIZE;
1497
0
    raw_pub_size = MLDSA44_PUBKEY_SIZE;
1498
0
    break;
1499
0
  case GNUTLS_PK_MLDSA65:
1500
0
    raw_priv_size = MLDSA65_PRIVKEY_SIZE;
1501
0
    raw_pub_size = MLDSA65_PUBKEY_SIZE;
1502
0
    break;
1503
0
  case GNUTLS_PK_MLDSA87:
1504
0
    raw_priv_size = MLDSA87_PRIVKEY_SIZE;
1505
0
    raw_pub_size = MLDSA87_PUBKEY_SIZE;
1506
0
    break;
1507
0
  default:
1508
0
    return gnutls_assert_val(
1509
0
      GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
1510
0
  }
1511
1512
  /* TODO: support OneAsymmetricKey to read public key from a
1513
   * separate field
1514
   */
1515
1516
0
  gnutls_pk_params_init(&pkey->params);
1517
0
  pkey->params.algo = algo;
1518
1519
0
  ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey",
1520
0
               &pkey->params.raw_priv,
1521
0
               ASN1_ETYPE_OCTET_STRING, 1);
1522
0
  if (ret < 0) {
1523
0
    gnutls_assert();
1524
0
    goto error;
1525
0
  }
1526
1527
0
  if (pkey->params.raw_priv.size != raw_priv_size + raw_pub_size) {
1528
0
    ret = gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR);
1529
0
    goto error;
1530
0
  }
1531
1532
0
  ret = _gnutls_set_datum(&pkey->params.raw_pub,
1533
0
        &pkey->params.raw_priv.data[raw_priv_size],
1534
0
        raw_pub_size);
1535
0
  if (ret < 0) {
1536
0
    gnutls_assert();
1537
0
    goto error;
1538
0
  }
1539
1540
0
  pkey->params.raw_priv.size = raw_priv_size;
1541
1542
0
  return GNUTLS_E_SUCCESS;
1543
1544
0
error:
1545
0
  gnutls_pk_params_clear(&pkey->params);
1546
0
  gnutls_pk_params_release(&pkey->params);
1547
1548
0
  return ret;
1549
0
}
1550
1551
static int decode_private_key_info(const gnutls_datum_t *der,
1552
           gnutls_x509_privkey_t pkey)
1553
0
{
1554
0
  int result, len;
1555
0
  char oid[MAX_OID_SIZE];
1556
0
  asn1_node pkcs8_asn = NULL;
1557
0
  gnutls_datum_t sder;
1558
0
  int ret;
1559
1560
0
  if ((result = asn1_create_element(_gnutls_get_pkix(),
1561
0
            "PKIX1.pkcs-8-PrivateKeyInfo",
1562
0
            &pkcs8_asn)) != ASN1_SUCCESS) {
1563
0
    gnutls_assert();
1564
0
    result = _gnutls_asn2err(result);
1565
0
    goto error;
1566
0
  }
1567
1568
0
  result =
1569
0
    _asn1_strict_der_decode(&pkcs8_asn, der->data, der->size, NULL);
1570
0
  if (result != ASN1_SUCCESS) {
1571
0
    gnutls_assert();
1572
0
    result = _gnutls_asn2err(result);
1573
0
    goto error;
1574
0
  }
1575
1576
  /* Check the private key algorithm OID
1577
   */
1578
0
  len = sizeof(oid);
1579
0
  result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.algorithm",
1580
0
         oid, &len);
1581
0
  if (result != ASN1_SUCCESS) {
1582
0
    gnutls_assert();
1583
0
    result = _gnutls_asn2err(result);
1584
0
    goto error;
1585
0
  }
1586
1587
0
  pkey->params.algo = gnutls_oid_to_pk(oid);
1588
0
  if (pkey->params.algo == GNUTLS_PK_UNKNOWN) {
1589
0
    gnutls_assert();
1590
0
    _gnutls_debug_log(
1591
0
      "PKCS #8 private key OID '%s' is unsupported.\n", oid);
1592
0
    result = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
1593
0
    goto error;
1594
0
  }
1595
1596
  /* Get the DER encoding of the actual private key.
1597
   */
1598
1599
0
  switch (pkey->params.algo) {
1600
0
  case GNUTLS_PK_RSA:
1601
0
    result = _decode_pkcs8_rsa_key(pkcs8_asn, pkey);
1602
0
    break;
1603
0
  case GNUTLS_PK_RSA_PSS:
1604
0
    result = _decode_pkcs8_rsa_pss_key(pkcs8_asn, pkey);
1605
0
    break;
1606
0
  case GNUTLS_PK_RSA_OAEP:
1607
0
    result = _decode_pkcs8_rsa_oaep_key(pkcs8_asn, pkey);
1608
0
    break;
1609
0
  case GNUTLS_PK_DSA:
1610
0
    result = _decode_pkcs8_dsa_key(pkcs8_asn, pkey);
1611
0
    break;
1612
0
  case GNUTLS_PK_ECDSA:
1613
0
    result = _decode_pkcs8_ecc_key(pkcs8_asn, pkey);
1614
0
    break;
1615
0
  case GNUTLS_PK_EDDSA_ED25519:
1616
0
  case GNUTLS_PK_EDDSA_ED448:
1617
0
    result = _decode_pkcs8_eddsa_key(pkcs8_asn, pkey, oid);
1618
0
    break;
1619
0
  case GNUTLS_PK_ECDH_X25519:
1620
0
  case GNUTLS_PK_ECDH_X448:
1621
0
    result = _decode_pkcs8_modern_ecdh_key(pkcs8_asn, pkey, oid);
1622
0
    break;
1623
0
  case GNUTLS_PK_GOST_01:
1624
0
  case GNUTLS_PK_GOST_12_256:
1625
0
  case GNUTLS_PK_GOST_12_512:
1626
0
    result = _decode_pkcs8_gost_key(pkcs8_asn, pkey,
1627
0
            pkey->params.algo);
1628
0
    break;
1629
0
  case GNUTLS_PK_MLDSA44:
1630
0
  case GNUTLS_PK_MLDSA65:
1631
0
  case GNUTLS_PK_MLDSA87:
1632
0
    result = _decode_pkcs8_ml_dsa_key(pkcs8_asn, pkey,
1633
0
              pkey->params.algo);
1634
0
    break;
1635
0
  default:
1636
0
    result = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1637
0
    goto error;
1638
0
  }
1639
1640
0
  if (result < 0) {
1641
0
    gnutls_assert();
1642
0
    goto error;
1643
0
  }
1644
1645
  /* check for provable parameters attribute */
1646
0
  ret = _x509_parse_attribute(pkcs8_asn, "attributes", OID_ATTR_PROV_SEED,
1647
0
            0, 1, &sder);
1648
0
  if (ret >= 0) { /* ignore it when not being present */
1649
0
    ret = _x509_decode_provable_seed(pkey, &sder);
1650
0
    gnutls_free(sder.data);
1651
0
    if (ret < 0) {
1652
0
      gnutls_assert();
1653
0
    }
1654
0
  }
1655
1656
0
  result = 0;
1657
1658
0
error:
1659
0
  asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
1660
0
  return result;
1661
0
}
1662
1663
/**
1664
 * gnutls_x509_privkey_import_pkcs8:
1665
 * @key: The data to store the parsed key
1666
 * @data: The DER or PEM encoded key.
1667
 * @format: One of DER or PEM
1668
 * @password: the password to decrypt the key (if it is encrypted).
1669
 * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted.
1670
 *
1671
 * This function will convert the given DER or PEM encoded PKCS8 2.0
1672
 * encrypted key to the native gnutls_x509_privkey_t format. The
1673
 * output will be stored in @key.  Both RSA and DSA keys can be
1674
 * imported, and flags can only be used to indicate an unencrypted
1675
 * key.
1676
 *
1677
 * The @password can be either ASCII or UTF-8 in the default PBES2
1678
 * encryption schemas, or ASCII for the PKCS12 schemas.
1679
 *
1680
 * If the Certificate is PEM encoded it should have a header of
1681
 * "ENCRYPTED PRIVATE KEY", or "PRIVATE KEY". You only need to
1682
 * specify the flags if the key is DER encoded, since in that case
1683
 * the encryption status cannot be auto-detected.
1684
 *
1685
 * If the %GNUTLS_PKCS_PLAIN flag is specified and the supplied data
1686
 * are encrypted then %GNUTLS_E_DECRYPTION_FAILED is returned.
1687
 *
1688
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1689
 *   negative error value.
1690
 **/
1691
int gnutls_x509_privkey_import_pkcs8(gnutls_x509_privkey_t key,
1692
             const gnutls_datum_t *data,
1693
             gnutls_x509_crt_fmt_t format,
1694
             const char *password, unsigned int flags)
1695
0
{
1696
0
  int result = 0, need_free = 0;
1697
0
  gnutls_datum_t _data;
1698
1699
0
  if (key == NULL) {
1700
0
    gnutls_assert();
1701
0
    return GNUTLS_E_INVALID_REQUEST;
1702
0
  }
1703
1704
0
  _data.data = data->data;
1705
0
  _data.size = data->size;
1706
1707
0
  key->params.algo = GNUTLS_PK_UNKNOWN;
1708
1709
  /* If the Certificate is in PEM format then decode it
1710
   */
1711
0
  if (format == GNUTLS_X509_FMT_PEM) {
1712
    /* Try the first header 
1713
     */
1714
0
    result = _gnutls_fbase64_decode(PEM_UNENCRYPTED_PKCS8,
1715
0
            data->data, data->size, &_data);
1716
1717
0
    if (result < 0) { /* Try the encrypted header 
1718
           */
1719
0
      result = _gnutls_fbase64_decode(PEM_PKCS8, data->data,
1720
0
              data->size, &_data);
1721
1722
0
      if (result < 0) {
1723
0
        gnutls_assert();
1724
0
        return result;
1725
0
      }
1726
0
    } else if (flags == 0)
1727
0
      flags |= GNUTLS_PKCS_PLAIN;
1728
1729
0
    need_free = 1;
1730
0
  }
1731
1732
0
  if (key->expanded) {
1733
0
    _gnutls_x509_privkey_reinit(key);
1734
0
  }
1735
0
  key->expanded = 1;
1736
1737
  /* Here we don't check for password == NULL to maintain a backwards
1738
   * compatibility behavior, with old versions that were encrypting using
1739
   * a NULL password.
1740
   */
1741
0
  if (flags & GNUTLS_PKCS_PLAIN) {
1742
0
    result = decode_private_key_info(&_data, key);
1743
0
    if (result < 0) { /* check if it is encrypted */
1744
0
      if (pkcs8_key_decode(&_data, "", key, 0) == 0)
1745
0
        result = GNUTLS_E_DECRYPTION_FAILED;
1746
0
    }
1747
0
  } else { /* encrypted. */
1748
0
    result = pkcs8_key_decode(&_data, password, key, 1);
1749
0
  }
1750
1751
0
  if (result < 0) {
1752
0
    gnutls_assert();
1753
0
    goto cleanup;
1754
0
  }
1755
1756
  /* This part is necessary to get the public key on certain algorithms.
1757
   * In the import above we only get the private key. */
1758
0
  result =
1759
0
    _gnutls_pk_fixup(key->params.algo, GNUTLS_IMPORT, &key->params);
1760
0
  if (result < 0) {
1761
0
    gnutls_assert();
1762
0
    goto cleanup;
1763
0
  }
1764
1765
0
  if (need_free)
1766
0
    _gnutls_free_datum(&_data);
1767
1768
  /* The key has now been decoded.
1769
   */
1770
0
  return 0;
1771
1772
0
cleanup:
1773
0
  asn1_delete_structure2(&key->key, ASN1_DELETE_FLAG_ZEROIZE);
1774
0
  key->params.algo = GNUTLS_PK_UNKNOWN;
1775
0
  if (need_free) {
1776
0
    zeroize_temp_key(_data.data, _data.size);
1777
0
    _gnutls_free_datum(&_data);
1778
0
  }
1779
0
  return result;
1780
0
}