1 /*
2 * GnuTLS public key support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Copyright (C) 2017 Red Hat, Inc.
5 *
6 * Author: Nikos Mavrogiannopoulos
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 */
21
22 #include "gnutls_int.h"
23 #include <gnutls/pkcs11.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "errors.h"
27 #include <datum.h>
28 #include <pkcs11_int.h>
29 #include <gnutls/abstract.h>
30 #include <tls-sig.h>
31 #include <pk.h>
32 #include <x509_int.h>
33 #include <num.h>
34 #include <x509/common.h>
35 #include <x509_b64.h>
36 #include <abstract_int.h>
37 #include <fips.h>
38 #include "urls.h"
39 #include <ecc.h>
40
41 static int
42 pubkey_verify_hashed_data(const gnutls_sign_entry_st *se,
43 const mac_entry_st *me,
44 const gnutls_datum_t * hash,
45 const gnutls_datum_t * signature,
46 gnutls_pk_params_st * params,
47 gnutls_x509_spki_st * sign_params,
48 unsigned flags);
49
50 static
51 int pubkey_supports_sig(gnutls_pubkey_t pubkey,
52 const gnutls_sign_entry_st *se);
53
pubkey_to_bits(const gnutls_pk_params_st * params)54 unsigned pubkey_to_bits(const gnutls_pk_params_st * params)
55 {
56 switch (params->algo) {
57 case GNUTLS_PK_RSA:
58 case GNUTLS_PK_RSA_PSS:
59 return _gnutls_mpi_get_nbits(params->params[RSA_MODULUS]);
60 case GNUTLS_PK_DSA:
61 return _gnutls_mpi_get_nbits(params->params[DSA_P]);
62 case GNUTLS_PK_ECDSA:
63 case GNUTLS_PK_EDDSA_ED25519:
64 case GNUTLS_PK_EDDSA_ED448:
65 case GNUTLS_PK_GOST_01:
66 case GNUTLS_PK_GOST_12_256:
67 case GNUTLS_PK_GOST_12_512:
68 return gnutls_ecc_curve_get_size(params->curve) * 8;
69 default:
70 return 0;
71 }
72 }
73
74 /**
75 * gnutls_pubkey_get_pk_algorithm:
76 * @key: should contain a #gnutls_pubkey_t type
77 * @bits: If set will return the number of bits of the parameters (may be NULL)
78 *
79 * This function will return the public key algorithm of a public
80 * key and if possible will return a number of bits that indicates
81 * the security parameter of the key.
82 *
83 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
84 * success, or a negative error code on error.
85 *
86 * Since: 2.12.0
87 **/
gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key,unsigned int * bits)88 int gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key, unsigned int *bits)
89 {
90 if (bits)
91 *bits = key->bits;
92
93 return key->params.algo;
94 }
95
96 /**
97 * gnutls_pubkey_get_key_usage:
98 * @key: should contain a #gnutls_pubkey_t type
99 * @usage: If set will return the number of bits of the parameters (may be NULL)
100 *
101 * This function will return the key usage of the public key.
102 *
103 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
104 * negative error value.
105 *
106 * Since: 2.12.0
107 **/
gnutls_pubkey_get_key_usage(gnutls_pubkey_t key,unsigned int * usage)108 int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage)
109 {
110 if (usage)
111 *usage = key->key_usage;
112
113 return 0;
114 }
115
116 /**
117 * gnutls_pubkey_init:
118 * @key: A pointer to the type to be initialized
119 *
120 * This function will initialize a public key.
121 *
122 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
123 * negative error value.
124 *
125 * Since: 2.12.0
126 **/
gnutls_pubkey_init(gnutls_pubkey_t * key)127 int gnutls_pubkey_init(gnutls_pubkey_t * key)
128 {
129 FAIL_IF_LIB_ERROR;
130
131 *key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st));
132 if (*key == NULL) {
133 gnutls_assert();
134 return GNUTLS_E_MEMORY_ERROR;
135 }
136
137 return 0;
138 }
139
140 /**
141 * gnutls_pubkey_deinit:
142 * @key: The key to be deinitialized
143 *
144 * This function will deinitialize a public key structure.
145 *
146 * Since: 2.12.0
147 **/
gnutls_pubkey_deinit(gnutls_pubkey_t key)148 void gnutls_pubkey_deinit(gnutls_pubkey_t key)
149 {
150 if (!key)
151 return;
152 gnutls_pk_params_release(&key->params);
153 gnutls_free(key);
154 }
155
156 /**
157 * gnutls_pubkey_import_x509:
158 * @key: The public key
159 * @crt: The certificate to be imported
160 * @flags: should be zero
161 *
162 * This function will import the given public key to the abstract
163 * #gnutls_pubkey_t type.
164 *
165 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
166 * negative error value.
167 *
168 * Since: 2.12.0
169 **/
170 int
gnutls_pubkey_import_x509(gnutls_pubkey_t key,gnutls_x509_crt_t crt,unsigned int flags)171 gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt,
172 unsigned int flags)
173 {
174 int ret;
175
176 gnutls_pk_params_release(&key->params);
177 /* params initialized in _gnutls_x509_crt_get_mpis */
178
179 ret = gnutls_x509_crt_get_pk_algorithm(crt, &key->bits);
180 if (ret < 0)
181 return gnutls_assert_val(ret);
182
183 key->params.algo = ret;
184
185 ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL);
186 if (ret < 0)
187 key->key_usage = 0;
188
189 ret = _gnutls_x509_crt_get_mpis(crt, &key->params);
190 if (ret < 0) {
191 gnutls_assert();
192 return ret;
193 }
194
195 return 0;
196 }
197
198 /**
199 * gnutls_pubkey_import_x509_crq:
200 * @key: The public key
201 * @crq: The certificate to be imported
202 * @flags: should be zero
203 *
204 * This function will import the given public key to the abstract
205 * #gnutls_pubkey_t type.
206 *
207 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
208 * negative error value.
209 *
210 * Since: 3.1.5
211 **/
212 int
gnutls_pubkey_import_x509_crq(gnutls_pubkey_t key,gnutls_x509_crq_t crq,unsigned int flags)213 gnutls_pubkey_import_x509_crq(gnutls_pubkey_t key, gnutls_x509_crq_t crq,
214 unsigned int flags)
215 {
216 int ret;
217
218 gnutls_pk_params_release(&key->params);
219 /* params initialized in _gnutls_x509_crq_get_mpis */
220
221 key->params.algo = gnutls_x509_crq_get_pk_algorithm(crq, &key->bits);
222
223 ret = gnutls_x509_crq_get_key_usage(crq, &key->key_usage, NULL);
224 if (ret < 0)
225 key->key_usage = 0;
226
227 ret = _gnutls_x509_crq_get_mpis(crq, &key->params);
228 if (ret < 0) {
229 gnutls_assert();
230 return ret;
231 }
232
233 return 0;
234 }
235
236 /**
237 * gnutls_pubkey_import_privkey:
238 * @key: The public key
239 * @pkey: The private key
240 * @usage: GNUTLS_KEY_* key usage flags.
241 * @flags: should be zero
242 *
243 * Imports the public key from a private. This function will import
244 * the given public key to the abstract #gnutls_pubkey_t type.
245 *
246 * Note that in certain keys this operation may not be possible, e.g.,
247 * in other than RSA PKCS#11 keys.
248 *
249 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
250 * negative error value.
251 *
252 * Since: 2.12.0
253 **/
254 int
gnutls_pubkey_import_privkey(gnutls_pubkey_t key,gnutls_privkey_t pkey,unsigned int usage,unsigned int flags)255 gnutls_pubkey_import_privkey(gnutls_pubkey_t key, gnutls_privkey_t pkey,
256 unsigned int usage, unsigned int flags)
257 {
258 gnutls_pk_params_release(&key->params);
259 gnutls_pk_params_init(&key->params);
260
261 key->key_usage = usage;
262 key->params.algo = gnutls_privkey_get_pk_algorithm(pkey, &key->bits);
263
264 return _gnutls_privkey_get_public_mpis(pkey, &key->params);
265 }
266
267 /**
268 * gnutls_pubkey_get_preferred_hash_algorithm:
269 * @key: Holds the certificate
270 * @hash: The result of the call with the hash algorithm used for signature
271 * @mand: If non zero it means that the algorithm MUST use this hash. May be NULL.
272 *
273 * This function will read the certificate and return the appropriate digest
274 * algorithm to use for signing with this certificate. Some certificates (i.e.
275 * DSA might not be able to sign without the preferred algorithm).
276 *
277 * To get the signature algorithm instead of just the hash use gnutls_pk_to_sign()
278 * with the algorithm of the certificate/key and the provided @hash.
279 *
280 * Returns: the 0 if the hash algorithm is found. A negative error code is
281 * returned on error.
282 *
283 * Since: 2.12.0
284 **/
285 int
gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,gnutls_digest_algorithm_t * hash,unsigned int * mand)286 gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
287 gnutls_digest_algorithm_t *
288 hash, unsigned int *mand)
289 {
290 int ret;
291 const mac_entry_st *me;
292
293 if (key == NULL) {
294 gnutls_assert();
295 return GNUTLS_E_INVALID_REQUEST;
296 }
297
298 if (mand)
299 *mand = 0;
300
301 switch (key->params.algo) {
302 case GNUTLS_PK_DSA:
303 if (mand)
304 *mand = 1;
305 FALLTHROUGH;
306 case GNUTLS_PK_ECDSA:
307
308 me = _gnutls_dsa_q_to_hash(&key->params, NULL);
309 if (hash)
310 *hash = (gnutls_digest_algorithm_t)me->id;
311
312 ret = 0;
313 break;
314 case GNUTLS_PK_EDDSA_ED25519:
315 if (hash)
316 *hash = GNUTLS_DIG_SHA512;
317
318 ret = 0;
319 break;
320 case GNUTLS_PK_EDDSA_ED448:
321 if (hash)
322 *hash = GNUTLS_DIG_SHAKE_256;
323
324 ret = 0;
325 break;
326 case GNUTLS_PK_GOST_01:
327 case GNUTLS_PK_GOST_12_256:
328 case GNUTLS_PK_GOST_12_512:
329 if (hash)
330 *hash = _gnutls_gost_digest(key->params.algo);
331 if (mand)
332 *mand = 1;
333
334 ret = 0;
335 break;
336 case GNUTLS_PK_RSA_PSS:
337 if (mand && key->params.spki.rsa_pss_dig)
338 *mand = 1;
339
340 if (hash) {
341 if (key->params.spki.rsa_pss_dig) {
342 *hash = key->params.spki.rsa_pss_dig;
343 } else {
344 *hash = _gnutls_pk_bits_to_sha_hash(pubkey_to_bits(&key->params));
345 }
346 }
347 ret = 0;
348 break;
349 case GNUTLS_PK_RSA:
350 if (hash)
351 *hash = _gnutls_pk_bits_to_sha_hash(pubkey_to_bits(&key->params));
352 ret = 0;
353 break;
354
355 default:
356 gnutls_assert();
357 ret = GNUTLS_E_INTERNAL_ERROR;
358 }
359
360 return ret;
361 }
362
363 #ifdef ENABLE_PKCS11
364
365 /* The EC_PARAMS attribute can contain either printable string with curve name
366 * or OID defined in RFC 8410 */
367 static int
gnutls_pubkey_parse_ecc_eddsa_params(const gnutls_datum_t * parameters,gnutls_ecc_curve_t * outcurve)368 gnutls_pubkey_parse_ecc_eddsa_params(const gnutls_datum_t *parameters,
369 gnutls_ecc_curve_t *outcurve)
370 {
371 gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID;
372 ASN1_TYPE asn1 = ASN1_TYPE_EMPTY;
373 unsigned int etype = ASN1_ETYPE_INVALID;
374 char str[MAX_OID_SIZE];
375 int str_size;
376 int ret;
377
378 ret = asn1_create_element(_gnutls_get_gnutls_asn(),
379 "GNUTLS.pkcs-11-ec-Parameters", &asn1);
380 if (ret != ASN1_SUCCESS) {
381 gnutls_assert();
382 return _gnutls_asn2err(ret);
383 }
384
385 ret = asn1_der_decoding(&asn1, parameters->data, parameters->size,
386 NULL);
387 if (ret != ASN1_SUCCESS) {
388 gnutls_assert();
389 ret = _gnutls_asn2err(ret);
390 goto cleanup;
391 }
392
393 /* Read the type of choice.
394 */
395 str_size = sizeof(str) - 1;
396 ret = asn1_read_value(asn1, "", str, &str_size);
397 if (ret != ASN1_SUCCESS) {
398 gnutls_assert();
399 ret = _gnutls_asn2err(ret);
400 goto cleanup;
401 }
402 str[str_size] = 0;
403
404 /* Convert the choice to enum type */
405 if (strcmp(str, "oId") == 0) {
406 etype = ASN1_ETYPE_OBJECT_ID;
407 } else if (strcmp(str, "curveName") == 0) {
408 etype = ASN1_ETYPE_PRINTABLE_STRING;
409 }
410
411 str_size = sizeof(str) - 1;
412 switch (etype) {
413 case ASN1_ETYPE_OBJECT_ID:
414 ret = asn1_read_value(asn1, "oId", str, &str_size);
415 if (ret != ASN1_SUCCESS) {
416 gnutls_assert();
417 ret = _gnutls_asn2err(ret);
418 break;
419 }
420
421 curve = gnutls_oid_to_ecc_curve(str);
422 if (curve != GNUTLS_ECC_CURVE_ED25519 &&
423 curve != GNUTLS_ECC_CURVE_ED448) {
424 _gnutls_debug_log("Curve %s is not supported for EdDSA\n", str);
425 gnutls_assert();
426 curve = GNUTLS_ECC_CURVE_INVALID;
427 ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
428 break;
429 }
430
431 ret = GNUTLS_E_SUCCESS;
432 break;
433
434 case ASN1_ETYPE_PRINTABLE_STRING:
435 ret = asn1_read_value(asn1, "curveName", str, &str_size);
436 if (ret != ASN1_SUCCESS) {
437 gnutls_assert();
438 ret = _gnutls_asn2err(ret);
439 break;
440 }
441
442 if (str_size == strlen("edwards25519") &&
443 strncmp(str, "edwards25519", str_size) == 0) {
444 curve = GNUTLS_ECC_CURVE_ED25519;
445 ret = GNUTLS_E_SUCCESS;
446 break;
447 } else if (str_size == strlen("edwards448") &&
448 strncmp(str, "edwards448", str_size) == 0) {
449 curve = GNUTLS_ECC_CURVE_ED448;
450 ret = GNUTLS_E_SUCCESS;
451 break;
452 }
453 /* FALLTHROUGH */
454
455 default:
456 /* Neither of CHOICEs found. Fail */
457 gnutls_assert();
458 ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
459 curve = GNUTLS_ECC_CURVE_INVALID;
460 break;
461 }
462
463
464 cleanup:
465 asn1_delete_structure(&asn1);
466 *outcurve = curve;
467 return ret;
468 }
469
470
471 static int
gnutls_pubkey_import_ecc_eddsa(gnutls_pubkey_t key,const gnutls_datum_t * parameters,const gnutls_datum_t * ecpoint)472 gnutls_pubkey_import_ecc_eddsa(gnutls_pubkey_t key,
473 const gnutls_datum_t * parameters,
474 const gnutls_datum_t * ecpoint)
475 {
476 int ret;
477
478 gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID;
479 gnutls_datum_t raw_point = {NULL, 0};
480
481 ret = gnutls_pubkey_parse_ecc_eddsa_params(parameters, &curve);
482 if (ret < 0) {
483 return gnutls_assert_val(ret);
484 }
485
486 ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
487 ecpoint->data, ecpoint->size,
488 &raw_point, 0);
489 if (ret < 0) {
490 gnutls_assert();
491 gnutls_free(raw_point.data);
492 return ret;
493 }
494 ret = gnutls_pubkey_import_ecc_raw(key, curve, &raw_point, NULL);
495
496 gnutls_free(raw_point.data);
497 return ret;
498 }
499
500 /**
501 * gnutls_pubkey_import_pkcs11:
502 * @key: The public key
503 * @obj: The parameters to be imported
504 * @flags: should be zero
505 *
506 * Imports a public key from a pkcs11 key. This function will import
507 * the given public key to the abstract #gnutls_pubkey_t type.
508 *
509 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
510 * negative error value.
511 *
512 * Since: 2.12.0
513 **/
514 int
gnutls_pubkey_import_pkcs11(gnutls_pubkey_t key,gnutls_pkcs11_obj_t obj,unsigned int flags)515 gnutls_pubkey_import_pkcs11(gnutls_pubkey_t key,
516 gnutls_pkcs11_obj_t obj, unsigned int flags)
517 {
518 int ret, type;
519
520 type = gnutls_pkcs11_obj_get_type(obj);
521 if (type != GNUTLS_PKCS11_OBJ_PUBKEY
522 && type != GNUTLS_PKCS11_OBJ_X509_CRT) {
523 gnutls_assert();
524 return GNUTLS_E_INVALID_REQUEST;
525 }
526
527 if (type == GNUTLS_PKCS11_OBJ_X509_CRT) {
528 gnutls_x509_crt_t xcrt;
529
530 ret = gnutls_x509_crt_init(&xcrt);
531 if (ret < 0) {
532 gnutls_assert()
533 return ret;
534 }
535
536 ret = gnutls_x509_crt_import_pkcs11(xcrt, obj);
537 if (ret < 0) {
538 gnutls_assert();
539 goto cleanup_crt;
540 }
541
542 ret = gnutls_pubkey_import_x509(key, xcrt, 0);
543 if (ret < 0) {
544 gnutls_assert();
545 goto cleanup_crt;
546 }
547
548 ret = gnutls_x509_crt_get_key_usage(xcrt, &key->key_usage, NULL);
549 if (ret < 0)
550 key->key_usage = 0;
551
552 ret = 0;
553 cleanup_crt:
554 gnutls_x509_crt_deinit(xcrt);
555 return ret;
556 }
557
558 key->key_usage = obj->key_usage;
559
560 switch (obj->pk_algorithm) {
561 case GNUTLS_PK_RSA:
562 case GNUTLS_PK_RSA_PSS:
563 ret = gnutls_pubkey_import_rsa_raw(key, &obj->pubkey[0],
564 &obj->pubkey[1]);
565 break;
566 case GNUTLS_PK_DSA:
567 ret = gnutls_pubkey_import_dsa_raw(key, &obj->pubkey[0],
568 &obj->pubkey[1],
569 &obj->pubkey[2],
570 &obj->pubkey[3]);
571 break;
572 case GNUTLS_PK_EC:
573 ret = gnutls_pubkey_import_ecc_x962(key, &obj->pubkey[0],
574 &obj->pubkey[1]);
575 break;
576 case GNUTLS_PK_EDDSA_ED25519:
577 ret = gnutls_pubkey_import_ecc_eddsa(key, &obj->pubkey[0],
578 &obj->pubkey[1]);
579 break;
580 default:
581 gnutls_assert();
582 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
583 }
584
585 if (ret < 0) {
586 gnutls_assert();
587 return ret;
588 }
589
590 return 0;
591 }
592
593 #endif /* ENABLE_PKCS11 */
594
595 /**
596 * gnutls_pubkey_export:
597 * @key: Holds the certificate
598 * @format: the format of output params. One of PEM or DER.
599 * @output_data: will contain a certificate PEM or DER encoded
600 * @output_data_size: holds the size of output_data (and will be
601 * replaced by the actual size of parameters)
602 *
603 * This function will export the public key to DER or PEM format.
604 * The contents of the exported data is the SubjectPublicKeyInfo
605 * X.509 structure.
606 *
607 * If the buffer provided is not long enough to hold the output, then
608 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
609 * be returned.
610 *
611 * If the structure is PEM encoded, it will have a header
612 * of "BEGIN CERTIFICATE".
613 *
614 * Returns: In case of failure a negative error code will be
615 * returned, and 0 on success.
616 *
617 * Since: 2.12.0
618 **/
619 int
gnutls_pubkey_export(gnutls_pubkey_t key,gnutls_x509_crt_fmt_t format,void * output_data,size_t * output_data_size)620 gnutls_pubkey_export(gnutls_pubkey_t key,
621 gnutls_x509_crt_fmt_t format, void *output_data,
622 size_t * output_data_size)
623 {
624 int result;
625 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
626
627 if (key == NULL) {
628 gnutls_assert();
629 return GNUTLS_E_INVALID_REQUEST;
630 }
631
632 if ((result = asn1_create_element
633 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
634 != ASN1_SUCCESS) {
635 gnutls_assert();
636 return _gnutls_asn2err(result);
637 }
638
639 result =
640 _gnutls_x509_encode_and_copy_PKI_params(spk, "",
641 &key->params);
642 if (result < 0) {
643 gnutls_assert();
644 goto cleanup;
645 }
646
647 result = _gnutls_x509_export_int_named(spk, "",
648 format, PEM_PK,
649 output_data,
650 output_data_size);
651 if (result < 0) {
652 gnutls_assert();
653 goto cleanup;
654 }
655
656 result = 0;
657
658 cleanup:
659 asn1_delete_structure(&spk);
660
661 return result;
662 }
663
664 /**
665 * gnutls_pubkey_export2:
666 * @key: Holds the certificate
667 * @format: the format of output params. One of PEM or DER.
668 * @out: will contain a certificate PEM or DER encoded
669 *
670 * This function will export the public key to DER or PEM format.
671 * The contents of the exported data is the SubjectPublicKeyInfo
672 * X.509 structure.
673 *
674 * The output buffer will be allocated using gnutls_malloc().
675 *
676 * If the structure is PEM encoded, it will have a header
677 * of "BEGIN CERTIFICATE".
678 *
679 * Returns: In case of failure a negative error code will be
680 * returned, and 0 on success.
681 *
682 * Since: 3.1.3
683 **/
684 int
gnutls_pubkey_export2(gnutls_pubkey_t key,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)685 gnutls_pubkey_export2(gnutls_pubkey_t key,
686 gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
687 {
688 int result;
689 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
690
691 if (key == NULL) {
692 gnutls_assert();
693 return GNUTLS_E_INVALID_REQUEST;
694 }
695
696 if ((result = asn1_create_element
697 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
698 != ASN1_SUCCESS) {
699 gnutls_assert();
700 return _gnutls_asn2err(result);
701 }
702
703 result =
704 _gnutls_x509_encode_and_copy_PKI_params(spk, "",
705 &key->params);
706 if (result < 0) {
707 gnutls_assert();
708 goto cleanup;
709 }
710
711 result = _gnutls_x509_export_int_named2(spk, "",
712 format, PEM_PK,
713 out);
714 if (result < 0) {
715 gnutls_assert();
716 goto cleanup;
717 }
718
719 result = 0;
720
721 cleanup:
722 asn1_delete_structure(&spk);
723
724 return result;
725 }
726
727 /**
728 * gnutls_pubkey_get_key_id:
729 * @key: Holds the public key
730 * @flags: should be one of the flags from %gnutls_keyid_flags_t
731 * @output_data: will contain the key ID
732 * @output_data_size: holds the size of output_data (and will be
733 * replaced by the actual size of parameters)
734 *
735 * This function will return a unique ID that depends on the public
736 * key parameters. This ID can be used in checking whether a
737 * certificate corresponds to the given public key.
738 *
739 * If the buffer provided is not long enough to hold the output, then
740 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
741 * be returned. The output will normally be a SHA-1 hash output,
742 * which is 20 bytes.
743 *
744 * Returns: In case of failure a negative error code will be
745 * returned, and 0 on success.
746 *
747 * Since: 2.12.0
748 **/
749 int
gnutls_pubkey_get_key_id(gnutls_pubkey_t key,unsigned int flags,unsigned char * output_data,size_t * output_data_size)750 gnutls_pubkey_get_key_id(gnutls_pubkey_t key, unsigned int flags,
751 unsigned char *output_data,
752 size_t * output_data_size)
753 {
754 int ret = 0;
755
756 if (key == NULL) {
757 gnutls_assert();
758 return GNUTLS_E_INVALID_REQUEST;
759 }
760
761 ret =
762 _gnutls_get_key_id(&key->params,
763 output_data, output_data_size, flags);
764 if (ret < 0) {
765 gnutls_assert();
766 return ret;
767 }
768
769 return 0;
770 }
771
772 /**
773 * gnutls_pubkey_export_rsa_raw2:
774 * @key: Holds the certificate
775 * @m: will hold the modulus (may be %NULL)
776 * @e: will hold the public exponent (may be %NULL)
777 * @flags: flags from %gnutls_abstract_export_flags_t
778 *
779 * This function will export the RSA public key's parameters found in
780 * the given structure. The new parameters will be allocated using
781 * gnutls_malloc() and will be stored in the appropriate datum.
782 *
783 * This function allows for %NULL parameters since 3.4.1.
784 *
785 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
786 *
787 * Since: 3.6.0
788 **/
789 int
gnutls_pubkey_export_rsa_raw2(gnutls_pubkey_t key,gnutls_datum_t * m,gnutls_datum_t * e,unsigned flags)790 gnutls_pubkey_export_rsa_raw2(gnutls_pubkey_t key,
791 gnutls_datum_t * m, gnutls_datum_t * e,
792 unsigned flags)
793 {
794 int ret;
795 mpi_dprint_func dprint = _gnutls_mpi_dprint_lz;
796
797 if (flags & GNUTLS_EXPORT_FLAG_NO_LZ)
798 dprint = _gnutls_mpi_dprint;
799
800 if (key == NULL) {
801 gnutls_assert();
802 return GNUTLS_E_INVALID_REQUEST;
803 }
804
805 if (!GNUTLS_PK_IS_RSA(key->params.algo)) {
806 gnutls_assert();
807 return GNUTLS_E_INVALID_REQUEST;
808 }
809
810 if (m) {
811 ret = dprint(key->params.params[0], m);
812 if (ret < 0) {
813 gnutls_assert();
814 return ret;
815 }
816 }
817
818 if (e) {
819 ret = dprint(key->params.params[1], e);
820 if (ret < 0) {
821 gnutls_assert();
822 _gnutls_free_datum(m);
823 return ret;
824 }
825 }
826
827 return 0;
828 }
829
830 /**
831 * gnutls_pubkey_export_rsa_raw:
832 * @key: Holds the certificate
833 * @m: will hold the modulus (may be %NULL)
834 * @e: will hold the public exponent (may be %NULL)
835 *
836 * This function will export the RSA public key's parameters found in
837 * the given structure. The new parameters will be allocated using
838 * gnutls_malloc() and will be stored in the appropriate datum.
839 *
840 * This function allows for %NULL parameters since 3.4.1.
841 *
842 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
843 *
844 * Since: 3.3.0
845 **/
846 int
gnutls_pubkey_export_rsa_raw(gnutls_pubkey_t key,gnutls_datum_t * m,gnutls_datum_t * e)847 gnutls_pubkey_export_rsa_raw(gnutls_pubkey_t key,
848 gnutls_datum_t * m, gnutls_datum_t * e)
849 {
850 return gnutls_pubkey_export_rsa_raw2(key, m, e, 0);
851 }
852
853
854 /**
855 * gnutls_pubkey_export_dsa_raw:
856 * @key: Holds the public key
857 * @p: will hold the p (may be %NULL)
858 * @q: will hold the q (may be %NULL)
859 * @g: will hold the g (may be %NULL)
860 * @y: will hold the y (may be %NULL)
861 *
862 * This function will export the DSA public key's parameters found in
863 * the given certificate. The new parameters will be allocated using
864 * gnutls_malloc() and will be stored in the appropriate datum.
865 *
866 * This function allows for %NULL parameters since 3.4.1.
867 *
868 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
869 *
870 * Since: 3.3.0
871 **/
872 int
gnutls_pubkey_export_dsa_raw(gnutls_pubkey_t key,gnutls_datum_t * p,gnutls_datum_t * q,gnutls_datum_t * g,gnutls_datum_t * y)873 gnutls_pubkey_export_dsa_raw(gnutls_pubkey_t key,
874 gnutls_datum_t * p, gnutls_datum_t * q,
875 gnutls_datum_t * g, gnutls_datum_t * y)
876 {
877 return gnutls_pubkey_export_dsa_raw2(key, p, q, g, y, 0);
878 }
879
880 /**
881 * gnutls_pubkey_export_dsa_raw2:
882 * @key: Holds the public key
883 * @p: will hold the p (may be %NULL)
884 * @q: will hold the q (may be %NULL)
885 * @g: will hold the g (may be %NULL)
886 * @y: will hold the y (may be %NULL)
887 * @flags: flags from %gnutls_abstract_export_flags_t
888 *
889 * This function will export the DSA public key's parameters found in
890 * the given certificate. The new parameters will be allocated using
891 * gnutls_malloc() and will be stored in the appropriate datum.
892 *
893 * This function allows for %NULL parameters since 3.4.1.
894 *
895 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
896 *
897 * Since: 3.6.0
898 **/
899 int
gnutls_pubkey_export_dsa_raw2(gnutls_pubkey_t key,gnutls_datum_t * p,gnutls_datum_t * q,gnutls_datum_t * g,gnutls_datum_t * y,unsigned flags)900 gnutls_pubkey_export_dsa_raw2(gnutls_pubkey_t key,
901 gnutls_datum_t * p, gnutls_datum_t * q,
902 gnutls_datum_t * g, gnutls_datum_t * y,
903 unsigned flags)
904 {
905 int ret;
906 mpi_dprint_func dprint = _gnutls_mpi_dprint_lz;
907
908 if (flags & GNUTLS_EXPORT_FLAG_NO_LZ)
909 dprint = _gnutls_mpi_dprint;
910
911 if (key == NULL) {
912 gnutls_assert();
913 return GNUTLS_E_INVALID_REQUEST;
914 }
915
916 if (key->params.algo != GNUTLS_PK_DSA) {
917 gnutls_assert();
918 return GNUTLS_E_INVALID_REQUEST;
919 }
920
921 /* P */
922 if (p) {
923 ret = dprint(key->params.params[0], p);
924 if (ret < 0) {
925 gnutls_assert();
926 return ret;
927 }
928 }
929
930 /* Q */
931 if (q) {
932 ret = dprint(key->params.params[1], q);
933 if (ret < 0) {
934 gnutls_assert();
935 _gnutls_free_datum(p);
936 return ret;
937 }
938 }
939
940 /* G */
941 if (g) {
942 ret = dprint(key->params.params[2], g);
943 if (ret < 0) {
944 gnutls_assert();
945 _gnutls_free_datum(p);
946 _gnutls_free_datum(q);
947 return ret;
948 }
949 }
950
951 /* Y */
952 if (y) {
953 ret = dprint(key->params.params[3], y);
954 if (ret < 0) {
955 gnutls_assert();
956 _gnutls_free_datum(p);
957 _gnutls_free_datum(g);
958 _gnutls_free_datum(q);
959 return ret;
960 }
961 }
962
963 return 0;
964 }
965
966 /**
967 * gnutls_pubkey_export_ecc_raw:
968 * @key: Holds the public key
969 * @curve: will hold the curve (may be %NULL)
970 * @x: will hold x-coordinate (may be %NULL)
971 * @y: will hold y-coordinate (may be %NULL)
972 *
973 * This function will export the ECC public key's parameters found in
974 * the given key. The new parameters will be allocated using
975 * gnutls_malloc() and will be stored in the appropriate datum.
976 *
977 * In EdDSA curves the @y parameter will be %NULL and the other parameters
978 * will be in the native format for the curve.
979 *
980 * This function allows for %NULL parameters since 3.4.1.
981 *
982 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
983 *
984 * Since: 3.0
985 **/
986 int
gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key,gnutls_ecc_curve_t * curve,gnutls_datum_t * x,gnutls_datum_t * y)987 gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key,
988 gnutls_ecc_curve_t * curve,
989 gnutls_datum_t * x, gnutls_datum_t * y)
990 {
991 return gnutls_pubkey_export_ecc_raw2(key, curve, x, y, 0);
992 }
993
994 /**
995 * gnutls_pubkey_export_ecc_raw2:
996 * @key: Holds the public key
997 * @curve: will hold the curve (may be %NULL)
998 * @x: will hold x-coordinate (may be %NULL)
999 * @y: will hold y-coordinate (may be %NULL)
1000 * @flags: flags from %gnutls_abstract_export_flags_t
1001 *
1002 * This function will export the ECC public key's parameters found in
1003 * the given key. The new parameters will be allocated using
1004 * gnutls_malloc() and will be stored in the appropriate datum.
1005 *
1006 * In EdDSA curves the @y parameter will be %NULL and the other parameters
1007 * will be in the native format for the curve.
1008 *
1009 * This function allows for %NULL parameters since 3.4.1.
1010 *
1011 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1012 *
1013 * Since: 3.6.0
1014 **/
1015 int
gnutls_pubkey_export_ecc_raw2(gnutls_pubkey_t key,gnutls_ecc_curve_t * curve,gnutls_datum_t * x,gnutls_datum_t * y,unsigned int flags)1016 gnutls_pubkey_export_ecc_raw2(gnutls_pubkey_t key,
1017 gnutls_ecc_curve_t * curve,
1018 gnutls_datum_t * x, gnutls_datum_t * y,
1019 unsigned int flags)
1020 {
1021 int ret;
1022 mpi_dprint_func dprint = _gnutls_mpi_dprint_lz;
1023
1024 if (flags & GNUTLS_EXPORT_FLAG_NO_LZ)
1025 dprint = _gnutls_mpi_dprint;
1026
1027 if (key == NULL) {
1028 gnutls_assert();
1029 return GNUTLS_E_INVALID_REQUEST;
1030 }
1031
1032 if (!IS_EC(key->params.algo)) {
1033 gnutls_assert();
1034 return GNUTLS_E_INVALID_REQUEST;
1035 }
1036
1037 if (curve)
1038 *curve = key->params.curve;
1039
1040 if (key->params.algo == GNUTLS_PK_EDDSA_ED25519 ||
1041 key->params.algo == GNUTLS_PK_EDDSA_ED448) {
1042 if (x) {
1043 ret = _gnutls_set_datum(x, key->params.raw_pub.data, key->params.raw_pub.size);
1044 if (ret < 0)
1045 return gnutls_assert_val(ret);
1046 }
1047 if (y) {
1048 y->data = NULL;
1049 y->size = 0;
1050 }
1051 return 0;
1052 }
1053
1054 /* ECDSA */
1055
1056 /* X */
1057 if (x) {
1058 ret = dprint(key->params.params[ECC_X], x);
1059 if (ret < 0) {
1060 gnutls_assert();
1061 return ret;
1062 }
1063 }
1064
1065 /* Y */
1066 if (y) {
1067 ret = dprint(key->params.params[ECC_Y], y);
1068 if (ret < 0) {
1069 gnutls_assert();
1070 _gnutls_free_datum(x);
1071 return ret;
1072 }
1073 }
1074
1075 return 0;
1076 }
1077
1078 /**
1079 * gnutls_pubkey_export_ecc_x962:
1080 * @key: Holds the public key
1081 * @parameters: DER encoding of an ANSI X9.62 parameters
1082 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1083 *
1084 * This function will export the ECC public key's parameters found in
1085 * the given certificate. The new parameters will be allocated using
1086 * gnutls_malloc() and will be stored in the appropriate datum.
1087 *
1088 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1089 *
1090 * Since: 3.3.0
1091 **/
gnutls_pubkey_export_ecc_x962(gnutls_pubkey_t key,gnutls_datum_t * parameters,gnutls_datum_t * ecpoint)1092 int gnutls_pubkey_export_ecc_x962(gnutls_pubkey_t key,
1093 gnutls_datum_t * parameters,
1094 gnutls_datum_t * ecpoint)
1095 {
1096 int ret;
1097 gnutls_datum_t raw_point = {NULL,0};
1098
1099 if (key == NULL || key->params.algo != GNUTLS_PK_EC)
1100 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1101
1102 ret = _gnutls_x509_write_ecc_pubkey(&key->params, &raw_point);
1103 if (ret < 0)
1104 return gnutls_assert_val(ret);
1105
1106 ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
1107 raw_point.data, raw_point.size, ecpoint);
1108 if (ret < 0) {
1109 gnutls_assert();
1110 goto cleanup;
1111 }
1112
1113 ret = _gnutls_x509_write_ecc_params(key->params.curve, parameters);
1114 if (ret < 0) {
1115 _gnutls_free_datum(ecpoint);
1116 gnutls_assert();
1117 goto cleanup;
1118 }
1119
1120 ret = 0;
1121 cleanup:
1122 gnutls_free(raw_point.data);
1123 return ret;
1124 }
1125
1126 /**
1127 * gnutls_pubkey_export_gost_raw2:
1128 * @key: Holds the public key
1129 * @curve: will hold the curve (may be %NULL)
1130 * @digest: will hold the curve (may be %NULL)
1131 * @paramset: will hold the parameters id (may be %NULL)
1132 * @x: will hold the x-coordinate (may be %NULL)
1133 * @y: will hold the y-coordinate (may be %NULL)
1134 * @flags: flags from %gnutls_abstract_export_flags_t
1135 *
1136 * This function will export the GOST public key's parameters found in
1137 * the given key. The new parameters will be allocated using
1138 * gnutls_malloc() and will be stored in the appropriate datum.
1139 *
1140 * Note: parameters will be stored with least significant byte first. On
1141 * version 3.6.3 this was incorrectly returned in big-endian format.
1142 *
1143 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
1144 *
1145 * Since: 3.6.3
1146 **/
1147 int
gnutls_pubkey_export_gost_raw2(gnutls_pubkey_t key,gnutls_ecc_curve_t * curve,gnutls_digest_algorithm_t * digest,gnutls_gost_paramset_t * paramset,gnutls_datum_t * x,gnutls_datum_t * y,unsigned int flags)1148 gnutls_pubkey_export_gost_raw2(gnutls_pubkey_t key,
1149 gnutls_ecc_curve_t * curve,
1150 gnutls_digest_algorithm_t * digest,
1151 gnutls_gost_paramset_t * paramset,
1152 gnutls_datum_t * x, gnutls_datum_t * y,
1153 unsigned int flags)
1154 {
1155 int ret;
1156
1157 mpi_dprint_func dprint = _gnutls_mpi_dprint_le;
1158
1159 if (key == NULL) {
1160 gnutls_assert();
1161 return GNUTLS_E_INVALID_REQUEST;
1162 }
1163
1164 if (key->params.algo != GNUTLS_PK_GOST_01 &&
1165 key->params.algo != GNUTLS_PK_GOST_12_256 &&
1166 key->params.algo != GNUTLS_PK_GOST_12_512) {
1167 gnutls_assert();
1168 return GNUTLS_E_INVALID_REQUEST;
1169 }
1170
1171 if (curve)
1172 *curve = key->params.curve;
1173
1174 if (digest)
1175 *digest = _gnutls_gost_digest(key->params.algo);
1176
1177 if (paramset)
1178 *paramset = key->params.gost_params;
1179
1180 /* X */
1181 if (x) {
1182 ret = dprint(key->params.params[GOST_X], x);
1183 if (ret < 0) {
1184 gnutls_assert();
1185 return ret;
1186 }
1187 }
1188
1189 /* Y */
1190 if (y) {
1191 ret = dprint(key->params.params[GOST_Y], y);
1192 if (ret < 0) {
1193 gnutls_assert();
1194 _gnutls_free_datum(x);
1195 return ret;
1196 }
1197 }
1198
1199 return 0;
1200 }
1201
1202 /**
1203 * gnutls_pubkey_import:
1204 * @key: The public key.
1205 * @data: The DER or PEM encoded certificate.
1206 * @format: One of DER or PEM
1207 *
1208 * This function will import the provided public key in
1209 * a SubjectPublicKeyInfo X.509 structure to a native
1210 * %gnutls_pubkey_t type. The output will be stored
1211 * in @key. If the public key is PEM encoded it should have a header
1212 * of "PUBLIC KEY".
1213 *
1214 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1215 * negative error value.
1216 *
1217 * Since: 2.12.0
1218 **/
1219 int
gnutls_pubkey_import(gnutls_pubkey_t key,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format)1220 gnutls_pubkey_import(gnutls_pubkey_t key,
1221 const gnutls_datum_t * data,
1222 gnutls_x509_crt_fmt_t format)
1223 {
1224 int result = 0, need_free = 0;
1225 gnutls_datum_t _data;
1226 ASN1_TYPE spk;
1227
1228 if (key == NULL) {
1229 gnutls_assert();
1230 return GNUTLS_E_INVALID_REQUEST;
1231 }
1232
1233 _data.data = data->data;
1234 _data.size = data->size;
1235
1236 /* If the Certificate is in PEM format then decode it
1237 */
1238 if (format == GNUTLS_X509_FMT_PEM) {
1239 /* Try the first header */
1240 result =
1241 _gnutls_fbase64_decode(PEM_PK, data->data,
1242 data->size, &_data);
1243
1244 if (result < 0) {
1245 gnutls_assert();
1246 return result;
1247 }
1248
1249 need_free = 1;
1250 }
1251
1252 if ((result = asn1_create_element
1253 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
1254 != ASN1_SUCCESS) {
1255 gnutls_assert();
1256 result = _gnutls_asn2err(result);
1257 goto cleanup;
1258 }
1259
1260 result = _asn1_strict_der_decode(&spk, _data.data, _data.size, NULL);
1261 if (result != ASN1_SUCCESS) {
1262 gnutls_assert();
1263 result = _gnutls_asn2err(result);
1264 goto cleanup;
1265 }
1266
1267 result = _gnutls_get_asn_mpis(spk, "", &key->params);
1268 if (result < 0) {
1269 gnutls_assert();
1270 goto cleanup;
1271 }
1272
1273 key->bits = pubkey_to_bits(&key->params);
1274 result = 0;
1275
1276 cleanup:
1277 asn1_delete_structure(&spk);
1278
1279 if (need_free)
1280 _gnutls_free_datum(&_data);
1281 return result;
1282 }
1283
1284 /**
1285 * gnutls_x509_crt_set_pubkey:
1286 * @crt: should contain a #gnutls_x509_crt_t type
1287 * @key: holds a public key
1288 *
1289 * This function will set the public parameters from the given public
1290 * key to the certificate. The @key can be deallocated after that.
1291 *
1292 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1293 * negative error value.
1294 *
1295 * Since: 2.12.0
1296 **/
gnutls_x509_crt_set_pubkey(gnutls_x509_crt_t crt,gnutls_pubkey_t key)1297 int gnutls_x509_crt_set_pubkey(gnutls_x509_crt_t crt, gnutls_pubkey_t key)
1298 {
1299 int result;
1300
1301 if (crt == NULL) {
1302 gnutls_assert();
1303 return GNUTLS_E_INVALID_REQUEST;
1304 }
1305
1306 result = _gnutls_x509_encode_and_copy_PKI_params(crt->cert,
1307 "tbsCertificate.subjectPublicKeyInfo",
1308 &key->params);
1309
1310 if (result < 0) {
1311 gnutls_assert();
1312 return result;
1313 }
1314
1315 if (key->key_usage)
1316 gnutls_x509_crt_set_key_usage(crt, key->key_usage);
1317
1318 return 0;
1319 }
1320
1321 /**
1322 * gnutls_x509_crq_set_pubkey:
1323 * @crq: should contain a #gnutls_x509_crq_t type
1324 * @key: holds a public key
1325 *
1326 * This function will set the public parameters from the given public
1327 * key to the request. The @key can be deallocated after that.
1328 *
1329 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1330 * negative error value.
1331 *
1332 * Since: 2.12.0
1333 **/
gnutls_x509_crq_set_pubkey(gnutls_x509_crq_t crq,gnutls_pubkey_t key)1334 int gnutls_x509_crq_set_pubkey(gnutls_x509_crq_t crq, gnutls_pubkey_t key)
1335 {
1336 int result;
1337
1338 if (crq == NULL) {
1339 gnutls_assert();
1340 return GNUTLS_E_INVALID_REQUEST;
1341 }
1342
1343 result = _gnutls_x509_encode_and_copy_PKI_params
1344 (crq->crq,
1345 "certificationRequestInfo.subjectPKInfo",
1346 &key->params);
1347
1348 if (result < 0) {
1349 gnutls_assert();
1350 return result;
1351 }
1352
1353 if (key->key_usage)
1354 gnutls_x509_crq_set_key_usage(crq, key->key_usage);
1355
1356 return 0;
1357 }
1358
1359 /**
1360 * gnutls_pubkey_set_key_usage:
1361 * @key: a certificate of type #gnutls_x509_crt_t
1362 * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1363 *
1364 * This function will set the key usage flags of the public key. This
1365 * is only useful if the key is to be exported to a certificate or
1366 * certificate request.
1367 *
1368 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1369 * negative error value.
1370 *
1371 * Since: 2.12.0
1372 **/
gnutls_pubkey_set_key_usage(gnutls_pubkey_t key,unsigned int usage)1373 int gnutls_pubkey_set_key_usage(gnutls_pubkey_t key, unsigned int usage)
1374 {
1375 key->key_usage = usage;
1376
1377 return 0;
1378 }
1379
1380 #ifdef ENABLE_PKCS11
1381
1382 #if 0
1383 /**
1384 * gnutls_pubkey_import_pkcs11_url:
1385 * @key: A key of type #gnutls_pubkey_t
1386 * @url: A PKCS 11 url
1387 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1388 *
1389 * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t
1390 * structure.
1391 *
1392 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1393 * negative error value.
1394 *
1395 * Since: 2.12.0
1396 **/
1397 int
1398 gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url,
1399 unsigned int flags)
1400 {
1401 int x;
1402 }
1403 #endif
1404
1405 static int
_gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key,const char * url,unsigned int flags)1406 _gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url,
1407 unsigned int flags)
1408 {
1409 gnutls_pkcs11_obj_t pcrt;
1410 int ret;
1411
1412 ret = gnutls_pkcs11_obj_init(&pcrt);
1413 if (ret < 0) {
1414 gnutls_assert();
1415 return ret;
1416 }
1417
1418 if (key->pin.cb)
1419 gnutls_pkcs11_obj_set_pin_function(pcrt, key->pin.cb,
1420 key->pin.data);
1421
1422 ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PUBKEY);
1423 if (ret < 0) {
1424 gnutls_assert();
1425 goto cleanup;
1426 }
1427
1428 ret = gnutls_pubkey_import_pkcs11(key, pcrt, flags);
1429 if (ret < 0) {
1430 gnutls_assert();
1431 goto cleanup;
1432 }
1433
1434 ret = 0;
1435 cleanup:
1436
1437 gnutls_pkcs11_obj_deinit(pcrt);
1438
1439 return ret;
1440 }
1441
1442 #endif /* ENABLE_PKCS11 */
1443
1444 /**
1445 * gnutls_pubkey_import_url:
1446 * @key: A key of type #gnutls_pubkey_t
1447 * @url: A PKCS 11 url
1448 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1449 *
1450 * This function will import a public key from the provided URL.
1451 *
1452 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1453 * negative error value.
1454 *
1455 * Since: 3.1.0
1456 **/
1457 int
gnutls_pubkey_import_url(gnutls_pubkey_t key,const char * url,unsigned int flags)1458 gnutls_pubkey_import_url(gnutls_pubkey_t key, const char *url,
1459 unsigned int flags)
1460 {
1461 unsigned i;
1462
1463 for (i=0;i<_gnutls_custom_urls_size;i++) {
1464 if (strncmp(url, _gnutls_custom_urls[i].name, _gnutls_custom_urls[i].name_size) == 0) {
1465 if (_gnutls_custom_urls[i].import_pubkey)
1466 return _gnutls_custom_urls[i].import_pubkey(key, url, flags);
1467 }
1468 }
1469
1470 if (strncmp(url, PKCS11_URL, PKCS11_URL_SIZE) == 0)
1471 #ifdef ENABLE_PKCS11
1472 return _gnutls_pubkey_import_pkcs11_url(key, url, flags);
1473 #else
1474 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1475 #endif
1476
1477 if (strncmp(url, TPMKEY_URL, TPMKEY_URL_SIZE) == 0)
1478 #ifdef HAVE_TROUSERS
1479 return gnutls_pubkey_import_tpm_url(key, url, NULL, 0);
1480 #else
1481 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1482 #endif
1483
1484 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1485 }
1486
1487 /**
1488 * gnutls_pubkey_import_rsa_raw:
1489 * @key: The key
1490 * @m: holds the modulus
1491 * @e: holds the public exponent
1492 *
1493 * This function will replace the parameters in the given structure.
1494 * The new parameters should be stored in the appropriate
1495 * gnutls_datum.
1496 *
1497 * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1498 *
1499 * Since: 2.12.0
1500 **/
1501 int
gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key,const gnutls_datum_t * m,const gnutls_datum_t * e)1502 gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key,
1503 const gnutls_datum_t * m,
1504 const gnutls_datum_t * e)
1505 {
1506 if (key == NULL) {
1507 gnutls_assert();
1508 return GNUTLS_E_INVALID_REQUEST;
1509 }
1510
1511 gnutls_pk_params_release(&key->params);
1512 gnutls_pk_params_init(&key->params);
1513
1514 if (_gnutls_mpi_init_scan_nz(&key->params.params[0], m->data, m->size)) {
1515 gnutls_assert();
1516 return GNUTLS_E_MPI_SCAN_FAILED;
1517 }
1518
1519 if (_gnutls_mpi_init_scan_nz(&key->params.params[1], e->data, e->size)) {
1520 gnutls_assert();
1521 _gnutls_mpi_release(&key->params.params[0]);
1522 return GNUTLS_E_MPI_SCAN_FAILED;
1523 }
1524
1525 key->params.params_nr = RSA_PUBLIC_PARAMS;
1526 key->params.algo = GNUTLS_PK_RSA;
1527 key->bits = pubkey_to_bits(&key->params);
1528
1529 return 0;
1530 }
1531
1532 /**
1533 * gnutls_pubkey_import_ecc_raw:
1534 * @key: The structure to store the parsed key
1535 * @curve: holds the curve
1536 * @x: holds the x-coordinate
1537 * @y: holds the y-coordinate
1538 *
1539 * This function will convert the given elliptic curve parameters to a
1540 * #gnutls_pubkey_t. The output will be stored in @key.
1541 *
1542 * In EdDSA curves the @y parameter should be %NULL and the @x parameter must
1543 * be the value in the native format for the curve.
1544 *
1545 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1546 * negative error value.
1547 *
1548 * Since: 3.0
1549 **/
1550 int
gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key,gnutls_ecc_curve_t curve,const gnutls_datum_t * x,const gnutls_datum_t * y)1551 gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key,
1552 gnutls_ecc_curve_t curve,
1553 const gnutls_datum_t * x,
1554 const gnutls_datum_t * y)
1555 {
1556 int ret;
1557
1558 if (key == NULL || x == NULL) {
1559 gnutls_assert();
1560 return GNUTLS_E_INVALID_REQUEST;
1561 }
1562
1563 gnutls_pk_params_release(&key->params);
1564 gnutls_pk_params_init(&key->params);
1565
1566 if (curve_is_eddsa(curve)) {
1567 unsigned size = gnutls_ecc_curve_get_size(curve);
1568 if (x->size != size) {
1569 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1570 goto cleanup;
1571 }
1572
1573 ret = _gnutls_set_datum(&key->params.raw_pub, x->data, x->size);
1574 if (ret < 0) {
1575 gnutls_assert();
1576 goto cleanup;
1577 }
1578
1579 switch (curve) {
1580 case GNUTLS_ECC_CURVE_ED25519:
1581 key->params.algo = GNUTLS_PK_EDDSA_ED25519;
1582 break;
1583 case GNUTLS_ECC_CURVE_ED448:
1584 key->params.algo = GNUTLS_PK_EDDSA_ED448;
1585 break;
1586 default:
1587 break;
1588 }
1589 key->params.curve = curve;
1590 key->bits = pubkey_to_bits(&key->params);
1591
1592 return 0;
1593 }
1594
1595 /* ECDSA */
1596 if (y == NULL) {
1597 gnutls_assert();
1598 return GNUTLS_E_INVALID_REQUEST;
1599 }
1600
1601 key->params.curve = curve;
1602
1603 if (_gnutls_mpi_init_scan_nz
1604 (&key->params.params[ECC_X], x->data, x->size)) {
1605 gnutls_assert();
1606 ret = GNUTLS_E_MPI_SCAN_FAILED;
1607 goto cleanup;
1608 }
1609 key->params.params_nr++;
1610
1611 if (_gnutls_mpi_init_scan_nz
1612 (&key->params.params[ECC_Y], y->data, y->size)) {
1613 gnutls_assert();
1614 ret = GNUTLS_E_MPI_SCAN_FAILED;
1615 goto cleanup;
1616 }
1617 key->params.params_nr++;
1618 key->params.algo = GNUTLS_PK_ECDSA;
1619 key->bits = pubkey_to_bits(&key->params);
1620
1621 return 0;
1622
1623 cleanup:
1624 gnutls_pk_params_release(&key->params);
1625 return ret;
1626 }
1627
1628 /**
1629 * gnutls_pubkey_import_ecc_x962:
1630 * @key: The structure to store the parsed key
1631 * @parameters: DER encoding of an ANSI X9.62 parameters
1632 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1633 *
1634 * This function will convert the given elliptic curve parameters to a
1635 * #gnutls_pubkey_t. The output will be stored in @key.
1636 *
1637 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1638 * negative error value.
1639 *
1640 * Since: 3.0
1641 **/
1642 int
gnutls_pubkey_import_ecc_x962(gnutls_pubkey_t key,const gnutls_datum_t * parameters,const gnutls_datum_t * ecpoint)1643 gnutls_pubkey_import_ecc_x962(gnutls_pubkey_t key,
1644 const gnutls_datum_t * parameters,
1645 const gnutls_datum_t * ecpoint)
1646 {
1647 int ret;
1648 gnutls_datum_t raw_point = {NULL,0};
1649
1650 if (key == NULL) {
1651 gnutls_assert();
1652 return GNUTLS_E_INVALID_REQUEST;
1653 }
1654
1655 gnutls_pk_params_release(&key->params);
1656 gnutls_pk_params_init(&key->params);
1657
1658 key->params.params_nr = 0;
1659
1660 ret =
1661 _gnutls_x509_read_ecc_params(parameters->data,
1662 parameters->size, &key->params.curve);
1663 if (ret < 0) {
1664 gnutls_assert();
1665 goto cleanup;
1666 }
1667
1668 ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
1669 ecpoint->data, ecpoint->size, &raw_point, 0);
1670 if (ret < 0) {
1671 gnutls_assert();
1672 goto cleanup;
1673 }
1674
1675 ret = _gnutls_ecc_ansi_x962_import(raw_point.data, raw_point.size,
1676 &key->params.params[ECC_X],
1677 &key->params.params[ECC_Y]);
1678 if (ret < 0) {
1679 gnutls_assert();
1680 goto cleanup;
1681 }
1682 key->params.params_nr += 2;
1683 key->params.algo = GNUTLS_PK_EC;
1684
1685 gnutls_free(raw_point.data);
1686 return 0;
1687
1688 cleanup:
1689 gnutls_pk_params_release(&key->params);
1690 gnutls_free(raw_point.data);
1691 return ret;
1692 }
1693
1694 /**
1695 * gnutls_pubkey_import_gost_raw:
1696 * @key: The structure to store the parsed key
1697 * @curve: holds the curve
1698 * @digest: holds the digest
1699 * @paramset: holds the parameters id
1700 * @x: holds the x-coordinate
1701 * @y: holds the y-coordinate
1702 *
1703 * This function will convert the given GOST public key's parameters to a
1704 * #gnutls_pubkey_t. The output will be stored in @key. @digest should be
1705 * one of GNUTLS_DIG_GOSR_94, GNUTLS_DIG_STREEBOG_256 or
1706 * GNUTLS_DIG_STREEBOG_512. If @paramset is set to GNUTLS_GOST_PARAMSET_UNKNOWN
1707 * default one will be selected depending on @digest.
1708 *
1709 * Note: parameters should be stored with least significant byte first. On
1710 * version 3.6.3 big-endian format was used incorrectly.
1711 *
1712 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1713 * negative error value.
1714 *
1715 * Since: 3.6.3
1716 **/
1717 int
gnutls_pubkey_import_gost_raw(gnutls_pubkey_t key,gnutls_ecc_curve_t curve,gnutls_digest_algorithm_t digest,gnutls_gost_paramset_t paramset,const gnutls_datum_t * x,const gnutls_datum_t * y)1718 gnutls_pubkey_import_gost_raw(gnutls_pubkey_t key,
1719 gnutls_ecc_curve_t curve,
1720 gnutls_digest_algorithm_t digest,
1721 gnutls_gost_paramset_t paramset,
1722 const gnutls_datum_t * x,
1723 const gnutls_datum_t * y)
1724 {
1725 int ret;
1726 gnutls_pk_algorithm_t pk_algo;
1727
1728 if (key == NULL) {
1729 gnutls_assert();
1730 return GNUTLS_E_INVALID_REQUEST;
1731 }
1732
1733 pk_algo = _gnutls_digest_gost(digest);
1734 if (pk_algo == GNUTLS_PK_UNKNOWN)
1735 return GNUTLS_E_ILLEGAL_PARAMETER;
1736
1737 if (paramset == GNUTLS_GOST_PARAMSET_UNKNOWN)
1738 paramset = _gnutls_gost_paramset_default(pk_algo);
1739
1740 gnutls_pk_params_release(&key->params);
1741 gnutls_pk_params_init(&key->params);
1742
1743 key->params.curve = curve;
1744 key->params.gost_params = paramset;
1745
1746 if (_gnutls_mpi_init_scan_le
1747 (&key->params.params[GOST_X], x->data, x->size)) {
1748 gnutls_assert();
1749 ret = GNUTLS_E_MPI_SCAN_FAILED;
1750 goto cleanup;
1751 }
1752 key->params.params_nr++;
1753
1754 if (_gnutls_mpi_init_scan_le
1755 (&key->params.params[GOST_Y], y->data, y->size)) {
1756 gnutls_assert();
1757 ret = GNUTLS_E_MPI_SCAN_FAILED;
1758 goto cleanup;
1759 }
1760 key->params.params_nr++;
1761 key->params.algo = pk_algo;
1762
1763 return 0;
1764
1765 cleanup:
1766 gnutls_pk_params_release(&key->params);
1767 return ret;
1768 }
1769
1770 /**
1771 * gnutls_pubkey_import_dsa_raw:
1772 * @key: The structure to store the parsed key
1773 * @p: holds the p
1774 * @q: holds the q
1775 * @g: holds the g
1776 * @y: holds the y
1777 *
1778 * This function will convert the given DSA raw parameters to the
1779 * native #gnutls_pubkey_t format. The output will be stored
1780 * in @key.
1781 *
1782 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1783 * negative error value.
1784 *
1785 * Since: 2.12.0
1786 **/
1787 int
gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,const gnutls_datum_t * p,const gnutls_datum_t * q,const gnutls_datum_t * g,const gnutls_datum_t * y)1788 gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,
1789 const gnutls_datum_t * p,
1790 const gnutls_datum_t * q,
1791 const gnutls_datum_t * g,
1792 const gnutls_datum_t * y)
1793 {
1794 size_t siz = 0;
1795
1796 if (key == NULL) {
1797 gnutls_assert();
1798 return GNUTLS_E_INVALID_REQUEST;
1799 }
1800
1801 gnutls_pk_params_release(&key->params);
1802 gnutls_pk_params_init(&key->params);
1803
1804 siz = p->size;
1805 if (_gnutls_mpi_init_scan_nz(&key->params.params[0], p->data, siz)) {
1806 gnutls_assert();
1807 return GNUTLS_E_MPI_SCAN_FAILED;
1808 }
1809
1810 siz = q->size;
1811 if (_gnutls_mpi_init_scan_nz(&key->params.params[1], q->data, siz)) {
1812 gnutls_assert();
1813 _gnutls_mpi_release(&key->params.params[0]);
1814 return GNUTLS_E_MPI_SCAN_FAILED;
1815 }
1816
1817 siz = g->size;
1818 if (_gnutls_mpi_init_scan_nz(&key->params.params[2], g->data, siz)) {
1819 gnutls_assert();
1820 _gnutls_mpi_release(&key->params.params[1]);
1821 _gnutls_mpi_release(&key->params.params[0]);
1822 return GNUTLS_E_MPI_SCAN_FAILED;
1823 }
1824
1825 siz = y->size;
1826 if (_gnutls_mpi_init_scan_nz(&key->params.params[3], y->data, siz)) {
1827 gnutls_assert();
1828 _gnutls_mpi_release(&key->params.params[2]);
1829 _gnutls_mpi_release(&key->params.params[1]);
1830 _gnutls_mpi_release(&key->params.params[0]);
1831 return GNUTLS_E_MPI_SCAN_FAILED;
1832 }
1833
1834 key->params.params_nr = DSA_PUBLIC_PARAMS;
1835 key->params.algo = GNUTLS_PK_DSA;
1836 key->bits = pubkey_to_bits(&key->params);
1837
1838 return 0;
1839
1840 }
1841
1842 /* Updates the gnutls_x509_spki_st parameters based on the signature
1843 * information, and reports any incompatibilities between the existing
1844 * parameters (if any) with the signature algorithm */
1845 static
fixup_spki_params(const gnutls_pk_params_st * key_params,const gnutls_sign_entry_st * se,const mac_entry_st * me,gnutls_x509_spki_st * params)1846 int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_entry_st *se,
1847 const mac_entry_st *me, gnutls_x509_spki_st *params)
1848 {
1849 unsigned bits;
1850
1851 if (se->pk != key_params->algo) {
1852 if (!sign_supports_priv_pk_algorithm(se, key_params->algo)) {
1853 _gnutls_debug_log("have key: %s/%d, with sign %s/%d\n",
1854 gnutls_pk_get_name(key_params->algo), key_params->algo,
1855 se->name, se->id);
1856 return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
1857 }
1858 }
1859
1860 if (params->pk == GNUTLS_PK_RSA_PSS) {
1861 int ret;
1862 if (!GNUTLS_PK_IS_RSA(key_params->algo))
1863 return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
1864
1865 /* The requested sign algorithm is RSA-PSS, while the
1866 * pubkey doesn't include parameter information. Fill
1867 * it with the same way as gnutls_privkey_sign*. */
1868 if (key_params->algo == GNUTLS_PK_RSA || params->rsa_pss_dig == 0) {
1869 bits = pubkey_to_bits(key_params);
1870 params->rsa_pss_dig = se->hash;
1871 ret = _gnutls_find_rsa_pss_salt_size(bits, me, 0);
1872 if (ret < 0)
1873 return gnutls_assert_val(ret);
1874
1875 params->salt_size = ret;
1876 }
1877
1878 if (params->rsa_pss_dig != se->hash)
1879 return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
1880 }
1881
1882 return 0;
1883 }
1884
1885 /**
1886 * gnutls_pubkey_verify_data2:
1887 * @pubkey: Holds the public key
1888 * @algo: The signature algorithm used
1889 * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
1890 * @data: holds the signed data
1891 * @signature: contains the signature
1892 *
1893 * This function will verify the given signed data, using the
1894 * parameters from the certificate.
1895 *
1896 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1897 * is returned, and zero or positive code on success. For known to be insecure
1898 * signatures this function will return %GNUTLS_E_INSUFFICIENT_SECURITY unless
1899 * the flag %GNUTLS_VERIFY_ALLOW_BROKEN is specified.
1900 *
1901 * Since: 3.0
1902 **/
1903 int
gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey,gnutls_sign_algorithm_t algo,unsigned int flags,const gnutls_datum_t * data,const gnutls_datum_t * signature)1904 gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey,
1905 gnutls_sign_algorithm_t algo,
1906 unsigned int flags,
1907 const gnutls_datum_t * data,
1908 const gnutls_datum_t * signature)
1909 {
1910 int ret;
1911 const mac_entry_st *me;
1912 gnutls_x509_spki_st params;
1913 const gnutls_sign_entry_st *se;
1914
1915 if (pubkey == NULL) {
1916 gnutls_assert();
1917 return GNUTLS_E_INVALID_REQUEST;
1918 }
1919
1920 if (flags & GNUTLS_VERIFY_USE_TLS1_RSA)
1921 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1922
1923 memcpy(¶ms, &pubkey->params.spki, sizeof(gnutls_x509_spki_st));
1924
1925 se = _gnutls_sign_to_entry(algo);
1926 if (se == NULL)
1927 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1928
1929 ret = pubkey_supports_sig(pubkey, se);
1930 if (ret < 0)
1931 return gnutls_assert_val(ret);
1932
1933 params.pk = se->pk;
1934
1935 me = hash_to_entry(se->hash);
1936 if (me == NULL && !_gnutls_pk_is_not_prehashed(se->pk))
1937 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1938
1939 ret = pubkey_verify_data(se, me, data, signature, &pubkey->params,
1940 ¶ms, flags);
1941 if (ret < 0) {
1942 gnutls_assert();
1943 return ret;
1944 }
1945
1946 return 0;
1947 }
1948
1949 /**
1950 * gnutls_pubkey_verify_hash2:
1951 * @key: Holds the public key
1952 * @algo: The signature algorithm used
1953 * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
1954 * @hash: holds the hash digest to be verified
1955 * @signature: contains the signature
1956 *
1957 * This function will verify the given signed digest, using the
1958 * parameters from the public key. Note that unlike gnutls_privkey_sign_hash(),
1959 * this function accepts a signature algorithm instead of a digest algorithm.
1960 * You can use gnutls_pk_to_sign() to get the appropriate value.
1961 *
1962 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1963 * is returned, and zero or positive code on success. For known to be insecure
1964 * signatures this function will return %GNUTLS_E_INSUFFICIENT_SECURITY unless
1965 * the flag %GNUTLS_VERIFY_ALLOW_BROKEN is specified.
1966 *
1967 * Since: 3.0
1968 **/
1969 int
gnutls_pubkey_verify_hash2(gnutls_pubkey_t key,gnutls_sign_algorithm_t algo,unsigned int flags,const gnutls_datum_t * hash,const gnutls_datum_t * signature)1970 gnutls_pubkey_verify_hash2(gnutls_pubkey_t key,
1971 gnutls_sign_algorithm_t algo,
1972 unsigned int flags,
1973 const gnutls_datum_t * hash,
1974 const gnutls_datum_t * signature)
1975 {
1976 const mac_entry_st *me;
1977 gnutls_x509_spki_st params;
1978 const gnutls_sign_entry_st *se;
1979 int ret;
1980
1981 if (key == NULL) {
1982 gnutls_assert();
1983 return GNUTLS_E_INVALID_REQUEST;
1984 }
1985
1986 if (_gnutls_pk_is_not_prehashed(key->params.algo)) {
1987 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1988 }
1989
1990 memcpy(¶ms, &key->params.spki, sizeof(gnutls_x509_spki_st));
1991
1992 if (flags & GNUTLS_VERIFY_USE_TLS1_RSA) {
1993 if (!GNUTLS_PK_IS_RSA(key->params.algo))
1994 return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
1995 params.pk = GNUTLS_PK_RSA;
1996 /* we do not check for insecure algorithms with this flag */
1997 return _gnutls_pk_verify(params.pk, hash, signature,
1998 &key->params, ¶ms);
1999 } else {
2000 se = _gnutls_sign_to_entry(algo);
2001 if (se == NULL)
2002 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2003
2004 ret = pubkey_supports_sig(key, se);
2005 if (ret < 0)
2006 return gnutls_assert_val(ret);
2007
2008 params.pk = se->pk;
2009
2010 me = hash_to_entry(se->hash);
2011 if (me == NULL && !_gnutls_pk_is_not_prehashed(se->pk))
2012 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2013
2014 ret = pubkey_verify_hashed_data(se, me, hash, signature,
2015 &key->params,
2016 ¶ms, flags);
2017 if (ret < 0) {
2018 gnutls_assert();
2019 return ret;
2020 }
2021 }
2022
2023 return 0;
2024 }
2025
2026 /**
2027 * gnutls_pubkey_encrypt_data:
2028 * @key: Holds the public key
2029 * @flags: should be 0 for now
2030 * @plaintext: The data to be encrypted
2031 * @ciphertext: contains the encrypted data
2032 *
2033 * This function will encrypt the given data, using the public
2034 * key. On success the @ciphertext will be allocated using gnutls_malloc().
2035 *
2036 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2037 * negative error value.
2038 *
2039 * Since: 3.0
2040 **/
2041 int
gnutls_pubkey_encrypt_data(gnutls_pubkey_t key,unsigned int flags,const gnutls_datum_t * plaintext,gnutls_datum_t * ciphertext)2042 gnutls_pubkey_encrypt_data(gnutls_pubkey_t key, unsigned int flags,
2043 const gnutls_datum_t * plaintext,
2044 gnutls_datum_t * ciphertext)
2045 {
2046 if (key == NULL) {
2047 gnutls_assert();
2048 return GNUTLS_E_INVALID_REQUEST;
2049 }
2050
2051 return _gnutls_pk_encrypt(key->params.algo, ciphertext,
2052 plaintext, &key->params);
2053 }
2054
2055 static
pubkey_supports_sig(gnutls_pubkey_t pubkey,const gnutls_sign_entry_st * se)2056 int pubkey_supports_sig(gnutls_pubkey_t pubkey,
2057 const gnutls_sign_entry_st *se)
2058 {
2059 if (pubkey->params.algo == GNUTLS_PK_ECDSA && se->curve) {
2060 gnutls_ecc_curve_t curve = pubkey->params.curve;
2061
2062 if (curve != se->curve) {
2063 _gnutls_handshake_log("have key: ECDSA with %s/%d, with sign %s/%d\n",
2064 gnutls_ecc_curve_get_name(curve), (int)curve,
2065 se->name, se->id);
2066 return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
2067 }
2068 }
2069
2070 if (se->pk != pubkey->params.algo) { /* if the PK algorithm of the signature differs to the one on the pubkey */
2071 if (!sign_supports_priv_pk_algorithm(se, pubkey->params.algo)) {
2072 _gnutls_handshake_log("have key: %s/%d, with sign %s/%d\n",
2073 gnutls_pk_get_name(pubkey->params.algo), pubkey->params.algo,
2074 se->name, se->id);
2075 return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
2076 }
2077 }
2078
2079 return 0;
2080 }
2081
2082 /* Checks whether the public key given is compatible with the
2083 * signature algorithm used. The session is only used for audit logging, and
2084 * it may be null.
2085 */
_gnutls_pubkey_compatible_with_sig(gnutls_session_t session,gnutls_pubkey_t pubkey,const version_entry_st * ver,gnutls_sign_algorithm_t sign)2086 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session,
2087 gnutls_pubkey_t pubkey,
2088 const version_entry_st * ver,
2089 gnutls_sign_algorithm_t sign)
2090 {
2091 unsigned int hash_size = 0;
2092 unsigned int sig_hash_size;
2093 const mac_entry_st *me;
2094 const gnutls_sign_entry_st *se;
2095 int ret;
2096
2097 se = _gnutls_sign_to_entry(sign);
2098 if (se != NULL) {
2099 ret = pubkey_supports_sig(pubkey, se);
2100 if (ret < 0)
2101 return gnutls_assert_val(ret);
2102 } else if (_gnutls_version_has_selectable_sighash(ver)) {
2103 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2104 }
2105
2106 if (pubkey->params.algo == GNUTLS_PK_DSA) {
2107 me = _gnutls_dsa_q_to_hash(&pubkey->params, &hash_size);
2108
2109 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
2110 if (!_gnutls_version_has_selectable_sighash(ver)) {
2111 if (me->id != GNUTLS_MAC_SHA1)
2112 return
2113 gnutls_assert_val
2114 (GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
2115 } else if (se != NULL) {
2116 me = hash_to_entry(se->hash);
2117
2118 sig_hash_size = _gnutls_hash_get_algo_len(me);
2119 if (sig_hash_size < hash_size)
2120 _gnutls_audit_log(session,
2121 "The hash size used in signature (%u) is less than the expected (%u)\n",
2122 sig_hash_size,
2123 hash_size);
2124 }
2125
2126 } else if (pubkey->params.algo == GNUTLS_PK_ECDSA) {
2127 if (_gnutls_version_has_selectable_sighash(ver)
2128 && se != NULL) {
2129 _gnutls_dsa_q_to_hash(&pubkey->params, &hash_size);
2130
2131 me = hash_to_entry(se->hash);
2132
2133 sig_hash_size = _gnutls_hash_get_algo_len(me);
2134
2135 if (sig_hash_size < hash_size)
2136 _gnutls_audit_log(session,
2137 "The hash size used in signature (%u) is less than the expected (%u)\n",
2138 sig_hash_size,
2139 hash_size);
2140 }
2141
2142 } else if (pubkey->params.algo == GNUTLS_PK_GOST_01 ||
2143 pubkey->params.algo == GNUTLS_PK_GOST_12_256 ||
2144 pubkey->params.algo == GNUTLS_PK_GOST_12_512) {
2145 if (_gnutls_version_has_selectable_sighash(ver)
2146 && se != NULL) {
2147 if (_gnutls_gost_digest(pubkey->params.algo) != se->hash) {
2148 _gnutls_audit_log(session,
2149 "The hash algo used in signature (%u) is not expected (%u)\n",
2150 se->hash, _gnutls_gost_digest(pubkey->params.algo));
2151 return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
2152 }
2153 }
2154
2155 } else if (pubkey->params.algo == GNUTLS_PK_RSA_PSS) {
2156 if (!_gnutls_version_has_selectable_sighash(ver))
2157 /* this should not have happened */
2158 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
2159
2160 /* RSA PSS public keys are restricted to a single digest, i.e., signature */
2161
2162 if (pubkey->params.spki.rsa_pss_dig && pubkey->params.spki.rsa_pss_dig != se->hash) {
2163 return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
2164 }
2165 }
2166
2167 return 0;
2168 }
2169
2170 /* Returns the public key.
2171 */
2172 int
_gnutls_pubkey_get_mpis(gnutls_pubkey_t key,gnutls_pk_params_st * params)2173 _gnutls_pubkey_get_mpis(gnutls_pubkey_t key, gnutls_pk_params_st * params)
2174 {
2175 return _gnutls_pk_params_copy(params, &key->params);
2176 }
2177
2178 /* if hash==MD5 then we do RSA-MD5
2179 * if hash==SHA then we do RSA-SHA
2180 * params[0] is modulus
2181 * params[1] is public key
2182 */
2183 static int
_pkcs1_rsa_verify_sig(gnutls_pk_algorithm_t pk,const mac_entry_st * me,const gnutls_datum_t * text,const gnutls_datum_t * prehash,const gnutls_datum_t * signature,gnutls_pk_params_st * params,gnutls_x509_spki_st * sign_params)2184 _pkcs1_rsa_verify_sig(gnutls_pk_algorithm_t pk,
2185 const mac_entry_st * me,
2186 const gnutls_datum_t * text,
2187 const gnutls_datum_t * prehash,
2188 const gnutls_datum_t * signature,
2189 gnutls_pk_params_st * params,
2190 gnutls_x509_spki_st * sign_params)
2191 {
2192 int ret;
2193 uint8_t md[MAX_HASH_SIZE], *cmp;
2194 unsigned int digest_size;
2195 gnutls_datum_t d, di;
2196
2197 if (unlikely(me == NULL))
2198 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2199
2200 digest_size = _gnutls_hash_get_algo_len(me);
2201 if (prehash) {
2202 if (prehash->data == NULL || prehash->size != digest_size)
2203 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2204
2205 cmp = prehash->data;
2206 } else {
2207 if (!text) {
2208 gnutls_assert();
2209 return GNUTLS_E_INVALID_REQUEST;
2210 }
2211
2212 ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
2213 text->data, text->size, md);
2214 if (ret < 0) {
2215 gnutls_assert();
2216 return ret;
2217 }
2218
2219 cmp = md;
2220 }
2221
2222 d.data = cmp;
2223 d.size = digest_size;
2224
2225 if (pk == GNUTLS_PK_RSA) {
2226 /* decrypted is a BER encoded data of type DigestInfo
2227 */
2228 ret = encode_ber_digest_info(me, &d, &di);
2229 if (ret < 0)
2230 return gnutls_assert_val(ret);
2231
2232 ret = _gnutls_pk_verify(pk, &di, signature, params,
2233 sign_params);
2234 _gnutls_free_datum(&di);
2235 } else {
2236 ret = _gnutls_pk_verify(pk, &d, signature, params,
2237 sign_params);
2238 }
2239
2240 return ret;
2241 }
2242
2243 /* Hashes input data and verifies a signature.
2244 */
2245 static int
dsa_verify_hashed_data(gnutls_pk_algorithm_t pk,const mac_entry_st * algo,const gnutls_datum_t * hash,const gnutls_datum_t * signature,gnutls_pk_params_st * params,gnutls_x509_spki_st * sign_params)2246 dsa_verify_hashed_data(gnutls_pk_algorithm_t pk,
2247 const mac_entry_st * algo,
2248 const gnutls_datum_t * hash,
2249 const gnutls_datum_t * signature,
2250 gnutls_pk_params_st * params,
2251 gnutls_x509_spki_st * sign_params)
2252 {
2253 gnutls_datum_t digest;
2254 unsigned int hash_len;
2255
2256 if (algo == NULL)
2257 algo = _gnutls_dsa_q_to_hash(params, &hash_len);
2258 else
2259 hash_len = _gnutls_hash_get_algo_len(algo);
2260
2261 /* SHA1 or better allowed */
2262 if (!hash->data || hash->size < hash_len) {
2263 gnutls_assert();
2264 _gnutls_debug_log
2265 ("Hash size (%d) does not correspond to hash %s(%d) or better.\n",
2266 (int) hash->size, _gnutls_mac_get_name(algo),
2267 hash_len);
2268
2269 if (hash->size != 20) /* SHA1 is allowed */
2270 return
2271 gnutls_assert_val
2272 (GNUTLS_E_PK_SIG_VERIFY_FAILED);
2273 }
2274
2275 digest.data = hash->data;
2276 digest.size = hash->size;
2277
2278 return _gnutls_pk_verify(pk, &digest, signature, params, sign_params);
2279 }
2280
2281 static int
dsa_verify_data(gnutls_pk_algorithm_t pk,const mac_entry_st * algo,const gnutls_datum_t * data,const gnutls_datum_t * signature,gnutls_pk_params_st * params,gnutls_x509_spki_st * sign_params)2282 dsa_verify_data(gnutls_pk_algorithm_t pk,
2283 const mac_entry_st * algo,
2284 const gnutls_datum_t * data,
2285 const gnutls_datum_t * signature,
2286 gnutls_pk_params_st * params,
2287 gnutls_x509_spki_st * sign_params)
2288 {
2289 int ret;
2290 uint8_t _digest[MAX_HASH_SIZE];
2291 gnutls_datum_t digest;
2292
2293 if (algo == NULL)
2294 algo = _gnutls_dsa_q_to_hash(params, NULL);
2295
2296 ret = _gnutls_hash_fast((gnutls_digest_algorithm_t)algo->id,
2297 data->data, data->size, _digest);
2298 if (ret < 0)
2299 return gnutls_assert_val(ret);
2300
2301 digest.data = _digest;
2302 digest.size = _gnutls_hash_get_algo_len(algo);
2303
2304 return _gnutls_pk_verify(pk, &digest, signature, params, sign_params);
2305 }
2306
2307 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
2308 * not verified, or 1 otherwise.
2309 */
2310 static int
pubkey_verify_hashed_data(const gnutls_sign_entry_st * se,const mac_entry_st * me,const gnutls_datum_t * hash,const gnutls_datum_t * signature,gnutls_pk_params_st * params,gnutls_x509_spki_st * sign_params,unsigned flags)2311 pubkey_verify_hashed_data(const gnutls_sign_entry_st *se,
2312 const mac_entry_st *me,
2313 const gnutls_datum_t * hash,
2314 const gnutls_datum_t * signature,
2315 gnutls_pk_params_st * params,
2316 gnutls_x509_spki_st * sign_params,
2317 unsigned flags)
2318 {
2319 int ret;
2320
2321 if (unlikely(me==NULL))
2322 return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
2323
2324 ret = fixup_spki_params(params, se, me, sign_params);
2325 if (ret < 0)
2326 return gnutls_assert_val(ret);
2327
2328 switch (se->pk) {
2329 case GNUTLS_PK_RSA:
2330 case GNUTLS_PK_RSA_PSS:
2331
2332 if (_pkcs1_rsa_verify_sig
2333 (se->pk, me, NULL, hash, signature, params, sign_params) != 0)
2334 {
2335 gnutls_assert();
2336 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2337 }
2338
2339 break;
2340
2341 case GNUTLS_PK_ECDSA:
2342 case GNUTLS_PK_GOST_01:
2343 case GNUTLS_PK_GOST_12_256:
2344 case GNUTLS_PK_GOST_12_512:
2345 case GNUTLS_PK_DSA:
2346 if (dsa_verify_hashed_data
2347 (se->pk, me, hash, signature, params, sign_params) != 0) {
2348 gnutls_assert();
2349 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2350 }
2351
2352 break;
2353 default:
2354 gnutls_assert();
2355 return GNUTLS_E_INVALID_REQUEST;
2356
2357 }
2358
2359 if (_gnutls_sign_is_secure2(se, 0) == 0 && _gnutls_is_broken_sig_allowed(se, flags) == 0) {
2360 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
2361 }
2362
2363 return 1;
2364 }
2365
2366 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
2367 * not verified, or 1 otherwise.
2368 */
2369 int
pubkey_verify_data(const gnutls_sign_entry_st * se,const mac_entry_st * me,const gnutls_datum_t * data,const gnutls_datum_t * signature,gnutls_pk_params_st * params,gnutls_x509_spki_st * sign_params,unsigned flags)2370 pubkey_verify_data(const gnutls_sign_entry_st *se,
2371 const mac_entry_st *me,
2372 const gnutls_datum_t * data,
2373 const gnutls_datum_t * signature,
2374 gnutls_pk_params_st * params,
2375 gnutls_x509_spki_st * sign_params,
2376 unsigned flags)
2377 {
2378 int ret;
2379
2380 if (unlikely(me == NULL))
2381 return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
2382
2383 ret = fixup_spki_params(params, se, me, sign_params);
2384 if (ret < 0)
2385 return gnutls_assert_val(ret);
2386
2387 switch (se->pk) {
2388 case GNUTLS_PK_RSA:
2389 case GNUTLS_PK_RSA_PSS:
2390 if (_pkcs1_rsa_verify_sig
2391 (se->pk, me, data, NULL, signature, params, sign_params) != 0) {
2392 gnutls_assert();
2393 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2394 }
2395
2396 break;
2397
2398 case GNUTLS_PK_EDDSA_ED25519:
2399 case GNUTLS_PK_EDDSA_ED448:
2400 if (_gnutls_pk_verify(se->pk, data, signature, params, sign_params) != 0) {
2401 gnutls_assert();
2402 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2403 }
2404
2405 break;
2406
2407 case GNUTLS_PK_EC:
2408 case GNUTLS_PK_DSA:
2409 case GNUTLS_PK_GOST_01:
2410 case GNUTLS_PK_GOST_12_256:
2411 case GNUTLS_PK_GOST_12_512:
2412 if (dsa_verify_data
2413 (se->pk, me, data, signature, params, sign_params) != 0) {
2414 gnutls_assert();
2415 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2416 }
2417
2418 break;
2419 default:
2420 gnutls_assert();
2421 return GNUTLS_E_INVALID_REQUEST;
2422
2423 }
2424
2425 if (_gnutls_sign_is_secure2(se,0) == 0 && _gnutls_is_broken_sig_allowed(se, flags) == 0) {
2426 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
2427 }
2428
2429 return 1;
2430 }
2431
_gnutls_dsa_q_to_hash(const gnutls_pk_params_st * params,unsigned int * hash_len)2432 const mac_entry_st *_gnutls_dsa_q_to_hash(const gnutls_pk_params_st *
2433 params, unsigned int *hash_len)
2434 {
2435 int bits = 0;
2436 int ret;
2437
2438 if (params->algo == GNUTLS_PK_DSA)
2439 bits = _gnutls_mpi_get_nbits(params->params[1]);
2440 else if (params->algo == GNUTLS_PK_EC)
2441 bits = gnutls_ecc_curve_get_size(params->curve) * 8;
2442
2443 if (bits <= 160) {
2444 if (hash_len)
2445 *hash_len = 20;
2446 ret = GNUTLS_DIG_SHA1;
2447 } else if (bits <= 192) {
2448 if (hash_len)
2449 *hash_len = 24;
2450 ret = GNUTLS_DIG_SHA256;
2451 } else if (bits <= 224) {
2452 if (hash_len)
2453 *hash_len = 28;
2454 ret = GNUTLS_DIG_SHA256;
2455 } else if (bits <= 256) {
2456 if (hash_len)
2457 *hash_len = 32;
2458 ret = GNUTLS_DIG_SHA256;
2459 } else if (bits <= 384) {
2460 if (hash_len)
2461 *hash_len = 48;
2462 ret = GNUTLS_DIG_SHA384;
2463 } else {
2464 if (hash_len)
2465 *hash_len = 64;
2466 ret = GNUTLS_DIG_SHA512;
2467 }
2468
2469 return mac_to_entry(ret);
2470 }
2471
2472 /**
2473 * gnutls_pubkey_set_pin_function:
2474 * @key: A key of type #gnutls_pubkey_t
2475 * @fn: the callback
2476 * @userdata: data associated with the callback
2477 *
2478 * This function will set a callback function to be used when
2479 * required to access the object. This function overrides any other
2480 * global PIN functions.
2481 *
2482 * Note that this function must be called right after initialization
2483 * to have effect.
2484 *
2485 * Since: 3.1.0
2486 *
2487 **/
gnutls_pubkey_set_pin_function(gnutls_pubkey_t key,gnutls_pin_callback_t fn,void * userdata)2488 void gnutls_pubkey_set_pin_function(gnutls_pubkey_t key,
2489 gnutls_pin_callback_t fn,
2490 void *userdata)
2491 {
2492 key->pin.cb = fn;
2493 key->pin.data = userdata;
2494 }
2495
2496 /**
2497 * gnutls_pubkey_import_x509_raw:
2498 * @pkey: The public key
2499 * @data: The public key data to be imported
2500 * @format: The format of the public key
2501 * @flags: should be zero
2502 *
2503 * This function will import the given public key to the abstract
2504 * #gnutls_pubkey_t type.
2505 *
2506 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2507 * negative error value.
2508 *
2509 * Since: 3.1.3
2510 **/
gnutls_pubkey_import_x509_raw(gnutls_pubkey_t pkey,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format,unsigned int flags)2511 int gnutls_pubkey_import_x509_raw(gnutls_pubkey_t pkey,
2512 const gnutls_datum_t * data,
2513 gnutls_x509_crt_fmt_t format,
2514 unsigned int flags)
2515 {
2516 gnutls_x509_crt_t xpriv;
2517 int ret;
2518
2519 ret = gnutls_x509_crt_init(&xpriv);
2520 if (ret < 0)
2521 return gnutls_assert_val(ret);
2522
2523 ret = gnutls_x509_crt_import(xpriv, data, format);
2524 if (ret < 0) {
2525 gnutls_assert();
2526 goto cleanup;
2527 }
2528
2529 ret = gnutls_pubkey_import_x509(pkey, xpriv, flags);
2530 if (ret < 0) {
2531 gnutls_assert();
2532 goto cleanup;
2533 }
2534
2535 ret = 0;
2536
2537 cleanup:
2538 gnutls_x509_crt_deinit(xpriv);
2539
2540 return ret;
2541 }
2542
2543 /**
2544 * gnutls_pubkey_verify_params:
2545 * @key: should contain a #gnutls_pubkey_t type
2546 *
2547 * This function will verify the public key parameters.
2548 *
2549 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2550 * negative error value.
2551 *
2552 * Since: 3.3.0
2553 **/
gnutls_pubkey_verify_params(gnutls_pubkey_t key)2554 int gnutls_pubkey_verify_params(gnutls_pubkey_t key)
2555 {
2556 int ret;
2557
2558 ret = _gnutls_pk_verify_pub_params(key->params.algo, &key->params);
2559 if (ret < 0) {
2560 gnutls_assert();
2561 return ret;
2562 }
2563
2564 return 0;
2565 }
2566
2567 /**
2568 * gnutls_pubkey_get_spki:
2569 * @pubkey: a public key of type #gnutls_pubkey_t
2570 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_pubkey_spki_t
2571 * @flags: must be zero
2572 *
2573 * This function will return the public key information if available.
2574 * The provided @spki must be initialized.
2575 *
2576 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2577 * negative error value.
2578 *
2579 * Since: 3.6.0
2580 **/
2581 int
gnutls_pubkey_get_spki(gnutls_pubkey_t pubkey,gnutls_x509_spki_t spki,unsigned int flags)2582 gnutls_pubkey_get_spki(gnutls_pubkey_t pubkey, gnutls_x509_spki_t spki, unsigned int flags)
2583 {
2584 if (pubkey == NULL) {
2585 gnutls_assert();
2586 return GNUTLS_E_INVALID_REQUEST;
2587 }
2588
2589 if (pubkey->params.spki.pk == GNUTLS_PK_UNKNOWN)
2590 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2591
2592 memcpy(spki, &pubkey->params.spki, sizeof(gnutls_x509_spki_st));
2593
2594 return 0;
2595 }
2596
2597 /**
2598 * gnutls_pubkey_set_spki:
2599 * @pubkey: a public key of type #gnutls_pubkey_t
2600 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_pubkey_spki_t
2601 * @flags: must be zero
2602 *
2603 * This function will set the public key information.
2604 * The provided @spki must be initialized.
2605 *
2606 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2607 * negative error value.
2608 *
2609 * Since: 3.6.0
2610 **/
2611 int
gnutls_pubkey_set_spki(gnutls_pubkey_t pubkey,const gnutls_x509_spki_t spki,unsigned int flags)2612 gnutls_pubkey_set_spki(gnutls_pubkey_t pubkey, const gnutls_x509_spki_t spki, unsigned int flags)
2613 {
2614 if (pubkey == NULL) {
2615 gnutls_assert();
2616 return GNUTLS_E_INVALID_REQUEST;
2617 }
2618
2619 if (!_gnutls_pk_are_compat(pubkey->params.algo, spki->pk))
2620 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2621
2622 memcpy(&pubkey->params.spki, spki, sizeof(gnutls_x509_spki_st));
2623
2624 pubkey->params.algo = spki->pk;
2625
2626 return 0;
2627 }
2628