xref: /openbsd-src/lib/libtls/tls_signer.c (revision 8e652f1740c86323e13ef461f7c5ec9d380cb333)
1*8e652f17Sop /* $OpenBSD: tls_signer.c,v 1.13 2024/06/11 16:35:24 op Exp $ */
29ecbddc1Seric /*
39ecbddc1Seric  * Copyright (c) 2021 Eric Faurot <eric@openbsd.org>
49ecbddc1Seric  *
59ecbddc1Seric  * Permission to use, copy, modify, and distribute this software for any
69ecbddc1Seric  * purpose with or without fee is hereby granted, provided that the above
79ecbddc1Seric  * copyright notice and this permission notice appear in all copies.
89ecbddc1Seric  *
99ecbddc1Seric  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109ecbddc1Seric  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119ecbddc1Seric  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129ecbddc1Seric  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139ecbddc1Seric  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149ecbddc1Seric  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159ecbddc1Seric  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169ecbddc1Seric  */
179ecbddc1Seric 
18d44afd84Sinoguchi #include <limits.h>
19*8e652f17Sop #include <pthread.h>
20*8e652f17Sop #include <stdint.h>
21*8e652f17Sop #include <stdio.h>
22*8e652f17Sop #include <stdlib.h>
23*8e652f17Sop #include <string.h>
24d44afd84Sinoguchi 
25*8e652f17Sop #include <openssl/bio.h>
26*8e652f17Sop #include <openssl/ec.h>
279ecbddc1Seric #include <openssl/err.h>
28*8e652f17Sop #include <openssl/evp.h>
29*8e652f17Sop #include <openssl/pem.h>
3082e78bf1Sjsing #include <openssl/rsa.h>
31*8e652f17Sop #include <openssl/x509.h>
329ecbddc1Seric 
339ecbddc1Seric #include "tls.h"
349ecbddc1Seric #include "tls_internal.h"
359ecbddc1Seric 
369ecbddc1Seric struct tls_signer_key {
379ecbddc1Seric 	char *hash;
389ecbddc1Seric 	RSA *rsa;
399ecbddc1Seric 	EC_KEY *ecdsa;
409ecbddc1Seric 	struct tls_signer_key *next;
419ecbddc1Seric };
429ecbddc1Seric 
439ecbddc1Seric struct tls_signer {
449ecbddc1Seric 	struct tls_error error;
459ecbddc1Seric 	struct tls_signer_key *keys;
469ecbddc1Seric };
479ecbddc1Seric 
489ecbddc1Seric static pthread_mutex_t signer_method_lock = PTHREAD_MUTEX_INITIALIZER;
499ecbddc1Seric 
509ecbddc1Seric struct tls_signer *
tls_signer_new(void)519ecbddc1Seric tls_signer_new(void)
529ecbddc1Seric {
539ecbddc1Seric 	struct tls_signer *signer;
549ecbddc1Seric 
559ecbddc1Seric 	if ((signer = calloc(1, sizeof(*signer))) == NULL)
569ecbddc1Seric 		return (NULL);
579ecbddc1Seric 
589ecbddc1Seric 	return (signer);
599ecbddc1Seric }
609ecbddc1Seric 
619ecbddc1Seric void
tls_signer_free(struct tls_signer * signer)629ecbddc1Seric tls_signer_free(struct tls_signer *signer)
639ecbddc1Seric {
649ecbddc1Seric 	struct tls_signer_key *skey;
659ecbddc1Seric 
669ecbddc1Seric 	if (signer == NULL)
679ecbddc1Seric 		return;
689ecbddc1Seric 
699ecbddc1Seric 	tls_error_clear(&signer->error);
709ecbddc1Seric 
719ecbddc1Seric 	while (signer->keys) {
729ecbddc1Seric 		skey = signer->keys;
739ecbddc1Seric 		signer->keys = skey->next;
749ecbddc1Seric 		RSA_free(skey->rsa);
759ecbddc1Seric 		EC_KEY_free(skey->ecdsa);
769ecbddc1Seric 		free(skey->hash);
779ecbddc1Seric 		free(skey);
789ecbddc1Seric 	}
799ecbddc1Seric 
809ecbddc1Seric 	free(signer);
819ecbddc1Seric }
829ecbddc1Seric 
839ecbddc1Seric const char *
tls_signer_error(struct tls_signer * signer)849ecbddc1Seric tls_signer_error(struct tls_signer *signer)
859ecbddc1Seric {
869ecbddc1Seric 	return (signer->error.msg);
879ecbddc1Seric }
889ecbddc1Seric 
899ecbddc1Seric int
tls_signer_add_keypair_mem(struct tls_signer * signer,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len)909ecbddc1Seric tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert,
919ecbddc1Seric     size_t cert_len, const uint8_t *key, size_t key_len)
929ecbddc1Seric {
939ecbddc1Seric 	struct tls_signer_key *skey = NULL;
949ecbddc1Seric 	char *errstr = "unknown";
959ecbddc1Seric 	int ssl_err;
969ecbddc1Seric 	EVP_PKEY *pkey = NULL;
979ecbddc1Seric 	X509 *x509 = NULL;
989ecbddc1Seric 	BIO *bio = NULL;
999ecbddc1Seric 	char *hash = NULL;
1009ecbddc1Seric 
1019ecbddc1Seric 	/* Compute certificate hash */
1029ecbddc1Seric 	if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) {
1037a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1049ecbddc1Seric 		    "failed to create certificate bio");
1059ecbddc1Seric 		goto err;
1069ecbddc1Seric 	}
1079ecbddc1Seric 	if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
1089ecbddc1Seric 	    NULL)) == NULL) {
1099ecbddc1Seric 		if ((ssl_err = ERR_peek_error()) != 0)
1109ecbddc1Seric 			errstr = ERR_error_string(ssl_err, NULL);
1117a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1127a756d37Sjoshua 		    "failed to load certificate: %s", errstr);
1139ecbddc1Seric 		goto err;
1149ecbddc1Seric 	}
1159ecbddc1Seric 	if (tls_cert_pubkey_hash(x509, &hash) == -1) {
1167a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1179ecbddc1Seric 		    "failed to get certificate hash");
1189ecbddc1Seric 		goto err;
1199ecbddc1Seric 	}
1209ecbddc1Seric 
1219ecbddc1Seric 	X509_free(x509);
1229ecbddc1Seric 	x509 = NULL;
1239ecbddc1Seric 	BIO_free(bio);
1249ecbddc1Seric 	bio = NULL;
1259ecbddc1Seric 
1269ecbddc1Seric 	/* Read private key */
1279ecbddc1Seric 	if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) {
1287a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1297a756d37Sjoshua 		    "failed to create key bio");
1309ecbddc1Seric 		goto err;
1319ecbddc1Seric 	}
1329ecbddc1Seric 	if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
1339ecbddc1Seric 	    NULL)) == NULL) {
1347a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1357a756d37Sjoshua 		    "failed to read private key");
1369ecbddc1Seric 		goto err;
1379ecbddc1Seric 	}
1389ecbddc1Seric 
1399ecbddc1Seric 	if ((skey = calloc(1, sizeof(*skey))) == NULL) {
1403620689eSjoshua 		tls_error_set(&signer->error, TLS_ERROR_OUT_OF_MEMORY,
1413620689eSjoshua 		    "out of memory");
1429ecbddc1Seric 		goto err;
1439ecbddc1Seric 	}
1449ecbddc1Seric 	skey->hash = hash;
1459ecbddc1Seric 	if ((skey->rsa = EVP_PKEY_get1_RSA(pkey)) == NULL &&
1469ecbddc1Seric 	    (skey->ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
1477a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
1487a756d37Sjoshua 		    "unknown key type");
1499ecbddc1Seric 		goto err;
1509ecbddc1Seric 	}
1519ecbddc1Seric 
1529ecbddc1Seric 	skey->next = signer->keys;
1539ecbddc1Seric 	signer->keys = skey;
1549ecbddc1Seric 	EVP_PKEY_free(pkey);
1559ecbddc1Seric 	BIO_free(bio);
1569ecbddc1Seric 
1579ecbddc1Seric 	return (0);
1589ecbddc1Seric 
1599ecbddc1Seric  err:
1609ecbddc1Seric 	EVP_PKEY_free(pkey);
1619ecbddc1Seric 	X509_free(x509);
1629ecbddc1Seric 	BIO_free(bio);
1639ecbddc1Seric 	free(hash);
1649ecbddc1Seric 	free(skey);
1659ecbddc1Seric 
1669ecbddc1Seric 	return (-1);
1679ecbddc1Seric }
1689ecbddc1Seric 
1699ecbddc1Seric int
tls_signer_add_keypair_file(struct tls_signer * signer,const char * cert_file,const char * key_file)1709ecbddc1Seric tls_signer_add_keypair_file(struct tls_signer *signer, const char *cert_file,
1719ecbddc1Seric     const char *key_file)
1729ecbddc1Seric {
1739ecbddc1Seric 	char *cert = NULL, *key = NULL;
1749ecbddc1Seric 	size_t cert_len, key_len;
1759ecbddc1Seric 	int rv = -1;
1769ecbddc1Seric 
1779ecbddc1Seric 	if (tls_config_load_file(&signer->error, "certificate", cert_file,
1789ecbddc1Seric 	    &cert, &cert_len) == -1)
1799ecbddc1Seric 		goto err;
1809ecbddc1Seric 
1819ecbddc1Seric 	if (tls_config_load_file(&signer->error, "key", key_file, &key,
1829ecbddc1Seric 	    &key_len) == -1)
1839ecbddc1Seric 		goto err;
1849ecbddc1Seric 
1859ecbddc1Seric 	rv = tls_signer_add_keypair_mem(signer, cert, cert_len, key, key_len);
1869ecbddc1Seric 
1879ecbddc1Seric  err:
1889ecbddc1Seric 	free(cert);
1899ecbddc1Seric 	free(key);
1909ecbddc1Seric 
1919ecbddc1Seric 	return (rv);
1929ecbddc1Seric }
1939ecbddc1Seric 
1949ecbddc1Seric static int
tls_sign_rsa(struct tls_signer * signer,struct tls_signer_key * skey,const uint8_t * input,size_t input_len,int padding_type,uint8_t ** out_signature,size_t * out_signature_len)1959ecbddc1Seric tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey,
19682e78bf1Sjsing     const uint8_t *input, size_t input_len, int padding_type,
19782e78bf1Sjsing     uint8_t **out_signature, size_t *out_signature_len)
1989ecbddc1Seric {
199bce97392Sjsing 	int rsa_padding, rsa_size, signature_len;
20082e78bf1Sjsing 	char *signature = NULL;
2019ecbddc1Seric 
20282e78bf1Sjsing 	*out_signature = NULL;
20382e78bf1Sjsing 	*out_signature_len = 0;
2049ecbddc1Seric 
205bce97392Sjsing 	if (padding_type == TLS_PADDING_NONE) {
206bce97392Sjsing 		rsa_padding = RSA_NO_PADDING;
207bce97392Sjsing 	} else if (padding_type == TLS_PADDING_RSA_PKCS1) {
208bce97392Sjsing 		rsa_padding = RSA_PKCS1_PADDING;
209bce97392Sjsing 	} else {
2107a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2117a756d37Sjoshua 		    "invalid RSA padding type (%d)", padding_type);
212bce97392Sjsing 		return (-1);
213bce97392Sjsing 	}
214bce97392Sjsing 
21582e78bf1Sjsing 	if (input_len > INT_MAX) {
2162d60058eSjoshua 		tls_error_setx(&signer->error, TLS_ERROR_INVALID_ARGUMENT,
2177a756d37Sjoshua 		    "input too large");
21882e78bf1Sjsing 		return (-1);
21982e78bf1Sjsing 	}
22082e78bf1Sjsing 	if ((rsa_size = RSA_size(skey->rsa)) <= 0) {
2217a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2227a756d37Sjoshua 		    "invalid RSA size: %d", rsa_size);
22382e78bf1Sjsing 		return (-1);
22482e78bf1Sjsing 	}
22582e78bf1Sjsing 	if ((signature = calloc(1, rsa_size)) == NULL) {
2263620689eSjoshua 		tls_error_set(&signer->error, TLS_ERROR_OUT_OF_MEMORY,
2273620689eSjoshua 		    "out of memory");
2289ecbddc1Seric 		return (-1);
2299ecbddc1Seric 	}
2309ecbddc1Seric 
23182e78bf1Sjsing 	if ((signature_len = RSA_private_encrypt((int)input_len, input,
232bce97392Sjsing 	    signature, skey->rsa, rsa_padding)) <= 0) {
23382e78bf1Sjsing 		/* XXX - include further details from libcrypto. */
2347a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2357a756d37Sjoshua 		    "RSA signing failed");
23682e78bf1Sjsing 		free(signature);
2379ecbddc1Seric 		return (-1);
2389ecbddc1Seric 	}
2399ecbddc1Seric 
24082e78bf1Sjsing 	*out_signature = signature;
24182e78bf1Sjsing 	*out_signature_len = (size_t)signature_len;
2429ecbddc1Seric 
2439ecbddc1Seric 	return (0);
2449ecbddc1Seric }
2459ecbddc1Seric 
2469ecbddc1Seric static int
tls_sign_ecdsa(struct tls_signer * signer,struct tls_signer_key * skey,const uint8_t * input,size_t input_len,int padding_type,uint8_t ** out_signature,size_t * out_signature_len)2479ecbddc1Seric tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey,
24882e78bf1Sjsing     const uint8_t *input, size_t input_len, int padding_type,
24982e78bf1Sjsing     uint8_t **out_signature, size_t *out_signature_len)
2509ecbddc1Seric {
25182e78bf1Sjsing 	unsigned char *signature;
25282e78bf1Sjsing 	int signature_len;
2539ecbddc1Seric 
25482e78bf1Sjsing 	*out_signature = NULL;
25582e78bf1Sjsing 	*out_signature_len = 0;
2569ecbddc1Seric 
257bce97392Sjsing 	if (padding_type != TLS_PADDING_NONE) {
2587a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2597a756d37Sjoshua 		    "invalid ECDSA padding");
260bce97392Sjsing 		return (-1);
261bce97392Sjsing 	}
262bce97392Sjsing 
26382e78bf1Sjsing 	if (input_len > INT_MAX) {
2642d60058eSjoshua 		tls_error_setx(&signer->error, TLS_ERROR_INVALID_ARGUMENT,
2657a756d37Sjoshua 		    "digest too large");
2669ecbddc1Seric 		return (-1);
2679ecbddc1Seric 	}
26882e78bf1Sjsing 	if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) {
2697a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2707a756d37Sjoshua 		    "invalid ECDSA size: %d", signature_len);
27182e78bf1Sjsing 		return (-1);
27282e78bf1Sjsing 	}
27382e78bf1Sjsing 	if ((signature = calloc(1, signature_len)) == NULL) {
2743620689eSjoshua 		tls_error_set(&signer->error, TLS_ERROR_OUT_OF_MEMORY,
2753620689eSjoshua 		    "out of memory");
2769ecbddc1Seric 		return (-1);
2779ecbddc1Seric 	}
2789ecbddc1Seric 
27982e78bf1Sjsing 	if (!ECDSA_sign(0, input, input_len, signature, &signature_len,
28082e78bf1Sjsing 	    skey->ecdsa)) {
28182e78bf1Sjsing 		/* XXX - include further details from libcrypto. */
2827a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN,
2837a756d37Sjoshua 		    "ECDSA signing failed");
28482e78bf1Sjsing 		free(signature);
2859ecbddc1Seric 		return (-1);
2869ecbddc1Seric 	}
2879ecbddc1Seric 
28882e78bf1Sjsing 	*out_signature = signature;
28982e78bf1Sjsing 	*out_signature_len = signature_len;
2909ecbddc1Seric 
2919ecbddc1Seric 	return (0);
2929ecbddc1Seric }
2939ecbddc1Seric 
2949ecbddc1Seric int
tls_signer_sign(struct tls_signer * signer,const char * pubkey_hash,const uint8_t * input,size_t input_len,int padding_type,uint8_t ** out_signature,size_t * out_signature_len)29582e78bf1Sjsing tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash,
29682e78bf1Sjsing     const uint8_t *input, size_t input_len, int padding_type,
29782e78bf1Sjsing     uint8_t **out_signature, size_t *out_signature_len)
2989ecbddc1Seric {
2999ecbddc1Seric 	struct tls_signer_key *skey;
3009ecbddc1Seric 
30182e78bf1Sjsing 	*out_signature = NULL;
30282e78bf1Sjsing 	*out_signature_len = 0;
30382e78bf1Sjsing 
3049ecbddc1Seric 	for (skey = signer->keys; skey; skey = skey->next)
30582e78bf1Sjsing 		if (!strcmp(pubkey_hash, skey->hash))
3069ecbddc1Seric 			break;
3079ecbddc1Seric 
3089ecbddc1Seric 	if (skey == NULL) {
3097a756d37Sjoshua 		tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "key not found");
3109ecbddc1Seric 		return (-1);
3119ecbddc1Seric 	}
3129ecbddc1Seric 
3139ecbddc1Seric 	if (skey->rsa != NULL)
31482e78bf1Sjsing 		return tls_sign_rsa(signer, skey, input, input_len,
31582e78bf1Sjsing 		    padding_type, out_signature, out_signature_len);
3169ecbddc1Seric 
3179ecbddc1Seric 	if (skey->ecdsa != NULL)
31882e78bf1Sjsing 		return tls_sign_ecdsa(signer, skey, input, input_len,
31982e78bf1Sjsing 		    padding_type, out_signature, out_signature_len);
3209ecbddc1Seric 
3217a756d37Sjoshua 	tls_error_setx(&signer->error, TLS_ERROR_UNKNOWN, "unknown key type");
32282e78bf1Sjsing 
3239ecbddc1Seric 	return (-1);
3249ecbddc1Seric }
3259ecbddc1Seric 
3269ecbddc1Seric static int
tls_rsa_priv_enc(int from_len,const unsigned char * from,unsigned char * to,RSA * rsa,int rsa_padding)32782e78bf1Sjsing tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to,
32882e78bf1Sjsing     RSA *rsa, int rsa_padding)
3299ecbddc1Seric {
3309ecbddc1Seric 	struct tls_config *config;
33182e78bf1Sjsing 	uint8_t *signature = NULL;
33282e78bf1Sjsing 	size_t signature_len = 0;
33382e78bf1Sjsing 	const char *pubkey_hash;
334bce97392Sjsing 	int padding_type;
3359ecbddc1Seric 
33682e78bf1Sjsing 	/*
33782e78bf1Sjsing 	 * This function is called via RSA_private_encrypt() and has to conform
33882e78bf1Sjsing 	 * to its calling convention/signature. The caller is required to
33982e78bf1Sjsing 	 * provide a 'to' buffer of at least RSA_size() bytes.
34082e78bf1Sjsing 	 */
34182e78bf1Sjsing 
34282e78bf1Sjsing 	pubkey_hash = RSA_get_ex_data(rsa, 0);
3439ecbddc1Seric 	config = RSA_get_ex_data(rsa, 1);
3449ecbddc1Seric 
34582e78bf1Sjsing 	if (pubkey_hash == NULL || config == NULL)
34682e78bf1Sjsing 		goto err;
3479ecbddc1Seric 
348bce97392Sjsing 	if (rsa_padding == RSA_NO_PADDING) {
349bce97392Sjsing 		padding_type = TLS_PADDING_NONE;
350bce97392Sjsing 	} else if (rsa_padding == RSA_PKCS1_PADDING) {
351bce97392Sjsing 		padding_type = TLS_PADDING_RSA_PKCS1;
352bce97392Sjsing 	} else {
353bce97392Sjsing 		goto err;
354bce97392Sjsing 	}
355bce97392Sjsing 
35682e78bf1Sjsing 	if (from_len < 0)
35782e78bf1Sjsing 		goto err;
3589ecbddc1Seric 
35982e78bf1Sjsing 	if (config->sign_cb(config->sign_cb_arg, pubkey_hash, from, from_len,
360bce97392Sjsing 	    padding_type, &signature, &signature_len) == -1)
36182e78bf1Sjsing 		goto err;
3629ecbddc1Seric 
36382e78bf1Sjsing 	if (signature_len > INT_MAX || (int)signature_len > RSA_size(rsa))
36482e78bf1Sjsing 		goto err;
36582e78bf1Sjsing 
36682e78bf1Sjsing 	memcpy(to, signature, signature_len);
36782e78bf1Sjsing 	free(signature);
36882e78bf1Sjsing 
36982e78bf1Sjsing 	return ((int)signature_len);
37082e78bf1Sjsing 
37182e78bf1Sjsing  err:
37282e78bf1Sjsing 	free(signature);
37382e78bf1Sjsing 
37482e78bf1Sjsing 	return (-1);
3759ecbddc1Seric }
3769ecbddc1Seric 
3779ecbddc1Seric RSA_METHOD *
tls_signer_rsa_method(void)3789ecbddc1Seric tls_signer_rsa_method(void)
3799ecbddc1Seric {
3809ecbddc1Seric 	static RSA_METHOD *rsa_method = NULL;
3819ecbddc1Seric 
3829ecbddc1Seric 	pthread_mutex_lock(&signer_method_lock);
3839ecbddc1Seric 
3849ecbddc1Seric 	if (rsa_method != NULL)
3859ecbddc1Seric 		goto out;
3869ecbddc1Seric 
3879ecbddc1Seric 	rsa_method = RSA_meth_new("libtls RSA method", 0);
3889ecbddc1Seric 	if (rsa_method == NULL)
3899ecbddc1Seric 		goto out;
3909ecbddc1Seric 
3919ecbddc1Seric 	RSA_meth_set_priv_enc(rsa_method, tls_rsa_priv_enc);
3929ecbddc1Seric 
3939ecbddc1Seric  out:
3949ecbddc1Seric 	pthread_mutex_unlock(&signer_method_lock);
3959ecbddc1Seric 
3969ecbddc1Seric 	return (rsa_method);
3979ecbddc1Seric }
3989ecbddc1Seric 
3999ecbddc1Seric static ECDSA_SIG *
tls_ecdsa_do_sign(const unsigned char * dgst,int dgst_len,const BIGNUM * inv,const BIGNUM * rp,EC_KEY * eckey)4009ecbddc1Seric tls_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
4019ecbddc1Seric     const BIGNUM *rp, EC_KEY *eckey)
4029ecbddc1Seric {
4039ecbddc1Seric 	struct tls_config *config;
40482e78bf1Sjsing 	ECDSA_SIG *ecdsa_sig = NULL;
40582e78bf1Sjsing 	uint8_t *signature = NULL;
40682e78bf1Sjsing 	size_t signature_len = 0;
40782e78bf1Sjsing 	const unsigned char *p;
40882e78bf1Sjsing 	const char *pubkey_hash;
4099ecbddc1Seric 
41082e78bf1Sjsing 	/*
41182e78bf1Sjsing 	 * This function is called via ECDSA_do_sign_ex() and has to conform
41282e78bf1Sjsing 	 * to its calling convention/signature.
41382e78bf1Sjsing 	 */
41482e78bf1Sjsing 
41590f859cfStb 	pubkey_hash = EC_KEY_get_ex_data(eckey, 0);
41690f859cfStb 	config = EC_KEY_get_ex_data(eckey, 1);
4179ecbddc1Seric 
41882e78bf1Sjsing 	if (pubkey_hash == NULL || config == NULL)
41982e78bf1Sjsing 		goto err;
42082e78bf1Sjsing 
42182e78bf1Sjsing 	if (dgst_len < 0)
42282e78bf1Sjsing 		goto err;
42382e78bf1Sjsing 
42482e78bf1Sjsing 	if (config->sign_cb(config->sign_cb_arg, pubkey_hash, dgst, dgst_len,
425bce97392Sjsing 	    TLS_PADDING_NONE, &signature, &signature_len) == -1)
42682e78bf1Sjsing 		goto err;
42782e78bf1Sjsing 
42882e78bf1Sjsing 	p = signature;
42982e78bf1Sjsing 	if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, signature_len)) == NULL)
43082e78bf1Sjsing 		goto err;
43182e78bf1Sjsing 
43282e78bf1Sjsing 	free(signature);
43382e78bf1Sjsing 
43482e78bf1Sjsing 	return (ecdsa_sig);
43582e78bf1Sjsing 
43682e78bf1Sjsing  err:
43782e78bf1Sjsing 	free(signature);
43882e78bf1Sjsing 
4399ecbddc1Seric 	return (NULL);
4409ecbddc1Seric }
4419ecbddc1Seric 
4429dba47cfSop EC_KEY_METHOD *
tls_signer_ecdsa_method(void)4439ecbddc1Seric tls_signer_ecdsa_method(void)
4449ecbddc1Seric {
4459dba47cfSop 	static EC_KEY_METHOD *ecdsa_method = NULL;
446043c47ebStb 	const EC_KEY_METHOD *default_method;
447043c47ebStb 	int (*sign)(int type, const unsigned char *dgst, int dlen,
448043c47ebStb 	    unsigned char *sig, unsigned int *siglen,
449043c47ebStb 	    const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey);
450043c47ebStb 	int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
451043c47ebStb 	    BIGNUM **kinvp, BIGNUM **rp);
4529ecbddc1Seric 
4539ecbddc1Seric 	pthread_mutex_lock(&signer_method_lock);
4549ecbddc1Seric 
4559ecbddc1Seric 	if (ecdsa_method != NULL)
4569ecbddc1Seric 		goto out;
4579ecbddc1Seric 
458fb5793d3Stb 	default_method = EC_KEY_get_default_method();
459fb5793d3Stb 	ecdsa_method = EC_KEY_METHOD_new(default_method);
4609ecbddc1Seric 	if (ecdsa_method == NULL)
4619ecbddc1Seric 		goto out;
4629ecbddc1Seric 
463043c47ebStb 	EC_KEY_METHOD_get_sign(default_method, &sign, &sign_setup, NULL);
464043c47ebStb 	EC_KEY_METHOD_set_sign(ecdsa_method, sign, sign_setup,
465043c47ebStb 	    tls_ecdsa_do_sign);
466043c47ebStb 
4679ecbddc1Seric  out:
4689ecbddc1Seric 	pthread_mutex_unlock(&signer_method_lock);
4699ecbddc1Seric 
4709ecbddc1Seric 	return (ecdsa_method);
4719ecbddc1Seric }
472