Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/x509/privkey.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2012-2016 Nikos Mavrogiannopoulos
4
 * Copyright (C) 2015-2017 Red Hat, Inc.
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
#include <datum.h>
27
#include <global.h>
28
#include "errors.h"
29
#include <tls-sig.h>
30
#include <common.h>
31
#include <x509.h>
32
#include <x509_b64.h>
33
#include <x509_int.h>
34
#include <pk.h>
35
#include <mpi.h>
36
#include <ecc.h>
37
#include <pin.h>
38
39
/**
40
 * gnutls_x509_privkey_init:
41
 * @key: A pointer to the type to be initialized
42
 *
43
 * This function will initialize a private key type.
44
 *
45
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
46
 *   negative error value.
47
 **/
48
int gnutls_x509_privkey_init(gnutls_x509_privkey_t * key)
49
0
{
50
0
  *key = NULL;
51
0
  FAIL_IF_LIB_ERROR;
52
53
0
  *key = gnutls_calloc(1, sizeof(gnutls_x509_privkey_int));
54
55
0
  if (*key) {
56
0
    (*key)->key = NULL;
57
0
    return 0; /* success */
58
0
  }
59
60
0
  return GNUTLS_E_MEMORY_ERROR;
61
0
}
62
63
void _gnutls_x509_privkey_reinit(gnutls_x509_privkey_t key)
64
0
{
65
0
  gnutls_pk_params_clear(&key->params);
66
0
  gnutls_pk_params_release(&key->params);
67
  /* avoid re-use of fields which may have had some sensible value */
68
0
  zeroize_key(&key->params, sizeof(key->params));
69
70
0
  if (key->key)
71
0
    asn1_delete_structure2(&key->key, ASN1_DELETE_FLAG_ZEROIZE);
72
0
  key->key = NULL;
73
0
}
74
75
/**
76
 * gnutls_x509_privkey_deinit:
77
 * @key: The key to be deinitialized
78
 *
79
 * This function will deinitialize a private key structure.
80
 **/
81
void gnutls_x509_privkey_deinit(gnutls_x509_privkey_t key)
82
0
{
83
0
  if (!key)
84
0
    return;
85
86
0
  _gnutls_x509_privkey_reinit(key);
87
0
  gnutls_free(key);
88
0
}
89
90
/**
91
 * gnutls_x509_privkey_cpy:
92
 * @dst: The destination key, which should be initialized.
93
 * @src: The source key
94
 *
95
 * This function will copy a private key from source to destination
96
 * key. Destination has to be initialized.
97
 *
98
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
99
 *   negative error value.
100
 **/
101
int
102
gnutls_x509_privkey_cpy(gnutls_x509_privkey_t dst, gnutls_x509_privkey_t src)
103
0
{
104
0
  int ret;
105
106
0
  if (!src || !dst)
107
0
    return GNUTLS_E_INVALID_REQUEST;
108
109
0
  ret = _gnutls_pk_params_copy(&dst->params, &src->params);
110
0
  if (ret < 0) {
111
0
    return gnutls_assert_val(ret);
112
0
  }
113
114
0
  ret = _gnutls_asn1_encode_privkey(&dst->key, &dst->params);
115
0
  if (ret < 0) {
116
0
    gnutls_assert();
117
0
    gnutls_pk_params_release(&dst->params);
118
0
    return ret;
119
0
  }
120
121
0
  return 0;
122
0
}
123
124
/* Converts an RSA PKCS#1 key to
125
 * an internal structure (gnutls_private_key)
126
 */
127
asn1_node
128
_gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * raw_key,
129
             gnutls_x509_privkey_t pkey)
130
0
{
131
0
  int result;
132
0
  asn1_node pkey_asn;
133
134
0
  gnutls_pk_params_init(&pkey->params);
135
136
0
  if (asn1_create_element(_gnutls_get_gnutls_asn(),
137
0
        "GNUTLS.RSAPrivateKey",
138
0
        &pkey_asn) != ASN1_SUCCESS) {
139
0
    gnutls_assert();
140
0
    return NULL;
141
0
  }
142
143
0
  result =
144
0
      _asn1_strict_der_decode(&pkey_asn, raw_key->data, raw_key->size,
145
0
            NULL);
146
0
  if (result != ASN1_SUCCESS) {
147
0
    gnutls_assert();
148
0
    goto error;
149
0
  }
150
151
0
  if (_gnutls_x509_read_int(pkey_asn, "modulus",
152
0
          &pkey->params.params[0]) < 0) {
153
0
    gnutls_assert();
154
0
    goto error;
155
0
  }
156
0
  pkey->params.params_nr++;
157
158
0
  if (_gnutls_x509_read_int(pkey_asn, "publicExponent",
159
0
          &pkey->params.params[1]) < 0) {
160
0
    gnutls_assert();
161
0
    goto error;
162
0
  }
163
0
  pkey->params.params_nr++;
164
165
0
  if (_gnutls_x509_read_key_int(pkey_asn, "privateExponent",
166
0
              &pkey->params.params[2]) < 0) {
167
0
    gnutls_assert();
168
0
    goto error;
169
0
  }
170
0
  pkey->params.params_nr++;
171
172
0
  if (_gnutls_x509_read_key_int(pkey_asn, "prime1",
173
0
              &pkey->params.params[3]) < 0) {
174
0
    gnutls_assert();
175
0
    goto error;
176
0
  }
177
0
  pkey->params.params_nr++;
178
179
0
  if (_gnutls_x509_read_key_int(pkey_asn, "prime2",
180
0
              &pkey->params.params[4]) < 0) {
181
0
    gnutls_assert();
182
0
    goto error;
183
0
  }
184
0
  pkey->params.params_nr++;
185
186
0
  if (_gnutls_x509_read_key_int(pkey_asn, "coefficient",
187
0
              &pkey->params.params[5]) < 0) {
188
0
    gnutls_assert();
189
0
    goto error;
190
0
  }
191
0
  pkey->params.params_nr++;
192
193
0
  if (_gnutls_x509_read_key_int(pkey_asn, "exponent1",
194
0
              &pkey->params.params[6]) < 0) {
195
0
    gnutls_assert();
196
0
    goto error;
197
0
  }
198
0
  pkey->params.params_nr++;
199
200
0
  if (_gnutls_x509_read_key_int(pkey_asn, "exponent2",
201
0
              &pkey->params.params[7]) < 0) {
202
0
    gnutls_assert();
203
0
    goto error;
204
0
  }
205
0
  pkey->params.params_nr++;
206
207
0
  pkey->params.params_nr = RSA_PRIVATE_PARAMS;
208
0
  pkey->params.algo = GNUTLS_PK_RSA;
209
210
0
  return pkey_asn;
211
212
0
 error:
213
0
  asn1_delete_structure2(&pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
214
0
  gnutls_pk_params_clear(&pkey->params);
215
0
  gnutls_pk_params_release(&pkey->params);
216
0
  return NULL;
217
0
}
218
219
/* Converts an ECC key to
220
 * an internal structure (gnutls_private_key)
221
 */
222
int
223
_gnutls_privkey_decode_ecc_key(asn1_node * pkey_asn,
224
             const gnutls_datum_t * raw_key,
225
             gnutls_x509_privkey_t pkey,
226
             gnutls_ecc_curve_t curve)
227
0
{
228
0
  int ret;
229
0
  unsigned int version;
230
0
  char oid[MAX_OID_SIZE];
231
0
  int oid_size;
232
0
  gnutls_datum_t out;
233
234
0
  if (curve_is_eddsa(curve)) {
235
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
236
0
  }
237
238
0
  gnutls_pk_params_init(&pkey->params);
239
240
0
  if ((ret =
241
0
       asn1_create_element(_gnutls_get_gnutls_asn(),
242
0
         "GNUTLS.ECPrivateKey",
243
0
         pkey_asn)) != ASN1_SUCCESS) {
244
0
    gnutls_assert();
245
0
    return _gnutls_asn2err(ret);
246
0
  }
247
248
0
  ret =
249
0
      _asn1_strict_der_decode(pkey_asn, raw_key->data, raw_key->size,
250
0
            NULL);
251
0
  if (ret != ASN1_SUCCESS) {
252
0
    gnutls_assert();
253
0
    ret = _gnutls_asn2err(ret);
254
0
    goto error;
255
0
  }
256
257
0
  ret = _gnutls_x509_read_uint(*pkey_asn, "Version", &version);
258
0
  if (ret < 0) {
259
0
    gnutls_assert();
260
0
    goto error;
261
0
  }
262
263
0
  if (version != 1) {
264
0
    _gnutls_debug_log
265
0
        ("ECC private key version %u is not supported\n", version);
266
0
    gnutls_assert();
267
0
    ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
268
0
    goto error;
269
0
  }
270
271
  /* read the curve */
272
0
  if (curve == GNUTLS_ECC_CURVE_INVALID) {
273
0
    oid_size = sizeof(oid);
274
0
    ret =
275
0
        asn1_read_value(*pkey_asn, "parameters.namedCurve", oid,
276
0
            &oid_size);
277
0
    if (ret != ASN1_SUCCESS) {
278
0
      gnutls_assert();
279
0
      ret = _gnutls_asn2err(ret);
280
0
      goto error;
281
0
    }
282
283
0
    pkey->params.curve = gnutls_oid_to_ecc_curve(oid);
284
285
0
    if (pkey->params.curve == GNUTLS_ECC_CURVE_INVALID) {
286
0
      _gnutls_debug_log("Curve %s is not supported\n", oid);
287
0
      gnutls_assert();
288
0
      ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
289
0
      goto error;
290
0
    }
291
0
  } else {
292
0
    pkey->params.curve = curve;
293
0
  }
294
295
  /* read the public key */
296
0
  ret = _gnutls_x509_read_value(*pkey_asn, "publicKey", &out);
297
0
  if (ret < 0) {
298
0
    gnutls_assert();
299
0
    goto error;
300
0
  }
301
302
0
  ret =
303
0
      _gnutls_ecc_ansi_x962_import(out.data, out.size,
304
0
           &pkey->params.params[ECC_X],
305
0
           &pkey->params.params[ECC_Y]);
306
307
0
  _gnutls_free_datum(&out);
308
0
  if (ret < 0) {
309
0
    gnutls_assert();
310
0
    goto error;
311
0
  }
312
0
  pkey->params.params_nr += 2;
313
314
  /* read the private key */
315
0
  ret =
316
0
      _gnutls_x509_read_key_int(*pkey_asn, "privateKey",
317
0
              &pkey->params.params[ECC_K]);
318
0
  if (ret < 0) {
319
0
    gnutls_assert();
320
0
    goto error;
321
0
  }
322
0
  pkey->params.params_nr++;
323
0
  pkey->params.algo = GNUTLS_PK_EC;
324
325
0
  return 0;
326
327
0
 error:
328
0
  asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
329
0
  gnutls_pk_params_clear(&pkey->params);
330
0
  gnutls_pk_params_release(&pkey->params);
331
0
  return ret;
332
333
0
}
334
335
static asn1_node
336
decode_dsa_key(const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey)
337
0
{
338
0
  int result;
339
0
  asn1_node dsa_asn;
340
0
  gnutls_datum_t seed = { NULL, 0 };
341
0
  char oid[MAX_OID_SIZE];
342
0
  int oid_size;
343
344
0
  if (asn1_create_element(_gnutls_get_gnutls_asn(),
345
0
        "GNUTLS.DSAPrivateKey",
346
0
        &dsa_asn) != ASN1_SUCCESS) {
347
0
    gnutls_assert();
348
0
    return NULL;
349
0
  }
350
351
0
  gnutls_pk_params_init(&pkey->params);
352
353
0
  result =
354
0
      _asn1_strict_der_decode(&dsa_asn, raw_key->data, raw_key->size,
355
0
            NULL);
356
0
  if (result != ASN1_SUCCESS) {
357
0
    gnutls_assert();
358
0
    goto error;
359
0
  }
360
361
0
  if (_gnutls_x509_read_int(dsa_asn, "p", &pkey->params.params[0]) < 0) {
362
0
    gnutls_assert();
363
0
    goto error;
364
0
  }
365
0
  pkey->params.params_nr++;
366
367
0
  if (_gnutls_x509_read_int(dsa_asn, "q", &pkey->params.params[1]) < 0) {
368
0
    gnutls_assert();
369
0
    goto error;
370
0
  }
371
0
  pkey->params.params_nr++;
372
373
0
  if (_gnutls_x509_read_int(dsa_asn, "g", &pkey->params.params[2]) < 0) {
374
0
    gnutls_assert();
375
0
    goto error;
376
0
  }
377
0
  pkey->params.params_nr++;
378
379
0
  if (_gnutls_x509_read_int(dsa_asn, "Y", &pkey->params.params[3]) < 0) {
380
0
    gnutls_assert();
381
0
    goto error;
382
0
  }
383
0
  pkey->params.params_nr++;
384
385
0
  if (_gnutls_x509_read_key_int(dsa_asn, "priv",
386
0
              &pkey->params.params[4]) < 0) {
387
0
    gnutls_assert();
388
0
    goto error;
389
0
  }
390
0
  pkey->params.params_nr++;
391
0
  pkey->params.algo = GNUTLS_PK_DSA;
392
393
0
  oid_size = sizeof(oid);
394
0
  result = asn1_read_value(dsa_asn, "seed.algorithm", oid, &oid_size);
395
0
  if (result == ASN1_SUCCESS) {
396
0
    pkey->params.palgo = gnutls_oid_to_digest(oid);
397
398
0
    result = _gnutls_x509_read_value(dsa_asn, "seed.seed", &seed);
399
0
    if (result == ASN1_SUCCESS) {
400
0
      if (seed.size <= sizeof(pkey->params.seed)) {
401
0
        memcpy(pkey->params.seed, seed.data, seed.size);
402
0
        pkey->params.seed_size = seed.size;
403
0
      }
404
0
      gnutls_free(seed.data);
405
0
    }
406
0
  }
407
408
0
  return dsa_asn;
409
410
0
 error:
411
0
  asn1_delete_structure2(&dsa_asn, ASN1_DELETE_FLAG_ZEROIZE);
412
0
  gnutls_pk_params_clear(&pkey->params);
413
0
  gnutls_pk_params_release(&pkey->params);
414
0
  return NULL;
415
416
0
}
417
418
0
#define PEM_KEY_DSA "DSA PRIVATE KEY"
419
0
#define PEM_KEY_RSA "RSA PRIVATE KEY"
420
0
#define PEM_KEY_ECC "EC PRIVATE KEY"
421
0
#define PEM_KEY_PKCS8 "PRIVATE KEY"
422
423
0
#define MAX_PEM_HEADER_SIZE 25
424
425
/**
426
 * gnutls_x509_privkey_import:
427
 * @key: The data to store the parsed key
428
 * @data: The DER or PEM encoded certificate.
429
 * @format: One of DER or PEM
430
 *
431
 * This function will convert the given DER or PEM encoded key to the
432
 * native #gnutls_x509_privkey_t format. The output will be stored in
433
 * @key .
434
 *
435
 * If the key is PEM encoded it should have a header that contains "PRIVATE
436
 * KEY". Note that this function falls back to PKCS #8 decoding without
437
 * password, if the default format fails to import.
438
 *
439
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
440
 *   negative error value.
441
 **/
442
int
443
gnutls_x509_privkey_import(gnutls_x509_privkey_t key,
444
         const gnutls_datum_t * data,
445
         gnutls_x509_crt_fmt_t format)
446
0
{
447
0
  int result = 0, need_free = 0;
448
0
  gnutls_datum_t _data;
449
450
0
  if (key == NULL) {
451
0
    gnutls_assert();
452
0
    return GNUTLS_E_INVALID_REQUEST;
453
0
  }
454
455
0
  _data.data = data->data;
456
0
  _data.size = data->size;
457
458
0
  key->params.algo = GNUTLS_PK_UNKNOWN;
459
460
  /* If the Certificate is in PEM format then decode it
461
   */
462
0
  if (format == GNUTLS_X509_FMT_PEM) {
463
0
    unsigned left;
464
0
    char *ptr;
465
0
    uint8_t *begin_ptr;
466
467
0
    ptr =
468
0
        memmem(data->data, data->size, "PRIVATE KEY-----",
469
0
         sizeof("PRIVATE KEY-----") - 1);
470
471
0
    result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
472
473
0
    if (ptr != NULL) {
474
0
      left =
475
0
          data->size - ((ptrdiff_t)ptr -
476
0
            (ptrdiff_t)data->data);
477
478
0
      if (data->size - left > MAX_PEM_HEADER_SIZE) {
479
0
        ptr -= MAX_PEM_HEADER_SIZE;
480
0
        left += MAX_PEM_HEADER_SIZE;
481
0
      } else {
482
0
        ptr = (char *)data->data;
483
0
        left = data->size;
484
0
      }
485
486
0
      ptr =
487
0
          memmem(ptr, left, "-----BEGIN ",
488
0
           sizeof("-----BEGIN ") - 1);
489
0
      if (ptr != NULL) {
490
0
        begin_ptr = (uint8_t *) ptr;
491
0
        left =
492
0
            data->size - ((ptrdiff_t)begin_ptr -
493
0
              (ptrdiff_t)data->data);
494
495
0
        ptr += sizeof("-----BEGIN ") - 1;
496
497
0
        if (left > sizeof(PEM_KEY_RSA)
498
0
            && memcmp(ptr, PEM_KEY_RSA,
499
0
                sizeof(PEM_KEY_RSA) - 1) == 0) {
500
0
          result =
501
0
              _gnutls_fbase64_decode(PEM_KEY_RSA,
502
0
                   begin_ptr,
503
0
                   left,
504
0
                   &_data);
505
0
          if (result >= 0)
506
0
            key->params.algo =
507
0
                GNUTLS_PK_RSA;
508
0
        } else if (left > sizeof(PEM_KEY_ECC)
509
0
             && memcmp(ptr, PEM_KEY_ECC,
510
0
                 sizeof(PEM_KEY_ECC) - 1) ==
511
0
             0) {
512
0
          result =
513
0
              _gnutls_fbase64_decode(PEM_KEY_ECC,
514
0
                   begin_ptr,
515
0
                   left,
516
0
                   &_data);
517
0
          if (result >= 0)
518
0
            key->params.algo = GNUTLS_PK_EC;
519
0
        } else if (left > sizeof(PEM_KEY_DSA)
520
0
             && memcmp(ptr, PEM_KEY_DSA,
521
0
                 sizeof(PEM_KEY_DSA) - 1) ==
522
0
             0) {
523
0
          result =
524
0
              _gnutls_fbase64_decode(PEM_KEY_DSA,
525
0
                   begin_ptr,
526
0
                   left,
527
0
                   &_data);
528
0
          if (result >= 0)
529
0
            key->params.algo =
530
0
                GNUTLS_PK_DSA;
531
0
        }
532
533
0
        if (key->params.algo == GNUTLS_PK_UNKNOWN
534
0
            && left >= sizeof(PEM_KEY_PKCS8)) {
535
0
          if (memcmp
536
0
              (ptr, PEM_KEY_PKCS8,
537
0
               sizeof(PEM_KEY_PKCS8) - 1) == 0) {
538
0
            result =
539
0
                _gnutls_fbase64_decode
540
0
                (PEM_KEY_PKCS8, begin_ptr,
541
0
                 left, &_data);
542
0
            if (result >= 0) {
543
              /* signal for PKCS #8 keys */
544
0
              key->params.algo = -1;
545
0
            }
546
0
          }
547
0
        }
548
0
      }
549
550
0
    }
551
552
0
    if (result < 0) {
553
0
      gnutls_assert();
554
0
      return result;
555
0
    }
556
557
0
    need_free = 1;
558
0
  }
559
560
0
  if (key->expanded) {
561
0
    _gnutls_x509_privkey_reinit(key);
562
0
  }
563
0
  key->expanded = 1;
564
565
0
  if (key->params.algo == (gnutls_pk_algorithm_t) - 1) {
566
0
    result =
567
0
        gnutls_x509_privkey_import_pkcs8(key, data, format,
568
0
                 NULL, GNUTLS_PKCS_PLAIN);
569
0
    if (result < 0) {
570
0
      gnutls_assert();
571
0
      key->key = NULL;
572
0
      goto cleanup;
573
0
    } else {
574
      /* some keys under PKCS#8 don't set key->key */
575
0
      goto finish;
576
0
    }
577
0
  } else if (key->params.algo == GNUTLS_PK_RSA) {
578
0
    key->key = _gnutls_privkey_decode_pkcs1_rsa_key(&_data, key);
579
0
    if (key->key == NULL)
580
0
      gnutls_assert();
581
0
  } else if (key->params.algo == GNUTLS_PK_DSA) {
582
0
    key->key = decode_dsa_key(&_data, key);
583
0
    if (key->key == NULL)
584
0
      gnutls_assert();
585
0
  } else if (key->params.algo == GNUTLS_PK_EC) {
586
0
    result =
587
0
        _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0);
588
0
    if (result < 0) {
589
0
      gnutls_assert();
590
0
      key->key = NULL;
591
0
    }
592
0
  } else {
593
    /* Try decoding each of the keys, and accept the one that
594
     * succeeds.
595
     */
596
0
    key->params.algo = GNUTLS_PK_RSA;
597
0
    key->key = _gnutls_privkey_decode_pkcs1_rsa_key(&_data, key);
598
599
0
    if (key->key == NULL) {
600
0
      key->params.algo = GNUTLS_PK_DSA;
601
0
      key->key = decode_dsa_key(&_data, key);
602
0
      if (key->key == NULL) {
603
0
        key->params.algo = GNUTLS_PK_EC;
604
0
        result =
605
0
            _gnutls_privkey_decode_ecc_key(&key->key,
606
0
                   &_data, key,
607
0
                   0);
608
0
        if (result < 0) {
609
0
          result =
610
0
              gnutls_x509_privkey_import_pkcs8
611
0
              (key, data, format, NULL,
612
0
               GNUTLS_PKCS_PLAIN);
613
0
          if (result >= 0) {
614
            /* there are keys (ed25519) which leave key->key NULL */
615
0
            goto finish;
616
0
          }
617
618
          /* result < 0 */
619
0
          gnutls_assert();
620
0
          key->key = NULL;
621
622
0
          if (result ==
623
0
              GNUTLS_E_PK_INVALID_PRIVKEY)
624
0
            goto cleanup;
625
0
        }
626
0
      }
627
0
    }
628
0
  }
629
630
0
  if (key->key == NULL) {
631
0
    gnutls_assert();
632
0
    result = GNUTLS_E_ASN1_DER_ERROR;
633
0
    goto cleanup;
634
0
  }
635
636
0
 finish:
637
0
  result =
638
0
      _gnutls_pk_fixup(key->params.algo, GNUTLS_IMPORT, &key->params);
639
0
  if (result < 0) {
640
0
    gnutls_assert();
641
0
  }
642
643
0
 cleanup:
644
0
  if (need_free) {
645
0
    zeroize_temp_key(_data.data, _data.size);
646
0
    _gnutls_free_datum(&_data);
647
0
  }
648
649
  /* The key has now been decoded.
650
   */
651
652
0
  return result;
653
0
}
654
655
static int import_pkcs12_privkey(gnutls_x509_privkey_t key,
656
         const gnutls_datum_t * data,
657
         gnutls_x509_crt_fmt_t format,
658
         const char *password, unsigned int flags)
659
0
{
660
0
  int ret;
661
0
  gnutls_pkcs12_t p12;
662
0
  gnutls_x509_privkey_t newkey;
663
664
0
  ret = gnutls_pkcs12_init(&p12);
665
0
  if (ret < 0)
666
0
    return gnutls_assert_val(ret);
667
668
0
  ret = gnutls_pkcs12_import(p12, data, format, flags);
669
0
  if (ret < 0) {
670
0
    gnutls_assert();
671
0
    goto fail;
672
0
  }
673
674
0
  ret =
675
0
      gnutls_pkcs12_simple_parse(p12, password, &newkey, NULL, NULL,
676
0
               NULL, NULL, NULL, 0);
677
0
  if (ret < 0) {
678
0
    gnutls_assert();
679
0
    goto fail;
680
0
  }
681
682
0
  ret = gnutls_x509_privkey_cpy(key, newkey);
683
0
  gnutls_x509_privkey_deinit(newkey);
684
0
  if (ret < 0) {
685
0
    gnutls_assert();
686
0
    goto fail;
687
0
  }
688
689
0
  ret = 0;
690
0
 fail:
691
692
0
  gnutls_pkcs12_deinit(p12);
693
694
0
  return ret;
695
0
}
696
697
/**
698
 * gnutls_x509_privkey_import2:
699
 * @key: The data to store the parsed key
700
 * @data: The DER or PEM encoded key.
701
 * @format: One of DER or PEM
702
 * @password: A password (optional)
703
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
704
 *
705
 * This function will import the given DER or PEM encoded key, to 
706
 * the native #gnutls_x509_privkey_t format, irrespective of the
707
 * input format. The input format is auto-detected.
708
 *
709
 * The supported formats are basic unencrypted key, PKCS8, PKCS12,
710
 * and the openssl format.
711
 *
712
 * If the provided key is encrypted but no password was given, then
713
 * %GNUTLS_E_DECRYPTION_FAILED is returned. Since GnuTLS 3.4.0 this
714
 * function will utilize the PIN callbacks if any.
715
 *
716
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
717
 *   negative error value.
718
 **/
719
int
720
gnutls_x509_privkey_import2(gnutls_x509_privkey_t key,
721
          const gnutls_datum_t * data,
722
          gnutls_x509_crt_fmt_t format,
723
          const char *password, unsigned int flags)
724
0
{
725
0
  int ret = 0;
726
0
  int saved_ret = GNUTLS_E_PARSING_ERROR;
727
0
  char pin[GNUTLS_PKCS11_MAX_PIN_LEN];
728
0
  unsigned head_enc = 1;
729
730
0
  if (format == GNUTLS_X509_FMT_PEM) {
731
0
    size_t left;
732
0
    char *ptr;
733
734
0
    ptr =
735
0
        memmem(data->data, data->size, "PRIVATE KEY-----",
736
0
         sizeof("PRIVATE KEY-----") - 1);
737
738
0
    if (ptr != NULL) {
739
0
      left =
740
0
          data->size - ((ptrdiff_t)ptr -
741
0
            (ptrdiff_t)data->data);
742
743
0
      if (data->size - left > 15) {
744
0
        ptr -= 15;
745
0
        left += 15;
746
0
      } else {
747
0
        ptr = (char *)data->data;
748
0
        left = data->size;
749
0
      }
750
751
0
      ptr =
752
0
          memmem(ptr, left, "-----BEGIN ",
753
0
           sizeof("-----BEGIN ") - 1);
754
0
      if (ptr != NULL) {
755
0
        ptr += sizeof("-----BEGIN ") - 1;
756
0
        left =
757
0
            data->size - ((ptrdiff_t)ptr -
758
0
              (ptrdiff_t)data->data);
759
0
      }
760
761
0
      if (ptr != NULL && left > sizeof(PEM_KEY_RSA)) {
762
0
        if (memcmp
763
0
            (ptr, PEM_KEY_RSA,
764
0
             sizeof(PEM_KEY_RSA) - 1) == 0
765
0
            || memcmp(ptr, PEM_KEY_ECC,
766
0
                sizeof(PEM_KEY_ECC) - 1) == 0
767
0
            || memcmp(ptr, PEM_KEY_DSA,
768
0
                sizeof(PEM_KEY_DSA) - 1) == 0) {
769
0
          head_enc = 0;
770
0
        }
771
0
      }
772
0
    }
773
0
  }
774
775
0
  if (head_enc == 0
776
0
      || (password == NULL && !(flags & GNUTLS_PKCS_NULL_PASSWORD))) {
777
0
    ret = gnutls_x509_privkey_import(key, data, format);
778
0
    if (ret >= 0)
779
0
      return ret;
780
781
0
    gnutls_assert();
782
0
    saved_ret = ret;
783
    /* fall through to PKCS #8 decoding */
784
0
  }
785
786
0
  if ((password != NULL || (flags & GNUTLS_PKCS_NULL_PASSWORD))
787
0
      || ret < 0) {
788
789
0
    ret =
790
0
        gnutls_x509_privkey_import_pkcs8(key, data, format,
791
0
                 password, flags);
792
793
0
    if (ret == GNUTLS_E_DECRYPTION_FAILED &&
794
0
        password == NULL && (!(flags & GNUTLS_PKCS_PLAIN))) {
795
      /* use the callback if any */
796
0
      ret =
797
0
          _gnutls_retrieve_pin(&key->pin, "key:", "", 0, pin,
798
0
             sizeof(pin));
799
0
      if (ret == 0) {
800
0
        password = pin;
801
0
      }
802
803
0
      ret =
804
0
          gnutls_x509_privkey_import_pkcs8(key, data, format,
805
0
                   password, flags);
806
0
    }
807
808
0
    if (saved_ret == GNUTLS_E_PARSING_ERROR)
809
0
      saved_ret = ret;
810
811
0
    if (ret < 0) {
812
0
      if (ret == GNUTLS_E_DECRYPTION_FAILED)
813
0
        goto cleanup;
814
0
      ret =
815
0
          import_pkcs12_privkey(key, data, format,
816
0
              password, flags);
817
0
      if (ret < 0 && format == GNUTLS_X509_FMT_PEM) {
818
0
        if (ret == GNUTLS_E_DECRYPTION_FAILED)
819
0
          goto cleanup;
820
821
0
        ret =
822
0
            gnutls_x509_privkey_import_openssl(key,
823
0
                       data,
824
0
                       password);
825
826
0
        if (ret == GNUTLS_E_DECRYPTION_FAILED
827
0
            && password == NULL && (key->pin.cb
828
0
                  ||
829
0
                  _gnutls_pin_func)) {
830
          /* use the callback if any */
831
0
          memset(pin, 0,
832
0
                 GNUTLS_PKCS11_MAX_PIN_LEN);
833
0
          ret =
834
0
              _gnutls_retrieve_pin(&key->pin,
835
0
                 "key:", "", 0,
836
0
                 pin,
837
0
                 sizeof(pin));
838
0
          if (ret == 0) {
839
0
            ret =
840
0
                gnutls_x509_privkey_import_openssl
841
0
                (key, data, pin);
842
0
          }
843
0
        }
844
845
0
        if (ret < 0) {
846
0
          gnutls_assert();
847
0
          goto cleanup;
848
0
        }
849
0
      } else {
850
0
        gnutls_assert();
851
0
        goto cleanup;
852
0
      }
853
0
    }
854
0
  }
855
856
0
  ret = 0;
857
858
0
 cleanup:
859
0
  if (ret == GNUTLS_E_PARSING_ERROR)
860
0
    ret = saved_ret;
861
862
0
  return ret;
863
0
}
864
865
/**
866
 * gnutls_x509_privkey_import_rsa_raw:
867
 * @key: The data to store the parsed key
868
 * @m: holds the modulus
869
 * @e: holds the public exponent
870
 * @d: holds the private exponent
871
 * @p: holds the first prime (p)
872
 * @q: holds the second prime (q)
873
 * @u: holds the coefficient
874
 *
875
 * This function will convert the given RSA raw parameters to the
876
 * native #gnutls_x509_privkey_t format.  The output will be stored in
877
 * @key.
878
 *
879
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
880
 *   negative error value.
881
 **/
882
int
883
gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey_t key,
884
           const gnutls_datum_t * m,
885
           const gnutls_datum_t * e,
886
           const gnutls_datum_t * d,
887
           const gnutls_datum_t * p,
888
           const gnutls_datum_t * q,
889
           const gnutls_datum_t * u)
890
0
{
891
0
  return gnutls_x509_privkey_import_rsa_raw2(key, m, e, d, p, q, u,
892
0
               NULL, NULL);
893
0
}
894
895
/**
896
 * gnutls_x509_privkey_import_rsa_raw2:
897
 * @key: The data to store the parsed key
898
 * @m: holds the modulus
899
 * @e: holds the public exponent
900
 * @d: holds the private exponent
901
 * @p: holds the first prime (p)
902
 * @q: holds the second prime (q)
903
 * @u: holds the coefficient (optional)
904
 * @e1: holds e1 = d mod (p-1) (optional)
905
 * @e2: holds e2 = d mod (q-1) (optional)
906
 *
907
 * This function will convert the given RSA raw parameters to the
908
 * native #gnutls_x509_privkey_t format.  The output will be stored in
909
 * @key.
910
 *
911
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
912
 *   negative error value.
913
 **/
914
int
915
gnutls_x509_privkey_import_rsa_raw2(gnutls_x509_privkey_t key,
916
            const gnutls_datum_t * m,
917
            const gnutls_datum_t * e,
918
            const gnutls_datum_t * d,
919
            const gnutls_datum_t * p,
920
            const gnutls_datum_t * q,
921
            const gnutls_datum_t * u,
922
            const gnutls_datum_t * e1,
923
            const gnutls_datum_t * e2)
924
0
{
925
0
  int ret;
926
0
  size_t siz = 0;
927
928
0
  if (key == NULL) {
929
0
    gnutls_assert();
930
0
    return GNUTLS_E_INVALID_REQUEST;
931
0
  }
932
933
0
  gnutls_pk_params_init(&key->params);
934
935
0
  siz = m->size;
936
0
  if (_gnutls_mpi_init_scan_nz
937
0
      (&key->params.params[RSA_MODULUS], m->data, siz)) {
938
0
    gnutls_assert();
939
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
940
0
    goto cleanup;
941
0
  }
942
0
  key->params.params_nr++;
943
944
0
  siz = e->size;
945
0
  if (_gnutls_mpi_init_scan_nz
946
0
      (&key->params.params[RSA_PUB], e->data, siz)) {
947
0
    gnutls_assert();
948
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
949
0
    goto cleanup;
950
0
  }
951
0
  key->params.params_nr++;
952
953
0
  if (d) {
954
0
    siz = d->size;
955
0
    if (_gnutls_mpi_init_scan_nz
956
0
        (&key->params.params[RSA_PRIV], d->data, siz)) {
957
0
      gnutls_assert();
958
0
      ret = GNUTLS_E_MPI_SCAN_FAILED;
959
0
      goto cleanup;
960
0
    }
961
0
    key->params.params_nr++;
962
0
  }
963
964
0
  siz = p->size;
965
0
  if (_gnutls_mpi_init_scan_nz
966
0
      (&key->params.params[RSA_PRIME1], p->data, siz)) {
967
0
    gnutls_assert();
968
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
969
0
    goto cleanup;
970
0
  }
971
0
  key->params.params_nr++;
972
973
0
  siz = q->size;
974
0
  if (_gnutls_mpi_init_scan_nz
975
0
      (&key->params.params[RSA_PRIME2], q->data, siz)) {
976
0
    gnutls_assert();
977
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
978
0
    goto cleanup;
979
0
  }
980
0
  key->params.params_nr++;
981
982
0
  if (u) {
983
0
    siz = u->size;
984
0
    if (_gnutls_mpi_init_scan_nz
985
0
        (&key->params.params[RSA_COEF], u->data, siz)) {
986
0
      gnutls_assert();
987
0
      ret = GNUTLS_E_MPI_SCAN_FAILED;
988
0
      goto cleanup;
989
0
    }
990
0
    key->params.params_nr++;
991
0
  }
992
993
0
  if (e1 && e2) {
994
0
    siz = e1->size;
995
0
    if (_gnutls_mpi_init_scan_nz
996
0
        (&key->params.params[RSA_E1], e1->data, siz)) {
997
0
      gnutls_assert();
998
0
      ret = GNUTLS_E_MPI_SCAN_FAILED;
999
0
      goto cleanup;
1000
0
    }
1001
0
    key->params.params_nr++;
1002
1003
0
    siz = e2->size;
1004
0
    if (_gnutls_mpi_init_scan_nz
1005
0
        (&key->params.params[RSA_E2], e2->data, siz)) {
1006
0
      gnutls_assert();
1007
0
      ret = GNUTLS_E_MPI_SCAN_FAILED;
1008
0
      goto cleanup;
1009
0
    }
1010
0
    key->params.params_nr++;
1011
0
  }
1012
1013
0
  key->params.algo = GNUTLS_PK_RSA;
1014
1015
0
  ret = _gnutls_pk_fixup(GNUTLS_PK_RSA, GNUTLS_IMPORT, &key->params);
1016
0
  if (ret < 0) {
1017
0
    gnutls_assert();
1018
0
    goto cleanup;
1019
0
  }
1020
1021
0
  key->params.params_nr = RSA_PRIVATE_PARAMS;
1022
0
  key->params.algo = GNUTLS_PK_RSA;
1023
1024
0
  ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
1025
0
  if (ret < 0) {
1026
0
    gnutls_assert();
1027
0
    goto cleanup;
1028
0
  }
1029
1030
0
  return 0;
1031
1032
0
 cleanup:
1033
0
  gnutls_pk_params_clear(&key->params);
1034
0
  gnutls_pk_params_release(&key->params);
1035
0
  return ret;
1036
1037
0
}
1038
1039
/**
1040
 * gnutls_x509_privkey_import_dsa_raw:
1041
 * @key: The data to store the parsed key
1042
 * @p: holds the p
1043
 * @q: holds the q
1044
 * @g: holds the g
1045
 * @y: holds the y (optional)
1046
 * @x: holds the x
1047
 *
1048
 * This function will convert the given DSA raw parameters to the
1049
 * native #gnutls_x509_privkey_t format.  The output will be stored
1050
 * in @key.
1051
 *
1052
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1053
 *   negative error value.
1054
 **/
1055
int
1056
gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey_t key,
1057
           const gnutls_datum_t * p,
1058
           const gnutls_datum_t * q,
1059
           const gnutls_datum_t * g,
1060
           const gnutls_datum_t * y,
1061
           const gnutls_datum_t * x)
1062
0
{
1063
0
  int ret;
1064
0
  size_t siz = 0;
1065
1066
0
  if (key == NULL) {
1067
0
    gnutls_assert();
1068
0
    return GNUTLS_E_INVALID_REQUEST;
1069
0
  }
1070
1071
0
  gnutls_pk_params_init(&key->params);
1072
1073
0
  siz = p->size;
1074
0
  if (_gnutls_mpi_init_scan_nz(&key->params.params[0], p->data, siz)) {
1075
0
    gnutls_assert();
1076
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1077
0
    goto cleanup;
1078
0
  }
1079
1080
0
  siz = q->size;
1081
0
  if (_gnutls_mpi_init_scan_nz(&key->params.params[1], q->data, siz)) {
1082
0
    gnutls_assert();
1083
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1084
0
    goto cleanup;
1085
0
  }
1086
1087
0
  siz = g->size;
1088
0
  if (_gnutls_mpi_init_scan_nz(&key->params.params[2], g->data, siz)) {
1089
0
    gnutls_assert();
1090
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1091
0
    goto cleanup;
1092
0
  }
1093
1094
0
  if (y) {
1095
0
    siz = y->size;
1096
0
    if (_gnutls_mpi_init_scan_nz
1097
0
        (&key->params.params[3], y->data, siz)) {
1098
0
      gnutls_assert();
1099
0
      ret = GNUTLS_E_MPI_SCAN_FAILED;
1100
0
      goto cleanup;
1101
0
    }
1102
0
  }
1103
1104
0
  siz = x->size;
1105
0
  if (_gnutls_mpi_init_scan_nz(&key->params.params[4], x->data, siz)) {
1106
0
    gnutls_assert();
1107
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1108
0
    goto cleanup;
1109
0
  }
1110
1111
0
  ret = _gnutls_pk_fixup(GNUTLS_PK_DSA, GNUTLS_IMPORT, &key->params);
1112
0
  if (ret < 0) {
1113
0
    gnutls_assert();
1114
0
    goto cleanup;
1115
0
  }
1116
1117
0
  key->params.algo = GNUTLS_PK_DSA;
1118
0
  key->params.params_nr = DSA_PRIVATE_PARAMS;
1119
1120
0
  ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
1121
0
  if (ret < 0) {
1122
0
    gnutls_assert();
1123
0
    goto cleanup;
1124
0
  }
1125
1126
0
  return 0;
1127
1128
0
 cleanup:
1129
0
  gnutls_pk_params_clear(&key->params);
1130
0
  gnutls_pk_params_release(&key->params);
1131
0
  return ret;
1132
1133
0
}
1134
1135
/**
1136
 * gnutls_x509_privkey_import_ecc_raw:
1137
 * @key: The data to store the parsed key
1138
 * @curve: holds the curve
1139
 * @x: holds the x-coordinate
1140
 * @y: holds the y-coordinate
1141
 * @k: holds the k
1142
 *
1143
 * This function will convert the given elliptic curve parameters to the
1144
 * native #gnutls_x509_privkey_t format.  The output will be stored
1145
 * in @key. For EdDSA keys, the @x and @k values must be in the
1146
 * native to curve format.
1147
 *
1148
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1149
 *   negative error value.
1150
 *
1151
 * Since: 3.0
1152
 **/
1153
int
1154
gnutls_x509_privkey_import_ecc_raw(gnutls_x509_privkey_t key,
1155
           gnutls_ecc_curve_t curve,
1156
           const gnutls_datum_t * x,
1157
           const gnutls_datum_t * y,
1158
           const gnutls_datum_t * k)
1159
0
{
1160
0
  int ret;
1161
1162
0
  if (key == NULL) {
1163
0
    gnutls_assert();
1164
0
    return GNUTLS_E_INVALID_REQUEST;
1165
0
  }
1166
1167
0
  gnutls_pk_params_init(&key->params);
1168
1169
0
  key->params.curve = curve;
1170
1171
0
  if (curve_is_eddsa(curve)) {
1172
0
    unsigned size;
1173
0
    switch (curve) {
1174
0
    case GNUTLS_ECC_CURVE_ED25519:
1175
0
      key->params.algo = GNUTLS_PK_EDDSA_ED25519;
1176
0
      break;
1177
0
    case GNUTLS_ECC_CURVE_ED448:
1178
0
      key->params.algo = GNUTLS_PK_EDDSA_ED448;
1179
0
      break;
1180
0
    default:
1181
0
      ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1182
0
      goto cleanup;
1183
0
    }
1184
1185
0
    size = gnutls_ecc_curve_get_size(curve);
1186
0
    if (x->size != size || k->size != size) {
1187
0
      ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1188
0
      goto cleanup;
1189
0
    }
1190
1191
0
    ret = _gnutls_set_datum(&key->params.raw_pub, x->data, x->size);
1192
0
    if (ret < 0) {
1193
0
      gnutls_assert();
1194
0
      goto cleanup;
1195
0
    }
1196
1197
0
    ret =
1198
0
        _gnutls_set_datum(&key->params.raw_priv, k->data, k->size);
1199
0
    if (ret < 0) {
1200
0
      gnutls_assert();
1201
0
      goto cleanup;
1202
0
    }
1203
1204
0
    return 0;
1205
0
  }
1206
1207
0
  if (_gnutls_mpi_init_scan_nz
1208
0
      (&key->params.params[ECC_X], x->data, x->size)) {
1209
0
    gnutls_assert();
1210
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1211
0
    goto cleanup;
1212
0
  }
1213
0
  key->params.params_nr++;
1214
1215
0
  if (_gnutls_mpi_init_scan_nz
1216
0
      (&key->params.params[ECC_Y], y->data, y->size)) {
1217
0
    gnutls_assert();
1218
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1219
0
    goto cleanup;
1220
0
  }
1221
0
  key->params.params_nr++;
1222
1223
0
  if (_gnutls_mpi_init_scan_nz
1224
0
      (&key->params.params[ECC_K], k->data, k->size)) {
1225
0
    gnutls_assert();
1226
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1227
0
    goto cleanup;
1228
0
  }
1229
0
  key->params.params_nr++;
1230
1231
0
  key->params.algo = GNUTLS_PK_EC;
1232
1233
0
  ret = _gnutls_pk_fixup(GNUTLS_PK_EC, GNUTLS_IMPORT, &key->params);
1234
0
  if (ret < 0) {
1235
0
    gnutls_assert();
1236
0
    goto cleanup;
1237
0
  }
1238
1239
0
  ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
1240
0
  if (ret < 0) {
1241
0
    gnutls_assert();
1242
0
    goto cleanup;
1243
0
  }
1244
1245
0
  return 0;
1246
1247
0
 cleanup:
1248
0
  gnutls_pk_params_clear(&key->params);
1249
0
  gnutls_pk_params_release(&key->params);
1250
0
  return ret;
1251
1252
0
}
1253
1254
/**
1255
 * gnutls_x509_privkey_import_gost_raw:
1256
 * @key: The data to store the parsed key
1257
 * @curve: holds the curve
1258
 * @digest: will hold the digest
1259
 * @paramset: will hold the GOST parameter set ID
1260
 * @x: holds the x-coordinate
1261
 * @y: holds the y-coordinate
1262
 * @k: holds the k (private key)
1263
 *
1264
 * This function will convert the given GOST private key's parameters to the
1265
 * native #gnutls_x509_privkey_t format.  The output will be stored
1266
 * in @key.  @digest should be one of GNUTLS_DIG_GOSR_94,
1267
 * GNUTLS_DIG_STREEBOG_256 or GNUTLS_DIG_STREEBOG_512.  If @paramset is set to
1268
 * GNUTLS_GOST_PARAMSET_UNKNOWN default one will be selected depending on
1269
 * @digest.
1270
 *
1271
 * Note: parameters should be stored with least significant byte first. On
1272
 * version 3.6.3 big-endian format was used incorrectly.
1273
 *
1274
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1275
 *   negative error value.
1276
 *
1277
 * Since: 3.6.3
1278
 **/
1279
int
1280
gnutls_x509_privkey_import_gost_raw(gnutls_x509_privkey_t key,
1281
            gnutls_ecc_curve_t curve,
1282
            gnutls_digest_algorithm_t digest,
1283
            gnutls_gost_paramset_t paramset,
1284
            const gnutls_datum_t * x,
1285
            const gnutls_datum_t * y,
1286
            const gnutls_datum_t * k)
1287
0
{
1288
0
  int ret;
1289
1290
0
  if (key == NULL) {
1291
0
    gnutls_assert();
1292
0
    return GNUTLS_E_INVALID_REQUEST;
1293
0
  }
1294
1295
0
  key->params.curve = curve;
1296
0
  key->params.algo = _gnutls_digest_gost(digest);
1297
1298
0
  if (paramset == GNUTLS_GOST_PARAMSET_UNKNOWN)
1299
0
    paramset = _gnutls_gost_paramset_default(key->params.algo);
1300
1301
0
  key->params.gost_params = paramset;
1302
1303
0
  if (_gnutls_mpi_init_scan_le
1304
0
      (&key->params.params[GOST_X], x->data, x->size)) {
1305
0
    gnutls_assert();
1306
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1307
0
    goto cleanup;
1308
0
  }
1309
0
  key->params.params_nr++;
1310
1311
0
  if (_gnutls_mpi_init_scan_le
1312
0
      (&key->params.params[GOST_Y], y->data, y->size)) {
1313
0
    gnutls_assert();
1314
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1315
0
    goto cleanup;
1316
0
  }
1317
0
  key->params.params_nr++;
1318
1319
0
  if (_gnutls_mpi_init_scan_le
1320
0
      (&key->params.params[GOST_K], k->data, k->size)) {
1321
0
    gnutls_assert();
1322
0
    ret = GNUTLS_E_MPI_SCAN_FAILED;
1323
0
    goto cleanup;
1324
0
  }
1325
0
  key->params.params_nr++;
1326
1327
0
  ret = _gnutls_pk_fixup(key->params.algo, GNUTLS_IMPORT, &key->params);
1328
0
  if (ret < 0) {
1329
0
    gnutls_assert();
1330
0
    goto cleanup;
1331
0
  }
1332
1333
0
  return 0;
1334
1335
0
 cleanup:
1336
0
  gnutls_pk_params_clear(&key->params);
1337
0
  gnutls_pk_params_release(&key->params);
1338
0
  return ret;
1339
1340
0
}
1341
1342
/**
1343
 * gnutls_x509_privkey_get_pk_algorithm:
1344
 * @key: should contain a #gnutls_x509_privkey_t type
1345
 *
1346
 * This function will return the public key algorithm of a private
1347
 * key.
1348
 *
1349
 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
1350
 *   success, or a negative error code on error.
1351
 **/
1352
int gnutls_x509_privkey_get_pk_algorithm(gnutls_x509_privkey_t key)
1353
0
{
1354
0
  if (key == NULL) {
1355
0
    gnutls_assert();
1356
0
    return GNUTLS_E_INVALID_REQUEST;
1357
0
  }
1358
1359
0
  return key->params.algo;
1360
0
}
1361
1362
/**
1363
 * gnutls_x509_privkey_get_pk_algorithm2:
1364
 * @key: should contain a #gnutls_x509_privkey_t type
1365
 * @bits: The number of bits in the public key algorithm
1366
 *
1367
 * This function will return the public key algorithm of a private
1368
 * key.
1369
 *
1370
 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
1371
 *   success, or a negative error code on error.
1372
 **/
1373
int
1374
gnutls_x509_privkey_get_pk_algorithm2(gnutls_x509_privkey_t key,
1375
              unsigned int *bits)
1376
0
{
1377
0
  int ret;
1378
1379
0
  if (key == NULL) {
1380
0
    gnutls_assert();
1381
0
    return GNUTLS_E_INVALID_REQUEST;
1382
0
  }
1383
1384
0
  if (bits) {
1385
0
    ret = pubkey_to_bits(&key->params);
1386
0
    if (ret < 0)
1387
0
      ret = 0;
1388
0
    *bits = ret;
1389
0
  }
1390
1391
0
  return key->params.algo;
1392
0
}
1393
1394
void
1395
_gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key,
1396
             gnutls_x509_spki_st * params)
1397
0
{
1398
0
  memcpy(params, &key->params.spki, sizeof(gnutls_x509_spki_st));
1399
0
}
1400
1401
/**
1402
 * gnutls_x509_privkey_get_spki:
1403
 * @key: should contain a #gnutls_x509_privkey_t type
1404
 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_x509_spki_t
1405
 * @flags: must be zero
1406
 *
1407
 * This function will return the public key information of a private
1408
 * key. The provided @spki must be initialized.
1409
 *
1410
 * Returns: Zero on success, or a negative error code on error.
1411
 **/
1412
int
1413
gnutls_x509_privkey_get_spki(gnutls_x509_privkey_t key, gnutls_x509_spki_t spki,
1414
           unsigned int flags)
1415
0
{
1416
0
  if (key == NULL) {
1417
0
    gnutls_assert();
1418
0
    return GNUTLS_E_INVALID_REQUEST;
1419
0
  }
1420
1421
0
  if (key->params.spki.pk == GNUTLS_PK_UNKNOWN)
1422
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1423
1424
0
  _gnutls_x509_privkey_get_spki_params(key, spki);
1425
1426
0
  return 0;
1427
0
}
1428
1429
/**
1430
 * gnutls_x509_privkey_set_spki:
1431
 * @key: should contain a #gnutls_x509_privkey_t type
1432
 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_x509_spki_t
1433
 * @flags: must be zero
1434
 *
1435
 * This function will return the public key information of a private
1436
 * key. The provided @spki must be initialized.
1437
 *
1438
 * Returns: Zero on success, or a negative error code on error.
1439
 **/
1440
int
1441
gnutls_x509_privkey_set_spki(gnutls_x509_privkey_t key,
1442
           const gnutls_x509_spki_t spki, unsigned int flags)
1443
0
{
1444
0
  gnutls_pk_params_st tparams;
1445
0
  int ret;
1446
1447
0
  if (key == NULL) {
1448
0
    gnutls_assert();
1449
0
    return GNUTLS_E_INVALID_REQUEST;
1450
0
  }
1451
1452
0
  if (!_gnutls_pk_are_compat(key->params.algo, spki->pk))
1453
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1454
1455
0
  memcpy(&tparams, &key->params, sizeof(gnutls_pk_params_st));
1456
0
  memcpy(&tparams.spki, spki, sizeof(gnutls_x509_spki_st));
1457
0
  ret = _gnutls_x509_check_pubkey_params(&tparams);
1458
0
  if (ret < 0)
1459
0
    return gnutls_assert_val(ret);
1460
1461
0
  memcpy(&key->params.spki, spki, sizeof(gnutls_x509_spki_st));
1462
1463
0
  key->params.algo = spki->pk;
1464
1465
0
  return 0;
1466
0
}
1467
1468
static const char *set_msg(gnutls_x509_privkey_t key)
1469
0
{
1470
0
  if (GNUTLS_PK_IS_RSA(key->params.algo)) {
1471
0
    return PEM_KEY_RSA;
1472
0
  } else if (key->params.algo == GNUTLS_PK_DSA) {
1473
0
    return PEM_KEY_DSA;
1474
0
  } else if (key->params.algo == GNUTLS_PK_EC)
1475
0
    return PEM_KEY_ECC;
1476
0
  else
1477
0
    return "UNKNOWN";
1478
0
}
1479
1480
/**
1481
 * gnutls_x509_privkey_export:
1482
 * @key: Holds the key
1483
 * @format: the format of output params. One of PEM or DER.
1484
 * @output_data: will contain a private key PEM or DER encoded
1485
 * @output_data_size: holds the size of output_data (and will be
1486
 *   replaced by the actual size of parameters)
1487
 *
1488
 * This function will export the private key to a PKCS#1 structure for
1489
 * RSA or RSA-PSS keys, and integer sequence for DSA keys. Other keys types
1490
 * will be exported in PKCS#8 form.
1491
 *
1492
 * If the structure is PEM encoded, it will have a header
1493
 * of "BEGIN RSA PRIVATE KEY".
1494
 *
1495
 * It is recommended to use gnutls_x509_privkey_export_pkcs8() instead
1496
 * of this function, when a consistent output format is required.
1497
 *
1498
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1499
 *   negative error value.
1500
 **/
1501
int
1502
gnutls_x509_privkey_export(gnutls_x509_privkey_t key,
1503
         gnutls_x509_crt_fmt_t format, void *output_data,
1504
         size_t *output_data_size)
1505
0
{
1506
0
  gnutls_datum_t out;
1507
0
  int ret;
1508
1509
0
  ret = gnutls_x509_privkey_export2(key, format, &out);
1510
0
  if (ret < 0)
1511
0
    return gnutls_assert_val(ret);
1512
1513
0
  if (format == GNUTLS_X509_FMT_PEM)
1514
0
    ret = _gnutls_copy_string(&out, output_data, output_data_size);
1515
0
  else
1516
0
    ret = _gnutls_copy_data(&out, output_data, output_data_size);
1517
0
  gnutls_free(out.data);
1518
1519
0
  return ret;
1520
0
}
1521
1522
/**
1523
 * gnutls_x509_privkey_export2:
1524
 * @key: Holds the key
1525
 * @format: the format of output params. One of PEM or DER.
1526
 * @out: will contain a private key PEM or DER encoded
1527
 *
1528
 * This function will export the private key to a PKCS#1 structure for
1529
 * RSA or RSA-PSS keys, and integer sequence for DSA keys. Other keys types
1530
 * will be exported in PKCS#8 form.
1531
 *
1532
 * The output buffer is allocated using gnutls_malloc().
1533
 *
1534
 * It is recommended to use gnutls_x509_privkey_export2_pkcs8() instead
1535
 * of this function, when a consistent output format is required.
1536
 *
1537
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1538
 *   negative error value.
1539
 *
1540
 * Since 3.1.3
1541
 **/
1542
int
1543
gnutls_x509_privkey_export2(gnutls_x509_privkey_t key,
1544
          gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
1545
0
{
1546
0
  const char *msg;
1547
0
  int ret;
1548
1549
0
  if (key == NULL) {
1550
0
    gnutls_assert();
1551
0
    return GNUTLS_E_INVALID_REQUEST;
1552
0
  }
1553
1554
0
  if (key->key == NULL) { /* can only export in PKCS#8 form */
1555
0
    return gnutls_x509_privkey_export2_pkcs8(key, format, NULL, 0,
1556
0
               out);
1557
0
  }
1558
1559
0
  msg = set_msg(key);
1560
1561
0
  if (key->flags & GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT) {
1562
0
    ret = gnutls_x509_privkey_fix(key);
1563
0
    if (ret < 0)
1564
0
      return gnutls_assert_val(ret);
1565
0
  }
1566
1567
0
  return _gnutls_x509_export_int2(key->key, format, msg, out);
1568
0
}
1569
1570
/**
1571
 * gnutls_x509_privkey_sec_param:
1572
 * @key: a key
1573
 *
1574
 * This function will return the security parameter appropriate with
1575
 * this private key.
1576
 *
1577
 * Returns: On success, a valid security parameter is returned otherwise
1578
 * %GNUTLS_SEC_PARAM_UNKNOWN is returned.
1579
 *
1580
 * Since: 2.12.0
1581
 **/
1582
gnutls_sec_param_t gnutls_x509_privkey_sec_param(gnutls_x509_privkey_t key)
1583
0
{
1584
0
  int bits;
1585
1586
0
  bits = pubkey_to_bits(&key->params);
1587
0
  if (bits <= 0)
1588
0
    return GNUTLS_SEC_PARAM_UNKNOWN;
1589
1590
0
  return gnutls_pk_bits_to_sec_param(key->params.algo, bits);
1591
0
}
1592
1593
/**
1594
 * gnutls_x509_privkey_export_ecc_raw:
1595
 * @key: a key
1596
 * @curve: will hold the curve
1597
 * @x: will hold the x-coordinate
1598
 * @y: will hold the y-coordinate
1599
 * @k: will hold the private key
1600
 *
1601
 * This function will export the ECC private key's parameters found
1602
 * in the given structure. The new parameters will be allocated using
1603
 * gnutls_malloc() and will be stored in the appropriate datum.
1604
 *
1605
 * In EdDSA curves the @y parameter will be %NULL and the other parameters
1606
 * will be in the native format for the curve.
1607
 *
1608
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1609
 *   negative error value.
1610
 *
1611
 * Since: 3.0
1612
 **/
1613
int gnutls_x509_privkey_export_ecc_raw(gnutls_x509_privkey_t key,
1614
               gnutls_ecc_curve_t * curve,
1615
               gnutls_datum_t * x,
1616
               gnutls_datum_t * y, gnutls_datum_t * k)
1617
0
{
1618
0
  if (key == NULL) {
1619
0
    gnutls_assert();
1620
0
    return GNUTLS_E_INVALID_REQUEST;
1621
0
  }
1622
1623
0
  return _gnutls_params_get_ecc_raw(&key->params, curve, x, y, k, 0);
1624
0
}
1625
1626
/**
1627
 * gnutls_x509_privkey_export_gost_raw:
1628
 * @key: a key
1629
 * @curve: will hold the curve
1630
 * @digest: will hold the digest
1631
 * @paramset: will hold the GOST parameter set ID
1632
 * @x: will hold the x-coordinate
1633
 * @y: will hold the y-coordinate
1634
 * @k: will hold the private key
1635
 *
1636
 * This function will export the GOST private key's parameters found
1637
 * in the given structure. The new parameters will be allocated using
1638
 * gnutls_malloc() and will be stored in the appropriate datum.
1639
 *
1640
 * Note: parameters will be stored with least significant byte first. On
1641
 * version 3.6.3 this was incorrectly returned in big-endian format.
1642
 *
1643
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1644
 *   negative error value.
1645
 *
1646
 * Since: 3.6.3
1647
 **/
1648
int gnutls_x509_privkey_export_gost_raw(gnutls_x509_privkey_t key,
1649
          gnutls_ecc_curve_t * curve,
1650
          gnutls_digest_algorithm_t * digest,
1651
          gnutls_gost_paramset_t * paramset,
1652
          gnutls_datum_t * x,
1653
          gnutls_datum_t * y, gnutls_datum_t * k)
1654
0
{
1655
0
  if (key == NULL) {
1656
0
    gnutls_assert();
1657
0
    return GNUTLS_E_INVALID_REQUEST;
1658
0
  }
1659
1660
0
  return _gnutls_params_get_gost_raw(&key->params, curve, digest,
1661
0
             paramset, x, y, k, 0);
1662
0
}
1663
1664
/**
1665
 * gnutls_x509_privkey_export_rsa_raw:
1666
 * @key: a key
1667
 * @m: will hold the modulus
1668
 * @e: will hold the public exponent
1669
 * @d: will hold the private exponent
1670
 * @p: will hold the first prime (p)
1671
 * @q: will hold the second prime (q)
1672
 * @u: will hold the coefficient
1673
 *
1674
 * This function will export the RSA private key's parameters found
1675
 * in the given structure. The new parameters will be allocated using
1676
 * gnutls_malloc() and will be stored in the appropriate datum.
1677
 *
1678
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1679
 *   negative error value.
1680
 **/
1681
int
1682
gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey_t key,
1683
           gnutls_datum_t * m, gnutls_datum_t * e,
1684
           gnutls_datum_t * d, gnutls_datum_t * p,
1685
           gnutls_datum_t * q, gnutls_datum_t * u)
1686
0
{
1687
0
  return _gnutls_params_get_rsa_raw(&key->params, m, e, d, p, q, u, NULL,
1688
0
            NULL, 0);
1689
0
}
1690
1691
/**
1692
 * gnutls_x509_privkey_export_rsa_raw2:
1693
 * @key: a key
1694
 * @m: will hold the modulus
1695
 * @e: will hold the public exponent
1696
 * @d: will hold the private exponent
1697
 * @p: will hold the first prime (p)
1698
 * @q: will hold the second prime (q)
1699
 * @u: will hold the coefficient
1700
 * @e1: will hold e1 = d mod (p-1)
1701
 * @e2: will hold e2 = d mod (q-1)
1702
 *
1703
 * This function will export the RSA private key's parameters found
1704
 * in the given structure. The new parameters will be allocated using
1705
 * gnutls_malloc() and will be stored in the appropriate datum.
1706
 *
1707
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1708
 *   negative error value.
1709
 *
1710
 * Since: 2.12.0
1711
 **/
1712
int
1713
gnutls_x509_privkey_export_rsa_raw2(gnutls_x509_privkey_t key,
1714
            gnutls_datum_t * m, gnutls_datum_t * e,
1715
            gnutls_datum_t * d, gnutls_datum_t * p,
1716
            gnutls_datum_t * q, gnutls_datum_t * u,
1717
            gnutls_datum_t * e1, gnutls_datum_t * e2)
1718
0
{
1719
0
  return _gnutls_params_get_rsa_raw(&key->params, m, e, d, p, q, u, e1,
1720
0
            e2, 0);
1721
0
}
1722
1723
/**
1724
 * gnutls_x509_privkey_export_dsa_raw:
1725
 * @key: a key
1726
 * @p: will hold the p
1727
 * @q: will hold the q
1728
 * @g: will hold the g
1729
 * @y: will hold the y
1730
 * @x: will hold the x
1731
 *
1732
 * This function will export the DSA private key's parameters found
1733
 * in the given structure. The new parameters will be allocated using
1734
 * gnutls_malloc() and will be stored in the appropriate datum.
1735
 *
1736
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1737
 *   negative error value.
1738
 **/
1739
int
1740
gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey_t key,
1741
           gnutls_datum_t * p, gnutls_datum_t * q,
1742
           gnutls_datum_t * g, gnutls_datum_t * y,
1743
           gnutls_datum_t * x)
1744
0
{
1745
0
  return _gnutls_params_get_dsa_raw(&key->params, p, q, g, y, x, 0);
1746
0
}
1747
1748
/**
1749
 * gnutls_x509_privkey_generate:
1750
 * @key: an initialized key
1751
 * @algo: is one of the algorithms in #gnutls_pk_algorithm_t.
1752
 * @bits: the size of the parameters to generate
1753
 * @flags: Must be zero or flags from #gnutls_privkey_flags_t.
1754
 *
1755
 * This function will generate a random private key. Note that this
1756
 * function must be called on an initialized private key.
1757
 *
1758
 * The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE
1759
 * instructs the key generation process to use algorithms like Shawe-Taylor
1760
 * (from FIPS PUB186-4) which generate provable parameters out of a seed
1761
 * for RSA and DSA keys. See gnutls_x509_privkey_generate2() for more
1762
 * information.
1763
 *
1764
 * Note that when generating an elliptic curve key, the curve
1765
 * can be substituted in the place of the bits parameter using the
1766
 * GNUTLS_CURVE_TO_BITS() macro. The input to the macro is any curve from
1767
 * %gnutls_ecc_curve_t.
1768
 *
1769
 * For DSA keys, if the subgroup size needs to be specified check
1770
 * the GNUTLS_SUBGROUP_TO_BITS() macro.
1771
 *
1772
 * It is recommended to do not set the number of @bits directly, use gnutls_sec_param_to_pk_bits() instead .
1773
 *
1774
 * See also gnutls_privkey_generate(), gnutls_x509_privkey_generate2().
1775
 *
1776
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1777
 *   negative error value.
1778
 **/
1779
int
1780
gnutls_x509_privkey_generate(gnutls_x509_privkey_t key,
1781
           gnutls_pk_algorithm_t algo, unsigned int bits,
1782
           unsigned int flags)
1783
0
{
1784
0
  return gnutls_x509_privkey_generate2(key, algo, bits, flags, NULL, 0);
1785
0
}
1786
1787
/**
1788
 * gnutls_x509_privkey_generate2:
1789
 * @key: a key
1790
 * @algo: is one of the algorithms in #gnutls_pk_algorithm_t.
1791
 * @bits: the size of the modulus
1792
 * @flags: Must be zero or flags from #gnutls_privkey_flags_t.
1793
 * @data: Allow specifying %gnutls_keygen_data_st types such as the seed to be used.
1794
 * @data_size: The number of @data available.
1795
 *
1796
 * This function will generate a random private key. Note that this
1797
 * function must be called on an initialized private key.
1798
 *
1799
 * The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE
1800
 * instructs the key generation process to use algorithms like Shawe-Taylor
1801
 * (from FIPS PUB186-4) which generate provable parameters out of a seed
1802
 * for RSA and DSA keys. On DSA keys the PQG parameters are generated using the
1803
 * seed, while on RSA the two primes. To specify an explicit seed
1804
 * (by default a random seed is used), use the @data with a %GNUTLS_KEYGEN_SEED
1805
 * type.
1806
 *
1807
 * Note that when generating an elliptic curve key, the curve
1808
 * can be substituted in the place of the bits parameter using the
1809
 * GNUTLS_CURVE_TO_BITS() macro.
1810
 *
1811
 * To export the generated keys in memory or in files it is recommended to use the
1812
 * PKCS#8 form as it can handle all key types, and can store additional parameters
1813
 * such as the seed, in case of provable RSA or DSA keys.
1814
 * Generated keys can be exported in memory using gnutls_privkey_export_x509(),
1815
 * and then with gnutls_x509_privkey_export2_pkcs8().
1816
 *
1817
 * If key generation is part of your application, avoid setting the number
1818
 * of bits directly, and instead use gnutls_sec_param_to_pk_bits().
1819
 * That way the generated keys will adapt to the security levels
1820
 * of the underlying GnuTLS library.
1821
 *
1822
 * See also gnutls_privkey_generate2().
1823
 *
1824
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1825
 *   negative error value.
1826
 **/
1827
int
1828
gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
1829
            gnutls_pk_algorithm_t algo, unsigned int bits,
1830
            unsigned int flags,
1831
            const gnutls_keygen_data_st * data,
1832
            unsigned data_size)
1833
0
{
1834
0
  int ret;
1835
0
  unsigned i;
1836
0
  gnutls_x509_spki_t tpki = NULL;
1837
1838
0
  if (key == NULL) {
1839
0
    gnutls_assert();
1840
0
    return GNUTLS_E_INVALID_REQUEST;
1841
0
  }
1842
1843
0
  gnutls_pk_params_init(&key->params);
1844
1845
0
  for (i = 0; i < data_size; i++) {
1846
0
    if (data[i].type == GNUTLS_KEYGEN_SEED
1847
0
        && data[i].size < sizeof(key->params.seed)) {
1848
0
      key->params.seed_size = data[i].size;
1849
0
      memcpy(key->params.seed, data[i].data, data[i].size);
1850
0
    } else if (data[i].type == GNUTLS_KEYGEN_DIGEST) {
1851
0
      key->params.palgo = data[i].size;
1852
0
    } else if (data[i].type == GNUTLS_KEYGEN_SPKI) {
1853
0
      tpki = (void *)data[i].data;
1854
0
    }
1855
0
  }
1856
1857
0
  if (IS_EC(algo)) {
1858
0
    if (GNUTLS_BITS_ARE_CURVE(bits))
1859
0
      bits = GNUTLS_BITS_TO_CURVE(bits);
1860
0
    else
1861
0
      bits = _gnutls_ecc_bits_to_curve(algo, bits);
1862
1863
0
    if (gnutls_ecc_curve_get_pk(bits) != algo) {
1864
0
      _gnutls_debug_log
1865
0
          ("curve is incompatible with public key algorithm\n");
1866
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1867
0
    }
1868
0
  }
1869
1870
0
  if (IS_GOSTEC(algo)) {
1871
0
    int size;
1872
1873
0
    if (GNUTLS_BITS_ARE_CURVE(bits))
1874
0
      bits = GNUTLS_BITS_TO_CURVE(bits);
1875
0
    else
1876
0
      bits = _gnutls_ecc_bits_to_curve(algo, bits);
1877
1878
0
    size = gnutls_ecc_curve_get_size(bits);
1879
1880
0
    if ((algo == GNUTLS_PK_GOST_01 && size != 32) ||
1881
0
        (algo == GNUTLS_PK_GOST_12_256 && size != 32) ||
1882
0
        (algo == GNUTLS_PK_GOST_12_512 && size != 64)) {
1883
0
      _gnutls_debug_log
1884
0
          ("curve is incompatible with public key algorithm\n");
1885
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1886
0
    }
1887
1888
0
    key->params.gost_params = _gnutls_gost_paramset_default(algo);
1889
0
  }
1890
1891
0
  if (flags & GNUTLS_PRIVKEY_FLAG_PROVABLE) {
1892
0
    key->params.pkflags |= GNUTLS_PK_FLAG_PROVABLE;
1893
0
  }
1894
1895
0
  key->params.algo = algo;
1896
1897
0
  ret = _gnutls_pk_generate_params(algo, bits, &key->params);
1898
0
  if (ret < 0) {
1899
0
    gnutls_assert();
1900
0
    return ret;
1901
0
  }
1902
1903
0
  if (algo == GNUTLS_PK_RSA_PSS && (flags & GNUTLS_PRIVKEY_FLAG_CA) &&
1904
0
      !key->params.spki.pk) {
1905
0
    const mac_entry_st *me;
1906
0
    key->params.spki.pk = GNUTLS_PK_RSA_PSS;
1907
1908
0
    key->params.spki.rsa_pss_dig =
1909
0
        _gnutls_pk_bits_to_sha_hash(bits);
1910
1911
0
    me = hash_to_entry(key->params.spki.rsa_pss_dig);
1912
0
    if (unlikely(me == NULL)) {
1913
0
      gnutls_assert();
1914
0
      ret = GNUTLS_E_INVALID_REQUEST;
1915
0
      goto cleanup;
1916
0
    }
1917
1918
0
    ret = _gnutls_find_rsa_pss_salt_size(bits, me, 0);
1919
0
    if (ret < 0) {
1920
0
      gnutls_assert();
1921
0
      goto cleanup;
1922
0
    }
1923
1924
0
    key->params.spki.salt_size = ret;
1925
0
  }
1926
1927
0
  ret = _gnutls_pk_generate_keys(algo, bits, &key->params, 0);
1928
0
  if (ret < 0) {
1929
0
    gnutls_assert();
1930
0
    goto cleanup;
1931
0
  }
1932
1933
0
  ret = _gnutls_pk_verify_priv_params(algo, &key->params);
1934
0
  if (ret < 0) {
1935
0
    gnutls_assert();
1936
0
    goto cleanup;
1937
0
  }
1938
1939
0
  if (tpki) {
1940
0
    ret = gnutls_x509_privkey_set_spki(key, tpki, 0);
1941
0
    if (ret < 0) {
1942
0
      gnutls_assert();
1943
0
      goto cleanup;
1944
0
    }
1945
0
  }
1946
1947
0
  ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
1948
0
  if (ret < 0) {
1949
0
    gnutls_assert();
1950
0
    goto cleanup;
1951
0
  }
1952
1953
0
  return 0;
1954
1955
0
 cleanup:
1956
0
  key->params.algo = GNUTLS_PK_UNKNOWN;
1957
0
  gnutls_pk_params_clear(&key->params);
1958
0
  gnutls_pk_params_release(&key->params);
1959
1960
0
  return ret;
1961
0
}
1962
1963
/**
1964
 * gnutls_x509_privkey_get_seed:
1965
 * @key: should contain a #gnutls_x509_privkey_t type
1966
 * @digest: if non-NULL it will contain the digest algorithm used for key generation (if applicable)
1967
 * @seed: where seed will be copied to
1968
 * @seed_size: originally holds the size of @seed, will be updated with actual size
1969
 *
1970
 * This function will return the seed that was used to generate the
1971
 * given private key. That function will succeed only if the key was generated
1972
 * as a provable key.
1973
 *
1974
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1975
 *   negative error value.
1976
 *
1977
 * Since: 3.5.0
1978
 **/
1979
int gnutls_x509_privkey_get_seed(gnutls_x509_privkey_t key,
1980
         gnutls_digest_algorithm_t * digest, void *seed,
1981
         size_t *seed_size)
1982
0
{
1983
0
  if (key->params.seed_size == 0)
1984
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1985
1986
0
  if (seed_size == NULL || seed == NULL) {
1987
0
    if (key->params.seed_size)
1988
0
      return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1989
0
    else
1990
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1991
0
  }
1992
1993
0
  if (*seed_size < key->params.seed_size) {
1994
0
    *seed_size = key->params.seed_size;
1995
0
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1996
0
  }
1997
1998
0
  if (digest)
1999
0
    *digest = key->params.palgo;
2000
2001
0
  memcpy(seed, key->params.seed, key->params.seed_size);
2002
0
  *seed_size = key->params.seed_size;
2003
0
  return 0;
2004
0
}
2005
2006
static
2007
int cmp_rsa_key(gnutls_x509_privkey_t key1, gnutls_x509_privkey_t key2)
2008
0
{
2009
0
  gnutls_datum_t m1 = { NULL, 0 }, e1 = { NULL, 0 }, d1 =
2010
0
      { NULL, 0 }, p1 = { NULL, 0 }, q1 = { NULL, 0 };
2011
0
  gnutls_datum_t m2 = { NULL, 0 }, e2 = { NULL, 0 }, d2 =
2012
0
      { NULL, 0 }, p2 = { NULL, 0 }, q2 = { NULL, 0 };
2013
0
  int ret;
2014
2015
0
  ret =
2016
0
      gnutls_x509_privkey_export_rsa_raw(key1, &m1, &e1, &d1, &p1, &q1,
2017
0
                 NULL);
2018
0
  if (ret < 0) {
2019
0
    gnutls_assert();
2020
0
    return ret;
2021
0
  }
2022
2023
0
  ret =
2024
0
      gnutls_x509_privkey_export_rsa_raw(key2, &m2, &e2, &d2, &p2, &q2,
2025
0
                 NULL);
2026
0
  if (ret < 0) {
2027
0
    gnutls_assert();
2028
0
    goto cleanup;
2029
0
  }
2030
2031
0
  if (m1.size != m2.size || memcmp(m1.data, m2.data, m1.size) != 0) {
2032
0
    gnutls_assert();
2033
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2034
0
    goto cleanup;
2035
0
  }
2036
2037
0
  if (d1.size != d2.size || memcmp(d1.data, d2.data, d1.size) != 0) {
2038
0
    gnutls_assert();
2039
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2040
0
    goto cleanup;
2041
0
  }
2042
2043
0
  if (e1.size != e2.size || memcmp(e1.data, e2.data, e1.size) != 0) {
2044
0
    gnutls_assert();
2045
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2046
0
    goto cleanup;
2047
0
  }
2048
2049
0
  if (p1.size != p2.size || memcmp(p1.data, p2.data, p1.size) != 0) {
2050
0
    gnutls_assert();
2051
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2052
0
    goto cleanup;
2053
0
  }
2054
2055
0
  if (q1.size != q2.size || memcmp(q1.data, q2.data, q1.size) != 0) {
2056
0
    gnutls_assert();
2057
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2058
0
    goto cleanup;
2059
0
  }
2060
2061
0
  ret = 0;
2062
0
 cleanup:
2063
0
  gnutls_free(m1.data);
2064
0
  gnutls_free(e1.data);
2065
0
  gnutls_free(d1.data);
2066
0
  gnutls_free(p1.data);
2067
0
  gnutls_free(q1.data);
2068
0
  gnutls_free(m2.data);
2069
0
  gnutls_free(e2.data);
2070
0
  gnutls_free(d2.data);
2071
0
  gnutls_free(p2.data);
2072
0
  gnutls_free(q2.data);
2073
0
  return ret;
2074
0
}
2075
2076
static
2077
int cmp_dsa_key(gnutls_x509_privkey_t key1, gnutls_x509_privkey_t key2)
2078
0
{
2079
0
  gnutls_datum_t p1 = { NULL, 0 }, q1 = { NULL, 0 }, g1 = { NULL, 0 };
2080
0
  gnutls_datum_t p2 = { NULL, 0 }, q2 = { NULL, 0 }, g2 = { NULL, 0 };
2081
0
  int ret;
2082
2083
0
  ret =
2084
0
      gnutls_x509_privkey_export_dsa_raw(key1, &p1, &q1, &g1, NULL, NULL);
2085
0
  if (ret < 0) {
2086
0
    gnutls_assert();
2087
0
    return ret;
2088
0
  }
2089
2090
0
  ret =
2091
0
      gnutls_x509_privkey_export_dsa_raw(key2, &p2, &q2, &g2, NULL, NULL);
2092
0
  if (ret < 0) {
2093
0
    gnutls_assert();
2094
0
    goto cleanup;
2095
0
  }
2096
2097
0
  if (g1.size != g2.size || memcmp(g1.data, g2.data, g1.size) != 0) {
2098
0
    gnutls_assert();
2099
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2100
0
    goto cleanup;
2101
0
  }
2102
2103
0
  if (p1.size != p2.size || memcmp(p1.data, p2.data, p1.size) != 0) {
2104
0
    gnutls_assert();
2105
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2106
0
    goto cleanup;
2107
0
  }
2108
2109
0
  if (q1.size != q2.size || memcmp(q1.data, q2.data, q1.size) != 0) {
2110
0
    gnutls_assert();
2111
0
    ret = GNUTLS_E_PRIVKEY_VERIFICATION_ERROR;
2112
0
    goto cleanup;
2113
0
  }
2114
2115
0
  ret = 0;
2116
0
 cleanup:
2117
0
  gnutls_free(g1.data);
2118
0
  gnutls_free(p1.data);
2119
0
  gnutls_free(q1.data);
2120
0
  gnutls_free(g2.data);
2121
0
  gnutls_free(p2.data);
2122
0
  gnutls_free(q2.data);
2123
0
  return ret;
2124
0
}
2125
2126
/**
2127
 * gnutls_x509_privkey_verify_seed:
2128
 * @key: should contain a #gnutls_x509_privkey_t type
2129
 * @digest: it contains the digest algorithm used for key generation (if applicable)
2130
 * @seed: the seed of the key to be checked with
2131
 * @seed_size: holds the size of @seed
2132
 *
2133
 * This function will verify that the given private key was generated from
2134
 * the provided seed. If @seed is %NULL then the seed stored in the @key's structure
2135
 * will be used for verification.
2136
 *
2137
 * Returns: In case of a verification failure %GNUTLS_E_PRIVKEY_VERIFICATION_ERROR
2138
 * is returned, and zero or positive code on success.
2139
 *
2140
 * Since: 3.5.0
2141
 **/
2142
int gnutls_x509_privkey_verify_seed(gnutls_x509_privkey_t key,
2143
            gnutls_digest_algorithm_t digest,
2144
            const void *seed, size_t seed_size)
2145
0
{
2146
0
  int ret;
2147
0
  gnutls_x509_privkey_t okey;
2148
0
  unsigned bits;
2149
0
  gnutls_keygen_data_st data;
2150
2151
0
  if (key == NULL) {
2152
0
    gnutls_assert();
2153
0
    return GNUTLS_E_INVALID_REQUEST;
2154
0
  }
2155
2156
0
  if (key->params.algo != GNUTLS_PK_RSA
2157
0
      && key->params.algo != GNUTLS_PK_DSA)
2158
0
    return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
2159
2160
0
  ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits);
2161
0
  if (ret < 0)
2162
0
    return gnutls_assert_val(ret);
2163
2164
0
  ret = gnutls_x509_privkey_init(&okey);
2165
0
  if (ret < 0)
2166
0
    return gnutls_assert_val(ret);
2167
2168
0
  if (seed == NULL) {
2169
0
    seed = key->params.seed;
2170
0
    seed_size = key->params.seed_size;
2171
0
  }
2172
2173
0
  if (seed == NULL || seed_size == 0)
2174
0
    return gnutls_assert_val(GNUTLS_E_PK_NO_VALIDATION_PARAMS);
2175
2176
0
  data.type = GNUTLS_KEYGEN_SEED;
2177
0
  data.data = (void *)seed;
2178
0
  data.size = seed_size;
2179
2180
0
  ret = gnutls_x509_privkey_generate2(okey, key->params.algo, bits,
2181
0
              GNUTLS_PRIVKEY_FLAG_PROVABLE, &data,
2182
0
              1);
2183
0
  if (ret < 0) {
2184
0
    gnutls_assert();
2185
0
    goto cleanup;
2186
0
  }
2187
2188
0
  if (key->params.algo == GNUTLS_PK_RSA)
2189
0
    ret = cmp_rsa_key(key, okey);
2190
0
  else
2191
0
    ret = cmp_dsa_key(key, okey);
2192
2193
0
 cleanup:
2194
0
  gnutls_x509_privkey_deinit(okey);
2195
2196
0
  return ret;
2197
0
}
2198
2199
/**
2200
 * gnutls_x509_privkey_verify_params:
2201
 * @key: a key
2202
 *
2203
 * This function will verify the private key parameters.
2204
 *
2205
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2206
 *   negative error value.
2207
 **/
2208
int gnutls_x509_privkey_verify_params(gnutls_x509_privkey_t key)
2209
0
{
2210
0
  int ret;
2211
2212
0
  ret = _gnutls_pk_verify_priv_params(key->params.algo, &key->params);
2213
0
  if (ret < 0) {
2214
0
    gnutls_assert();
2215
0
    return ret;
2216
0
  }
2217
2218
0
  return 0;
2219
0
}
2220
2221
/**
2222
 * gnutls_x509_privkey_get_key_id:
2223
 * @key: a key
2224
 * @flags: should be one of the flags from %gnutls_keyid_flags_t
2225
 * @output_data: will contain the key ID
2226
 * @output_data_size: holds the size of output_data (and will be
2227
 *   replaced by the actual size of parameters)
2228
 *
2229
 * This function will return a unique ID that depends on the public key
2230
 * parameters. This ID can be used in checking whether a certificate
2231
 * corresponds to the given key.
2232
 *
2233
 * If the buffer provided is not long enough to hold the output, then
2234
 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
2235
 * be returned.  The output will normally be a SHA-1 hash output,
2236
 * which is 20 bytes.
2237
 *
2238
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2239
 *   negative error value.
2240
 **/
2241
int
2242
gnutls_x509_privkey_get_key_id(gnutls_x509_privkey_t key,
2243
             unsigned int flags,
2244
             unsigned char *output_data,
2245
             size_t *output_data_size)
2246
0
{
2247
0
  int ret;
2248
2249
0
  if (key == NULL) {
2250
0
    gnutls_assert();
2251
0
    return GNUTLS_E_INVALID_REQUEST;
2252
0
  }
2253
2254
0
  ret =
2255
0
      _gnutls_get_key_id(&key->params,
2256
0
             output_data, output_data_size, flags);
2257
0
  if (ret < 0) {
2258
0
    gnutls_assert();
2259
0
  }
2260
2261
0
  return ret;
2262
0
}
2263
2264
/**
2265
 * gnutls_x509_privkey_sign_hash:
2266
 * @key: a key
2267
 * @hash: holds the data to be signed
2268
 * @signature: will contain newly allocated signature
2269
 *
2270
 * This function will sign the given hash using the private key. Do not
2271
 * use this function directly unless you know what it is. Typical signing
2272
 * requires the data to be hashed and stored in special formats 
2273
 * (e.g. BER Digest-Info for RSA).
2274
 *
2275
 * This API is provided only for backwards compatibility, and thus
2276
 * restricted to RSA, DSA and ECDSA key types. For other key types please
2277
 * use gnutls_privkey_sign_hash() and gnutls_privkey_sign_data().
2278
 *
2279
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2280
 *   negative error value.
2281
 *
2282
 * Deprecated in: 2.12.0
2283
 */
2284
int
2285
gnutls_x509_privkey_sign_hash(gnutls_x509_privkey_t key,
2286
            const gnutls_datum_t * hash,
2287
            gnutls_datum_t * signature)
2288
0
{
2289
0
  int result;
2290
2291
0
  if (key == NULL) {
2292
0
    gnutls_assert();
2293
0
    return GNUTLS_E_INVALID_REQUEST;
2294
0
  }
2295
2296
0
  if (key->params.algo != GNUTLS_PK_RSA
2297
0
      && key->params.algo != GNUTLS_PK_ECDSA
2298
0
      && key->params.algo != GNUTLS_PK_DSA) {
2299
    /* too primitive API - use only with legacy types */
2300
0
    gnutls_assert();
2301
0
    return GNUTLS_E_INVALID_REQUEST;
2302
0
  }
2303
2304
0
  result =
2305
0
      _gnutls_pk_sign(key->params.algo, signature, hash,
2306
0
          &key->params, &key->params.spki);
2307
2308
0
  if (result < 0) {
2309
0
    gnutls_assert();
2310
0
    return result;
2311
0
  }
2312
2313
0
  return 0;
2314
0
}
2315
2316
/**
2317
 * gnutls_x509_privkey_sign_data:
2318
 * @key: a key
2319
 * @digest: should be a digest algorithm
2320
 * @flags: should be 0 for now
2321
 * @data: holds the data to be signed
2322
 * @signature: will contain the signature
2323
 * @signature_size: holds the size of signature (and will be replaced
2324
 *   by the new size)
2325
 *
2326
 * This function will sign the given data using a signature algorithm
2327
 * supported by the private key. Signature algorithms are always used
2328
 * together with a hash functions.  Different hash functions may be
2329
 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
2330
 *
2331
 * If the buffer provided is not long enough to hold the output, then
2332
 * *@signature_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
2333
 * be returned.
2334
 *
2335
 * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine
2336
 * the hash algorithm.
2337
 *
2338
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2339
 *   negative error value.
2340
 */
2341
int
2342
gnutls_x509_privkey_sign_data(gnutls_x509_privkey_t key,
2343
            gnutls_digest_algorithm_t digest,
2344
            unsigned int flags,
2345
            const gnutls_datum_t * data,
2346
            void *signature, size_t *signature_size)
2347
0
{
2348
0
  gnutls_privkey_t privkey;
2349
0
  gnutls_datum_t sig = { NULL, 0 };
2350
0
  int ret;
2351
2352
0
  ret = gnutls_privkey_init(&privkey);
2353
0
  if (ret < 0)
2354
0
    return gnutls_assert_val(ret);
2355
2356
0
  ret = gnutls_privkey_import_x509(privkey, key, 0);
2357
0
  if (ret < 0) {
2358
0
    gnutls_assert();
2359
0
    goto cleanup;
2360
0
  }
2361
2362
0
  ret = gnutls_privkey_sign_data(privkey, digest, flags, data, &sig);
2363
0
  if (ret < 0) {
2364
0
    gnutls_assert();
2365
0
    goto cleanup;
2366
0
  }
2367
2368
0
  if (*signature_size < sig.size) {
2369
0
    *signature_size = sig.size;
2370
0
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
2371
0
    goto cleanup;
2372
0
  }
2373
2374
0
  *signature_size = sig.size;
2375
0
  memcpy(signature, sig.data, sig.size);
2376
2377
0
 cleanup:
2378
0
  _gnutls_free_datum(&sig);
2379
0
  gnutls_privkey_deinit(privkey);
2380
0
  return ret;
2381
0
}
2382
2383
/**
2384
 * gnutls_x509_privkey_fix:
2385
 * @key: a key
2386
 *
2387
 * This function will recalculate the secondary parameters in a key.
2388
 * In RSA keys, this can be the coefficient and exponent1,2.
2389
 *
2390
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2391
 *   negative error value.
2392
 **/
2393
int gnutls_x509_privkey_fix(gnutls_x509_privkey_t key)
2394
0
{
2395
0
  int ret;
2396
2397
0
  if (key == NULL) {
2398
0
    gnutls_assert();
2399
0
    return GNUTLS_E_INVALID_REQUEST;
2400
0
  }
2401
2402
0
  if (key->key) {
2403
0
    asn1_delete_structure2(&key->key, ASN1_DELETE_FLAG_ZEROIZE);
2404
2405
0
    ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
2406
0
    if (ret < 0) {
2407
0
      gnutls_assert();
2408
0
      return ret;
2409
0
    }
2410
0
  }
2411
2412
0
  return 0;
2413
0
}
2414
2415
/**
2416
 * gnutls_x509_privkey_set_pin_function:
2417
 * @privkey: The certificate structure
2418
 * @fn: the callback
2419
 * @userdata: data associated with the callback
2420
 *
2421
 * This function will set a callback function to be used when
2422
 * it is required to access a protected object. This function overrides 
2423
 * the global function set using gnutls_pkcs11_set_pin_function().
2424
 *
2425
 * Note that this callback is used when decrypting a key.
2426
 *
2427
 * Since: 3.4.0
2428
 *
2429
 **/
2430
void gnutls_x509_privkey_set_pin_function(gnutls_x509_privkey_t privkey,
2431
            gnutls_pin_callback_t fn,
2432
            void *userdata)
2433
0
{
2434
0
  privkey->pin.cb = fn;
2435
0
  privkey->pin.data = userdata;
2436
0
}
2437
2438
/**
2439
 * gnutls_x509_privkey_set_flags:
2440
 * @key: A key of type #gnutls_x509_privkey_t
2441
 * @flags: flags from the %gnutls_privkey_flags
2442
 *
2443
 * This function will set flags for the specified private key, after
2444
 * it is generated. Currently this is useful for the %GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT
2445
 * to allow exporting a "provable" private key in backwards compatible way.
2446
 *
2447
 * Since: 3.5.0
2448
 *
2449
 **/
2450
void gnutls_x509_privkey_set_flags(gnutls_x509_privkey_t key,
2451
           unsigned int flags)
2452
0
{
2453
0
  key->flags |= flags;
2454
0
}