Coverage Report

Created: 2025-11-16 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/openssl-x509.c
Line
Count
Source
1
/*
2
 * libwebsockets - small server side websockets and web server implementation
3
 *
4
 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to
8
 * deal in the Software without restriction, including without limitation the
9
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
 * sell copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 */
24
25
#define WIN32_LEAN_AND_MEAN
26
#include "private-lib-core.h"
27
#include "private-lib-tls-openssl.h"
28
29
#if !defined(LWS_PLAT_OPTEE)
30
static int
31
dec(char c)
32
0
{
33
0
  return c - '0';
34
0
}
35
#endif
36
37
static time_t
38
lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
39
0
{
40
0
#if !defined(LWS_PLAT_OPTEE)
41
42
0
  const char *p = (const char *)as->data;
43
0
  struct tm t;
44
45
  /* [YY]YYMMDDHHMMSSZ */
46
47
0
  memset(&t, 0, sizeof(t));
48
49
0
  if (strlen(p) == 13) {
50
0
    t.tm_year = (dec(p[0]) * 10) + dec(p[1]);
51
0
    if (t.tm_year < 50) /* RFC5280: 13 char dates will break after 2049 */
52
0
      t.tm_year += 100; /* struct tm year is -1900, this gives 2000..2049 */
53
0
    p += 2;
54
0
  } else {
55
0
    t.tm_year = ((dec(p[0]) * 1000) + (dec(p[1]) * 100) +
56
0
          (dec(p[2]) * 10) + dec(p[3])) - 1900; /* struct tm year is -1900 */
57
0
    p += 4;
58
0
  }
59
0
  t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
60
0
  p += 2;
61
0
  t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
62
0
  p += 2;
63
0
  t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
64
0
  p += 2;
65
0
  t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
66
0
  p += 2;
67
0
  t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
68
0
  t.tm_isdst = 0;
69
70
0
  return mktime(&t);
71
#else
72
  return (time_t)-1;
73
#endif
74
0
}
75
76
#if defined(USE_WOLFSSL)
77
#define AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID
78
#endif
79
80
int
81
lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
82
        union lws_tls_cert_info_results *buf, size_t len)
83
0
{
84
0
#ifndef USE_WOLFSSL
85
0
  const unsigned char *dp;
86
0
  ASN1_OCTET_STRING *val;
87
0
  AUTHORITY_KEYID *akid;
88
0
  X509_EXTENSION *ext;
89
0
  int tag, xclass, r = 1;
90
0
  long xlen, loc;
91
0
#endif
92
0
  X509_NAME *xn;
93
0
#if !defined(LWS_PLAT_OPTEE)
94
0
  char *p, *p1;
95
0
  size_t rl;
96
0
#endif
97
98
0
  buf->ns.len = 0;
99
100
0
  if (!x509)
101
0
    return -1;
102
0
  if (!len)
103
0
    len = sizeof(buf->ns.name);
104
105
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
106
#define X509_get_notBefore(x) X509_getm_notBefore(x)
107
#define X509_get_notAfter(x)  X509_getm_notAfter(x)
108
#endif
109
110
0
  switch (type) {
111
0
  case LWS_TLS_CERT_INFO_VALIDITY_FROM:
112
0
    buf->time = lws_tls_openssl_asn1time_to_unix(
113
0
          X509_get_notBefore(x509));
114
0
    if (buf->time == (time_t)-1)
115
0
      return -1;
116
0
    break;
117
118
0
  case LWS_TLS_CERT_INFO_VALIDITY_TO:
119
0
    buf->time = lws_tls_openssl_asn1time_to_unix(
120
0
          X509_get_notAfter(x509));
121
0
    if (buf->time == (time_t)-1)
122
0
      return -1;
123
0
    break;
124
125
0
  case LWS_TLS_CERT_INFO_COMMON_NAME:
126
#if defined(LWS_PLAT_OPTEE)
127
    return -1;
128
#else
129
0
    xn = X509_get_subject_name(x509);
130
0
    if (!xn)
131
0
      return -1;
132
0
    X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
133
0
    p = strstr(buf->ns.name, "/CN=");
134
0
    if (p) {
135
0
      p += 4;
136
0
      p1 = strchr(p, '/');
137
0
      if (p1)
138
0
        rl = lws_ptr_diff_size_t(p1, p);
139
0
      else
140
0
        rl = strlen(p);
141
0
      memmove(buf->ns.name, p, rl);
142
0
      buf->ns.name[rl] = '\0';
143
0
    }
144
0
    buf->ns.len = (int)strlen(buf->ns.name);
145
0
    return 0;
146
0
#endif
147
0
  case LWS_TLS_CERT_INFO_ISSUER_NAME:
148
0
    xn = X509_get_issuer_name(x509);
149
0
    if (!xn)
150
0
      return -1;
151
0
    X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
152
0
    buf->ns.len = (int)strlen(buf->ns.name);
153
0
    return 0;
154
155
0
  case LWS_TLS_CERT_INFO_USAGE:
156
0
#if defined(LWS_HAVE_X509_get_key_usage)
157
0
    buf->usage = X509_get_key_usage(x509);
158
0
    break;
159
#else
160
    return -1;
161
#endif
162
163
0
  case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
164
0
  {
165
0
#ifndef USE_WOLFSSL
166
0
    size_t klen = (unsigned int)i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
167
0
    uint8_t *tmp, *ptmp;
168
169
0
    if (!klen || klen > len)
170
0
      return -1;
171
172
0
    tmp = (uint8_t *)OPENSSL_malloc(klen);
173
0
    if (!tmp)
174
0
      return -1;
175
176
0
    ptmp = tmp;
177
0
    if (i2d_X509_PUBKEY(
178
0
            X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
179
0
        !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
180
0
      lwsl_info("%s: cert public key extraction failed\n",
181
0
          __func__);
182
0
      if (ptmp)
183
0
        OPENSSL_free(tmp);
184
185
0
      return -1;
186
0
    }
187
188
0
    buf->ns.len = (int)klen;
189
0
    memcpy(buf->ns.name, tmp, klen);
190
0
    OPENSSL_free(tmp);
191
0
#endif
192
0
    return 0;
193
0
  }
194
0
  case LWS_TLS_CERT_INFO_DER_RAW:
195
0
  {
196
0
    int der_len = i2d_X509(x509, NULL);
197
0
    uint8_t *tmp = (uint8_t *)buf->ns.name;
198
199
0
    buf->ns.len = der_len < 0 ? 0 : der_len;
200
201
0
    if (der_len < 0 || (size_t)der_len > len)
202
0
      return -1;
203
204
0
    der_len = i2d_X509(x509, &tmp);
205
0
    if (der_len < 0)
206
0
      return -1;
207
208
0
    return 0;
209
0
  }
210
211
0
#ifndef USE_WOLFSSL
212
213
0
  case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID:
214
0
    loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
215
0
    if (loc < 0)
216
0
      return 1;
217
218
0
    ext = X509_get_ext(x509, (int)loc);
219
0
    if (!ext)
220
0
      return 1;
221
0
#ifndef USE_WOLFSSL
222
0
    akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
223
#else
224
    akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
225
#endif
226
0
    if (!akid || !akid->keyid)
227
0
      return 1;
228
0
    val = akid->keyid;
229
0
    dp = (const unsigned char *)val->data;
230
0
    xlen = val->length;
231
232
0
    buf->ns.len = (int)xlen;
233
0
    if (len < (size_t)buf->ns.len)
234
0
      return -1;
235
236
0
    memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
237
238
0
    AUTHORITY_KEYID_free(akid);
239
0
    break;
240
241
0
  case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER:
242
0
    loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
243
0
    if (loc < 0)
244
0
      return 1;
245
246
0
    ext = X509_get_ext(x509, (int)loc);
247
0
    if (!ext)
248
0
      return 1;
249
250
0
#ifndef USE_WOLFSSL
251
0
    akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
252
#else
253
    akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
254
#endif
255
0
    if (!akid || !akid->issuer)
256
0
      return 1;
257
258
0
#if defined(LWS_HAVE_OPENSSL_STACK)
259
0
    {
260
0
      const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
261
0
      STACK_OF(CONF_VALUE) *cv;
262
    #if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
263
      size_t j;
264
    #else
265
0
      int j;
266
0
    #endif
267
268
0
      cv = i2v_GENERAL_NAMES((X509V3_EXT_METHOD*)method, akid->issuer, NULL);
269
0
      if (!cv)
270
0
        goto bail_ak;
271
272
0
            for (j = 0; j < OPENSSL_sk_num((const OPENSSL_STACK *)&cv); j++) {
273
0
                CONF_VALUE *nval = OPENSSL_sk_value((const OPENSSL_STACK *)&cv, j);
274
0
                size_t ln = (nval->name ? strlen(nval->name) : 0),
275
0
                 lv = (nval->value ? strlen(nval->value) : 0),
276
0
                 l = ln + lv;
277
278
0
                if (len > l) {
279
0
                  if (nval->name)
280
0
                    memcpy(buf->ns.name + buf->ns.len, nval->name, ln);
281
0
                  if (nval->value)
282
0
                    memcpy(buf->ns.name + buf->ns.len + ln, nval->value, lv);
283
0
                  buf->ns.len = (int)((size_t)buf->ns.len + l);
284
0
                  len -= l;
285
0
                  buf->ns.name[buf->ns.len] = '\0';
286
287
0
                  r = 0;
288
0
                }
289
0
            }
290
0
    }
291
292
0
bail_ak:
293
0
#endif
294
0
    AUTHORITY_KEYID_free(akid);
295
296
0
    return r;
297
298
0
  case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL:
299
0
    loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
300
0
    if (loc < 0)
301
0
      return 1;
302
303
0
    ext = X509_get_ext(x509, (int)loc);
304
0
    if (!ext)
305
0
      return 1;
306
0
    akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
307
0
    if (!akid || !akid->serial)
308
0
      return 1;
309
310
#if 0
311
    // need to handle blobs, and ASN1_INTEGER_get_uint64 not
312
    // available on older openssl
313
    {
314
      uint64_t res;
315
      if (ASN1_INTEGER_get_uint64(&res, akid->serial) != 1)
316
        break;
317
      buf->ns.len = lws_snprintf(buf->ns.name, len, "%llu",
318
          (unsigned long long)res);
319
    }
320
#endif
321
0
    break;
322
323
0
  case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID:
324
325
0
    loc = X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1);
326
0
    if (loc < 0)
327
0
      return 1;
328
329
0
    ext = X509_get_ext(x509, (int)loc);
330
0
    if (!ext)
331
0
      return 1;
332
333
0
    val = X509_EXTENSION_get_data(ext);
334
0
    if (!val)
335
0
      return 1;
336
337
#if defined(USE_WOLFSSL)
338
    return 1;
339
#else
340
0
    dp = (const unsigned char *)val->data;
341
342
0
    if (ASN1_get_object(&dp, &xlen,
343
0
            &tag, &xclass, val->length) & 0x80)
344
0
      return -1;
345
346
0
    if (tag != V_ASN1_OCTET_STRING) {
347
0
      lwsl_notice("not octet string %d\n", (int)tag);
348
0
      return 1;
349
0
    }
350
0
#endif
351
0
    buf->ns.len = (int)xlen;
352
0
    if (len < (size_t)buf->ns.len)
353
0
      return -1;
354
355
0
    memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
356
0
    break;
357
0
#endif
358
359
0
  default:
360
0
    return -1;
361
0
  }
362
363
0
  return 0;
364
0
}
365
366
int
367
lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
368
        union lws_tls_cert_info_results *buf, size_t len)
369
0
{
370
0
  return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
371
0
}
372
373
#if defined(LWS_WITH_NETWORK)
374
int
375
lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
376
            union lws_tls_cert_info_results *buf, size_t len)
377
0
{
378
0
#if defined(LWS_HAVE_SSL_CTX_get0_certificate)
379
0
  X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
380
381
0
  return lws_tls_openssl_cert_info(x509, type, buf, len);
382
#else
383
  lwsl_notice("openssl is too old to support %s\n", __func__);
384
385
  return -1;
386
#endif
387
0
}
388
389
390
391
int
392
lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
393
           union lws_tls_cert_info_results *buf, size_t len)
394
0
{
395
0
  int rc = 0;
396
0
  X509 *x509;
397
398
0
  wsi = lws_get_network_wsi(wsi);
399
400
0
  x509 = SSL_get_peer_certificate(wsi->tls.ssl);
401
402
0
  if (!x509) {
403
0
    lwsl_debug("no peer cert\n");
404
405
0
    return -1;
406
0
  }
407
408
0
  switch (type) {
409
0
  case LWS_TLS_CERT_INFO_VERIFIED:
410
0
    buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
411
0
          X509_V_OK;
412
0
    break;
413
0
  default:
414
0
    rc = lws_tls_openssl_cert_info(x509, type, buf, len);
415
0
  }
416
417
0
  X509_free(x509);
418
419
0
  return rc;
420
0
}
421
#endif
422
423
int
424
lws_x509_create(struct lws_x509_cert **x509)
425
0
{
426
0
  *x509 = lws_malloc(sizeof(**x509), __func__);
427
0
  if (*x509)
428
0
    (*x509)->cert = NULL;
429
430
0
  return !(*x509);
431
0
}
432
433
int
434
lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
435
0
{
436
0
  BIO* bio = BIO_new(BIO_s_mem());
437
438
0
  BIO_write(bio, pem, (int)len);
439
0
  x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
440
0
  BIO_free(bio);
441
0
  if (!x509->cert) {
442
0
    lwsl_err("%s: unable to parse PEM cert\n", __func__);
443
0
    lws_tls_err_describe_clear();
444
445
0
    return -1;
446
0
  }
447
448
0
  return 0;
449
0
}
450
451
int
452
lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
453
    const char *common_name)
454
0
{
455
0
  char c[32], *p;
456
0
  int ret;
457
458
0
  if (common_name) {
459
0
    X509_NAME *xn = X509_get_subject_name(x509->cert);
460
0
    if (!xn)
461
0
      return -1;
462
0
    X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
463
0
    p = strstr(c, "/CN=");
464
0
    if (p)
465
0
      p = p + 4;
466
0
    else
467
0
      p = c;
468
469
0
    if (strcmp(p, common_name)) {
470
0
      lwsl_err("%s: common name mismatch\n", __func__);
471
0
      return -1;
472
0
    }
473
0
  }
474
475
0
  ret = X509_check_issued(trusted->cert, x509->cert);
476
0
  if (ret != X509_V_OK) {
477
0
    lwsl_err("%s: unable to verify cert relationship\n", __func__);
478
0
    lws_tls_err_describe_clear();
479
480
0
    return -1;
481
0
  }
482
483
0
  return 0;
484
0
}
485
486
#if defined(LWS_WITH_JOSE)
487
int
488
lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
489
           const char *curves, int rsa_min_bits)
490
{
491
  int id, n, ret = -1, count;
492
  ASN1_OBJECT *obj = NULL;
493
  const EC_POINT *ecpoint;
494
  const EC_GROUP *ecgroup;
495
  EC_KEY *ecpub = NULL;
496
  X509_PUBKEY *pubkey;
497
  RSA *rsapub = NULL;
498
  BIGNUM *mpi[4];
499
  EVP_PKEY *pkey;
500
501
  memset(jwk, 0, sizeof(*jwk));
502
503
  pubkey = X509_get_X509_PUBKEY(x509->cert);
504
  if (!pubkey) {
505
    lwsl_err("%s: missing pubkey alg in cert\n", __func__);
506
507
    goto bail;
508
  }
509
510
  if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
511
    lwsl_err("%s: missing pubkey alg in cert\n", __func__);
512
513
    goto bail;
514
  }
515
516
  id = OBJ_obj2nid(obj);
517
  if (id == NID_undef) {
518
    lwsl_err("%s: missing pubkey alg in cert\n", __func__);
519
520
    goto bail;
521
  }
522
523
  lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
524
525
  pkey = X509_get_pubkey(x509->cert);
526
  if (!pkey) {
527
    lwsl_notice("%s: unable to extract pubkey", __func__);
528
529
    goto bail;
530
  }
531
532
  switch (id) {
533
  case NID_X9_62_id_ecPublicKey:
534
    lwsl_debug("%s: EC key\n", __func__);
535
    jwk->kty = LWS_GENCRYPTO_KTY_EC;
536
537
    if (!curves) {
538
      lwsl_err("%s: ec curves not allowed\n", __func__);
539
540
      goto bail1;
541
    }
542
543
    ecpub = EVP_PKEY_get1_EC_KEY(pkey);
544
    if (!ecpub) {
545
      lwsl_notice("%s: missing EC pubkey\n", __func__);
546
547
      goto bail1;
548
    }
549
550
    ecpoint = EC_KEY_get0_public_key(ecpub);
551
    if (!ecpoint) {
552
      lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
553
      goto bail2;
554
    }
555
556
    ecgroup = EC_KEY_get0_group(ecpub);
557
    if (!ecgroup) {
558
      lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
559
      goto bail2;
560
    }
561
562
    /* validate the curve against ones we allow */
563
564
    if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
565
        EC_GROUP_get_curve_name(ecgroup), jwk))
566
      /* already logged */
567
      goto bail2;
568
569
    mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
570
    mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
571
    mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
572
    mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
573
574
#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
575
    if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
576
#else
577
    if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
578
#endif
579
              mpi[LWS_GENCRYPTO_EC_KEYEL_X],
580
              mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
581
                NULL) != 1) {
582
      BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
583
      BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
584
      lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
585
      goto bail2;
586
    }
587
    count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
588
    n = LWS_GENCRYPTO_EC_KEYEL_X;
589
    break;
590
591
  case NID_rsaEncryption:
592
    lwsl_debug("%s: rsa key\n", __func__);
593
    jwk->kty = LWS_GENCRYPTO_KTY_RSA;
594
595
    rsapub = EVP_PKEY_get1_RSA(pkey);
596
    if (!rsapub) {
597
      lwsl_notice("%s: missing RSA pubkey\n", __func__);
598
599
      goto bail1;
600
    }
601
602
    if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
603
      lwsl_err("%s: key bits %d less than minimum %d\n",
604
         __func__, RSA_size(rsapub) * 8, rsa_min_bits);
605
606
      goto bail2;
607
    }
608
609
#if defined(LWS_HAVE_RSA_SET0_KEY)
610
    /* we don't need d... but the api wants to write it */
611
    RSA_get0_key(rsapub,
612
          (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
613
          (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
614
          (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
615
#else
616
    mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
617
    mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
618
    mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
619
#endif
620
    count = LWS_GENCRYPTO_RSA_KEYEL_D;
621
    n = LWS_GENCRYPTO_RSA_KEYEL_E;
622
    break;
623
  default:
624
    lwsl_err("%s: unknown NID\n", __func__);
625
    goto bail2;
626
  }
627
628
  for (; n < count; n++) {
629
    if (!mpi[n])
630
      continue;
631
    jwk->e[n].len = (unsigned int)BN_num_bytes(mpi[n]);
632
    jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
633
    if (!jwk->e[n].buf) {
634
      if (id == NID_X9_62_id_ecPublicKey) {
635
        BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
636
        BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
637
      }
638
      goto bail2;
639
    }
640
    BN_bn2bin(mpi[n], jwk->e[n].buf);
641
  }
642
643
  if (id == NID_X9_62_id_ecPublicKey) {
644
    BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
645
    BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
646
  }
647
648
  ret = 0;
649
650
bail2:
651
  if (id == NID_X9_62_id_ecPublicKey)
652
    EC_KEY_free(ecpub);
653
  else
654
    RSA_free(rsapub);
655
656
bail1:
657
  EVP_PKEY_free(pkey);
658
bail:
659
  /* jwk destroy will clean any partial state */
660
  if (ret)
661
    lws_jwk_destroy(jwk);
662
663
  return ret;
664
}
665
666
static int
667
lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
668
{
669
  const char *pp = (const char *)u;
670
  size_t n = strlen(pp);
671
672
  if ((int)n > size - 1)
673
    return -1;
674
675
  memcpy(buf, pp, n + 1);
676
677
  return (int)n;
678
}
679
680
int
681
lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk,
682
       void *pem, size_t len, const char *passphrase)
683
{
684
  BIO* bio = BIO_new(BIO_s_mem());
685
  BIGNUM *mpi, *dummy[6];
686
  EVP_PKEY *pkey = NULL;
687
  EC_KEY *ecpriv = NULL;
688
  RSA *rsapriv = NULL;
689
  const BIGNUM *cmpi;
690
  int n, m, ret = -1;
691
692
  BIO_write(bio, pem, (int)len);
693
  PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
694
        (void *)passphrase);
695
  BIO_free(bio);
696
  lws_explicit_bzero((void *)pem, len);
697
  if (!pkey) {
698
    lwsl_err("%s: unable to parse PEM privkey\n", __func__);
699
    lws_tls_err_describe_clear();
700
701
    return -1;
702
  }
703
704
  /* confirm the key type matches the existing jwk situation */
705
706
  switch (jwk->kty) {
707
  case LWS_GENCRYPTO_KTY_EC:
708
    if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
709
      lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
710
711
      goto bail;
712
    }
713
    ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
714
    if (!ecpriv) {
715
      lwsl_notice("%s: missing EC key\n", __func__);
716
717
      goto bail;
718
    }
719
720
    cmpi = EC_KEY_get0_private_key(ecpriv);
721
722
    /* quick size check first */
723
724
    n = BN_num_bytes(cmpi);
725
    if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
726
      lwsl_err("%s: jwk key size doesn't match\n", __func__);
727
728
      goto bail1;
729
    }
730
731
    /* TODO.. check public curve / group + point */
732
733
    jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = (unsigned int)n;
734
    jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc((unsigned int)n, "ec");
735
    if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
736
      goto bail1;
737
738
    m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
739
              (int32_t)jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
740
    if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
741
      goto bail1;
742
743
    break;
744
745
  case LWS_GENCRYPTO_KTY_RSA:
746
    if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
747
      lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
748
749
      goto bail;
750
    }
751
    rsapriv = EVP_PKEY_get1_RSA(pkey);
752
    if (!rsapriv) {
753
      lwsl_notice("%s: missing RSA key\n", __func__);
754
755
      goto bail;
756
    }
757
758
#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
759
    RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
760
              (const BIGNUM **)&dummy[1], /* e */
761
              (const BIGNUM **)&mpi);   /* d */
762
    RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4],  /* p */
763
            (const BIGNUM **)&dummy[5]); /* q */
764
#else
765
    dummy[0] = rsapriv->n;
766
    dummy[1] = rsapriv->e;
767
    dummy[4] = rsapriv->p;
768
    dummy[5] = rsapriv->q;
769
    mpi = rsapriv->d;
770
#endif
771
772
    /* quick size check first */
773
774
    n = BN_num_bytes(mpi);
775
    if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
776
      lwsl_err("%s: jwk key size doesn't match\n", __func__);
777
778
      goto bail1;
779
    }
780
781
    /* then check that n & e match what we got from the cert */
782
783
    dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
784
             SSL_SIZE_CAST(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len),
785
             NULL);
786
    dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
787
             SSL_SIZE_CAST(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len),
788
             NULL);
789
790
    m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
791
    BN_clear_free(dummy[2]);
792
    BN_clear_free(dummy[3]);
793
    if (m) {
794
      lwsl_err("%s: privkey doesn't match jwk pubkey\n",
795
         __func__);
796
797
      goto bail1;
798
    }
799
800
    /* accept d from the PEM privkey into the JWK */
801
802
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = (unsigned int)n;
803
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc((unsigned int)n, "privjk");
804
    if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
805
      goto bail1;
806
807
    BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
808
809
    /* accept p and q from the PEM privkey into the JWK */
810
811
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = (unsigned int)BN_num_bytes(dummy[4]);
812
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc((unsigned int)n, "privjk");
813
    if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
814
      lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
815
      goto bail1;
816
    }
817
    BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
818
819
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = (unsigned int)BN_num_bytes(dummy[5]);
820
    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc((unsigned int)n, "privjk");
821
    if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
822
      lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
823
      lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
824
      goto bail1;
825
    }
826
    BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
827
    break;
828
  default:
829
    lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
830
    return -1;
831
  }
832
833
  ret = 0;
834
835
bail1:
836
  if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
837
    EC_KEY_free(ecpriv);
838
  else
839
    RSA_free(rsapriv);
840
841
bail:
842
  EVP_PKEY_free(pkey);
843
844
  return ret;
845
}
846
#endif
847
848
void
849
lws_x509_destroy(struct lws_x509_cert **x509)
850
0
{
851
0
  if (!*x509)
852
0
    return;
853
854
0
  if ((*x509)->cert) {
855
0
    X509_free((*x509)->cert);
856
0
    (*x509)->cert = NULL;
857
0
  }
858
859
  lws_free_set_NULL(*x509);
860
0
}