2 * GnuTLS public key support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 #include <gnutls_int.h>
22 #include <gnutls/pkcs11.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <pkcs11_int.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls_sig.h>
30 #include <gnutls_pk.h>
32 #include <openpgp/openpgp_int.h>
33 #include <gnutls_num.h>
34 #include <x509/common.h>
36 #include <abstract_int.h>
39 #include <gnutls_ecc.h>
42 #define OPENPGP_KEY_PRIMARY 2
43 #define OPENPGP_KEY_SUBKEY 1
46 int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params)
50 return _gnutls_mpi_get_nbits(params->params[0]);
52 return _gnutls_mpi_get_nbits(params->params[3]);
54 return gnutls_ecc_curve_get_size(params->flags) * 8;
61 * gnutls_pubkey_get_pk_algorithm:
62 * @key: should contain a #gnutls_pubkey_t structure
63 * @bits: If set will return the number of bits of the parameters (may be NULL)
65 * This function will return the public key algorithm of a public
66 * key and if possible will return a number of bits that indicates
67 * the security parameter of the key.
69 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
70 * success, or a negative error code on error.
74 int gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key, unsigned int *bits)
79 return key->pk_algorithm;
83 * gnutls_pubkey_get_key_usage:
84 * @key: should contain a #gnutls_pubkey_t structure
85 * @usage: If set will return the number of bits of the parameters (may be NULL)
87 * This function will return the key usage of the public key.
89 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
90 * negative error value.
94 int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage)
97 *usage = key->key_usage;
103 * gnutls_pubkey_init:
104 * @key: The structure to be initialized
106 * This function will initialize an public key structure.
108 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
109 * negative error value.
113 int gnutls_pubkey_init(gnutls_pubkey_t * key)
117 *key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st));
120 return GNUTLS_E_MEMORY_ERROR;
127 * gnutls_pubkey_deinit:
128 * @key: The structure to be deinitialized
130 * This function will deinitialize a public key structure.
134 void gnutls_pubkey_deinit(gnutls_pubkey_t key)
138 gnutls_pk_params_release(&key->params);
143 * gnutls_pubkey_import_x509:
144 * @key: The public key
145 * @crt: The certificate to be imported
146 * @flags: should be zero
148 * This function will import the given public key to the abstract
149 * #gnutls_pubkey_t structure.
151 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
152 * negative error value.
157 gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt,
162 gnutls_pk_params_release(&key->params);
163 /* params initialized in _gnutls_x509_crt_get_mpis */
166 gnutls_x509_crt_get_pk_algorithm(crt, &key->bits);
168 ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL);
172 ret = _gnutls_x509_crt_get_mpis(crt, &key->params);
182 * gnutls_pubkey_import_x509_crq:
183 * @key: The public key
184 * @crq: The certificate to be imported
185 * @flags: should be zero
187 * This function will import the given public key to the abstract
188 * #gnutls_pubkey_t structure.
190 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
191 * negative error value.
196 gnutls_pubkey_import_x509_crq(gnutls_pubkey_t key, gnutls_x509_crq_t crq,
201 gnutls_pk_params_release(&key->params);
202 /* params initialized in _gnutls_x509_crq_get_mpis */
205 gnutls_x509_crq_get_pk_algorithm(crq, &key->bits);
207 ret = gnutls_x509_crq_get_key_usage(crq, &key->key_usage, NULL);
211 ret = _gnutls_x509_crq_get_mpis(crq, &key->params);
221 * gnutls_pubkey_import_privkey:
222 * @key: The public key
223 * @pkey: The private key
224 * @usage: GNUTLS_KEY_* key usage flags.
225 * @flags: should be zero
227 * Imports the public key from a private. This function will import
228 * the given public key to the abstract #gnutls_pubkey_t structure.
230 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
231 * negative error value.
236 gnutls_pubkey_import_privkey(gnutls_pubkey_t key, gnutls_privkey_t pkey,
237 unsigned int usage, unsigned int flags)
239 gnutls_pk_params_release(&key->params);
240 gnutls_pk_params_init(&key->params);
243 gnutls_privkey_get_pk_algorithm(pkey, &key->bits);
245 key->key_usage = usage;
247 return _gnutls_privkey_get_public_mpis(pkey, &key->params);
251 * gnutls_pubkey_get_preferred_hash_algorithm:
252 * @key: Holds the certificate
253 * @hash: The result of the call with the hash algorithm used for signature
254 * @mand: If non zero it means that the algorithm MUST use this hash. May be NULL.
256 * This function will read the certifcate and return the appropriate digest
257 * algorithm to use for signing with this certificate. Some certificates (i.e.
258 * DSA might not be able to sign without the preferred algorithm).
260 * To get the signature algorithm instead of just the hash use gnutls_pk_to_sign()
261 * with the algorithm of the certificate/key and the provided @hash.
263 * Returns: the 0 if the hash algorithm is found. A negative error code is
269 gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
270 gnutls_digest_algorithm_t *
271 hash, unsigned int *mand)
274 const mac_entry_st *me;
278 return GNUTLS_E_INVALID_REQUEST;
284 switch (key->pk_algorithm) {
290 me = _gnutls_dsa_q_to_hash(key->pk_algorithm, &key->params, NULL);
292 *hash = (gnutls_digest_algorithm_t)me->id;
298 *hash = GNUTLS_DIG_SHA256;
304 ret = GNUTLS_E_INTERNAL_ERROR;
313 * gnutls_pubkey_import_pkcs11:
314 * @key: The public key
315 * @obj: The parameters to be imported
316 * @flags: should be zero
318 * Imports a public key from a pkcs11 key. This function will import
319 * the given public key to the abstract #gnutls_pubkey_t structure.
321 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
322 * negative error value.
327 gnutls_pubkey_import_pkcs11(gnutls_pubkey_t key,
328 gnutls_pkcs11_obj_t obj, unsigned int flags)
332 type = gnutls_pkcs11_obj_get_type(obj);
333 if (type != GNUTLS_PKCS11_OBJ_PUBKEY
334 && type != GNUTLS_PKCS11_OBJ_X509_CRT) {
336 return GNUTLS_E_INVALID_REQUEST;
339 if (type == GNUTLS_PKCS11_OBJ_X509_CRT) {
340 gnutls_x509_crt_t xcrt;
342 ret = gnutls_x509_crt_init(&xcrt);
348 ret = gnutls_x509_crt_import_pkcs11(xcrt, obj);
354 ret = gnutls_pubkey_import_x509(key, xcrt, 0);
360 gnutls_x509_crt_get_key_usage(xcrt, &key->key_usage, NULL);
364 gnutls_x509_crt_deinit(xcrt);
368 key->key_usage = obj->key_usage;
370 switch (obj->pk_algorithm) {
372 ret = gnutls_pubkey_import_rsa_raw(key, &obj->pubkey[0],
376 ret = gnutls_pubkey_import_dsa_raw(key, &obj->pubkey[0],
382 ret = gnutls_pubkey_import_ecc_x962(key, &obj->pubkey[0],
387 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
398 #endif /* ENABLE_PKCS11 */
400 #ifdef ENABLE_OPENPGP
403 * gnutls_pubkey_import_openpgp:
404 * @key: The public key
405 * @crt: The certificate to be imported
406 * @flags: should be zero
408 * Imports a public key from an openpgp key. This function will import
409 * the given public key to the abstract #gnutls_pubkey_t
410 * structure. The subkey set as preferred will be imported or the
411 * master key otherwise.
413 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
414 * negative error value.
419 gnutls_pubkey_import_openpgp(gnutls_pubkey_t key,
420 gnutls_openpgp_crt_t crt, unsigned int flags)
425 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
428 len = sizeof(key->openpgp_key_fpr);
430 gnutls_openpgp_crt_get_fingerprint(crt, key->openpgp_key_fpr,
433 return gnutls_assert_val(ret);
434 key->openpgp_key_fpr_set = 1;
436 ret = gnutls_openpgp_crt_get_preferred_key_id(crt, keyid);
437 if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR) {
439 gnutls_openpgp_crt_get_pk_algorithm(crt, &key->bits);
440 key->openpgp_key_id_set = OPENPGP_KEY_PRIMARY;
443 gnutls_openpgp_crt_get_key_id(crt,
444 key->openpgp_key_id);
446 return gnutls_assert_val(ret);
449 gnutls_openpgp_crt_get_key_usage(crt, &key->key_usage);
459 key->openpgp_key_id_set = OPENPGP_KEY_SUBKEY;
461 KEYID_IMPORT(kid32, keyid);
464 idx = gnutls_openpgp_crt_get_subkey_idx(crt, keyid);
467 gnutls_openpgp_crt_get_subkey_id(crt, idx,
468 key->openpgp_key_id);
470 return gnutls_assert_val(ret);
473 gnutls_openpgp_crt_get_subkey_usage(crt, idx,
479 gnutls_openpgp_crt_get_subkey_pk_algorithm(crt, idx,
483 ret = _gnutls_openpgp_crt_get_mpis(crt, k, &key->params);
485 return gnutls_assert_val(ret);
491 * gnutls_pubkey_get_openpgp_key_id:
492 * @key: Holds the public key
493 * @flags: should be 0 or %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT
494 * @output_data: will contain the key ID
495 * @output_data_size: holds the size of output_data (and will be
496 * replaced by the actual size of parameters)
497 * @subkey: Will be non zero if the key ID corresponds to a subkey
499 * This function returns the OpenPGP key ID of the corresponding key.
500 * The key is a unique ID that depends on the public
503 * If the flag %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT is specified
504 * this function returns the fingerprint of the master key.
506 * If the buffer provided is not long enough to hold the output, then
507 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
508 * be returned. The output is %GNUTLS_OPENPGP_KEYID_SIZE bytes long.
510 * Returns: In case of failure a negative error code will be
511 * returned, and 0 on success.
516 gnutls_pubkey_get_openpgp_key_id(gnutls_pubkey_t key, unsigned int flags,
517 unsigned char *output_data,
518 size_t * output_data_size,
519 unsigned int *subkey)
523 return GNUTLS_E_INVALID_REQUEST;
526 if (flags & GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT) {
527 if (*output_data_size < sizeof(key->openpgp_key_fpr)) {
528 *output_data_size = sizeof(key->openpgp_key_fpr);
531 (GNUTLS_E_SHORT_MEMORY_BUFFER);
534 if (key->openpgp_key_fpr_set == 0)
535 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
538 memcpy(output_data, key->openpgp_key_fpr,
539 sizeof(key->openpgp_key_fpr));
540 *output_data_size = sizeof(key->openpgp_key_fpr);
545 if (*output_data_size < sizeof(key->openpgp_key_id)) {
546 *output_data_size = sizeof(key->openpgp_key_id);
547 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
550 if (key->openpgp_key_id_set == 0)
551 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
554 if (key->openpgp_key_id_set == OPENPGP_KEY_SUBKEY)
561 memcpy(output_data, key->openpgp_key_id,
562 sizeof(key->openpgp_key_id));
564 *output_data_size = sizeof(key->openpgp_key_id);
570 * gnutls_pubkey_import_openpgp_raw:
571 * @pkey: The public key
572 * @data: The public key data to be imported
573 * @format: The format of the public key
574 * @keyid: The key id to use (optional)
575 * @flags: Should be zero
577 * This function will import the given public key to the abstract
578 * #gnutls_pubkey_t structure.
580 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
581 * negative error value.
585 int gnutls_pubkey_import_openpgp_raw(gnutls_pubkey_t pkey,
586 const gnutls_datum_t * data,
587 gnutls_openpgp_crt_fmt_t format,
588 const gnutls_openpgp_keyid_t keyid,
591 gnutls_openpgp_crt_t xpriv;
594 ret = gnutls_openpgp_crt_init(&xpriv);
596 return gnutls_assert_val(ret);
598 ret = gnutls_openpgp_crt_import(xpriv, data, format);
606 gnutls_openpgp_crt_set_preferred_key_id(xpriv, keyid);
613 ret = gnutls_pubkey_import_openpgp(pkey, xpriv, flags);
622 gnutls_openpgp_crt_deinit(xpriv);
630 * gnutls_pubkey_export:
631 * @key: Holds the certificate
632 * @format: the format of output params. One of PEM or DER.
633 * @output_data: will contain a certificate PEM or DER encoded
634 * @output_data_size: holds the size of output_data (and will be
635 * replaced by the actual size of parameters)
637 * This function will export the public key to DER or PEM format.
638 * The contents of the exported data is the SubjectPublicKeyInfo
641 * If the buffer provided is not long enough to hold the output, then
642 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
645 * If the structure is PEM encoded, it will have a header
646 * of "BEGIN CERTIFICATE".
648 * Returns: In case of failure a negative error code will be
649 * returned, and 0 on success.
654 gnutls_pubkey_export(gnutls_pubkey_t key,
655 gnutls_x509_crt_fmt_t format, void *output_data,
656 size_t * output_data_size)
659 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
663 return GNUTLS_E_INVALID_REQUEST;
666 if ((result = asn1_create_element
667 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
670 return _gnutls_asn2err(result);
674 _gnutls_x509_encode_and_copy_PKI_params(spk, "",
682 result = _gnutls_x509_export_int_named(spk, "",
694 asn1_delete_structure(&spk);
700 * gnutls_pubkey_export2:
701 * @key: Holds the certificate
702 * @format: the format of output params. One of PEM or DER.
703 * @out: will contain a certificate PEM or DER encoded
705 * This function will export the public key to DER or PEM format.
706 * The contents of the exported data is the SubjectPublicKeyInfo
709 * The output buffer will be allocated using gnutls_malloc().
711 * If the structure is PEM encoded, it will have a header
712 * of "BEGIN CERTIFICATE".
714 * Returns: In case of failure a negative error code will be
715 * returned, and 0 on success.
720 gnutls_pubkey_export2(gnutls_pubkey_t key,
721 gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
724 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
728 return GNUTLS_E_INVALID_REQUEST;
731 if ((result = asn1_create_element
732 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
735 return _gnutls_asn2err(result);
739 _gnutls_x509_encode_and_copy_PKI_params(spk, "",
747 result = _gnutls_x509_export_int_named2(spk, "",
758 asn1_delete_structure(&spk);
764 * gnutls_pubkey_get_key_id:
765 * @key: Holds the public key
766 * @flags: should be 0 for now
767 * @output_data: will contain the key ID
768 * @output_data_size: holds the size of output_data (and will be
769 * replaced by the actual size of parameters)
771 * This function will return a unique ID that depends on the public
772 * key parameters. This ID can be used in checking whether a
773 * certificate corresponds to the given public key.
775 * If the buffer provided is not long enough to hold the output, then
776 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
777 * be returned. The output will normally be a SHA-1 hash output,
780 * Returns: In case of failure a negative error code will be
781 * returned, and 0 on success.
786 gnutls_pubkey_get_key_id(gnutls_pubkey_t key, unsigned int flags,
787 unsigned char *output_data,
788 size_t * output_data_size)
794 return GNUTLS_E_INVALID_REQUEST;
798 _gnutls_get_key_id(key->pk_algorithm, &key->params,
799 output_data, output_data_size);
809 * gnutls_pubkey_export_rsa_raw:
810 * @key: Holds the certificate
811 * @m: will hold the modulus
812 * @e: will hold the public exponent
814 * This function will export the RSA public key's parameters found in
815 * the given structure. The new parameters will be allocated using
816 * gnutls_malloc() and will be stored in the appropriate datum.
818 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
823 gnutls_pubkey_export_rsa_raw(gnutls_pubkey_t key,
824 gnutls_datum_t * m, gnutls_datum_t * e)
830 return GNUTLS_E_INVALID_REQUEST;
833 if (key->pk_algorithm != GNUTLS_PK_RSA) {
835 return GNUTLS_E_INVALID_REQUEST;
838 ret = _gnutls_mpi_dprint_lz(key->params.params[0], m);
844 ret = _gnutls_mpi_dprint_lz(key->params.params[1], e);
847 _gnutls_free_datum(m);
856 * gnutls_pubkey_export_dsa_raw:
857 * @key: Holds the public key
858 * @p: will hold the p
859 * @q: will hold the q
860 * @g: will hold the g
861 * @y: will hold the y
863 * This function will export the DSA public key's parameters found in
864 * the given certificate. The new parameters will be allocated using
865 * gnutls_malloc() and will be stored in the appropriate datum.
867 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
872 gnutls_pubkey_export_dsa_raw(gnutls_pubkey_t key,
873 gnutls_datum_t * p, gnutls_datum_t * q,
874 gnutls_datum_t * g, gnutls_datum_t * y)
880 return GNUTLS_E_INVALID_REQUEST;
883 if (key->pk_algorithm != GNUTLS_PK_DSA) {
885 return GNUTLS_E_INVALID_REQUEST;
889 ret = _gnutls_mpi_dprint_lz(key->params.params[0], p);
896 ret = _gnutls_mpi_dprint_lz(key->params.params[1], q);
899 _gnutls_free_datum(p);
905 ret = _gnutls_mpi_dprint_lz(key->params.params[2], g);
908 _gnutls_free_datum(p);
909 _gnutls_free_datum(q);
915 ret = _gnutls_mpi_dprint_lz(key->params.params[3], y);
918 _gnutls_free_datum(p);
919 _gnutls_free_datum(g);
920 _gnutls_free_datum(q);
928 * gnutls_pubkey_export_ecc_raw:
929 * @key: Holds the public key
930 * @curve: will hold the curve
934 * This function will export the ECC public key's parameters found in
935 * the given certificate. The new parameters will be allocated using
936 * gnutls_malloc() and will be stored in the appropriate datum.
938 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
943 gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key,
944 gnutls_ecc_curve_t * curve,
945 gnutls_datum_t * x, gnutls_datum_t * y)
951 return GNUTLS_E_INVALID_REQUEST;
954 if (key->pk_algorithm != GNUTLS_PK_EC) {
956 return GNUTLS_E_INVALID_REQUEST;
959 *curve = key->params.flags;
962 ret = _gnutls_mpi_dprint_lz(key->params.params[ECC_X], x);
969 ret = _gnutls_mpi_dprint_lz(key->params.params[ECC_Y], y);
972 _gnutls_free_datum(x);
980 * gnutls_pubkey_export_ecc_x962:
981 * @key: Holds the public key
982 * @parameters: DER encoding of an ANSI X9.62 parameters
983 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
985 * This function will export the ECC public key's parameters found in
986 * the given certificate. The new parameters will be allocated using
987 * gnutls_malloc() and will be stored in the appropriate datum.
989 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
993 int gnutls_pubkey_export_ecc_x962(gnutls_pubkey_t key,
994 gnutls_datum_t * parameters,
995 gnutls_datum_t * ecpoint)
998 gnutls_datum_t raw_point = {NULL,0};
1000 if (key == NULL || key->pk_algorithm != GNUTLS_PK_EC)
1001 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1003 ret = _gnutls_x509_write_ecc_pubkey(&key->params, &raw_point);
1005 return gnutls_assert_val(ret);
1007 ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
1008 raw_point.data, raw_point.size, ecpoint);
1014 ret = _gnutls_x509_write_ecc_params(key->params.flags, parameters);
1016 _gnutls_free_datum(ecpoint);
1023 gnutls_free(raw_point.data);
1028 * gnutls_pubkey_import:
1029 * @key: The structure to store the parsed public key.
1030 * @data: The DER or PEM encoded certificate.
1031 * @format: One of DER or PEM
1033 * This function will import the provided public key in
1034 * a SubjectPublicKeyInfo X.509 structure to a native
1035 * %gnutls_pubkey_t structure. The output will be stored
1036 * in @key. If the public key is PEM encoded it should have a header
1039 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1040 * negative error value.
1045 gnutls_pubkey_import(gnutls_pubkey_t key,
1046 const gnutls_datum_t * data,
1047 gnutls_x509_crt_fmt_t format)
1049 int result = 0, need_free = 0;
1050 gnutls_datum_t _data;
1055 return GNUTLS_E_INVALID_REQUEST;
1058 _data.data = data->data;
1059 _data.size = data->size;
1061 /* If the Certificate is in PEM format then decode it
1063 if (format == GNUTLS_X509_FMT_PEM) {
1064 /* Try the first header */
1066 _gnutls_fbase64_decode(PEM_PK, data->data,
1067 data->size, &_data);
1077 if ((result = asn1_create_element
1078 (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
1081 result = _gnutls_asn2err(result);
1085 result = asn1_der_decoding(&spk, _data.data, _data.size, NULL);
1086 if (result != ASN1_SUCCESS) {
1088 result = _gnutls_asn2err(result);
1092 result = _gnutls_get_asn_mpis(spk, "", &key->params);
1098 /* this has already been called by get_asn_mpis() thus it cannot
1101 key->pk_algorithm = _gnutls_x509_get_pk_algorithm(spk, "", NULL);
1102 key->bits = pubkey_to_bits(key->pk_algorithm, &key->params);
1107 asn1_delete_structure(&spk);
1110 _gnutls_free_datum(&_data);
1115 * gnutls_x509_crt_set_pubkey:
1116 * @crt: should contain a #gnutls_x509_crt_t structure
1117 * @key: holds a public key
1119 * This function will set the public parameters from the given public
1120 * key to the request.
1122 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1123 * negative error value.
1127 int gnutls_x509_crt_set_pubkey(gnutls_x509_crt_t crt, gnutls_pubkey_t key)
1133 return GNUTLS_E_INVALID_REQUEST;
1136 result = _gnutls_x509_encode_and_copy_PKI_params(crt->cert,
1137 "tbsCertificate.subjectPublicKeyInfo",
1147 gnutls_x509_crt_set_key_usage(crt, key->key_usage);
1153 * gnutls_x509_crq_set_pubkey:
1154 * @crq: should contain a #gnutls_x509_crq_t structure
1155 * @key: holds a public key
1157 * This function will set the public parameters from the given public
1158 * key to the request.
1160 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1161 * negative error value.
1165 int gnutls_x509_crq_set_pubkey(gnutls_x509_crq_t crq, gnutls_pubkey_t key)
1171 return GNUTLS_E_INVALID_REQUEST;
1174 result = _gnutls_x509_encode_and_copy_PKI_params
1176 "certificationRequestInfo.subjectPKInfo",
1177 key->pk_algorithm, &key->params);
1185 gnutls_x509_crq_set_key_usage(crq, key->key_usage);
1191 * gnutls_pubkey_set_key_usage:
1192 * @key: a certificate of type #gnutls_x509_crt_t
1193 * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1195 * This function will set the key usage flags of the public key. This
1196 * is only useful if the key is to be exported to a certificate or
1197 * certificate request.
1199 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1200 * negative error value.
1204 int gnutls_pubkey_set_key_usage(gnutls_pubkey_t key, unsigned int usage)
1206 key->key_usage = usage;
1211 #ifdef ENABLE_PKCS11
1214 * gnutls_pubkey_import_pkcs11_url:
1215 * @key: A key of type #gnutls_pubkey_t
1216 * @url: A PKCS 11 url
1217 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1219 * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t
1222 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1223 * negative error value.
1228 gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url,
1231 gnutls_pkcs11_obj_t pcrt;
1234 ret = gnutls_pkcs11_obj_init(&pcrt);
1241 gnutls_pkcs11_obj_set_pin_function(pcrt, key->pin.cb,
1244 ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags);
1250 ret = gnutls_pubkey_import_pkcs11(key, pcrt, 0);
1259 gnutls_pkcs11_obj_deinit(pcrt);
1264 #endif /* ENABLE_PKCS11 */
1267 * gnutls_pubkey_import_url:
1268 * @key: A key of type #gnutls_pubkey_t
1269 * @url: A PKCS 11 url
1270 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1272 * This function will import a public key from the provided URL.
1274 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1275 * negative error value.
1280 gnutls_pubkey_import_url(gnutls_pubkey_t key, const char *url,
1285 if (strncmp(url, PKCS11_URL, PKCS11_URL_SIZE) == 0)
1286 #ifdef ENABLE_PKCS11
1287 return gnutls_pubkey_import_pkcs11_url(key, url, flags);
1289 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1292 if (strncmp(url, TPMKEY_URL, TPMKEY_URL_SIZE) == 0)
1293 #ifdef HAVE_TROUSERS
1294 return gnutls_pubkey_import_tpm_url(key, url, NULL, 0);
1296 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1299 for (i=0;i<_gnutls_custom_urls_size;i++) {
1300 if (strncmp(url, _gnutls_custom_urls[i].name, _gnutls_custom_urls[i].name_size) == 0) {
1301 if (_gnutls_custom_urls[i].import_pubkey)
1302 return _gnutls_custom_urls[i].import_pubkey(key, url, flags);
1306 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1310 * gnutls_pubkey_import_rsa_raw:
1311 * @key: Is a structure will hold the parameters
1312 * @m: holds the modulus
1313 * @e: holds the public exponent
1315 * This function will replace the parameters in the given structure.
1316 * The new parameters should be stored in the appropriate
1319 * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1324 gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key,
1325 const gnutls_datum_t * m,
1326 const gnutls_datum_t * e)
1332 return GNUTLS_E_INVALID_REQUEST;
1335 gnutls_pk_params_release(&key->params);
1336 gnutls_pk_params_init(&key->params);
1339 if (_gnutls_mpi_init_scan_nz(&key->params.params[0], m->data, siz)) {
1341 return GNUTLS_E_MPI_SCAN_FAILED;
1345 if (_gnutls_mpi_init_scan_nz(&key->params.params[1], e->data, siz)) {
1347 _gnutls_mpi_release(&key->params.params[0]);
1348 return GNUTLS_E_MPI_SCAN_FAILED;
1351 key->params.params_nr = RSA_PUBLIC_PARAMS;
1352 key->pk_algorithm = GNUTLS_PK_RSA;
1353 key->bits = pubkey_to_bits(GNUTLS_PK_RSA, &key->params);
1359 * gnutls_pubkey_import_ecc_raw:
1360 * @key: The structure to store the parsed key
1361 * @curve: holds the curve
1365 * This function will convert the given elliptic curve parameters to a
1366 * #gnutls_pubkey_t. The output will be stored in @key.
1368 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1369 * negative error value.
1374 gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key,
1375 gnutls_ecc_curve_t curve,
1376 const gnutls_datum_t * x,
1377 const gnutls_datum_t * y)
1383 return GNUTLS_E_INVALID_REQUEST;
1386 gnutls_pk_params_release(&key->params);
1387 gnutls_pk_params_init(&key->params);
1389 key->params.flags = curve;
1391 if (_gnutls_mpi_init_scan_nz
1392 (&key->params.params[ECC_X], x->data, x->size)) {
1394 ret = GNUTLS_E_MPI_SCAN_FAILED;
1397 key->params.params_nr++;
1399 if (_gnutls_mpi_init_scan_nz
1400 (&key->params.params[ECC_Y], y->data, y->size)) {
1402 ret = GNUTLS_E_MPI_SCAN_FAILED;
1405 key->params.params_nr++;
1406 key->pk_algorithm = GNUTLS_PK_EC;
1411 gnutls_pk_params_release(&key->params);
1416 * gnutls_pubkey_import_ecc_x962:
1417 * @key: The structure to store the parsed key
1418 * @parameters: DER encoding of an ANSI X9.62 parameters
1419 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1421 * This function will convert the given elliptic curve parameters to a
1422 * #gnutls_pubkey_t. The output will be stored in @key.
1424 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1425 * negative error value.
1430 gnutls_pubkey_import_ecc_x962(gnutls_pubkey_t key,
1431 const gnutls_datum_t * parameters,
1432 const gnutls_datum_t * ecpoint)
1435 gnutls_datum_t raw_point = {NULL,0};
1439 return GNUTLS_E_INVALID_REQUEST;
1442 gnutls_pk_params_release(&key->params);
1443 gnutls_pk_params_init(&key->params);
1445 key->params.params_nr = 0;
1448 _gnutls_x509_read_ecc_params(parameters->data,
1449 parameters->size, &key->params.flags);
1455 ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
1456 ecpoint->data, ecpoint->size, &raw_point);
1462 ret = _gnutls_ecc_ansi_x963_import(raw_point.data, raw_point.size,
1463 &key->params.params[ECC_X],
1464 &key->params.params[ECC_Y]);
1469 key->params.params_nr += 2;
1470 key->pk_algorithm = GNUTLS_PK_EC;
1472 gnutls_free(raw_point.data);
1476 gnutls_pk_params_release(&key->params);
1477 gnutls_free(raw_point.data);
1482 * gnutls_pubkey_import_dsa_raw:
1483 * @key: The structure to store the parsed key
1489 * This function will convert the given DSA raw parameters to the
1490 * native #gnutls_pubkey_t format. The output will be stored
1493 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1494 * negative error value.
1499 gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,
1500 const gnutls_datum_t * p,
1501 const gnutls_datum_t * q,
1502 const gnutls_datum_t * g,
1503 const gnutls_datum_t * y)
1509 return GNUTLS_E_INVALID_REQUEST;
1512 gnutls_pk_params_release(&key->params);
1513 gnutls_pk_params_init(&key->params);
1516 if (_gnutls_mpi_init_scan_nz(&key->params.params[0], p->data, siz)) {
1518 return GNUTLS_E_MPI_SCAN_FAILED;
1522 if (_gnutls_mpi_init_scan_nz(&key->params.params[1], q->data, siz)) {
1524 _gnutls_mpi_release(&key->params.params[0]);
1525 return GNUTLS_E_MPI_SCAN_FAILED;
1529 if (_gnutls_mpi_init_scan_nz(&key->params.params[2], g->data, siz)) {
1531 _gnutls_mpi_release(&key->params.params[1]);
1532 _gnutls_mpi_release(&key->params.params[0]);
1533 return GNUTLS_E_MPI_SCAN_FAILED;
1537 if (_gnutls_mpi_init_scan_nz(&key->params.params[3], y->data, siz)) {
1539 _gnutls_mpi_release(&key->params.params[2]);
1540 _gnutls_mpi_release(&key->params.params[1]);
1541 _gnutls_mpi_release(&key->params.params[0]);
1542 return GNUTLS_E_MPI_SCAN_FAILED;
1545 key->params.params_nr = DSA_PUBLIC_PARAMS;
1546 key->pk_algorithm = GNUTLS_PK_DSA;
1547 key->bits = pubkey_to_bits(GNUTLS_PK_DSA, &key->params);
1554 * gnutls_pubkey_verify_data2:
1555 * @pubkey: Holds the public key
1556 * @algo: The signature algorithm used
1557 * @flags: Zero or one of %gnutls_pubkey_flags_t
1558 * @data: holds the signed data
1559 * @signature: contains the signature
1561 * This function will verify the given signed data, using the
1562 * parameters from the certificate.
1564 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1565 * is returned, and zero or positive code on success.
1570 gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey,
1571 gnutls_sign_algorithm_t algo,
1573 const gnutls_datum_t * data,
1574 const gnutls_datum_t * signature)
1577 const mac_entry_st *me;
1579 if (pubkey == NULL) {
1581 return GNUTLS_E_INVALID_REQUEST;
1584 if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA)
1585 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1587 me = hash_to_entry(gnutls_sign_get_hash_algorithm(algo));
1589 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1591 ret = pubkey_verify_data(pubkey->pk_algorithm, me,
1592 data, signature, &pubkey->params);
1601 * gnutls_pubkey_verify_hash2:
1602 * @key: Holds the public key
1603 * @algo: The signature algorithm used
1604 * @flags: Zero or one of %gnutls_pubkey_flags_t
1605 * @hash: holds the hash digest to be verified
1606 * @signature: contains the signature
1608 * This function will verify the given signed digest, using the
1609 * parameters from the public key. Note that unlike gnutls_privkey_sign_hash(),
1610 * this function accepts a signature algorithm instead of a digest algorithm.
1611 * You can use gnutls_pk_to_sign() to get the appropriate value.
1613 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1614 * is returned, and zero or positive code on success.
1619 gnutls_pubkey_verify_hash2(gnutls_pubkey_t key,
1620 gnutls_sign_algorithm_t algo,
1622 const gnutls_datum_t * hash,
1623 const gnutls_datum_t * signature)
1625 const mac_entry_st *me;
1629 return GNUTLS_E_INVALID_REQUEST;
1632 if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA) {
1633 return _gnutls_pk_verify(GNUTLS_PK_RSA, hash, signature,
1636 me = hash_to_entry(gnutls_sign_get_hash_algorithm(algo));
1637 return pubkey_verify_hashed_data(key->pk_algorithm, me,
1644 * gnutls_pubkey_encrypt_data:
1645 * @key: Holds the public key
1646 * @flags: should be 0 for now
1647 * @plaintext: The data to be encrypted
1648 * @ciphertext: contains the encrypted data
1650 * This function will encrypt the given data, using the public
1653 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1654 * negative error value.
1659 gnutls_pubkey_encrypt_data(gnutls_pubkey_t key, unsigned int flags,
1660 const gnutls_datum_t * plaintext,
1661 gnutls_datum_t * ciphertext)
1665 return GNUTLS_E_INVALID_REQUEST;
1668 return _gnutls_pk_encrypt(key->pk_algorithm, ciphertext,
1669 plaintext, &key->params);
1672 /* Checks whether the public key given is compatible with the
1673 * signature algorithm used. The session is only used for audit logging, and
1676 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session,
1677 gnutls_pubkey_t pubkey,
1678 const version_entry_st * ver,
1679 gnutls_sign_algorithm_t sign)
1681 unsigned int hash_size = 0;
1682 unsigned int sig_hash_size;
1683 const mac_entry_st *me;
1685 if (pubkey->pk_algorithm == GNUTLS_PK_DSA) {
1686 me = _gnutls_dsa_q_to_hash(pubkey->pk_algorithm,
1687 &pubkey->params, &hash_size);
1689 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
1690 if (!_gnutls_version_has_selectable_sighash(ver)) {
1691 if (me->id != GNUTLS_MAC_SHA1)
1694 (GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
1695 } else if (sign != GNUTLS_SIGN_UNKNOWN) {
1696 me = hash_to_entry(gnutls_sign_get_hash_algorithm
1698 sig_hash_size = _gnutls_hash_get_algo_len(me);
1699 if (sig_hash_size < hash_size)
1700 _gnutls_audit_log(session,
1701 "The hash size used in signature (%u) is less than the expected (%u)\n",
1706 } else if (pubkey->pk_algorithm == GNUTLS_PK_EC) {
1707 if (_gnutls_version_has_selectable_sighash(ver)
1708 && sign != GNUTLS_SIGN_UNKNOWN) {
1709 _gnutls_dsa_q_to_hash(pubkey->pk_algorithm,
1713 me = hash_to_entry(gnutls_sign_get_hash_algorithm
1715 sig_hash_size = _gnutls_hash_get_algo_len(me);
1717 if (sig_hash_size < hash_size)
1718 _gnutls_audit_log(session,
1719 "The hash size used in signature (%u) is less than the expected (%u)\n",
1729 /* Returns the public key.
1732 _gnutls_pubkey_get_mpis(gnutls_pubkey_t key, gnutls_pk_params_st * params)
1734 return _gnutls_pk_params_copy(params, &key->params);
1737 /* if hash==MD5 then we do RSA-MD5
1738 * if hash==SHA then we do RSA-SHA
1739 * params[0] is modulus
1740 * params[1] is public key
1743 _pkcs1_rsa_verify_sig(const mac_entry_st * me,
1744 const gnutls_datum_t * text,
1745 const gnutls_datum_t * prehash,
1746 const gnutls_datum_t * signature,
1747 gnutls_pk_params_st * params)
1750 uint8_t md[MAX_HASH_SIZE], *cmp;
1751 unsigned int digest_size;
1752 gnutls_datum_t d, di;
1754 digest_size = _gnutls_hash_get_algo_len(me);
1756 if (prehash->data == NULL || prehash->size != digest_size)
1757 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1759 cmp = prehash->data;
1763 return GNUTLS_E_INVALID_REQUEST;
1766 ret = _gnutls_hash_fast(me->id, text->data, text->size, md);
1776 d.size = digest_size;
1778 /* decrypted is a BER encoded data of type DigestInfo
1780 ret = encode_ber_digest_info(me, &d, &di);
1782 return gnutls_assert_val(ret);
1784 ret = _gnutls_pk_verify(GNUTLS_PK_RSA, &di, signature, params);
1785 _gnutls_free_datum(&di);
1790 /* Hashes input data and verifies a signature.
1793 dsa_verify_hashed_data(gnutls_pk_algorithm_t pk,
1794 const mac_entry_st * algo,
1795 const gnutls_datum_t * hash,
1796 const gnutls_datum_t * signature,
1797 gnutls_pk_params_st * params)
1799 gnutls_datum_t digest;
1800 unsigned int hash_len;
1803 algo = _gnutls_dsa_q_to_hash(pk, params, &hash_len);
1805 hash_len = _gnutls_hash_get_algo_len(algo);
1807 /* SHA1 or better allowed */
1808 if (!hash->data || hash->size < hash_len) {
1811 ("Hash size (%d) does not correspond to hash %s(%d) or better.\n",
1812 (int) hash->size, _gnutls_mac_get_name(algo),
1815 if (hash->size != 20) /* SHA1 is allowed */
1818 (GNUTLS_E_PK_SIG_VERIFY_FAILED);
1821 digest.data = hash->data;
1822 digest.size = hash->size;
1824 return _gnutls_pk_verify(pk, &digest, signature, params);
1828 dsa_verify_data(gnutls_pk_algorithm_t pk,
1829 const mac_entry_st * algo,
1830 const gnutls_datum_t * data,
1831 const gnutls_datum_t * signature,
1832 gnutls_pk_params_st * params)
1835 uint8_t _digest[MAX_HASH_SIZE];
1836 gnutls_datum_t digest;
1839 algo = _gnutls_dsa_q_to_hash(pk, params, NULL);
1841 ret = _gnutls_hash_fast(algo->id, data->data, data->size, _digest);
1843 return gnutls_assert_val(ret);
1845 digest.data = _digest;
1846 digest.size = _gnutls_hash_get_algo_len(algo);
1848 return _gnutls_pk_verify(pk, &digest, signature, params);
1851 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1852 * not verified, or 1 otherwise.
1855 pubkey_verify_hashed_data(gnutls_pk_algorithm_t pk,
1856 const mac_entry_st * hash_algo,
1857 const gnutls_datum_t * hash,
1858 const gnutls_datum_t * signature,
1859 gnutls_pk_params_st * issuer_params)
1865 if (_pkcs1_rsa_verify_sig
1866 (hash_algo, NULL, hash, signature, issuer_params) != 0)
1869 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1877 if (dsa_verify_hashed_data
1878 (pk, hash_algo, hash, signature, issuer_params) != 0) {
1880 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1887 return GNUTLS_E_INTERNAL_ERROR;
1892 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1893 * not verified, or 1 otherwise.
1896 pubkey_verify_data(gnutls_pk_algorithm_t pk,
1897 const mac_entry_st * me,
1898 const gnutls_datum_t * data,
1899 const gnutls_datum_t * signature,
1900 gnutls_pk_params_st * issuer_params)
1906 if (_pkcs1_rsa_verify_sig
1907 (me, data, NULL, signature, issuer_params) != 0) {
1909 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1917 if (dsa_verify_data(pk, me, data, signature, issuer_params)
1920 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1927 return GNUTLS_E_INTERNAL_ERROR;
1932 const mac_entry_st *_gnutls_dsa_q_to_hash(gnutls_pk_algorithm_t algo,
1933 const gnutls_pk_params_st *
1934 params, unsigned int *hash_len)
1939 if (algo == GNUTLS_PK_DSA)
1940 bits = _gnutls_mpi_get_nbits(params->params[1]);
1941 else if (algo == GNUTLS_PK_EC)
1942 bits = gnutls_ecc_curve_get_size(params->flags) * 8;
1947 ret = GNUTLS_DIG_SHA1;
1948 } else if (bits <= 192) {
1951 ret = GNUTLS_DIG_SHA256;
1952 } else if (bits <= 224) {
1955 ret = GNUTLS_DIG_SHA256;
1956 } else if (bits <= 256) {
1959 ret = GNUTLS_DIG_SHA256;
1960 } else if (bits <= 384) {
1963 ret = GNUTLS_DIG_SHA384;
1967 ret = GNUTLS_DIG_SHA512;
1970 return mac_to_entry(ret);
1974 * gnutls_pubkey_set_pin_function:
1975 * @key: A key of type #gnutls_pubkey_t
1977 * @userdata: data associated with the callback
1979 * This function will set a callback function to be used when
1980 * required to access the object. This function overrides any other
1981 * global PIN functions.
1983 * Note that this function must be called right after initialization
1989 void gnutls_pubkey_set_pin_function(gnutls_pubkey_t key,
1990 gnutls_pin_callback_t fn,
1994 key->pin.data = userdata;
1998 * gnutls_pubkey_import_x509_raw:
1999 * @pkey: The public key
2000 * @data: The public key data to be imported
2001 * @format: The format of the public key
2002 * @flags: should be zero
2004 * This function will import the given public key to the abstract
2005 * #gnutls_pubkey_t structure.
2007 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2008 * negative error value.
2012 int gnutls_pubkey_import_x509_raw(gnutls_pubkey_t pkey,
2013 const gnutls_datum_t * data,
2014 gnutls_x509_crt_fmt_t format,
2017 gnutls_x509_crt_t xpriv;
2020 ret = gnutls_x509_crt_init(&xpriv);
2022 return gnutls_assert_val(ret);
2024 ret = gnutls_x509_crt_import(xpriv, data, format);
2030 ret = gnutls_pubkey_import_x509(pkey, xpriv, flags);
2039 gnutls_x509_crt_deinit(xpriv);
2045 * gnutls_pubkey_verify_params:
2046 * @key: should contain a #gnutls_pubkey_t structure
2048 * This function will verify the private key parameters.
2050 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2051 * negative error value.
2055 int gnutls_pubkey_verify_params(gnutls_pubkey_t key)
2059 ret = _gnutls_pk_verify_pub_params(key->pk_algorithm, &key->params);