Coverage Report

Created: 2026-09-27 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cjose/src/jwk.c
Line
Count
Source
1
/*!
2
 * Copyrights
3
 *
4
 * Portions created or assigned to Cisco Systems, Inc. are
5
 * Copyright (c) 2014-2016 Cisco Systems, Inc.  All Rights Reserved.
6
 */
7
8
#include "include/jwk_int.h"
9
#include "include/util_int.h"
10
11
#include <cjose/base64.h>
12
#include <cjose/util.h>
13
14
#include <limits.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <stdio.h>
18
19
#include <openssl/bn.h>
20
#include <openssl/err.h>
21
#include <openssl/obj_mac.h>
22
#include <openssl/rand.h>
23
#include <openssl/rsa.h>
24
#include <openssl/evp.h>
25
#include <openssl/hmac.h>
26
#include <openssl/evp.h>
27
28
// internal data structures
29
30
static const char CJOSE_JWK_EC_P_256_STR[] = "P-256";
31
static const char CJOSE_JWK_EC_SECP_256K1_STR[] = "secp256k1";
32
static const char CJOSE_JWK_EC_P_384_STR[] = "P-384";
33
static const char CJOSE_JWK_EC_P_521_STR[] = "P-521";
34
static const char CJOSE_JWK_KTY_STR[] = "kty";
35
static const char CJOSE_JWK_KID_STR[] = "kid";
36
static const char CJOSE_JWK_KTY_EC_STR[] = "EC";
37
static const char CJOSE_JWK_KTY_RSA_STR[] = "RSA";
38
static const char CJOSE_JWK_KTY_OCT_STR[] = "oct";
39
static const char CJOSE_JWK_KTY_OKP_STR[] = "OKP";
40
static const char CJOSE_JWK_CRV_STR[] = "crv";
41
static const char CJOSE_JWK_X_STR[] = "x";
42
static const char CJOSE_JWK_Y_STR[] = "y";
43
static const char CJOSE_JWK_D_STR[] = "d";
44
static const char CJOSE_JWK_N_STR[] = "n";
45
static const char CJOSE_JWK_E_STR[] = "e";
46
static const char CJOSE_JWK_P_STR[] = "p";
47
static const char CJOSE_JWK_Q_STR[] = "q";
48
static const char CJOSE_JWK_DP_STR[] = "dp";
49
static const char CJOSE_JWK_DQ_STR[] = "dq";
50
static const char CJOSE_JWK_QI_STR[] = "qi";
51
static const char CJOSE_JWK_OTH_STR[] = "oth";
52
static const char CJOSE_JWK_K_STR[] = "k";
53
54
static const char *JWK_KTY_NAMES[] = { CJOSE_JWK_KTY_RSA_STR, CJOSE_JWK_KTY_EC_STR, CJOSE_JWK_KTY_OCT_STR, CJOSE_JWK_KTY_OKP_STR };
55
56
void _cjose_jwk_rsa_get(RSA *rsa, BIGNUM **rsa_n, BIGNUM **rsa_e, BIGNUM **rsa_d)
57
0
{
58
0
    if (rsa == NULL)
59
0
        return;
60
0
#if defined(CJOSE_OPENSSL_11X)
61
0
    RSA_get0_key(rsa, (const BIGNUM **)rsa_n, (const BIGNUM **)rsa_e, (const BIGNUM **)rsa_d);
62
#else
63
    *rsa_n = rsa->n;
64
    *rsa_e = rsa->e;
65
    *rsa_d = rsa->d;
66
#endif
67
0
}
68
69
bool _cjose_jwk_rsa_set(RSA *rsa, uint8_t *n, size_t n_len, uint8_t *e, size_t e_len, uint8_t *d, size_t d_len)
70
0
{
71
0
    BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
72
73
    // RSA_set0_key doesn't work without each of those on the first call!
74
0
    if ((n == NULL) || (n_len <= 0) || (e == NULL) || (e_len <= 0))
75
0
        return false;
76
77
0
    if (n && n_len > 0)
78
0
        rsa_n = BN_bin2bn(n, n_len, NULL);
79
0
    if (e && e_len > 0)
80
0
        rsa_e = BN_bin2bn(e, e_len, NULL);
81
0
    if (d && d_len > 0)
82
0
        rsa_d = BN_bin2bn(d, d_len, NULL);
83
84
0
#if defined(CJOSE_OPENSSL_11X)
85
0
    if (1 != RSA_set0_key(rsa, rsa_n, rsa_e, rsa_d))
86
0
    {
87
        // the setter takes ownership only on success; free the BIGNUMs it
88
        // refused (e.g. if a BN_bin2bn above failed) rather than leaking them
89
0
        BN_free(rsa_n);
90
0
        BN_free(rsa_e);
91
0
        BN_free(rsa_d);
92
0
        return false;
93
0
    }
94
0
    return true;
95
#else
96
    rsa->n = rsa_n;
97
    rsa->e = rsa_e;
98
    rsa->d = rsa_d;
99
    return true;
100
#endif
101
0
}
102
103
void _cjose_jwk_rsa_get_factors(RSA *rsa, BIGNUM **p, BIGNUM **q)
104
0
{
105
0
#if defined(CJOSE_OPENSSL_11X)
106
0
    RSA_get0_factors(rsa, (const BIGNUM **)p, (const BIGNUM **)q);
107
#else
108
    *p = rsa->p;
109
    *q = rsa->q;
110
#endif
111
0
}
112
113
bool _cjose_jwk_rsa_set_factors(RSA *rsa, uint8_t *p, size_t p_len, uint8_t *q, size_t q_len)
114
0
{
115
0
    BIGNUM *rsa_p = NULL, *rsa_q = NULL;
116
117
0
    if (p && p_len > 0)
118
0
        rsa_p = BN_bin2bn(p, p_len, NULL);
119
0
    if (q && q_len > 0)
120
0
        rsa_q = BN_bin2bn(q, q_len, NULL);
121
122
    // no factors supplied: a valid (n, e, d)-only private key
123
0
    if (NULL == rsa_p && NULL == rsa_q)
124
0
        return true;
125
126
    // p and q are required together; reject (and free) an incomplete pair
127
    // instead of leaking the BIGNUM the setter refuses to take ownership of
128
0
    if (NULL == rsa_p || NULL == rsa_q)
129
0
    {
130
0
        BN_free(rsa_p);
131
0
        BN_free(rsa_q);
132
0
        return false;
133
0
    }
134
135
0
#if defined(CJOSE_OPENSSL_11X)
136
0
    if (1 != RSA_set0_factors(rsa, rsa_p, rsa_q))
137
0
    {
138
0
        BN_free(rsa_p);
139
0
        BN_free(rsa_q);
140
0
        return false;
141
0
    }
142
#else
143
    rsa->p = rsa_p;
144
    rsa->q = rsa_q;
145
#endif
146
0
    return true;
147
0
}
148
149
void _cjose_jwk_rsa_get_crt(RSA *rsa, BIGNUM **dmp1, BIGNUM **dmq1, BIGNUM **iqmp)
150
0
{
151
0
#if defined(CJOSE_OPENSSL_11X)
152
0
    RSA_get0_crt_params(rsa, (const BIGNUM **)dmp1, (const BIGNUM **)dmq1, (const BIGNUM **)iqmp);
153
#else
154
    *dmp1 = rsa->dmp1;
155
    *dmq1 = rsa->dmq1;
156
    *iqmp = rsa->iqmp;
157
#endif
158
0
}
159
160
bool _cjose_jwk_rsa_set_crt(
161
    RSA *rsa, uint8_t *dmp1, size_t dmp1_len, uint8_t *dmq1, size_t dmq1_len, uint8_t *iqmp, size_t iqmp_len)
162
0
{
163
0
    BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL, *rsa_iqmp = NULL;
164
165
0
    if (dmp1 && dmp1_len > 0)
166
0
        rsa_dmp1 = BN_bin2bn(dmp1, dmp1_len, NULL);
167
0
    if (dmq1 && dmq1_len > 0)
168
0
        rsa_dmq1 = BN_bin2bn(dmq1, dmq1_len, NULL);
169
0
    if (iqmp && iqmp_len > 0)
170
0
        rsa_iqmp = BN_bin2bn(iqmp, iqmp_len, NULL);
171
172
    // no CRT params supplied: nothing to set
173
0
    if (NULL == rsa_dmp1 && NULL == rsa_dmq1 && NULL == rsa_iqmp)
174
0
        return true;
175
176
    // the CRT params are required together; reject (and free) an incomplete
177
    // set instead of leaking the BIGNUMs the setter refuses to take ownership of
178
0
    if (NULL == rsa_dmp1 || NULL == rsa_dmq1 || NULL == rsa_iqmp)
179
0
    {
180
0
        BN_free(rsa_dmp1);
181
0
        BN_free(rsa_dmq1);
182
0
        BN_free(rsa_iqmp);
183
0
        return false;
184
0
    }
185
186
0
#if defined(CJOSE_OPENSSL_11X)
187
0
    if (1 != RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp))
188
0
    {
189
0
        BN_free(rsa_dmp1);
190
0
        BN_free(rsa_dmq1);
191
0
        BN_free(rsa_iqmp);
192
0
        return false;
193
0
    }
194
#else
195
    rsa->dmp1 = rsa_dmp1;
196
    rsa->dmq1 = rsa_dmq1;
197
    rsa->iqmp = rsa_iqmp;
198
#endif
199
200
0
    return true;
201
0
}
202
203
// interface functions -- Generic
204
205
const char *cjose_jwk_name_for_kty(cjose_jwk_kty_t kty, cjose_err *err)
206
0
{
207
    // reject anything outside [CJOSE_JWK_KTY_RSA, CJOSE_JWK_KTY_OKP]; a value
208
    // below RSA (e.g. a negative sentinel, if the enum is signed) would index
209
    // JWK_KTY_NAMES out of bounds
210
0
    if (kty < CJOSE_JWK_KTY_RSA || CJOSE_JWK_KTY_OKP < kty)
211
0
    {
212
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
213
0
        return NULL;
214
0
    }
215
216
0
    return JWK_KTY_NAMES[kty - CJOSE_JWK_KTY_RSA];
217
0
}
218
219
cjose_jwk_t *cjose_jwk_retain(cjose_jwk_t *jwk, cjose_err *err)
220
0
{
221
0
    if (!jwk)
222
0
    {
223
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
224
0
        return NULL;
225
0
    }
226
227
0
    if (UINT_MAX == jwk->retained)
228
0
    {
229
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_STATE);
230
0
        return NULL;
231
0
    }
232
233
0
    ++(jwk->retained);
234
235
0
    return jwk;
236
0
}
237
238
bool cjose_jwk_release(cjose_jwk_t *jwk)
239
0
{
240
0
    if (!jwk)
241
0
    {
242
0
        return false;
243
0
    }
244
245
0
    --(jwk->retained);
246
0
    if (0 == jwk->retained)
247
0
    {
248
0
        cjose_get_dealloc()(jwk->kid);
249
0
        jwk->kid = NULL;
250
251
        // assumes freefunc is set
252
0
        if (NULL != jwk->fns->free_func)
253
0
        {
254
0
            jwk->fns->free_func(jwk);
255
0
        }
256
0
        jwk = NULL;
257
0
    }
258
259
0
    return (NULL != jwk);
260
0
}
261
262
cjose_jwk_kty_t cjose_jwk_get_kty(const cjose_jwk_t *jwk, cjose_err *err)
263
0
{
264
0
    if (!jwk)
265
0
    {
266
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
267
0
        return -1;
268
0
    }
269
270
0
    return jwk->kty;
271
0
}
272
size_t cjose_jwk_get_keysize(const cjose_jwk_t *jwk, cjose_err *err)
273
0
{
274
0
    if (!jwk)
275
0
    {
276
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
277
0
        return 0;
278
0
    }
279
0
    return jwk->keysize;
280
0
}
281
282
void *cjose_jwk_get_keydata(const cjose_jwk_t *jwk, cjose_err *err)
283
0
{
284
0
    if (!jwk)
285
0
    {
286
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
287
0
        return NULL;
288
0
    }
289
0
    return jwk->keydata;
290
0
}
291
292
const char *cjose_jwk_get_kid(const cjose_jwk_t *jwk, cjose_err *err)
293
0
{
294
0
    if (!jwk)
295
0
    {
296
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
297
0
        return NULL;
298
0
    }
299
300
0
    return jwk->kid;
301
0
}
302
303
bool cjose_jwk_set_kid(cjose_jwk_t *jwk, const char *kid, size_t len, cjose_err *err)
304
0
{
305
0
    if (!jwk || !kid)
306
0
    {
307
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
308
0
        return false;
309
0
    }
310
0
    if (jwk->kid)
311
0
    {
312
0
        cjose_get_dealloc()(jwk->kid);
313
0
    }
314
0
    jwk->kid = (char *)cjose_get_alloc()(len + 1);
315
0
    if (!jwk->kid)
316
0
    {
317
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
318
0
        return false;
319
0
    }
320
    // copy exactly len bytes from the caller-supplied (length-delimited, not
321
    // necessarily NUL-terminated) kid and terminate ourselves; strncpy(len + 1)
322
    // would read one byte past kid and could leave jwk->kid unterminated.
323
0
    memcpy(jwk->kid, kid, len);
324
0
    jwk->kid[len] = '\0';
325
0
    return true;
326
0
}
327
328
char *cjose_jwk_to_json(const cjose_jwk_t *jwk, bool priv, cjose_err *err)
329
0
{
330
0
    char *result = NULL;
331
332
0
    if (!jwk)
333
0
    {
334
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
335
0
        return NULL;
336
0
    }
337
338
0
    json_t *json = json_object(), *field = NULL;
339
0
    if (!json)
340
0
    {
341
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
342
0
        goto to_json_cleanup;
343
0
    }
344
345
    // set kty
346
0
    const char *kty = cjose_jwk_name_for_kty(jwk->kty, err);
347
0
    field = json_string(kty);
348
0
    if (!field)
349
0
    {
350
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
351
0
        goto to_json_cleanup;
352
0
    }
353
0
    json_object_set(json, "kty", field);
354
0
    json_decref(field);
355
0
    field = NULL;
356
357
    // set kid
358
0
    if (NULL != jwk->kid)
359
0
    {
360
0
        field = json_string(jwk->kid);
361
0
        if (!field)
362
0
        {
363
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
364
0
            goto to_json_cleanup;
365
0
        }
366
0
        json_object_set(json, CJOSE_JWK_KID_STR, field);
367
0
        json_decref(field);
368
0
        field = NULL;
369
0
    }
370
371
    // set public fields
372
0
    if (jwk->fns->public_json && !jwk->fns->public_json(jwk, json, err))
373
0
    {
374
0
        goto to_json_cleanup;
375
0
    }
376
377
    // set private fields
378
0
    if (priv && jwk->fns->private_json && !jwk->fns->private_json(jwk, json, err))
379
0
    {
380
0
        goto to_json_cleanup;
381
0
    }
382
383
    // generate the string ...
384
0
    char *str_jwk = json_dumps(json, JSON_ENCODE_ANY | JSON_COMPACT | JSON_PRESERVE_ORDER);
385
0
    if (!str_jwk)
386
0
    {
387
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
388
0
        goto to_json_cleanup;
389
0
    }
390
0
    result = _cjose_strndup(str_jwk, -1, err);
391
0
    if (!result)
392
0
    {
393
0
        cjose_get_dealloc()(str_jwk);
394
0
        goto to_json_cleanup;
395
0
    }
396
0
    cjose_get_dealloc()(str_jwk);
397
398
0
to_json_cleanup:
399
0
    if (json)
400
0
    {
401
0
        json_decref(json);
402
0
        json = NULL;
403
0
    }
404
0
    if (field)
405
0
    {
406
0
        json_decref(field);
407
0
        field = NULL;
408
0
    }
409
410
0
    return result;
411
0
}
412
413
//////////////// Octet String ////////////////
414
// internal data & functions -- Octet String
415
416
static void _cjose_jwk_oct_free(cjose_jwk_t *jwk);
417
static bool _cjose_jwk_oct_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
418
static bool _cjose_jwk_oct_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
419
420
static const key_fntable OCT_FNTABLE = { _cjose_jwk_oct_free, _cjose_jwk_oct_public_fields, _cjose_jwk_oct_private_fields };
421
422
static cjose_jwk_t *_cjose_jwk_oct_new(uint8_t *buffer, size_t keysize, cjose_err *err)
423
0
{
424
0
    cjose_jwk_t *jwk = (cjose_jwk_t *)cjose_get_alloc()(sizeof(cjose_jwk_t));
425
0
    if (NULL == jwk)
426
0
    {
427
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
428
0
    }
429
0
    else
430
0
    {
431
0
        memset(jwk, 0, sizeof(cjose_jwk_t));
432
0
        jwk->retained = 1;
433
0
        jwk->kty = CJOSE_JWK_KTY_OCT;
434
0
        jwk->keysize = keysize;
435
0
        jwk->keydata = buffer;
436
0
        jwk->fns = &OCT_FNTABLE;
437
0
    }
438
439
0
    return jwk;
440
0
}
441
442
static void _cjose_jwk_oct_free(cjose_jwk_t *jwk)
443
0
{
444
0
    uint8_t *buffer = (uint8_t *)jwk->keydata;
445
0
    jwk->keydata = NULL;
446
0
    if (buffer)
447
0
    {
448
0
        _cjose_cleanse_dealloc(buffer, jwk->keysize / 8);
449
0
    }
450
0
    cjose_get_dealloc()(jwk);
451
0
}
452
453
0
static bool _cjose_jwk_oct_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err) { return true; }
454
455
static bool _cjose_jwk_oct_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
456
0
{
457
0
    json_t *field = NULL;
458
0
    char *k = NULL;
459
0
    size_t klen = 0;
460
0
    uint8_t *keydata = (uint8_t *)jwk->keydata;
461
0
    size_t keysize = jwk->keysize / 8;
462
463
0
    if (!cjose_base64url_encode(keydata, keysize, &k, &klen, err))
464
0
    {
465
0
        return false;
466
0
    }
467
468
0
    field = _cjose_json_stringn(k, klen, err);
469
    // k holds the base64url-encoded symmetric key; wipe it before release
470
0
    _cjose_cleanse_dealloc(k, klen);
471
0
    k = NULL;
472
0
    if (!field)
473
0
    {
474
0
        return false;
475
0
    }
476
0
    json_object_set(json, "k", field);
477
0
    json_decref(field);
478
479
0
    return true;
480
0
}
481
482
// interface functions -- Octet String
483
484
cjose_jwk_t *cjose_jwk_create_oct_random(size_t keysize, cjose_err *err)
485
0
{
486
0
    cjose_jwk_t *jwk = NULL;
487
0
    uint8_t *buffer = NULL;
488
489
0
    if (0 == keysize)
490
0
    {
491
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
492
0
        goto create_oct_failed;
493
0
    }
494
495
    // resize to bytes
496
0
    size_t buffersize = sizeof(uint8_t) * (keysize / 8);
497
498
0
    buffer = (uint8_t *)cjose_get_alloc()(buffersize);
499
0
    if (NULL == buffer)
500
0
    {
501
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
502
0
        goto create_oct_failed;
503
0
    }
504
0
    if (1 != RAND_bytes(buffer, buffersize))
505
0
    {
506
0
        goto create_oct_failed;
507
0
    }
508
509
0
    jwk = _cjose_jwk_oct_new(buffer, keysize, err);
510
0
    if (NULL == jwk)
511
0
    {
512
0
        goto create_oct_failed;
513
0
    }
514
0
    return jwk;
515
516
0
create_oct_failed:
517
0
    if (buffer)
518
0
    {
519
0
        cjose_get_dealloc()(buffer);
520
0
        buffer = NULL;
521
0
    }
522
523
0
    return NULL;
524
0
}
525
526
cjose_jwk_t *cjose_jwk_create_oct_spec(const uint8_t *data, size_t len, cjose_err *err)
527
0
{
528
0
    cjose_jwk_t *jwk = NULL;
529
0
    uint8_t *buffer = NULL;
530
531
0
    if (NULL == data || 0 == len)
532
0
    {
533
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
534
0
        goto create_oct_failed;
535
0
    }
536
537
0
    buffer = (uint8_t *)cjose_get_alloc()(len);
538
0
    if (!buffer)
539
0
    {
540
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
541
0
        goto create_oct_failed;
542
0
    }
543
0
    memcpy(buffer, data, len);
544
545
0
    jwk = _cjose_jwk_oct_new(buffer, len * 8, err);
546
0
    if (NULL == jwk)
547
0
    {
548
0
        goto create_oct_failed;
549
0
    }
550
551
0
    return jwk;
552
553
0
create_oct_failed:
554
0
    if (buffer)
555
0
    {
556
0
        cjose_get_dealloc()(buffer);
557
0
        buffer = NULL;
558
0
    }
559
560
0
    return NULL;
561
0
}
562
563
//////////////// Elliptic Curve ////////////////
564
// internal data & functions -- Elliptic Curve
565
566
static void _cjose_jwk_EC_free(cjose_jwk_t *jwk);
567
static bool _cjose_jwk_EC_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
568
static bool _cjose_jwk_EC_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
569
570
static const key_fntable EC_FNTABLE = { _cjose_jwk_EC_free, _cjose_jwk_EC_public_fields, _cjose_jwk_EC_private_fields };
571
572
static inline int _cjose_jwk_ec_nid_for_curve(cjose_jwk_ec_curve crv)
573
0
{
574
0
    switch (crv)
575
0
    {
576
0
    case CJOSE_JWK_EC_P_256:
577
0
        return NID_X9_62_prime256v1;
578
0
    case CJOSE_JWK_EC_SECP_256K1:
579
0
        return NID_secp256k1;
580
0
    case CJOSE_JWK_EC_P_384:
581
0
        return NID_secp384r1;
582
0
    case CJOSE_JWK_EC_P_521:
583
0
        return NID_secp521r1;
584
0
    case CJOSE_JWK_EC_INVALID:
585
0
        return NID_undef;
586
0
    }
587
588
0
    return NID_undef;
589
0
}
590
591
static inline uint8_t _cjose_jwk_ec_size_for_curve(cjose_jwk_ec_curve crv, cjose_err *err)
592
0
{
593
0
    switch (crv)
594
0
    {
595
0
    case CJOSE_JWK_EC_P_256:
596
0
        return 32;
597
0
    case CJOSE_JWK_EC_SECP_256K1:
598
0
        return 32;
599
0
    case CJOSE_JWK_EC_P_384:
600
0
        return 48;
601
0
    case CJOSE_JWK_EC_P_521:
602
0
        return 66;
603
0
    case CJOSE_JWK_EC_INVALID:
604
0
        return 0;
605
0
    }
606
607
0
    return 0;
608
0
}
609
610
static inline const char *_cjose_jwk_ec_name_for_curve(cjose_jwk_ec_curve crv, cjose_err *err)
611
0
{
612
0
    switch (crv)
613
0
    {
614
0
    case CJOSE_JWK_EC_P_256:
615
0
        return CJOSE_JWK_EC_P_256_STR;
616
0
    case CJOSE_JWK_EC_SECP_256K1:
617
0
        return CJOSE_JWK_EC_SECP_256K1_STR;
618
0
    case CJOSE_JWK_EC_P_384:
619
0
        return CJOSE_JWK_EC_P_384_STR;
620
0
    case CJOSE_JWK_EC_P_521:
621
0
        return CJOSE_JWK_EC_P_521_STR;
622
0
    case CJOSE_JWK_EC_INVALID:
623
0
        return NULL;
624
0
    }
625
626
0
    return NULL;
627
0
}
628
629
static inline bool _cjose_jwk_ec_curve_from_name(const char *name, cjose_jwk_ec_curve *crv, cjose_err *err)
630
0
{
631
0
    bool retval = true;
632
0
    if (strncmp(name, CJOSE_JWK_EC_P_256_STR, sizeof(CJOSE_JWK_EC_P_256_STR)) == 0)
633
0
    {
634
0
        *crv = CJOSE_JWK_EC_P_256;
635
0
    }
636
0
    else if (strncmp(name, CJOSE_JWK_EC_SECP_256K1_STR, sizeof(CJOSE_JWK_EC_SECP_256K1_STR)) == 0)
637
0
    {
638
0
        *crv = CJOSE_JWK_EC_SECP_256K1;
639
0
    }
640
0
    else if (strncmp(name, CJOSE_JWK_EC_P_384_STR, sizeof(CJOSE_JWK_EC_P_384_STR)) == 0)
641
0
    {
642
0
        *crv = CJOSE_JWK_EC_P_384;
643
0
    }
644
0
    else if (strncmp(name, CJOSE_JWK_EC_P_521_STR, sizeof(CJOSE_JWK_EC_P_521_STR)) == 0)
645
0
    {
646
0
        *crv = CJOSE_JWK_EC_P_521;
647
0
    }
648
0
    else
649
0
    {
650
0
        retval = false;
651
0
    }
652
0
    return retval;
653
0
}
654
655
static inline bool _cjose_jwk_kty_from_name(const char *name, cjose_jwk_kty_t *kty, cjose_err *err)
656
0
{
657
0
    bool retval = true;
658
0
    if (strncmp(name, CJOSE_JWK_KTY_EC_STR, sizeof(CJOSE_JWK_KTY_EC_STR)) == 0)
659
0
    {
660
0
        *kty = CJOSE_JWK_KTY_EC;
661
0
    }
662
0
    else if (strncmp(name, CJOSE_JWK_KTY_RSA_STR, sizeof(CJOSE_JWK_KTY_RSA_STR)) == 0)
663
0
    {
664
0
        *kty = CJOSE_JWK_KTY_RSA;
665
0
    }
666
0
    else if (strncmp(name, CJOSE_JWK_KTY_OCT_STR, sizeof(CJOSE_JWK_KTY_OCT_STR)) == 0)
667
0
    {
668
0
        *kty = CJOSE_JWK_KTY_OCT;
669
0
    }
670
0
    else if (strncmp(name, CJOSE_JWK_KTY_OKP_STR, sizeof(CJOSE_JWK_KTY_OKP_STR)) == 0)
671
0
    {
672
0
        *kty = CJOSE_JWK_KTY_OKP;
673
0
    }
674
0
    else
675
0
    {
676
0
        retval = false;
677
0
    }
678
0
    return retval;
679
0
}
680
681
static cjose_jwk_t *_cjose_jwk_EC_new(cjose_jwk_ec_curve crv, EC_KEY *ec, cjose_err *err)
682
0
{
683
0
    ec_keydata *keydata = cjose_get_alloc()(sizeof(ec_keydata));
684
0
    if (!keydata)
685
0
    {
686
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
687
0
        return NULL;
688
0
    }
689
0
    keydata->crv = crv;
690
0
    keydata->key = ec;
691
692
0
    cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
693
0
    if (!jwk)
694
0
    {
695
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
696
0
        cjose_get_dealloc()(keydata);
697
0
        return NULL;
698
0
    }
699
0
    memset(jwk, 0, sizeof(cjose_jwk_t));
700
0
    jwk->retained = 1;
701
0
    jwk->kty = CJOSE_JWK_KTY_EC;
702
0
    switch (crv)
703
0
    {
704
0
    case CJOSE_JWK_EC_P_256:
705
0
        jwk->keysize = 256;
706
0
        break;
707
0
    case CJOSE_JWK_EC_SECP_256K1:
708
0
        jwk->keysize = 256;
709
0
        break;
710
0
    case CJOSE_JWK_EC_P_384:
711
0
        jwk->keysize = 384;
712
0
        break;
713
0
    case CJOSE_JWK_EC_P_521:
714
0
        jwk->keysize = 521;
715
0
        break;
716
0
    case CJOSE_JWK_EC_INVALID:
717
        // should never happen
718
0
        jwk->keysize = 0;
719
0
        break;
720
0
    }
721
0
    jwk->keydata = keydata;
722
0
    jwk->fns = &EC_FNTABLE;
723
724
0
    return jwk;
725
0
}
726
727
static void _cjose_jwk_EC_free(cjose_jwk_t *jwk)
728
0
{
729
0
    ec_keydata *keydata = (ec_keydata *)jwk->keydata;
730
0
    jwk->keydata = NULL;
731
732
0
    if (keydata)
733
0
    {
734
0
        EC_KEY *ec = keydata->key;
735
0
        keydata->key = NULL;
736
0
        if (ec)
737
0
        {
738
0
            EC_KEY_free(ec);
739
0
        }
740
0
        cjose_get_dealloc()(keydata);
741
0
    }
742
0
    cjose_get_dealloc()(jwk);
743
0
}
744
745
static bool _cjose_jwk_EC_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
746
0
{
747
0
    ec_keydata *keydata = (ec_keydata *)jwk->keydata;
748
0
    const EC_GROUP *params = NULL;
749
0
    const EC_POINT *pub = NULL;
750
0
    BIGNUM *bnX = NULL, *bnY = NULL;
751
0
    uint8_t *buffer = NULL;
752
0
    char *b64u = NULL;
753
0
    size_t len = 0, offset = 0;
754
0
    json_t *field = NULL;
755
0
    bool result = false;
756
757
    // track expected binary data size
758
0
    uint8_t numsize = _cjose_jwk_ec_size_for_curve(keydata->crv, err);
759
760
    // output the curve
761
0
    field = json_string(_cjose_jwk_ec_name_for_curve(keydata->crv, err));
762
0
    if (!field)
763
0
    {
764
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
765
0
        goto _ec_to_string_cleanup;
766
0
    }
767
0
    json_object_set(json, "crv", field);
768
0
    json_decref(field);
769
0
    field = NULL;
770
771
    // obtain the public key
772
0
    pub = EC_KEY_get0_public_key(keydata->key);
773
0
    params = EC_KEY_get0_group(keydata->key);
774
0
    if (!pub || !params)
775
0
    {
776
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
777
0
        goto _ec_to_string_cleanup;
778
0
    }
779
780
0
    buffer = cjose_get_alloc()(numsize);
781
0
    bnX = BN_new();
782
0
    bnY = BN_new();
783
0
    if (!buffer || !bnX || !bnY)
784
0
    {
785
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
786
0
        goto _ec_to_string_cleanup;
787
0
    }
788
789
0
    if (1 != EC_POINT_get_affine_coordinates_GFp(params, pub, bnX, bnY, NULL))
790
0
    {
791
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
792
0
        goto _ec_to_string_cleanup;
793
0
    }
794
795
    // output the x coordinate
796
0
    offset = numsize - BN_num_bytes(bnX);
797
0
    memset(buffer, 0, numsize);
798
0
    BN_bn2bin(bnX, (buffer + offset));
799
0
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
800
0
    {
801
0
        goto _ec_to_string_cleanup;
802
0
    }
803
0
    field = _cjose_json_stringn(b64u, len, err);
804
0
    if (!field)
805
0
    {
806
0
        goto _ec_to_string_cleanup;
807
0
    }
808
0
    json_object_set(json, "x", field);
809
0
    json_decref(field);
810
0
    field = NULL;
811
0
    cjose_get_dealloc()(b64u);
812
0
    b64u = NULL;
813
814
    // output the y coordinate
815
0
    offset = numsize - BN_num_bytes(bnY);
816
0
    memset(buffer, 0, numsize);
817
0
    BN_bn2bin(bnY, (buffer + offset));
818
0
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
819
0
    {
820
0
        goto _ec_to_string_cleanup;
821
0
    }
822
0
    field = _cjose_json_stringn(b64u, len, err);
823
0
    if (!field)
824
0
    {
825
0
        goto _ec_to_string_cleanup;
826
0
    }
827
0
    json_object_set(json, "y", field);
828
0
    json_decref(field);
829
0
    field = NULL;
830
0
    cjose_get_dealloc()(b64u);
831
0
    b64u = NULL;
832
833
0
    result = true;
834
835
0
_ec_to_string_cleanup:
836
0
    if (field)
837
0
    {
838
0
        json_decref(field);
839
0
    }
840
0
    if (bnX)
841
0
    {
842
0
        BN_free(bnX);
843
0
    }
844
0
    if (bnY)
845
0
    {
846
0
        BN_free(bnY);
847
0
    }
848
0
    if (buffer)
849
0
    {
850
0
        cjose_get_dealloc()(buffer);
851
0
    }
852
0
    if (b64u)
853
0
    {
854
0
        cjose_get_dealloc()(b64u);
855
0
    }
856
857
0
    return result;
858
0
}
859
860
static bool _cjose_jwk_EC_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
861
0
{
862
0
    ec_keydata *keydata = (ec_keydata *)jwk->keydata;
863
0
    const BIGNUM *bnD = EC_KEY_get0_private_key(keydata->key);
864
0
    uint8_t *buffer = NULL;
865
0
    char *b64u = NULL;
866
0
    size_t len = 0, offset = 0;
867
0
    json_t *field = NULL;
868
0
    bool result = false;
869
870
    // track expected binary data size
871
0
    uint8_t numsize = _cjose_jwk_ec_size_for_curve(keydata->crv, err);
872
873
    // short circuit if 'd' is NULL or 0
874
0
    if (!bnD || BN_is_zero(bnD))
875
0
    {
876
0
        return true;
877
0
    }
878
879
0
    buffer = cjose_get_alloc()(numsize);
880
0
    if (!buffer)
881
0
    {
882
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
883
0
        goto _ec_to_string_cleanup;
884
0
    }
885
886
0
    offset = numsize - BN_num_bytes(bnD);
887
0
    memset(buffer, 0, numsize);
888
0
    BN_bn2bin(bnD, (buffer + offset));
889
0
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
890
0
    {
891
0
        goto _ec_to_string_cleanup;
892
0
    }
893
0
    field = _cjose_json_stringn(b64u, len, err);
894
0
    if (!field)
895
0
    {
896
0
        goto _ec_to_string_cleanup;
897
0
    }
898
0
    json_object_set(json, "d", field);
899
0
    json_decref(field);
900
0
    field = NULL;
901
902
0
    result = true;
903
904
0
_ec_to_string_cleanup:
905
    // buffer and b64u hold the raw / base64url-encoded private key 'd';
906
    // wipe them before release on the success path as well as the
907
    // _cjose_json_stringn failure path (where b64u would otherwise leak)
908
0
    _cjose_cleanse_dealloc(buffer, numsize);
909
0
    _cjose_cleanse_dealloc(b64u, len);
910
911
0
    return result;
912
0
}
913
914
// interface functions -- Elliptic Curve
915
916
cjose_jwk_t *cjose_jwk_create_EC_random(cjose_jwk_ec_curve crv, cjose_err *err)
917
0
{
918
0
    cjose_jwk_t *jwk = NULL;
919
0
    EC_KEY *ec = NULL;
920
921
0
    ec = EC_KEY_new_by_curve_name(_cjose_jwk_ec_nid_for_curve(crv));
922
0
    if (!ec)
923
0
    {
924
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
925
0
        goto create_EC_failed;
926
0
    }
927
928
0
    if (1 != EC_KEY_generate_key(ec))
929
0
    {
930
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
931
0
        goto create_EC_failed;
932
0
    }
933
934
0
    jwk = _cjose_jwk_EC_new(crv, ec, err);
935
0
    if (!jwk)
936
0
    {
937
0
        goto create_EC_failed;
938
0
    }
939
940
0
    return jwk;
941
942
0
create_EC_failed:
943
0
    if (jwk)
944
0
    {
945
0
        cjose_get_dealloc()(jwk);
946
0
        jwk = NULL;
947
0
    }
948
0
    if (ec)
949
0
    {
950
0
        EC_KEY_free(ec);
951
0
        ec = NULL;
952
0
    }
953
954
0
    return NULL;
955
0
}
956
957
cjose_jwk_t *cjose_jwk_create_EC_spec(const cjose_jwk_ec_keyspec *spec, cjose_err *err)
958
0
{
959
0
    cjose_jwk_t *jwk = NULL;
960
0
    EC_KEY *ec = NULL;
961
0
    EC_GROUP *params = NULL;
962
0
    EC_POINT *Q = NULL;
963
0
    BIGNUM *bnD = NULL;
964
0
    BIGNUM *bnX = NULL;
965
0
    BIGNUM *bnY = NULL;
966
967
0
    if (!spec)
968
0
    {
969
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
970
0
        return NULL;
971
0
    }
972
973
0
    bool hasPriv = (NULL != spec->d && 0 < spec->dlen);
974
0
    bool hasPub = ((NULL != spec->x && 0 < spec->xlen) && (NULL != spec->y && 0 < spec->ylen));
975
0
    if (!hasPriv && !hasPub)
976
0
    {
977
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
978
0
        return NULL;
979
0
    }
980
981
0
    ec = EC_KEY_new_by_curve_name(_cjose_jwk_ec_nid_for_curve(spec->crv));
982
0
    if (NULL == ec)
983
0
    {
984
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
985
0
        goto create_EC_failed;
986
0
    }
987
988
0
    params = (EC_GROUP *)EC_KEY_get0_group(ec);
989
0
    if (NULL == params)
990
0
    {
991
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
992
0
        goto create_EC_failed;
993
0
    }
994
995
    // convert d from octet string to BIGNUM
996
0
    if (hasPriv)
997
0
    {
998
0
        bnD = BN_bin2bn(spec->d, spec->dlen, NULL);
999
0
        if (NULL == bnD)
1000
0
        {
1001
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1002
0
            goto create_EC_failed;
1003
0
        }
1004
0
        if (1 != EC_KEY_set_private_key(ec, bnD))
1005
0
        {
1006
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1007
0
            goto create_EC_failed;
1008
0
        }
1009
1010
        // calculate public key from private
1011
0
        Q = EC_POINT_new(params);
1012
0
        if (NULL == Q)
1013
0
        {
1014
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1015
0
            goto create_EC_failed;
1016
0
        }
1017
0
        if (1 != EC_POINT_mul(params, Q, bnD, NULL, NULL, NULL))
1018
0
        {
1019
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1020
0
            goto create_EC_failed;
1021
0
        }
1022
1023
        // public key is set below
1024
        // ignore provided public key!
1025
0
        hasPub = false;
1026
0
    }
1027
0
    if (hasPub)
1028
0
    {
1029
0
        Q = EC_POINT_new(params);
1030
0
        if (NULL == Q)
1031
0
        {
1032
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1033
0
            goto create_EC_failed;
1034
0
        }
1035
1036
0
        bnX = BN_bin2bn(spec->x, spec->xlen, NULL);
1037
0
        bnY = BN_bin2bn(spec->y, spec->ylen, NULL);
1038
0
        if (!bnX || !bnY)
1039
0
        {
1040
0
            CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1041
0
            goto create_EC_failed;
1042
0
        }
1043
1044
0
        if (1 != EC_POINT_set_affine_coordinates_GFp(params, Q, bnX, bnY, NULL))
1045
0
        {
1046
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1047
0
            goto create_EC_failed;
1048
0
        }
1049
1050
0
        if (1 != EC_POINT_is_on_curve(params, Q, NULL))
1051
0
        {
1052
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1053
0
            goto create_EC_failed;
1054
0
        }
1055
0
    }
1056
1057
    // always set the public key
1058
0
    if (1 != EC_KEY_set_public_key(ec, Q))
1059
0
    {
1060
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1061
0
        goto create_EC_failed;
1062
0
    }
1063
1064
0
    if (1 != EC_KEY_check_key(ec))
1065
0
    {
1066
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1067
0
        goto create_EC_failed;
1068
0
    }
1069
1070
0
    jwk = _cjose_jwk_EC_new(spec->crv, ec, err);
1071
0
    if (!jwk)
1072
0
    {
1073
0
        goto create_EC_failed;
1074
0
    }
1075
1076
    // jump to cleanup
1077
0
    goto create_EC_cleanup;
1078
1079
0
create_EC_failed:
1080
0
    if (jwk)
1081
0
    {
1082
0
        cjose_get_dealloc()(jwk);
1083
0
        jwk = NULL;
1084
0
    }
1085
0
    if (ec)
1086
0
    {
1087
0
        EC_KEY_free(ec);
1088
0
        ec = NULL;
1089
0
    }
1090
1091
0
create_EC_cleanup:
1092
0
    if (Q)
1093
0
    {
1094
0
        EC_POINT_free(Q);
1095
0
        Q = NULL;
1096
0
    }
1097
0
    if (bnD)
1098
0
    {
1099
0
        BN_free(bnD);
1100
0
        bnD = NULL;
1101
0
    }
1102
0
    if (bnX)
1103
0
    {
1104
0
        BN_free(bnX);
1105
0
        bnX = NULL;
1106
0
    }
1107
0
    if (bnY)
1108
0
    {
1109
0
        BN_free(bnY);
1110
0
        bnY = NULL;
1111
0
    }
1112
1113
0
    return jwk;
1114
0
}
1115
1116
cjose_jwk_ec_curve cjose_jwk_EC_get_curve(const cjose_jwk_t *jwk, cjose_err *err)
1117
0
{
1118
0
    if (NULL == jwk || CJOSE_JWK_KTY_EC != cjose_jwk_get_kty(jwk, err))
1119
0
    {
1120
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1121
0
        return CJOSE_JWK_EC_INVALID;
1122
0
    }
1123
1124
0
    ec_keydata *keydata = jwk->keydata;
1125
0
    return keydata->crv;
1126
0
}
1127
1128
//////////////// Octet Key Pair ////////////////
1129
// internal data & functions -- Octet Key Pair (RFC 8037)
1130
1131
#if defined(CJOSE_OPENSSL_111X)
1132
1133
static const char CJOSE_JWK_OKP_ED25519_STR[] = "Ed25519";
1134
static const char CJOSE_JWK_OKP_ED448_STR[] = "Ed448";
1135
static const char CJOSE_JWK_OKP_X25519_STR[] = "X25519";
1136
static const char CJOSE_JWK_OKP_X448_STR[] = "X448";
1137
1138
static void _cjose_jwk_OKP_free(cjose_jwk_t *jwk);
1139
static bool _cjose_jwk_OKP_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1140
static bool _cjose_jwk_OKP_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1141
1142
static const key_fntable OKP_FNTABLE = { _cjose_jwk_OKP_free, _cjose_jwk_OKP_public_fields, _cjose_jwk_OKP_private_fields };
1143
1144
static inline int _cjose_jwk_okp_nid_for_curve(cjose_jwk_okp_curve crv)
1145
0
{
1146
0
    switch (crv)
1147
0
    {
1148
0
    case CJOSE_JWK_OKP_ED25519:
1149
0
        return NID_ED25519;
1150
0
    case CJOSE_JWK_OKP_ED448:
1151
0
        return NID_ED448;
1152
0
    case CJOSE_JWK_OKP_X25519:
1153
0
        return NID_X25519;
1154
0
    case CJOSE_JWK_OKP_X448:
1155
0
        return NID_X448;
1156
0
    case CJOSE_JWK_OKP_INVALID:
1157
0
        return NID_undef;
1158
0
    }
1159
1160
0
    return NID_undef;
1161
0
}
1162
1163
// the fixed size of both the raw public key "x" and the raw private key "d"
1164
// (RFC 8032 sections 5.1.5 and 5.2.5, RFC 7748 section 5)
1165
static inline size_t _cjose_jwk_okp_size_for_curve(cjose_jwk_okp_curve crv)
1166
0
{
1167
0
    switch (crv)
1168
0
    {
1169
0
    case CJOSE_JWK_OKP_ED25519:
1170
0
        return 32;
1171
0
    case CJOSE_JWK_OKP_ED448:
1172
0
        return 57;
1173
0
    case CJOSE_JWK_OKP_X25519:
1174
0
        return 32;
1175
0
    case CJOSE_JWK_OKP_X448:
1176
0
        return 56;
1177
0
    case CJOSE_JWK_OKP_INVALID:
1178
0
        return 0;
1179
0
    }
1180
1181
0
    return 0;
1182
0
}
1183
1184
static inline const char *_cjose_jwk_okp_name_for_curve(cjose_jwk_okp_curve crv)
1185
0
{
1186
0
    switch (crv)
1187
0
    {
1188
0
    case CJOSE_JWK_OKP_ED25519:
1189
0
        return CJOSE_JWK_OKP_ED25519_STR;
1190
0
    case CJOSE_JWK_OKP_ED448:
1191
0
        return CJOSE_JWK_OKP_ED448_STR;
1192
0
    case CJOSE_JWK_OKP_X25519:
1193
0
        return CJOSE_JWK_OKP_X25519_STR;
1194
0
    case CJOSE_JWK_OKP_X448:
1195
0
        return CJOSE_JWK_OKP_X448_STR;
1196
0
    case CJOSE_JWK_OKP_INVALID:
1197
0
        return NULL;
1198
0
    }
1199
1200
0
    return NULL;
1201
0
}
1202
1203
static inline bool _cjose_jwk_okp_curve_from_name(const char *name, cjose_jwk_okp_curve *crv)
1204
0
{
1205
0
    bool retval = true;
1206
0
    if (strncmp(name, CJOSE_JWK_OKP_ED25519_STR, sizeof(CJOSE_JWK_OKP_ED25519_STR)) == 0)
1207
0
    {
1208
0
        *crv = CJOSE_JWK_OKP_ED25519;
1209
0
    }
1210
0
    else if (strncmp(name, CJOSE_JWK_OKP_ED448_STR, sizeof(CJOSE_JWK_OKP_ED448_STR)) == 0)
1211
0
    {
1212
0
        *crv = CJOSE_JWK_OKP_ED448;
1213
0
    }
1214
0
    else if (strncmp(name, CJOSE_JWK_OKP_X25519_STR, sizeof(CJOSE_JWK_OKP_X25519_STR)) == 0)
1215
0
    {
1216
0
        *crv = CJOSE_JWK_OKP_X25519;
1217
0
    }
1218
0
    else if (strncmp(name, CJOSE_JWK_OKP_X448_STR, sizeof(CJOSE_JWK_OKP_X448_STR)) == 0)
1219
0
    {
1220
0
        *crv = CJOSE_JWK_OKP_X448;
1221
0
    }
1222
0
    else
1223
0
    {
1224
0
        retval = false;
1225
0
    }
1226
0
    return retval;
1227
0
}
1228
1229
static cjose_jwk_t *_cjose_jwk_OKP_new(cjose_jwk_okp_curve crv, EVP_PKEY *pkey, cjose_err *err)
1230
0
{
1231
0
    okp_keydata *keydata = cjose_get_alloc()(sizeof(okp_keydata));
1232
0
    if (!keydata)
1233
0
    {
1234
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1235
0
        return NULL;
1236
0
    }
1237
0
    keydata->crv = crv;
1238
0
    keydata->key = pkey;
1239
1240
0
    cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
1241
0
    if (!jwk)
1242
0
    {
1243
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1244
0
        cjose_get_dealloc()(keydata);
1245
0
        return NULL;
1246
0
    }
1247
0
    memset(jwk, 0, sizeof(cjose_jwk_t));
1248
0
    jwk->retained = 1;
1249
0
    jwk->kty = CJOSE_JWK_KTY_OKP;
1250
0
    jwk->keysize = _cjose_jwk_okp_size_for_curve(crv) * 8;
1251
0
    jwk->keydata = keydata;
1252
0
    jwk->fns = &OKP_FNTABLE;
1253
1254
0
    return jwk;
1255
0
}
1256
1257
static void _cjose_jwk_OKP_free(cjose_jwk_t *jwk)
1258
0
{
1259
0
    okp_keydata *keydata = (okp_keydata *)jwk->keydata;
1260
0
    jwk->keydata = NULL;
1261
1262
0
    if (keydata)
1263
0
    {
1264
0
        EVP_PKEY_free(keydata->key);
1265
0
        keydata->key = NULL;
1266
0
        cjose_get_dealloc()(keydata);
1267
0
    }
1268
0
    cjose_get_dealloc()(jwk);
1269
0
}
1270
1271
static bool _cjose_jwk_OKP_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1272
0
{
1273
0
    okp_keydata *keydata = (okp_keydata *)jwk->keydata;
1274
0
    uint8_t *buffer = NULL;
1275
0
    char *b64u = NULL;
1276
0
    size_t len = 0;
1277
0
    json_t *field = NULL;
1278
0
    bool result = false;
1279
1280
    // the raw public key has the fixed size of the curve
1281
0
    size_t numsize = _cjose_jwk_okp_size_for_curve(keydata->crv);
1282
1283
    // output the curve
1284
0
    field = json_string(_cjose_jwk_okp_name_for_curve(keydata->crv));
1285
0
    if (!field)
1286
0
    {
1287
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1288
0
        goto _okp_to_string_cleanup;
1289
0
    }
1290
0
    json_object_set(json, "crv", field);
1291
0
    json_decref(field);
1292
0
    field = NULL;
1293
1294
    // obtain the raw public key
1295
0
    buffer = cjose_get_alloc()(numsize);
1296
0
    if (!buffer)
1297
0
    {
1298
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1299
0
        goto _okp_to_string_cleanup;
1300
0
    }
1301
0
    len = numsize;
1302
0
    if (1 != EVP_PKEY_get_raw_public_key(keydata->key, buffer, &len) || len != numsize)
1303
0
    {
1304
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1305
0
        goto _okp_to_string_cleanup;
1306
0
    }
1307
1308
    // output the public key x
1309
0
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
1310
0
    {
1311
0
        goto _okp_to_string_cleanup;
1312
0
    }
1313
0
    field = _cjose_json_stringn(b64u, len, err);
1314
0
    if (!field)
1315
0
    {
1316
0
        goto _okp_to_string_cleanup;
1317
0
    }
1318
0
    json_object_set(json, "x", field);
1319
0
    json_decref(field);
1320
0
    field = NULL;
1321
1322
0
    result = true;
1323
1324
0
_okp_to_string_cleanup:
1325
0
    cjose_get_dealloc()(buffer);
1326
0
    cjose_get_dealloc()(b64u);
1327
1328
0
    return result;
1329
0
}
1330
1331
static bool _cjose_jwk_OKP_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1332
0
{
1333
0
    okp_keydata *keydata = (okp_keydata *)jwk->keydata;
1334
0
    uint8_t *buffer = NULL;
1335
0
    char *b64u = NULL;
1336
0
    size_t len = 0;
1337
0
    size_t b64u_len = 0;
1338
0
    json_t *field = NULL;
1339
0
    int rc = 0;
1340
0
    bool result = false;
1341
1342
    // the raw private key has the fixed size of the curve
1343
0
    size_t numsize = _cjose_jwk_okp_size_for_curve(keydata->crv);
1344
1345
0
    buffer = cjose_get_alloc()(numsize);
1346
0
    if (!buffer)
1347
0
    {
1348
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1349
0
        goto _okp_to_string_cleanup;
1350
0
    }
1351
1352
    // short circuit if there is no private key; discard the error OpenSSL may
1353
    // queue for the missing key so it does not surface in a later cjose_err_message()
1354
0
    len = numsize;
1355
0
    ERR_set_mark();
1356
0
    rc = EVP_PKEY_get_raw_private_key(keydata->key, buffer, &len);
1357
0
    ERR_pop_to_mark();
1358
0
    if (1 != rc)
1359
0
    {
1360
0
        result = true;
1361
0
        goto _okp_to_string_cleanup;
1362
0
    }
1363
0
    if (len != numsize)
1364
0
    {
1365
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1366
0
        goto _okp_to_string_cleanup;
1367
0
    }
1368
1369
    // output the private key d
1370
0
    if (!cjose_base64url_encode(buffer, numsize, &b64u, &b64u_len, err))
1371
0
    {
1372
0
        goto _okp_to_string_cleanup;
1373
0
    }
1374
0
    field = _cjose_json_stringn(b64u, b64u_len, err);
1375
0
    if (!field)
1376
0
    {
1377
0
        goto _okp_to_string_cleanup;
1378
0
    }
1379
0
    json_object_set(json, "d", field);
1380
0
    json_decref(field);
1381
0
    field = NULL;
1382
1383
0
    result = true;
1384
1385
0
_okp_to_string_cleanup:
1386
    // buffer and b64u hold the raw / base64url-encoded private key 'd';
1387
    // wipe them before release
1388
0
    _cjose_cleanse_dealloc(buffer, numsize);
1389
0
    _cjose_cleanse_dealloc(b64u, b64u_len);
1390
1391
0
    return result;
1392
0
}
1393
1394
// interface functions -- Octet Key Pair
1395
1396
cjose_jwk_t *cjose_jwk_create_OKP_random(cjose_jwk_okp_curve crv, cjose_err *err)
1397
0
{
1398
0
    cjose_jwk_t *jwk = NULL;
1399
0
    EVP_PKEY_CTX *ctx = NULL;
1400
0
    EVP_PKEY *pkey = NULL;
1401
1402
0
    int nid = _cjose_jwk_okp_nid_for_curve(crv);
1403
0
    if (NID_undef == nid)
1404
0
    {
1405
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1406
0
        goto create_OKP_random_cleanup;
1407
0
    }
1408
1409
0
    ctx = EVP_PKEY_CTX_new_id(nid, NULL);
1410
0
    if (NULL == ctx)
1411
0
    {
1412
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1413
0
        goto create_OKP_random_cleanup;
1414
0
    }
1415
0
    if (1 != EVP_PKEY_keygen_init(ctx) || 1 != EVP_PKEY_keygen(ctx, &pkey))
1416
0
    {
1417
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1418
0
        goto create_OKP_random_cleanup;
1419
0
    }
1420
1421
0
    jwk = _cjose_jwk_OKP_new(crv, pkey, err);
1422
0
    if (NULL == jwk)
1423
0
    {
1424
0
        goto create_OKP_random_cleanup;
1425
0
    }
1426
    // the jwk owns the key now
1427
0
    pkey = NULL;
1428
1429
0
create_OKP_random_cleanup:
1430
0
    EVP_PKEY_free(pkey);
1431
0
    EVP_PKEY_CTX_free(ctx);
1432
1433
0
    return jwk;
1434
0
}
1435
1436
cjose_jwk_t *cjose_jwk_create_OKP_spec(const cjose_jwk_okp_keyspec *spec, cjose_err *err)
1437
0
{
1438
0
    cjose_jwk_t *jwk = NULL;
1439
0
    EVP_PKEY *pkey = NULL;
1440
0
    uint8_t *pub = NULL;
1441
0
    size_t pub_len = 0;
1442
1443
0
    if (!spec)
1444
0
    {
1445
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1446
0
        return NULL;
1447
0
    }
1448
1449
0
    int nid = _cjose_jwk_okp_nid_for_curve(spec->crv);
1450
0
    size_t numsize = _cjose_jwk_okp_size_for_curve(spec->crv);
1451
0
    if (NID_undef == nid || 0 == numsize)
1452
0
    {
1453
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1454
0
        return NULL;
1455
0
    }
1456
1457
0
    bool hasPriv = (NULL != spec->d && 0 < spec->dlen);
1458
0
    bool hasPub = (NULL != spec->x && 0 < spec->xlen);
1459
0
    if (!hasPriv && !hasPub)
1460
0
    {
1461
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1462
0
        return NULL;
1463
0
    }
1464
1465
    // the raw keys have the fixed size of the curve (RFC 8037 section 2);
1466
    // check that up front instead of relying on OpenSSL to reject them
1467
0
    if ((hasPriv && spec->dlen != numsize) || (hasPub && spec->xlen != numsize))
1468
0
    {
1469
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1470
0
        return NULL;
1471
0
    }
1472
1473
0
    if (hasPriv)
1474
0
    {
1475
0
        pkey = EVP_PKEY_new_raw_private_key(nid, NULL, spec->d, spec->dlen);
1476
0
        if (NULL == pkey)
1477
0
        {
1478
0
            CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1479
0
            goto create_OKP_spec_cleanup;
1480
0
        }
1481
1482
        // OpenSSL derives the public key from the private key; when a public
1483
        // key is supplied as well it must be that one
1484
0
        if (hasPub)
1485
0
        {
1486
0
            pub = cjose_get_alloc()(numsize);
1487
0
            if (NULL == pub)
1488
0
            {
1489
0
                CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1490
0
                goto create_OKP_spec_cleanup;
1491
0
            }
1492
0
            pub_len = numsize;
1493
0
            if (1 != EVP_PKEY_get_raw_public_key(pkey, pub, &pub_len) || pub_len != numsize)
1494
0
            {
1495
0
                CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1496
0
                goto create_OKP_spec_cleanup;
1497
0
            }
1498
0
            if (0 != cjose_const_memcmp(pub, spec->x, numsize))
1499
0
            {
1500
0
                CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1501
0
                goto create_OKP_spec_cleanup;
1502
0
            }
1503
0
        }
1504
0
    }
1505
0
    else
1506
0
    {
1507
0
        pkey = EVP_PKEY_new_raw_public_key(nid, NULL, spec->x, spec->xlen);
1508
0
        if (NULL == pkey)
1509
0
        {
1510
0
            CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1511
0
            goto create_OKP_spec_cleanup;
1512
0
        }
1513
0
    }
1514
1515
0
    jwk = _cjose_jwk_OKP_new(spec->crv, pkey, err);
1516
0
    if (NULL == jwk)
1517
0
    {
1518
0
        goto create_OKP_spec_cleanup;
1519
0
    }
1520
    // the jwk owns the key now
1521
0
    pkey = NULL;
1522
1523
0
create_OKP_spec_cleanup:
1524
0
    EVP_PKEY_free(pkey);
1525
0
    cjose_get_dealloc()(pub);
1526
1527
0
    return jwk;
1528
0
}
1529
1530
#else // !CJOSE_OPENSSL_111X
1531
1532
// the OKP key type needs the raw key API that arrived in OpenSSL 1.1.1
1533
1534
cjose_jwk_t *cjose_jwk_create_OKP_random(cjose_jwk_okp_curve crv, cjose_err *err)
1535
{
1536
    CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1537
    return NULL;
1538
}
1539
1540
cjose_jwk_t *cjose_jwk_create_OKP_spec(const cjose_jwk_okp_keyspec *spec, cjose_err *err)
1541
{
1542
    CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1543
    return NULL;
1544
}
1545
1546
#endif // CJOSE_OPENSSL_111X
1547
1548
cjose_jwk_okp_curve cjose_jwk_OKP_get_curve(const cjose_jwk_t *jwk, cjose_err *err)
1549
0
{
1550
0
    if (NULL == jwk || CJOSE_JWK_KTY_OKP != cjose_jwk_get_kty(jwk, err))
1551
0
    {
1552
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1553
0
        return CJOSE_JWK_OKP_INVALID;
1554
0
    }
1555
1556
0
    okp_keydata *keydata = jwk->keydata;
1557
0
    return keydata->crv;
1558
0
}
1559
1560
//////////////// RSA ////////////////
1561
// internal data & functions -- RSA
1562
1563
static void _cjose_jwk_RSA_free(cjose_jwk_t *jwk);
1564
static bool _cjose_jwk_RSA_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1565
static bool _cjose_jwk_RSA_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1566
1567
static const key_fntable RSA_FNTABLE = { _cjose_jwk_RSA_free, _cjose_jwk_RSA_public_fields, _cjose_jwk_RSA_private_fields };
1568
1569
static inline cjose_jwk_t *_cjose_jwk_RSA_new(RSA *rsa, cjose_err *err)
1570
0
{
1571
0
    cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
1572
0
    if (!jwk)
1573
0
    {
1574
        // _cjose_jwk_RSA_new owns rsa on every path; free it here so the callers that
1575
        // `return _cjose_jwk_RSA_new(rsa, err)` do not leak it on allocation failure
1576
0
        RSA_free(rsa);
1577
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1578
0
        return NULL;
1579
0
    }
1580
0
    memset(jwk, 0, sizeof(cjose_jwk_t));
1581
0
    jwk->retained = 1;
1582
0
    jwk->kty = CJOSE_JWK_KTY_RSA;
1583
0
    jwk->keysize = RSA_size(rsa) * 8;
1584
0
    jwk->keydata = rsa;
1585
0
    jwk->fns = &RSA_FNTABLE;
1586
1587
0
    return jwk;
1588
0
}
1589
1590
static void _cjose_jwk_RSA_free(cjose_jwk_t *jwk)
1591
0
{
1592
0
    RSA *rsa = (RSA *)jwk->keydata;
1593
0
    jwk->keydata = NULL;
1594
0
    if (rsa)
1595
0
    {
1596
0
        RSA_free(rsa);
1597
0
    }
1598
0
    cjose_get_dealloc()(jwk);
1599
0
}
1600
1601
static inline bool _cjose_jwk_RSA_json_field(BIGNUM *param, const char *name, json_t *json, cjose_err *err)
1602
0
{
1603
0
    json_t *field = NULL;
1604
0
    uint8_t *data = NULL;
1605
0
    char *b64u = NULL;
1606
0
    size_t datalen = 0, b64ulen = 0;
1607
0
    bool result = false;
1608
1609
0
    if (!param)
1610
0
    {
1611
0
        return true;
1612
0
    }
1613
1614
0
    datalen = BN_num_bytes(param);
1615
0
    data = cjose_get_alloc()(sizeof(uint8_t) * datalen);
1616
0
    if (!data)
1617
0
    {
1618
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1619
0
        goto RSA_json_field_cleanup;
1620
0
    }
1621
0
    BN_bn2bin(param, data);
1622
0
    if (!cjose_base64url_encode(data, datalen, &b64u, &b64ulen, err))
1623
0
    {
1624
0
        goto RSA_json_field_cleanup;
1625
0
    }
1626
0
    field = _cjose_json_stringn(b64u, b64ulen, err);
1627
0
    if (!field)
1628
0
    {
1629
0
        goto RSA_json_field_cleanup;
1630
0
    }
1631
0
    json_object_set(json, name, field);
1632
0
    json_decref(field);
1633
0
    field = NULL;
1634
0
    result = true;
1635
1636
0
RSA_json_field_cleanup:
1637
    // data / b64u may hold a private key component (d, p, q, dp, dq, qi);
1638
    // wipe them before release (harmless for the public n and e)
1639
0
    _cjose_cleanse_dealloc(b64u, b64ulen);
1640
0
    b64u = NULL;
1641
0
    _cjose_cleanse_dealloc(data, datalen);
1642
0
    data = NULL;
1643
1644
0
    return result;
1645
0
}
1646
1647
static bool _cjose_jwk_RSA_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1648
0
{
1649
0
    RSA *rsa = (RSA *)jwk->keydata;
1650
1651
0
    BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
1652
0
    _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d);
1653
1654
0
    if (!_cjose_jwk_RSA_json_field(rsa_e, "e", json, err))
1655
0
    {
1656
0
        return false;
1657
0
    }
1658
0
    if (!_cjose_jwk_RSA_json_field(rsa_n, "n", json, err))
1659
0
    {
1660
0
        return false;
1661
0
    }
1662
1663
0
    return true;
1664
0
}
1665
1666
static bool _cjose_jwk_RSA_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1667
0
{
1668
0
    RSA *rsa = (RSA *)jwk->keydata;
1669
1670
0
    BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
1671
0
    _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d);
1672
1673
0
    BIGNUM *rsa_p = NULL, *rsa_q = NULL;
1674
0
    _cjose_jwk_rsa_get_factors(rsa, &rsa_p, &rsa_q);
1675
1676
0
    BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL, *rsa_iqmp = NULL;
1677
0
    _cjose_jwk_rsa_get_crt(rsa, &rsa_dmp1, &rsa_dmq1, &rsa_iqmp);
1678
1679
0
    if (!_cjose_jwk_RSA_json_field(rsa_d, "d", json, err))
1680
0
    {
1681
0
        return false;
1682
0
    }
1683
0
    if (!_cjose_jwk_RSA_json_field(rsa_p, "p", json, err))
1684
0
    {
1685
0
        return false;
1686
0
    }
1687
0
    if (!_cjose_jwk_RSA_json_field(rsa_q, "q", json, err))
1688
0
    {
1689
0
        return false;
1690
0
    }
1691
0
    if (!_cjose_jwk_RSA_json_field(rsa_dmp1, "dp", json, err))
1692
0
    {
1693
0
        return false;
1694
0
    }
1695
0
    if (!_cjose_jwk_RSA_json_field(rsa_dmq1, "dq", json, err))
1696
0
    {
1697
0
        return false;
1698
0
    }
1699
0
    if (!_cjose_jwk_RSA_json_field(rsa_iqmp, "qi", json, err))
1700
0
    {
1701
0
        return false;
1702
0
    }
1703
1704
0
    return true;
1705
0
}
1706
1707
// interface functions -- RSA
1708
static const uint8_t *DEFAULT_E_DAT = (const uint8_t *)"\x01\x00\x01";
1709
static const size_t DEFAULT_E_LEN = 3;
1710
1711
cjose_jwk_t *cjose_jwk_create_RSA_random(size_t keysize, const uint8_t *e, size_t elen, cjose_err *err)
1712
0
{
1713
    // RFC 7518 §3.3 requires minimum 2048-bit RSA modulus for RS*/PS*/RSA-OAEP/RSA1_5
1714
0
    if (keysize < 2048)
1715
0
    {
1716
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1717
0
        return NULL;
1718
0
    }
1719
0
    if (NULL == e || 0 >= elen)
1720
0
    {
1721
0
        e = DEFAULT_E_DAT;
1722
0
        elen = DEFAULT_E_LEN;
1723
0
    }
1724
1725
0
    RSA *rsa = NULL;
1726
0
    BIGNUM *bn = NULL;
1727
1728
0
    rsa = RSA_new();
1729
0
    if (!rsa)
1730
0
    {
1731
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1732
0
        goto create_RSA_random_failed;
1733
0
    }
1734
1735
0
    bn = BN_bin2bn(e, elen, NULL);
1736
0
    if (!bn)
1737
0
    {
1738
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1739
0
        goto create_RSA_random_failed;
1740
0
    }
1741
1742
0
    if (0 == RSA_generate_key_ex(rsa, keysize, bn, NULL))
1743
0
    {
1744
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1745
0
        goto create_RSA_random_failed;
1746
0
    }
1747
1748
0
    BN_free(bn);
1749
0
    return _cjose_jwk_RSA_new(rsa, err);
1750
1751
0
create_RSA_random_failed:
1752
0
    if (bn)
1753
0
    {
1754
0
        BN_free(bn);
1755
0
    }
1756
0
    if (rsa)
1757
0
    {
1758
0
        RSA_free(rsa);
1759
0
    }
1760
0
    return NULL;
1761
0
}
1762
1763
cjose_jwk_t *cjose_jwk_create_RSA_spec(const cjose_jwk_rsa_keyspec *spec, cjose_err *err)
1764
0
{
1765
0
    if (NULL == spec)
1766
0
    {
1767
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1768
0
        return NULL;
1769
0
    }
1770
1771
0
    bool hasPub = (NULL != spec->n && 0 < spec->nlen) && (NULL != spec->e && 0 < spec->elen);
1772
0
    bool hasPriv = (NULL != spec->n && 0 < spec->nlen) && (NULL != spec->d && 0 < spec->dlen);
1773
0
    if (!hasPub && !hasPriv)
1774
0
    {
1775
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1776
0
        return NULL;
1777
0
    }
1778
1779
    // RFC 7518 §3.3 requires minimum 2048-bit RSA modulus for RS*/PS*/RSA-OAEP/RSA1_5
1780
0
    BIGNUM *n_bn = BN_bin2bn(spec->n, spec->nlen, NULL);
1781
0
    if (NULL == n_bn)
1782
0
    {
1783
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1784
0
        return NULL;
1785
0
    }
1786
0
    if (BN_num_bits(n_bn) < 2048)
1787
0
    {
1788
0
        BN_free(n_bn);
1789
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1790
0
        return NULL;
1791
0
    }
1792
0
    BN_free(n_bn);
1793
1794
0
    RSA *rsa = NULL;
1795
0
    rsa = RSA_new();
1796
0
    if (!rsa)
1797
0
    {
1798
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1799
0
        return NULL;
1800
0
    }
1801
1802
0
    if (hasPriv)
1803
0
    {
1804
0
        if (!_cjose_jwk_rsa_set(rsa, spec->n, spec->nlen, spec->e, spec->elen, spec->d, spec->dlen))
1805
0
        {
1806
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1807
0
            goto create_RSA_spec_failed;
1808
0
        }
1809
0
        if (!_cjose_jwk_rsa_set_factors(rsa, spec->p, spec->plen, spec->q, spec->qlen)
1810
0
            || !_cjose_jwk_rsa_set_crt(rsa, spec->dp, spec->dplen, spec->dq, spec->dqlen, spec->qi, spec->qilen))
1811
0
        {
1812
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1813
0
            goto create_RSA_spec_failed;
1814
0
        }
1815
0
    }
1816
0
    else if (hasPub)
1817
0
    {
1818
0
        if (!_cjose_jwk_rsa_set(rsa, spec->n, spec->nlen, spec->e, spec->elen, NULL, 0))
1819
0
        {
1820
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1821
0
            goto create_RSA_spec_failed;
1822
0
        }
1823
0
    }
1824
1825
0
    return _cjose_jwk_RSA_new(rsa, err);
1826
1827
0
create_RSA_spec_failed:
1828
0
    if (rsa)
1829
0
    {
1830
0
        RSA_free(rsa);
1831
0
    }
1832
1833
0
    return NULL;
1834
0
}
1835
1836
//////////////// Import ////////////////
1837
// internal data & functions -- JWK key import
1838
1839
static const char *_cjose_jwk_get_json_object_string_attribute(json_t *json, const char *key, cjose_err *err)
1840
485
{
1841
485
    const char *attr_str = NULL;
1842
485
    json_t *attr_json = json_object_get(json, key);
1843
485
    if (NULL != attr_json)
1844
0
    {
1845
0
        attr_str = json_string_value(attr_json);
1846
0
    }
1847
485
    return attr_str;
1848
485
}
1849
1850
/**
1851
 * Internal helper function for extracing an octet string from a base64url
1852
 * encoded field.  Caller provides the json object, the attribute key,
1853
 * and an expected length for the octet string.  On successful decoding,
1854
 * this will return a newly allocated buffer with the decoded octet string
1855
 * of the expected length.
1856
 *
1857
 * Note: caller is responsible for freeing the buffer returned by this function.
1858
 *
1859
 * \param[in]     json the JSON object from which to read the attribute.
1860
 * \param[in]     key the name of the attribute to be decoded.
1861
 * \param[out]    pointer to buffer of octet string (if decoding succeeds).
1862
 * \param[in/out] in as the expected length of the attribute, out as the
1863
 *                actual decoded length.  Note, this method succeeds only
1864
 *                if the actual decoded length matches the expected length.
1865
 *                If the in-value is 0 this indicates there is no particular
1866
 *                expected length (i.e. any length is ok).
1867
 * \returns true  if attribute is either not present or successfully decoded.
1868
 *                false otherwise.
1869
 */
1870
static bool _cjose_jwk_decode_json_object_base64url_attribute(
1871
    json_t *jwk_json, const char *key, uint8_t **buffer, size_t *buflen, cjose_err *err)
1872
0
{
1873
    // get the base64url encoded string value of the attribute (if any)
1874
0
    const char *str = _cjose_jwk_get_json_object_string_attribute(jwk_json, key, err);
1875
0
    if (str == NULL || strlen(str) == 0)
1876
0
    {
1877
0
        *buflen = 0;
1878
0
        *buffer = NULL;
1879
0
        return true;
1880
0
    }
1881
1882
    // if a particular decoded length is expected, check for that
1883
0
    if (*buflen != 0)
1884
0
    {
1885
0
        const char *end = NULL;
1886
0
        for (end = str + strlen(str) - 1; *end == '=' && end > str; --end)
1887
0
            ;
1888
0
        size_t unpadded_len = end + 1 - str - ((*end == '=') ? 1 : 0);
1889
        // number of unpadded base64url characters for *buflen bytes,
1890
        // i.e. ceil(4 * buflen / 3) computed with integer arithmetic
1891
0
        size_t expected_len = (4 * (*buflen) + 2) / 3;
1892
1893
0
        if (expected_len != unpadded_len)
1894
0
        {
1895
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1896
0
            *buflen = 0;
1897
0
            *buffer = NULL;
1898
0
            return false;
1899
0
        }
1900
0
    }
1901
1902
    // decode the base64url encoded string to the allocated buffer
1903
0
    if (!cjose_base64url_decode(str, strlen(str), buffer, buflen, err))
1904
0
    {
1905
0
        *buflen = 0;
1906
0
        *buffer = NULL;
1907
0
        return false;
1908
0
    }
1909
1910
0
    return true;
1911
0
}
1912
1913
// RFC 7518 section 6.3.2: a private member that is present but carries no
1914
// value is a malformed key, not a public one, so it must not be read as absent
1915
static bool _cjose_jwk_decode_private_attribute(json_t *jwk_json, const char *key, uint8_t **buffer, size_t *buflen, cjose_err *err)
1916
0
{
1917
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, key, buffer, buflen, err))
1918
0
    {
1919
0
        return false;
1920
0
    }
1921
0
    if (NULL != json_object_get(jwk_json, key))
1922
0
    {
1923
        // base64url padding on its own decodes to nothing, so the buffer can
1924
        // be present and still carry no octets, and octets that are all zero
1925
        // are the integer 0, which is no more a private key parameter than an
1926
        // absent one is
1927
0
        bool valueless = (NULL == *buffer || 0 == *buflen);
1928
0
        if (!valueless)
1929
0
        {
1930
0
            valueless = true;
1931
0
            for (size_t i = 0; i < *buflen; i++)
1932
0
            {
1933
0
                if (0 != (*buffer)[i])
1934
0
                {
1935
0
                    valueless = false;
1936
0
                    break;
1937
0
                }
1938
0
            }
1939
0
        }
1940
0
        if (valueless)
1941
0
        {
1942
0
            CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1943
0
            return false;
1944
0
        }
1945
0
    }
1946
0
    return true;
1947
0
}
1948
1949
static cjose_jwk_t *_cjose_jwk_import_EC(json_t *jwk_json, cjose_err *err)
1950
0
{
1951
0
    cjose_jwk_t *jwk = NULL;
1952
0
    uint8_t *x_buffer = NULL;
1953
0
    uint8_t *y_buffer = NULL;
1954
0
    uint8_t *d_buffer = NULL;
1955
0
    size_t x_buflen = 0;
1956
0
    size_t y_buflen = 0;
1957
0
    size_t d_buflen = 0;
1958
1959
    // get the value of the crv attribute
1960
0
    const char *crv_str = _cjose_jwk_get_json_object_string_attribute(jwk_json, CJOSE_JWK_CRV_STR, err);
1961
0
    if (crv_str == NULL)
1962
0
    {
1963
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1964
0
        goto import_EC_cleanup;
1965
0
    }
1966
1967
    // get the curve identifer for the curve named by crv
1968
0
    cjose_jwk_ec_curve crv;
1969
0
    if (!_cjose_jwk_ec_curve_from_name(crv_str, &crv, err))
1970
0
    {
1971
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1972
0
        goto import_EC_cleanup;
1973
0
    }
1974
1975
    // get the decoded value of the x coordinate
1976
0
    x_buflen = (size_t)_cjose_jwk_ec_size_for_curve(crv, err);
1977
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_X_STR, &x_buffer, &x_buflen, err))
1978
0
    {
1979
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1980
0
        goto import_EC_cleanup;
1981
0
    }
1982
1983
    // get the decoded value of the y coordinate
1984
0
    y_buflen = (size_t)_cjose_jwk_ec_size_for_curve(crv, err);
1985
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_Y_STR, &y_buffer, &y_buflen, err))
1986
0
    {
1987
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1988
0
        goto import_EC_cleanup;
1989
0
    }
1990
1991
    // get the decoded value of the private key d
1992
0
    d_buflen = (size_t)_cjose_jwk_ec_size_for_curve(crv, err);
1993
    // "d" is REQUIRED for a private key and MUST NOT be present for a public
1994
    // one (RFC 7518 section 6.2.2), so when the attribute is there it has to
1995
    // carry a usable value instead of quietly making a public key: the same
1996
    // rule the RSA import above applies to its private members
1997
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err))
1998
0
    {
1999
0
        goto import_EC_cleanup;
2000
0
    }
2001
2002
    // create an ec keyspec
2003
0
    cjose_jwk_ec_keyspec ec_keyspec;
2004
0
    memset(&ec_keyspec, 0, sizeof(cjose_jwk_ec_keyspec));
2005
0
    ec_keyspec.crv = crv;
2006
0
    ec_keyspec.x = x_buffer;
2007
0
    ec_keyspec.xlen = x_buflen;
2008
0
    ec_keyspec.y = y_buffer;
2009
0
    ec_keyspec.ylen = y_buflen;
2010
0
    ec_keyspec.d = d_buffer;
2011
0
    ec_keyspec.dlen = d_buflen;
2012
2013
    // create the jwk
2014
0
    jwk = cjose_jwk_create_EC_spec(&ec_keyspec, err);
2015
2016
0
import_EC_cleanup:
2017
0
    if (NULL != x_buffer)
2018
0
    {
2019
0
        cjose_get_dealloc()(x_buffer);
2020
0
    }
2021
0
    if (NULL != y_buffer)
2022
0
    {
2023
0
        cjose_get_dealloc()(y_buffer);
2024
0
    }
2025
    // d is the private key -> wipe the decoded copy before release
2026
0
    if (NULL != d_buffer)
2027
0
    {
2028
0
        _cjose_cleanse_dealloc(d_buffer, d_buflen);
2029
0
    }
2030
2031
0
    return jwk;
2032
0
}
2033
2034
static cjose_jwk_t *_cjose_jwk_import_RSA(json_t *jwk_json, cjose_err *err)
2035
0
{
2036
0
    cjose_jwk_t *jwk = NULL;
2037
0
    uint8_t *n_buffer = NULL;
2038
0
    uint8_t *e_buffer = NULL;
2039
0
    uint8_t *d_buffer = NULL;
2040
0
    uint8_t *p_buffer = NULL;
2041
0
    uint8_t *q_buffer = NULL;
2042
0
    uint8_t *dp_buffer = NULL;
2043
0
    uint8_t *dq_buffer = NULL;
2044
0
    uint8_t *qi_buffer = NULL;
2045
0
    size_t n_buflen = 0;
2046
0
    size_t e_buflen = 0;
2047
0
    size_t d_buflen = 0;
2048
0
    size_t p_buflen = 0;
2049
0
    size_t q_buflen = 0;
2050
0
    size_t dp_buflen = 0;
2051
0
    size_t dq_buflen = 0;
2052
0
    size_t qi_buflen = 0;
2053
2054
    // cjose supports only two-prime RSA keys; RFC 7518 section 6.3.2.7
2055
    // requires consumers that do not support multi-prime keys not to use a
2056
    // key carrying the "oth" parameter
2057
0
    if (NULL != json_object_get(jwk_json, CJOSE_JWK_OTH_STR))
2058
0
    {
2059
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2060
0
        goto import_RSA_cleanup;
2061
0
    }
2062
2063
    // get the decoded value of n (buflen = 0 means no particular expected len)
2064
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_N_STR, &n_buffer, &n_buflen, err))
2065
0
    {
2066
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2067
0
        goto import_RSA_cleanup;
2068
0
    }
2069
2070
    // get the decoded value of e
2071
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_E_STR, &e_buffer, &e_buflen, err))
2072
0
    {
2073
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2074
0
        goto import_RSA_cleanup;
2075
0
    }
2076
2077
    // get the decoded value of d
2078
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err))
2079
0
    {
2080
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2081
0
        goto import_RSA_cleanup;
2082
0
    }
2083
2084
    // get the decoded value of p
2085
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_P_STR, &p_buffer, &p_buflen, err))
2086
0
    {
2087
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2088
0
        goto import_RSA_cleanup;
2089
0
    }
2090
2091
    // get the decoded value of q
2092
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_Q_STR, &q_buffer, &q_buflen, err))
2093
0
    {
2094
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2095
0
        goto import_RSA_cleanup;
2096
0
    }
2097
2098
    // get the decoded value of dp
2099
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_DP_STR, &dp_buffer, &dp_buflen, err))
2100
0
    {
2101
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2102
0
        goto import_RSA_cleanup;
2103
0
    }
2104
2105
    // get the decoded value of dq
2106
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_DQ_STR, &dq_buffer, &dq_buflen, err))
2107
0
    {
2108
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2109
0
        goto import_RSA_cleanup;
2110
0
    }
2111
2112
    // get the decoded value of qi
2113
0
    if (!_cjose_jwk_decode_private_attribute(jwk_json, CJOSE_JWK_QI_STR, &qi_buffer, &qi_buflen, err))
2114
0
    {
2115
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2116
0
        goto import_RSA_cleanup;
2117
0
    }
2118
2119
    // create an rsa keyspec
2120
0
    cjose_jwk_rsa_keyspec rsa_keyspec;
2121
0
    memset(&rsa_keyspec, 0, sizeof(cjose_jwk_rsa_keyspec));
2122
0
    rsa_keyspec.n = n_buffer;
2123
0
    rsa_keyspec.nlen = n_buflen;
2124
0
    rsa_keyspec.e = e_buffer;
2125
0
    rsa_keyspec.elen = e_buflen;
2126
0
    rsa_keyspec.d = d_buffer;
2127
0
    rsa_keyspec.dlen = d_buflen;
2128
0
    rsa_keyspec.p = p_buffer;
2129
0
    rsa_keyspec.plen = p_buflen;
2130
0
    rsa_keyspec.q = q_buffer;
2131
0
    rsa_keyspec.qlen = q_buflen;
2132
0
    rsa_keyspec.dp = dp_buffer;
2133
0
    rsa_keyspec.dplen = dp_buflen;
2134
0
    rsa_keyspec.dq = dq_buffer;
2135
0
    rsa_keyspec.dqlen = dq_buflen;
2136
0
    rsa_keyspec.qi = qi_buffer;
2137
0
    rsa_keyspec.qilen = qi_buflen;
2138
2139
    // create the jwk
2140
0
    jwk = cjose_jwk_create_RSA_spec(&rsa_keyspec, err);
2141
2142
0
import_RSA_cleanup:
2143
    // n and e are public; the remaining decoded components are private -> wipe
2144
0
    cjose_get_dealloc()(n_buffer);
2145
0
    cjose_get_dealloc()(e_buffer);
2146
0
    _cjose_cleanse_dealloc(d_buffer, d_buflen);
2147
0
    _cjose_cleanse_dealloc(p_buffer, p_buflen);
2148
0
    _cjose_cleanse_dealloc(q_buffer, q_buflen);
2149
0
    _cjose_cleanse_dealloc(dp_buffer, dp_buflen);
2150
0
    _cjose_cleanse_dealloc(dq_buffer, dq_buflen);
2151
0
    _cjose_cleanse_dealloc(qi_buffer, qi_buflen);
2152
2153
0
    return jwk;
2154
0
}
2155
2156
static cjose_jwk_t *_cjose_jwk_import_oct(json_t *jwk_json, cjose_err *err)
2157
0
{
2158
0
    cjose_jwk_t *jwk = NULL;
2159
0
    uint8_t *k_buffer = NULL;
2160
2161
    // get the decoded value of k (buflen = 0 means no particular expected len)
2162
0
    size_t k_buflen = 0;
2163
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_K_STR, &k_buffer, &k_buflen, err))
2164
0
    {
2165
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2166
0
        goto import_oct_cleanup;
2167
0
    }
2168
2169
    // create the jwk
2170
0
    jwk = cjose_jwk_create_oct_spec(k_buffer, k_buflen, err);
2171
2172
0
import_oct_cleanup:
2173
    // k is secret symmetric key material -> wipe the decoded copy
2174
0
    _cjose_cleanse_dealloc(k_buffer, k_buflen);
2175
2176
0
    return jwk;
2177
0
}
2178
2179
#if defined(CJOSE_OPENSSL_111X)
2180
static cjose_jwk_t *_cjose_jwk_import_OKP(json_t *jwk_json, cjose_err *err)
2181
0
{
2182
0
    cjose_jwk_t *jwk = NULL;
2183
0
    uint8_t *x_buffer = NULL;
2184
0
    uint8_t *d_buffer = NULL;
2185
0
    size_t x_buflen = 0;
2186
0
    size_t d_buflen = 0;
2187
2188
    // get the value of the crv attribute
2189
0
    const char *crv_str = _cjose_jwk_get_json_object_string_attribute(jwk_json, CJOSE_JWK_CRV_STR, err);
2190
0
    if (crv_str == NULL)
2191
0
    {
2192
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2193
0
        goto import_OKP_cleanup;
2194
0
    }
2195
2196
    // get the curve identifier for the curve named by crv
2197
0
    cjose_jwk_okp_curve crv;
2198
0
    if (!_cjose_jwk_okp_curve_from_name(crv_str, &crv))
2199
0
    {
2200
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2201
0
        goto import_OKP_cleanup;
2202
0
    }
2203
2204
    // get the decoded value of the public key x (of the fixed size of the
2205
    // curve); x is REQUIRED for every OKP key (RFC 8037 section 2), and the
2206
    // decoder treats a missing, empty or non-string attribute alike, so a
2207
    // decoded value must have come out of it
2208
0
    x_buflen = _cjose_jwk_okp_size_for_curve(crv);
2209
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_X_STR, &x_buffer, &x_buflen, err)
2210
0
        || NULL == x_buffer)
2211
0
    {
2212
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2213
0
        goto import_OKP_cleanup;
2214
0
    }
2215
2216
    // get the decoded value of the private key d (of the fixed size of the
2217
    // curve); d is REQUIRED for a private key and MUST NOT be present for a
2218
    // public key (RFC 8037 section 2), so when the attribute is there it must
2219
    // decode to a key of the right size instead of quietly making a public key
2220
0
    d_buflen = _cjose_jwk_okp_size_for_curve(crv);
2221
0
    if (!_cjose_jwk_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err)
2222
0
        || (NULL != json_object_get(jwk_json, CJOSE_JWK_D_STR) && NULL == d_buffer))
2223
0
    {
2224
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2225
0
        goto import_OKP_cleanup;
2226
0
    }
2227
2228
    // create an okp keyspec
2229
0
    cjose_jwk_okp_keyspec okp_keyspec;
2230
0
    memset(&okp_keyspec, 0, sizeof(cjose_jwk_okp_keyspec));
2231
0
    okp_keyspec.crv = crv;
2232
0
    okp_keyspec.x = x_buffer;
2233
0
    okp_keyspec.xlen = x_buflen;
2234
0
    okp_keyspec.d = d_buffer;
2235
0
    okp_keyspec.dlen = d_buflen;
2236
2237
    // create the jwk
2238
0
    jwk = cjose_jwk_create_OKP_spec(&okp_keyspec, err);
2239
2240
0
import_OKP_cleanup:
2241
0
    cjose_get_dealloc()(x_buffer);
2242
    // d is the private key -> wipe the decoded copy before release
2243
0
    _cjose_cleanse_dealloc(d_buffer, d_buflen);
2244
2245
0
    return jwk;
2246
0
}
2247
#else
2248
static cjose_jwk_t *_cjose_jwk_import_OKP(json_t *jwk_json, cjose_err *err)
2249
{
2250
    // the OKP key type needs the raw key API that arrived in OpenSSL 1.1.1
2251
    CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2252
    return NULL;
2253
}
2254
#endif // CJOSE_OPENSSL_111X
2255
2256
cjose_jwk_t *cjose_jwk_import(const char *jwk_str, size_t len, cjose_err *err)
2257
829
{
2258
829
    cjose_jwk_t *jwk = NULL;
2259
2260
    // check params
2261
829
    if ((NULL == jwk_str) || (0 == len))
2262
0
    {
2263
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2264
0
        return NULL;
2265
0
    }
2266
2267
    // parse json content from the given string
2268
829
    json_t *jwk_json = json_loadb(jwk_str, len, 0, NULL);
2269
829
    if (NULL == jwk_json)
2270
0
    {
2271
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2272
0
        goto import_cleanup;
2273
0
    }
2274
2275
829
    jwk = cjose_jwk_import_json((cjose_header_t *)jwk_json, err);
2276
2277
// poor man's "finally"
2278
829
import_cleanup:
2279
829
    if (NULL != jwk_json)
2280
829
    {
2281
829
        json_decref(jwk_json);
2282
829
    }
2283
2284
829
    return jwk;
2285
829
}
2286
2287
cjose_jwk_t *cjose_jwk_import_json(cjose_header_t *json, cjose_err *err)
2288
829
{
2289
829
    cjose_jwk_t *jwk = NULL;
2290
2291
829
    json_t *jwk_json = (json_t *)json;
2292
2293
829
    if (NULL == jwk_json || JSON_OBJECT != json_typeof(jwk_json))
2294
344
    {
2295
344
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2296
344
        return NULL;
2297
344
    }
2298
2299
    // get the string value of the kty attribute of the jwk
2300
485
    const char *kty_str = _cjose_jwk_get_json_object_string_attribute(jwk_json, CJOSE_JWK_KTY_STR, err);
2301
485
    if (NULL == kty_str)
2302
485
    {
2303
485
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2304
485
        return NULL;
2305
485
    }
2306
2307
    // get kty corresponding to kty_str (kty is required)
2308
0
    cjose_jwk_kty_t kty;
2309
0
    if (!_cjose_jwk_kty_from_name(kty_str, &kty, err))
2310
0
    {
2311
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2312
0
        return NULL;
2313
0
    }
2314
2315
    // create a cjose_jwt_t based on the kty
2316
0
    switch (kty)
2317
0
    {
2318
0
    case CJOSE_JWK_KTY_EC:
2319
0
        jwk = _cjose_jwk_import_EC(jwk_json, err);
2320
0
        break;
2321
2322
0
    case CJOSE_JWK_KTY_RSA:
2323
0
        jwk = _cjose_jwk_import_RSA(jwk_json, err);
2324
0
        break;
2325
2326
0
    case CJOSE_JWK_KTY_OCT:
2327
0
        jwk = _cjose_jwk_import_oct(jwk_json, err);
2328
0
        break;
2329
2330
0
    case CJOSE_JWK_KTY_OKP:
2331
0
        jwk = _cjose_jwk_import_OKP(jwk_json, err);
2332
0
        break;
2333
2334
0
    default:
2335
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2336
0
        return NULL;
2337
0
    }
2338
0
    if (NULL == jwk)
2339
0
    {
2340
        // helper function will have already set err
2341
0
        return NULL;
2342
0
    }
2343
2344
    // get the value of the kid attribute (kid is optional)
2345
0
    const char *kid_str = _cjose_jwk_get_json_object_string_attribute(jwk_json, CJOSE_JWK_KID_STR, err);
2346
0
    if (kid_str != NULL)
2347
0
    {
2348
0
        jwk->kid = _cjose_strndup(kid_str, -1, err);
2349
0
        if (!jwk->kid)
2350
0
        {
2351
0
            cjose_jwk_release(jwk);
2352
0
            return NULL;
2353
0
        }
2354
0
    }
2355
2356
0
    return jwk;
2357
0
}
2358
2359
//////////////// ECDH ////////////////
2360
// internal data & functions -- ECDH derivation
2361
2362
static bool _cjose_jwk_evp_key_from_ec_key(const cjose_jwk_t *jwk, EVP_PKEY **key, cjose_err *err)
2363
0
{
2364
    // validate that the jwk is of type EC and we have a valid out-param
2365
0
    if (NULL == jwk || CJOSE_JWK_KTY_EC != jwk->kty || NULL == jwk->keydata || NULL == key || NULL != *key)
2366
0
    {
2367
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2368
0
        goto _cjose_jwk_evp_key_from_ec_key_fail;
2369
0
    }
2370
2371
    // create a blank EVP_PKEY
2372
0
    *key = EVP_PKEY_new();
2373
0
    if (NULL == *key)
2374
0
    {
2375
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2376
0
        goto _cjose_jwk_evp_key_from_ec_key_fail;
2377
0
    }
2378
2379
    // assign the EVP_PKEY to reference the jwk's internal EC_KEY structure
2380
0
    if (1 != EVP_PKEY_set1_EC_KEY(*key, ((struct _ec_keydata_int *)(jwk->keydata))->key))
2381
0
    {
2382
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2383
0
        goto _cjose_jwk_evp_key_from_ec_key_fail;
2384
0
    }
2385
2386
    // happy path
2387
0
    return true;
2388
2389
// fail path
2390
0
_cjose_jwk_evp_key_from_ec_key_fail:
2391
2392
0
    EVP_PKEY_free(*key);
2393
0
    *key = NULL;
2394
2395
0
    return false;
2396
0
}
2397
2398
cjose_jwk_t *cjose_jwk_derive_ecdh_secret(
2399
    const cjose_jwk_t *jwk_self, const cjose_jwk_t *jwk_peer, const uint8_t *salt, size_t salt_len, cjose_err *err)
2400
0
{
2401
0
    return cjose_jwk_derive_ecdh_ephemeral_key(jwk_self, jwk_peer, salt, salt_len, err);
2402
0
}
2403
2404
cjose_jwk_t *cjose_jwk_derive_ecdh_ephemeral_key(
2405
    const cjose_jwk_t *jwk_self, const cjose_jwk_t *jwk_peer, const uint8_t *salt, size_t salt_len, cjose_err *err)
2406
0
{
2407
0
    uint8_t *secret = NULL;
2408
0
    size_t secret_len = 0;
2409
0
    uint8_t *ephemeral_key = NULL;
2410
0
    size_t ephemeral_key_len = 0;
2411
0
    cjose_jwk_t *jwk_ephemeral_key = NULL;
2412
2413
0
    if (!cjose_jwk_derive_ecdh_bits(jwk_self, jwk_peer, &secret, &secret_len, err))
2414
0
    {
2415
0
        goto _cjose_jwk_derive_shared_secret_fail;
2416
0
    }
2417
2418
    // HKDF of the DH shared secret (SHA256, no info, 256 bit expand)
2419
0
    ephemeral_key_len = 32;
2420
0
    ephemeral_key = (uint8_t *)cjose_get_alloc()(ephemeral_key_len);
2421
0
    if (NULL == ephemeral_key)
2422
0
    {
2423
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
2424
0
        goto _cjose_jwk_derive_shared_secret_fail;
2425
0
    }
2426
0
    if (!cjose_jwk_hkdf(EVP_sha256(), salt, salt_len, (uint8_t *)"", 0, secret, secret_len, ephemeral_key, ephemeral_key_len, err))
2427
0
    {
2428
0
        goto _cjose_jwk_derive_shared_secret_fail;
2429
0
    }
2430
2431
    // create a JWK of the shared secret
2432
0
    jwk_ephemeral_key = cjose_jwk_create_oct_spec(ephemeral_key, ephemeral_key_len, err);
2433
0
    if (NULL == jwk_ephemeral_key)
2434
0
    {
2435
0
        goto _cjose_jwk_derive_shared_secret_fail;
2436
0
    }
2437
2438
    // happy path
2439
0
    _cjose_cleanse_dealloc(secret, secret_len);
2440
0
    _cjose_cleanse_dealloc(ephemeral_key, ephemeral_key_len);
2441
2442
0
    return jwk_ephemeral_key;
2443
2444
// fail path
2445
0
_cjose_jwk_derive_shared_secret_fail:
2446
2447
0
    if (NULL != jwk_ephemeral_key)
2448
0
    {
2449
0
        cjose_jwk_release(jwk_ephemeral_key);
2450
0
    }
2451
0
    _cjose_cleanse_dealloc(secret, secret_len);
2452
0
    _cjose_cleanse_dealloc(ephemeral_key, ephemeral_key_len);
2453
0
    return NULL;
2454
0
}
2455
2456
bool cjose_jwk_derive_ecdh_bits(
2457
    const cjose_jwk_t *jwk_self, const cjose_jwk_t *jwk_peer, uint8_t **output, size_t *output_len, cjose_err *err)
2458
0
{
2459
0
    EVP_PKEY_CTX *ctx = NULL;
2460
0
    EVP_PKEY *pkey_self = NULL;
2461
0
    EVP_PKEY *pkey_peer = NULL;
2462
0
    uint8_t *secret = NULL;
2463
0
    size_t secret_len = 0;
2464
2465
    // get EVP_KEY from jwk_self
2466
0
    if (!_cjose_jwk_evp_key_from_ec_key(jwk_self, &pkey_self, err))
2467
0
    {
2468
0
        goto _cjose_jwk_derive_bits_fail;
2469
0
    }
2470
2471
    // get EVP_KEY from jwk_peer
2472
0
    if (!_cjose_jwk_evp_key_from_ec_key(jwk_peer, &pkey_peer, err))
2473
0
    {
2474
0
        goto _cjose_jwk_derive_bits_fail;
2475
0
    }
2476
2477
    // create derivation context based on local key pair
2478
0
    ctx = EVP_PKEY_CTX_new(pkey_self, NULL);
2479
0
    if (NULL == ctx)
2480
0
    {
2481
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2482
0
        goto _cjose_jwk_derive_bits_fail;
2483
0
    }
2484
2485
    // initialize derivation context
2486
0
    if (1 != EVP_PKEY_derive_init(ctx))
2487
0
    {
2488
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2489
0
        goto _cjose_jwk_derive_bits_fail;
2490
0
    }
2491
2492
    // provide the peer public key
2493
0
    if (1 != EVP_PKEY_derive_set_peer(ctx, pkey_peer))
2494
0
    {
2495
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2496
0
        goto _cjose_jwk_derive_bits_fail;
2497
0
    }
2498
2499
    // determine buffer length for shared secret
2500
0
    if (1 != EVP_PKEY_derive(ctx, NULL, &secret_len))
2501
0
    {
2502
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2503
0
        goto _cjose_jwk_derive_bits_fail;
2504
0
    }
2505
2506
    // allocate buffer for shared secret
2507
0
    secret = (uint8_t *)cjose_get_alloc()(secret_len);
2508
0
    if (NULL == secret)
2509
0
    {
2510
0
        CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
2511
0
        goto _cjose_jwk_derive_bits_fail;
2512
0
    }
2513
0
    memset(secret, 0, secret_len);
2514
2515
    // derive the shared secret
2516
0
    if (1 != (EVP_PKEY_derive(ctx, secret, &secret_len)))
2517
0
    {
2518
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2519
0
        goto _cjose_jwk_derive_bits_fail;
2520
0
    }
2521
2522
    // happy path
2523
0
    EVP_PKEY_CTX_free(ctx);
2524
0
    EVP_PKEY_free(pkey_self);
2525
0
    EVP_PKEY_free(pkey_peer);
2526
2527
0
    *output = secret;
2528
0
    *output_len = secret_len;
2529
0
    return true;
2530
2531
0
_cjose_jwk_derive_bits_fail:
2532
2533
0
    if (NULL != ctx)
2534
0
    {
2535
0
        EVP_PKEY_CTX_free(ctx);
2536
0
    }
2537
0
    if (NULL != pkey_self)
2538
0
    {
2539
0
        EVP_PKEY_free(pkey_self);
2540
0
    }
2541
0
    if (NULL != pkey_peer)
2542
0
    {
2543
0
        EVP_PKEY_free(pkey_peer);
2544
0
    }
2545
0
    _cjose_cleanse_dealloc(secret, secret_len);
2546
2547
0
    return false;
2548
0
}
2549
2550
bool cjose_jwk_hkdf(const EVP_MD *md,
2551
                    const uint8_t *salt,
2552
                    size_t salt_len,
2553
                    const uint8_t *info,
2554
                    size_t info_len,
2555
                    const uint8_t *ikm,
2556
                    size_t ikm_len,
2557
                    uint8_t *okm,
2558
                    unsigned int okm_len,
2559
                    cjose_err *err)
2560
0
{
2561
    // current impl. is very limited: SHA256, 256 bit output, and no info
2562
0
    if ((EVP_sha256() != md) || (0 != info_len) || (32 != okm_len))
2563
0
    {
2564
0
        CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
2565
0
        return false;
2566
0
    }
2567
2568
    // HKDF-Extract, HMAC-SHA256(salt, IKM) -> PRK
2569
0
    unsigned int prk_len;
2570
0
    unsigned char prk[EVP_MAX_MD_SIZE];
2571
0
    if (NULL == HMAC(md, salt, salt_len, ikm, ikm_len, prk, &prk_len))
2572
0
    {
2573
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2574
0
        return false;
2575
0
    }
2576
2577
    // HKDF-Expand, HMAC-SHA256(PRK,0x01) -> OKM
2578
0
    const unsigned char t[] = { 0x01 };
2579
0
    if (NULL == HMAC(md, prk, prk_len, t, sizeof(t), okm, NULL))
2580
0
    {
2581
0
        CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
2582
0
        _cjose_cleanse(prk, sizeof(prk));
2583
0
        return false;
2584
0
    }
2585
2586
0
    _cjose_cleanse(prk, sizeof(prk));
2587
    return true;
2588
0
}