Coverage Report

Created: 2025-07-23 07:18

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