xref: /dragonfly/crypto/libressl/tls/tls_signer.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: tls_signer.c,v 1.4 2022/02/01 17:18:38 jsing Exp $ */
2 /*
3  * Copyright (c) 2021 Eric Faurot <eric@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <limits.h>
19 
20 #include <openssl/ecdsa.h>
21 #include <openssl/err.h>
22 #include <openssl/rsa.h>
23 
24 #include "tls.h"
25 #include "tls_internal.h"
26 
27 struct tls_signer_key {
28           char *hash;
29           RSA *rsa;
30           EC_KEY *ecdsa;
31           struct tls_signer_key *next;
32 };
33 
34 struct tls_signer {
35           struct tls_error error;
36           struct tls_signer_key *keys;
37 };
38 
39 static pthread_mutex_t signer_method_lock = PTHREAD_MUTEX_INITIALIZER;
40 
41 struct tls_signer *
tls_signer_new(void)42 tls_signer_new(void)
43 {
44           struct tls_signer *signer;
45 
46           if ((signer = calloc(1, sizeof(*signer))) == NULL)
47                     return (NULL);
48 
49           return (signer);
50 }
51 
52 void
tls_signer_free(struct tls_signer * signer)53 tls_signer_free(struct tls_signer *signer)
54 {
55           struct tls_signer_key *skey;
56 
57           if (signer == NULL)
58                     return;
59 
60           tls_error_clear(&signer->error);
61 
62           while (signer->keys) {
63                     skey = signer->keys;
64                     signer->keys = skey->next;
65                     RSA_free(skey->rsa);
66                     EC_KEY_free(skey->ecdsa);
67                     free(skey->hash);
68                     free(skey);
69           }
70 
71           free(signer);
72 }
73 
74 const char *
tls_signer_error(struct tls_signer * signer)75 tls_signer_error(struct tls_signer *signer)
76 {
77           return (signer->error.msg);
78 }
79 
80 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)81 tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert,
82     size_t cert_len, const uint8_t *key, size_t key_len)
83 {
84           struct tls_signer_key *skey = NULL;
85           char *errstr = "unknown";
86           int ssl_err;
87           EVP_PKEY *pkey = NULL;
88           X509 *x509 = NULL;
89           BIO *bio = NULL;
90           char *hash = NULL;
91 
92           /* Compute certificate hash */
93           if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) {
94                     tls_error_setx(&signer->error,
95                         "failed to create certificate bio");
96                     goto err;
97           }
98           if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
99               NULL)) == NULL) {
100                     if ((ssl_err = ERR_peek_error()) != 0)
101                               errstr = ERR_error_string(ssl_err, NULL);
102                     tls_error_setx(&signer->error, "failed to load certificate: %s",
103                         errstr);
104                     goto err;
105           }
106           if (tls_cert_pubkey_hash(x509, &hash) == -1) {
107                     tls_error_setx(&signer->error,
108                         "failed to get certificate hash");
109                     goto err;
110           }
111 
112           X509_free(x509);
113           x509 = NULL;
114           BIO_free(bio);
115           bio = NULL;
116 
117           /* Read private key */
118           if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) {
119                     tls_error_setx(&signer->error, "failed to create key bio");
120                     goto err;
121           }
122           if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
123               NULL)) == NULL) {
124                     tls_error_setx(&signer->error, "failed to read private key");
125                     goto err;
126           }
127 
128           if ((skey = calloc(1, sizeof(*skey))) == NULL) {
129                     tls_error_set(&signer->error, "failed to create key entry");
130                     goto err;
131           }
132           skey->hash = hash;
133           if ((skey->rsa = EVP_PKEY_get1_RSA(pkey)) == NULL &&
134               (skey->ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
135                     tls_error_setx(&signer->error, "unknown key type");
136                     goto err;
137           }
138 
139           skey->next = signer->keys;
140           signer->keys = skey;
141           EVP_PKEY_free(pkey);
142           BIO_free(bio);
143 
144           return (0);
145 
146  err:
147           EVP_PKEY_free(pkey);
148           X509_free(x509);
149           BIO_free(bio);
150           free(hash);
151           free(skey);
152 
153           return (-1);
154 }
155 
156 int
tls_signer_add_keypair_file(struct tls_signer * signer,const char * cert_file,const char * key_file)157 tls_signer_add_keypair_file(struct tls_signer *signer, const char *cert_file,
158     const char *key_file)
159 {
160           char *cert = NULL, *key = NULL;
161           size_t cert_len, key_len;
162           int rv = -1;
163 
164           if (tls_config_load_file(&signer->error, "certificate", cert_file,
165               &cert, &cert_len) == -1)
166                     goto err;
167 
168           if (tls_config_load_file(&signer->error, "key", key_file, &key,
169               &key_len) == -1)
170                     goto err;
171 
172           rv = tls_signer_add_keypair_mem(signer, cert, cert_len, key, key_len);
173 
174  err:
175           free(cert);
176           free(key);
177 
178           return (rv);
179 }
180 
181 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)182 tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey,
183     const uint8_t *input, size_t input_len, int padding_type,
184     uint8_t **out_signature, size_t *out_signature_len)
185 {
186           int rsa_padding, rsa_size, signature_len;
187           char *signature = NULL;
188 
189           *out_signature = NULL;
190           *out_signature_len = 0;
191 
192           if (padding_type == TLS_PADDING_NONE) {
193                     rsa_padding = RSA_NO_PADDING;
194           } else if (padding_type == TLS_PADDING_RSA_PKCS1) {
195                     rsa_padding = RSA_PKCS1_PADDING;
196           } else if (padding_type == TLS_PADDING_RSA_X9_31) {
197                     rsa_padding = RSA_X931_PADDING;
198           } else {
199                     tls_error_setx(&signer->error, "invalid RSA padding type (%d)",
200                         padding_type);
201                     return (-1);
202           }
203 
204           if (input_len > INT_MAX) {
205                     tls_error_setx(&signer->error, "input too large");
206                     return (-1);
207           }
208           if ((rsa_size = RSA_size(skey->rsa)) <= 0) {
209                     tls_error_setx(&signer->error, "invalid RSA size: %d",
210                         rsa_size);
211                     return (-1);
212           }
213           if ((signature = calloc(1, rsa_size)) == NULL) {
214                     tls_error_set(&signer->error, "RSA signature");
215                     return (-1);
216           }
217 
218           if ((signature_len = RSA_private_encrypt((int)input_len, input,
219               signature, skey->rsa, rsa_padding)) <= 0) {
220                     /* XXX - include further details from libcrypto. */
221                     tls_error_setx(&signer->error, "RSA signing failed");
222                     free(signature);
223                     return (-1);
224           }
225 
226           *out_signature = signature;
227           *out_signature_len = (size_t)signature_len;
228 
229           return (0);
230 }
231 
232 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)233 tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey,
234     const uint8_t *input, size_t input_len, int padding_type,
235     uint8_t **out_signature, size_t *out_signature_len)
236 {
237           unsigned char *signature;
238           int signature_len;
239 
240           *out_signature = NULL;
241           *out_signature_len = 0;
242 
243           if (padding_type != TLS_PADDING_NONE) {
244                     tls_error_setx(&signer->error, "invalid ECDSA padding");
245                     return (-1);
246           }
247 
248           if (input_len > INT_MAX) {
249                     tls_error_setx(&signer->error, "digest too large");
250                     return (-1);
251           }
252           if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) {
253                     tls_error_setx(&signer->error, "invalid ECDSA size: %d",
254                         signature_len);
255                     return (-1);
256           }
257           if ((signature = calloc(1, signature_len)) == NULL) {
258                     tls_error_set(&signer->error, "ECDSA signature");
259                     return (-1);
260           }
261 
262           if (!ECDSA_sign(0, input, input_len, signature, &signature_len,
263               skey->ecdsa)) {
264                     /* XXX - include further details from libcrypto. */
265                     tls_error_setx(&signer->error, "ECDSA signing failed");
266                     free(signature);
267                     return (-1);
268           }
269 
270           *out_signature = signature;
271           *out_signature_len = signature_len;
272 
273           return (0);
274 }
275 
276 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)277 tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash,
278     const uint8_t *input, size_t input_len, int padding_type,
279     uint8_t **out_signature, size_t *out_signature_len)
280 {
281           struct tls_signer_key *skey;
282 
283           *out_signature = NULL;
284           *out_signature_len = 0;
285 
286           for (skey = signer->keys; skey; skey = skey->next)
287                     if (!strcmp(pubkey_hash, skey->hash))
288                               break;
289 
290           if (skey == NULL) {
291                     tls_error_setx(&signer->error, "key not found");
292                     return (-1);
293           }
294 
295           if (skey->rsa != NULL)
296                     return tls_sign_rsa(signer, skey, input, input_len,
297                         padding_type, out_signature, out_signature_len);
298 
299           if (skey->ecdsa != NULL)
300                     return tls_sign_ecdsa(signer, skey, input, input_len,
301                         padding_type, out_signature, out_signature_len);
302 
303           tls_error_setx(&signer->error, "unknown key type");
304 
305           return (-1);
306 }
307 
308 static int
tls_rsa_priv_enc(int from_len,const unsigned char * from,unsigned char * to,RSA * rsa,int rsa_padding)309 tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to,
310     RSA *rsa, int rsa_padding)
311 {
312           struct tls_config *config;
313           uint8_t *signature = NULL;
314           size_t signature_len = 0;
315           const char *pubkey_hash;
316           int padding_type;
317 
318           /*
319            * This function is called via RSA_private_encrypt() and has to conform
320            * to its calling convention/signature. The caller is required to
321            * provide a 'to' buffer of at least RSA_size() bytes.
322            */
323 
324           pubkey_hash = RSA_get_ex_data(rsa, 0);
325           config = RSA_get_ex_data(rsa, 1);
326 
327           if (pubkey_hash == NULL || config == NULL)
328                     goto err;
329 
330           if (rsa_padding == RSA_NO_PADDING) {
331                     padding_type = TLS_PADDING_NONE;
332           } else if (rsa_padding == RSA_PKCS1_PADDING) {
333                     padding_type = TLS_PADDING_RSA_PKCS1;
334           } else if (rsa_padding == RSA_X931_PADDING) {
335                     padding_type = TLS_PADDING_RSA_X9_31;
336           } else {
337                     goto err;
338           }
339 
340           if (from_len < 0)
341                     goto err;
342 
343           if (config->sign_cb(config->sign_cb_arg, pubkey_hash, from, from_len,
344               padding_type, &signature, &signature_len) == -1)
345                     goto err;
346 
347           if (signature_len > INT_MAX || (int)signature_len > RSA_size(rsa))
348                     goto err;
349 
350           memcpy(to, signature, signature_len);
351           free(signature);
352 
353           return ((int)signature_len);
354 
355  err:
356           free(signature);
357 
358           return (-1);
359 }
360 
361 RSA_METHOD *
tls_signer_rsa_method(void)362 tls_signer_rsa_method(void)
363 {
364           static RSA_METHOD *rsa_method = NULL;
365 
366           pthread_mutex_lock(&signer_method_lock);
367 
368           if (rsa_method != NULL)
369                     goto out;
370 
371           rsa_method = RSA_meth_new("libtls RSA method", 0);
372           if (rsa_method == NULL)
373                     goto out;
374 
375           RSA_meth_set_priv_enc(rsa_method, tls_rsa_priv_enc);
376 
377  out:
378           pthread_mutex_unlock(&signer_method_lock);
379 
380           return (rsa_method);
381 }
382 
383 static ECDSA_SIG *
tls_ecdsa_do_sign(const unsigned char * dgst,int dgst_len,const BIGNUM * inv,const BIGNUM * rp,EC_KEY * eckey)384 tls_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
385     const BIGNUM *rp, EC_KEY *eckey)
386 {
387           struct tls_config *config;
388           ECDSA_SIG *ecdsa_sig = NULL;
389           uint8_t *signature = NULL;
390           size_t signature_len = 0;
391           const unsigned char *p;
392           const char *pubkey_hash;
393 
394           /*
395            * This function is called via ECDSA_do_sign_ex() and has to conform
396            * to its calling convention/signature.
397            */
398 
399           pubkey_hash = ECDSA_get_ex_data(eckey, 0);
400           config = ECDSA_get_ex_data(eckey, 1);
401 
402           if (pubkey_hash == NULL || config == NULL)
403                     goto err;
404 
405           if (dgst_len < 0)
406                     goto err;
407 
408           if (config->sign_cb(config->sign_cb_arg, pubkey_hash, dgst, dgst_len,
409               TLS_PADDING_NONE, &signature, &signature_len) == -1)
410                     goto err;
411 
412           p = signature;
413           if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, signature_len)) == NULL)
414                     goto err;
415 
416           free(signature);
417 
418           return (ecdsa_sig);
419 
420  err:
421           free(signature);
422 
423           return (NULL);
424 }
425 
426 ECDSA_METHOD *
tls_signer_ecdsa_method(void)427 tls_signer_ecdsa_method(void)
428 {
429           static ECDSA_METHOD *ecdsa_method = NULL;
430 
431           pthread_mutex_lock(&signer_method_lock);
432 
433           if (ecdsa_method != NULL)
434                     goto out;
435 
436           ecdsa_method = calloc(1, sizeof(*ecdsa_method));
437           if (ecdsa_method == NULL)
438                     goto out;
439 
440           ecdsa_method->ecdsa_do_sign = tls_ecdsa_do_sign;
441           ecdsa_method->name = strdup("libtls ECDSA method");
442           if (ecdsa_method->name == NULL) {
443                     free(ecdsa_method);
444                     ecdsa_method = NULL;
445           }
446 
447  out:
448           pthread_mutex_unlock(&signer_method_lock);
449 
450           return (ecdsa_method);
451 }
452