Fix License in spec
[platform/upstream/libwebsockets.git] / lib / tls / openssl / x509.c
1 /*
2  * libwebsockets - OpenSSL-specific lws apis
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #include "core/private.h"
23 #include "tls/openssl/private.h"
24
25 #if !defined(LWS_PLAT_OPTEE)
26 static int
27 dec(char c)
28 {
29         return c - '0';
30 }
31 #endif
32
33 static time_t
34 lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
35 {
36 #if !defined(LWS_PLAT_OPTEE)
37
38         const char *p = (const char *)as->data;
39         struct tm t;
40
41         /* [YY]YYMMDDHHMMSSZ */
42
43         memset(&t, 0, sizeof(t));
44
45         if (strlen(p) == 13) {
46                 t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
47                 p += 2;
48         } else {
49                 t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
50                             (dec(p[2]) * 10) + dec(p[3]);
51                 p += 4;
52         }
53         t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
54         p += 2;
55         t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
56         p += 2;
57         t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
58         p += 2;
59         t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
60         p += 2;
61         t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
62         t.tm_isdst = 0;
63
64         return mktime(&t);
65 #else
66         return (time_t)-1;
67 #endif
68 }
69
70 int
71 lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
72                           union lws_tls_cert_info_results *buf, size_t len)
73 {
74         X509_NAME *xn;
75 #if !defined(LWS_PLAT_OPTEE)
76         char *p;
77 #endif
78
79         if (!x509)
80                 return -1;
81
82 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
83 #define X509_get_notBefore(x)   X509_getm_notBefore(x)
84 #define X509_get_notAfter(x)    X509_getm_notAfter(x)
85 #endif
86
87         switch (type) {
88         case LWS_TLS_CERT_INFO_VALIDITY_FROM:
89                 buf->time = lws_tls_openssl_asn1time_to_unix(
90                                         X509_get_notBefore(x509));
91                 if (buf->time == (time_t)-1)
92                         return -1;
93                 break;
94
95         case LWS_TLS_CERT_INFO_VALIDITY_TO:
96                 buf->time = lws_tls_openssl_asn1time_to_unix(
97                                         X509_get_notAfter(x509));
98                 if (buf->time == (time_t)-1)
99                         return -1;
100                 break;
101
102         case LWS_TLS_CERT_INFO_COMMON_NAME:
103 #if defined(LWS_PLAT_OPTEE)
104                 return -1;
105 #else
106                 xn = X509_get_subject_name(x509);
107                 if (!xn)
108                         return -1;
109                 X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
110                 p = strstr(buf->ns.name, "/CN=");
111                 if (p)
112                         memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
113                 buf->ns.len = (int)strlen(buf->ns.name);
114                 return 0;
115 #endif
116         case LWS_TLS_CERT_INFO_ISSUER_NAME:
117                 xn = X509_get_issuer_name(x509);
118                 if (!xn)
119                         return -1;
120                 X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
121                 buf->ns.len = (int)strlen(buf->ns.name);
122                 return 0;
123
124         case LWS_TLS_CERT_INFO_USAGE:
125 #if defined(LWS_HAVE_X509_get_key_usage)
126                 buf->usage = X509_get_key_usage(x509);
127                 break;
128 #else
129                 return -1;
130 #endif
131
132         case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
133         {
134 #ifndef USE_WOLFSSL
135                 size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
136                 uint8_t *tmp, *ptmp;
137
138                 if (!klen || klen > len)
139                         return -1;
140
141                 tmp = (uint8_t *)OPENSSL_malloc(klen);
142                 if (!tmp)
143                         return -1;
144
145                 ptmp = tmp;
146                 if (i2d_X509_PUBKEY(
147                               X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
148                     !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
149                         lwsl_info("%s: cert public key extraction failed\n",
150                                   __func__);
151                         if (ptmp)
152                                 OPENSSL_free(tmp);
153
154                         return -1;
155                 }
156
157                 buf->ns.len = (int)klen;
158                 memcpy(buf->ns.name, tmp, klen);
159                 OPENSSL_free(tmp);
160 #endif
161                 return 0;
162         }
163         default:
164                 return -1;
165         }
166
167         return 0;
168 }
169
170 int
171 lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
172               union lws_tls_cert_info_results *buf, size_t len)
173 {
174         return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
175 }
176
177 #if defined(LWS_WITH_NETWORK)
178 int
179 lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
180                         union lws_tls_cert_info_results *buf, size_t len)
181 {
182 #if defined(LWS_HAVE_SSL_CTX_get0_certificate)
183         X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
184
185         return lws_tls_openssl_cert_info(x509, type, buf, len);
186 #else
187         lwsl_notice("openssl is too old to support %s\n", __func__);
188
189         return -1;
190 #endif
191 }
192
193
194
195 int
196 lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
197                        union lws_tls_cert_info_results *buf, size_t len)
198 {
199         int rc = 0;
200         X509 *x509;
201
202         wsi = lws_get_network_wsi(wsi);
203
204         x509 = SSL_get_peer_certificate(wsi->tls.ssl);
205
206         if (!x509) {
207                 lwsl_debug("no peer cert\n");
208
209                 return -1;
210         }
211
212         switch (type) {
213         case LWS_TLS_CERT_INFO_VERIFIED:
214                 buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
215                                         X509_V_OK;
216                 break;
217         default:
218                 rc = lws_tls_openssl_cert_info(x509, type, buf, len);
219         }
220
221         X509_free(x509);
222
223         return rc;
224 }
225 #endif
226
227 int
228 lws_x509_create(struct lws_x509_cert **x509)
229 {
230         *x509 = lws_malloc(sizeof(**x509), __func__);
231         if (*x509)
232                 (*x509)->cert = NULL;
233
234         return !(*x509);
235 }
236
237 int
238 lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
239 {
240         BIO* bio = BIO_new(BIO_s_mem());
241
242         BIO_write(bio, pem, len);
243         x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
244         BIO_free(bio);
245         if (!x509->cert) {
246                 lwsl_err("%s: unable to parse PEM cert\n", __func__);
247                 lws_tls_err_describe_clear();
248
249                 return -1;
250         }
251
252         return 0;
253 }
254
255 int
256 lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
257                 const char *common_name)
258 {
259         char c[32], *p;
260         int ret;
261
262         if (common_name) {
263                 X509_NAME *xn = X509_get_subject_name(x509->cert);
264                 if (!xn)
265                         return -1;
266                 X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
267                 p = strstr(c, "/CN=");
268                 if (p)
269                         p = p + 4;
270                 else
271                         p = c;
272
273                 if (strcmp(p, common_name)) {
274                         lwsl_err("%s: common name mismatch\n", __func__);
275                         return -1;
276                 }
277         }
278
279         ret = X509_check_issued(trusted->cert, x509->cert);
280         if (ret != X509_V_OK) {
281                 lwsl_err("%s: unable to verify cert relationship\n", __func__);
282                 lws_tls_err_describe_clear();
283
284                 return -1;
285         }
286
287         return 0;
288 }
289
290 #if defined(LWS_WITH_JOSE)
291 int
292 lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
293                        const char *curves, int rsa_min_bits)
294 {
295         int id, n, ret = -1, count;
296         ASN1_OBJECT *obj = NULL;
297         const EC_POINT *ecpoint;
298         const EC_GROUP *ecgroup;
299         EC_KEY *ecpub = NULL;
300         X509_PUBKEY *pubkey;
301         RSA *rsapub = NULL;
302         BIGNUM *mpi[4];
303         EVP_PKEY *pkey;
304
305         memset(jwk, 0, sizeof(*jwk));
306
307         pubkey = X509_get_X509_PUBKEY(x509->cert);
308         if (!pubkey) {
309                 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
310
311                 goto bail;
312         }
313
314         if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
315                 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
316
317                 goto bail;
318         }
319
320         id = OBJ_obj2nid(obj);
321         if (id == NID_undef) {
322                 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
323
324                 goto bail;
325         }
326
327         lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
328
329         pkey = X509_get_pubkey(x509->cert);
330         if (!pkey) {
331                 lwsl_notice("%s: unable to extract pubkey", __func__);
332
333                 goto bail;
334         }
335
336         switch (id) {
337         case NID_X9_62_id_ecPublicKey:
338                 lwsl_debug("%s: EC key\n", __func__);
339                 jwk->kty = LWS_GENCRYPTO_KTY_EC;
340
341                 if (!curves) {
342                         lwsl_err("%s: ec curves not allowed\n", __func__);
343
344                         goto bail1;
345                 }
346
347                 ecpub = EVP_PKEY_get1_EC_KEY(pkey);
348                 if (!ecpub) {
349                         lwsl_notice("%s: missing EC pubkey\n", __func__);
350
351                         goto bail1;
352                 }
353
354                 ecpoint = EC_KEY_get0_public_key(ecpub);
355                 if (!ecpoint) {
356                         lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
357                         goto bail2;
358                 }
359
360                 ecgroup = EC_KEY_get0_group(ecpub);
361                 if (!ecgroup) {
362                         lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
363                         goto bail2;
364                 }
365
366                 /* validate the curve against ones we allow */
367
368                 if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
369                                 EC_GROUP_get_curve_name(ecgroup), jwk))
370                         /* already logged */
371                         goto bail2;
372
373                 mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
374                 mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
375                 mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
376                 mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
377
378 #if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
379                 if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
380 #else
381                 if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
382 #endif
383                                                   mpi[LWS_GENCRYPTO_EC_KEYEL_X],
384                                                   mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
385                                                           NULL) != 1) {
386                         BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
387                         BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
388                         lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
389                         goto bail2;
390                 }
391                 count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
392                 n = LWS_GENCRYPTO_EC_KEYEL_X;
393                 break;
394
395         case NID_rsaEncryption:
396                 lwsl_debug("%s: rsa key\n", __func__);
397                 jwk->kty = LWS_GENCRYPTO_KTY_RSA;
398
399                 rsapub = EVP_PKEY_get1_RSA(pkey);
400                 if (!rsapub) {
401                         lwsl_notice("%s: missing RSA pubkey\n", __func__);
402
403                         goto bail1;
404                 }
405
406                 if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
407                         lwsl_err("%s: key bits %d less than minimum %d\n",
408                                  __func__, RSA_size(rsapub) * 8, rsa_min_bits);
409
410                         goto bail2;
411                 }
412
413 #if defined(LWS_HAVE_RSA_SET0_KEY)
414                 /* we don't need d... but the api wants to write it */
415                 RSA_get0_key(rsapub,
416                             (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
417                             (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
418                             (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
419 #else
420                 mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
421                 mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
422                 mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
423 #endif
424                 count = LWS_GENCRYPTO_RSA_KEYEL_D;
425                 n = LWS_GENCRYPTO_RSA_KEYEL_E;
426                 break;
427         default:
428                 lwsl_err("%s: unknown NID\n", __func__);
429                 goto bail2;
430         }
431
432         for (; n < count; n++) {
433                 if (!mpi[n])
434                         continue;
435                 jwk->e[n].len = BN_num_bytes(mpi[n]);
436                 jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
437                 if (!jwk->e[n].buf) {
438                         if (id == NID_X9_62_id_ecPublicKey) {
439                                 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
440                                 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
441                         }
442                         goto bail2;
443                 }
444                 BN_bn2bin(mpi[n], jwk->e[n].buf);
445         }
446
447         if (id == NID_X9_62_id_ecPublicKey) {
448                 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
449                 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
450         }
451
452         ret = 0;
453
454 bail2:
455         if (id == NID_X9_62_id_ecPublicKey)
456                 EC_KEY_free(ecpub);
457         else
458                 RSA_free(rsapub);
459
460 bail1:
461         EVP_PKEY_free(pkey);
462 bail:
463         /* jwk destroy will clean any partial state */
464         if (ret)
465                 lws_jwk_destroy(jwk);
466
467         return ret;
468 }
469
470 static int
471 lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
472 {
473         const char *pp = (const char *)u;
474         int n = strlen(pp);
475
476         if (n > size - 1)
477                 return -1;
478
479         memcpy(buf, pp, n + 1);
480
481         return n;
482 }
483
484 int
485 lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
486                          const char *passphrase)
487 {
488         BIO* bio = BIO_new(BIO_s_mem());
489         BIGNUM *mpi, *dummy[6];
490         EVP_PKEY *pkey = NULL;
491         EC_KEY *ecpriv = NULL;
492         RSA *rsapriv = NULL;
493         const BIGNUM *cmpi;
494         int n, m, ret = -1;
495
496         BIO_write(bio, pem, len);
497         PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
498                                 (void *)passphrase);
499         BIO_free(bio);
500         lws_explicit_bzero((void *)pem, len);
501         if (!pkey) {
502                 lwsl_err("%s: unable to parse PEM privkey\n", __func__);
503                 lws_tls_err_describe_clear();
504
505                 return -1;
506         }
507
508         /* confirm the key type matches the existing jwk situation */
509
510         switch (jwk->kty) {
511         case LWS_GENCRYPTO_KTY_EC:
512                 if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
513                         lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
514
515                         goto bail;
516                 }
517                 ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
518                 if (!ecpriv) {
519                         lwsl_notice("%s: missing EC key\n", __func__);
520
521                         goto bail;
522                 }
523
524                 cmpi = EC_KEY_get0_private_key(ecpriv);
525
526                 /* quick size check first */
527
528                 n = BN_num_bytes(cmpi);
529                 if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
530                         lwsl_err("%s: jwk key size doesn't match\n", __func__);
531
532                         goto bail1;
533                 }
534
535                 /* TODO.. check public curve / group + point */
536
537                 jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
538                 jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
539                 if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
540                         goto bail1;
541
542                 m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
543                                       jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
544                 if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
545                         goto bail1;
546
547                 break;
548
549         case LWS_GENCRYPTO_KTY_RSA:
550                 if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
551                         lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
552
553                         goto bail;
554                 }
555                 rsapriv = EVP_PKEY_get1_RSA(pkey);
556                 if (!rsapriv) {
557                         lwsl_notice("%s: missing RSA key\n", __func__);
558
559                         goto bail;
560                 }
561
562 #if defined(LWS_HAVE_RSA_SET0_KEY)
563                 RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
564                                       (const BIGNUM **)&dummy[1], /* e */
565                                       (const BIGNUM **)&mpi);     /* d */
566                 RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4],  /* p */
567                                           (const BIGNUM **)&dummy[5]); /* q */
568 #else
569                 dummy[0] = rsapriv->n;
570                 dummy[1] = rsapriv->e;
571                 dummy[4] = rsapriv->p;
572                 dummy[5] = rsapriv->q;
573                 mpi = rsapriv->d;
574 #endif
575
576                 /* quick size check first */
577
578                 n = BN_num_bytes(mpi);
579                 if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
580                         lwsl_err("%s: jwk key size doesn't match\n", __func__);
581
582                         goto bail1;
583                 }
584
585                 /* then check that n & e match what we got from the cert */
586
587                 dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
588                                      jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
589                                      NULL);
590                 dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
591                                      jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
592                                      NULL);
593
594                 m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
595                 BN_clear_free(dummy[2]);
596                 BN_clear_free(dummy[3]);
597                 if (m) {
598                         lwsl_err("%s: privkey doesn't match jwk pubkey\n",
599                                  __func__);
600
601                         goto bail1;
602                 }
603
604                 /* accept d from the PEM privkey into the JWK */
605
606                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
607                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
608                 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
609                         goto bail1;
610
611                 BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
612
613                 /* accept p and q from the PEM privkey into the JWK */
614
615                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
616                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
617                 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
618                         lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
619                         goto bail1;
620                 }
621                 BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
622
623                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
624                 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
625                 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
626                         lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
627                         lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
628                         goto bail1;
629                 }
630                 BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
631                 break;
632         default:
633                 lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
634                 return -1;
635         }
636
637         ret = 0;
638
639 bail1:
640         if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
641                 EC_KEY_free(ecpriv);
642         else
643                 RSA_free(rsapriv);
644
645 bail:
646         EVP_PKEY_free(pkey);
647
648         return ret;
649 }
650 #endif
651
652 void
653 lws_x509_destroy(struct lws_x509_cert **x509)
654 {
655         if (!*x509)
656                 return;
657
658         if ((*x509)->cert) {
659                 X509_free((*x509)->cert);
660                 (*x509)->cert = NULL;
661         }
662
663         lws_free_set_NULL(*x509);
664 }