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 <assert.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include <stdio.h>
19
20 #include <openssl/bn.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_P_384_STR[] = "P-384";
32 static const char CJOSE_JWK_EC_P_521_STR[] = "P-521";
33 static const char CJOSE_JWK_KTY_STR[] = "kty";
34 static const char CJOSE_JWK_KID_STR[] = "kid";
35 static const char CJOSE_JWK_KTY_EC_STR[] = "EC";
36 static const char CJOSE_JWK_KTY_RSA_STR[] = "RSA";
37 static const char CJOSE_JWK_KTY_OCT_STR[] = "oct";
38 static const char CJOSE_JWK_CRV_STR[] = "crv";
39 static const char CJOSE_JWK_X_STR[] = "x";
40 static const char CJOSE_JWK_Y_STR[] = "y";
41 static const char CJOSE_JWK_D_STR[] = "d";
42 static const char CJOSE_JWK_N_STR[] = "n";
43 static const char CJOSE_JWK_E_STR[] = "e";
44 static const char CJOSE_JWK_P_STR[] = "p";
45 static const char CJOSE_JWK_Q_STR[] = "q";
46 static const char CJOSE_JWK_DP_STR[] = "dp";
47 static const char CJOSE_JWK_DQ_STR[] = "dq";
48 static const char CJOSE_JWK_QI_STR[] = "qi";
49 static const char CJOSE_JWK_K_STR[] = "k";
50
51 static const char *JWK_KTY_NAMES[] = { CJOSE_JWK_KTY_RSA_STR, CJOSE_JWK_KTY_EC_STR, CJOSE_JWK_KTY_OCT_STR };
52
_cjose_jwk_rsa_get(RSA * rsa,BIGNUM ** rsa_n,BIGNUM ** rsa_e,BIGNUM ** rsa_d)53 void _cjose_jwk_rsa_get(RSA *rsa, BIGNUM **rsa_n, BIGNUM **rsa_e, BIGNUM **rsa_d)
54 {
55 if (rsa == NULL)
56 return;
57 #if defined(CJOSE_OPENSSL_11X)
58 RSA_get0_key(rsa, (const BIGNUM **)rsa_n, (const BIGNUM **)rsa_e, (const BIGNUM **)rsa_d);
59 #else
60 *rsa_n = rsa->n;
61 *rsa_e = rsa->e;
62 *rsa_d = rsa->d;
63 #endif
64 }
65
_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)66 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)
67 {
68 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
69
70 // RSA_set0_key doesn't work without each of those on the first call!
71 if ((n == NULL) || (n_len <= 0) || (e == NULL) || (e_len <= 0))
72 return false;
73
74 if (n && n_len > 0)
75 rsa_n = BN_bin2bn(n, n_len, NULL);
76 if (e && e_len > 0)
77 rsa_e = BN_bin2bn(e, e_len, NULL);
78 if (d && d_len > 0)
79 rsa_d = BN_bin2bn(d, d_len, NULL);
80
81 #if defined(CJOSE_OPENSSL_11X)
82 return RSA_set0_key(rsa, rsa_n, rsa_e, rsa_d) == 1;
83 #else
84 rsa->n = rsa_n;
85 rsa->e = rsa_e;
86 rsa->d = rsa_d;
87 return true;
88 #endif
89 }
90
_cjose_jwk_rsa_get_factors(RSA * rsa,BIGNUM ** p,BIGNUM ** q)91 void _cjose_jwk_rsa_get_factors(RSA *rsa, BIGNUM **p, BIGNUM **q)
92 {
93 #if defined(CJOSE_OPENSSL_11X)
94 RSA_get0_factors(rsa, (const BIGNUM **)p, (const BIGNUM **)q);
95 #else
96 *p = rsa->p;
97 *q = rsa->q;
98 #endif
99 }
100
_cjose_jwk_rsa_set_factors(RSA * rsa,uint8_t * p,size_t p_len,uint8_t * q,size_t q_len)101 void _cjose_jwk_rsa_set_factors(RSA *rsa, uint8_t *p, size_t p_len, uint8_t *q, size_t q_len)
102 {
103 BIGNUM *rsa_p = NULL, *rsa_q = NULL;
104
105 if (p && p_len > 0)
106 rsa_p = BN_bin2bn(p, p_len, NULL);
107 if (q && q_len > 0)
108 rsa_q = BN_bin2bn(q, q_len, NULL);
109
110 #if defined(CJOSE_OPENSSL_11X)
111 RSA_set0_factors(rsa, rsa_p, rsa_q);
112 #else
113 rsa->p = rsa_p;
114 rsa->q = rsa_q;
115 #endif
116 }
117
_cjose_jwk_rsa_get_crt(RSA * rsa,BIGNUM ** dmp1,BIGNUM ** dmq1,BIGNUM ** iqmp)118 void _cjose_jwk_rsa_get_crt(RSA *rsa, BIGNUM **dmp1, BIGNUM **dmq1, BIGNUM **iqmp)
119 {
120 #if defined(CJOSE_OPENSSL_11X)
121 RSA_get0_crt_params(rsa, (const BIGNUM **)dmp1, (const BIGNUM **)dmq1, (const BIGNUM **)iqmp);
122 #else
123 *dmp1 = rsa->dmp1;
124 *dmq1 = rsa->dmq1;
125 *iqmp = rsa->iqmp;
126 #endif
127 }
128
_cjose_jwk_rsa_set_crt(RSA * rsa,uint8_t * dmp1,size_t dmp1_len,uint8_t * dmq1,size_t dmq1_len,uint8_t * iqmp,size_t iqmp_len)129 void _cjose_jwk_rsa_set_crt(
130 RSA *rsa, uint8_t *dmp1, size_t dmp1_len, uint8_t *dmq1, size_t dmq1_len, uint8_t *iqmp, size_t iqmp_len)
131 {
132 BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL, *rsa_iqmp = NULL;
133
134 if (dmp1 && dmp1_len > 0)
135 rsa_dmp1 = BN_bin2bn(dmp1, dmp1_len, NULL);
136 if (dmq1 && dmq1_len > 0)
137 rsa_dmq1 = BN_bin2bn(dmq1, dmq1_len, NULL);
138 if (iqmp && iqmp_len > 0)
139 rsa_iqmp = BN_bin2bn(iqmp, iqmp_len, NULL);
140
141 #if defined(CJOSE_OPENSSL_11X)
142 RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp);
143 #else
144 rsa->dmp1 = rsa_dmp1;
145 rsa->dmq1 = rsa_dmq1;
146 rsa->iqmp = rsa_iqmp;
147 #endif
148 }
149
150 // interface functions -- Generic
151
cjose_jwk_name_for_kty(cjose_jwk_kty_t kty,cjose_err * err)152 const char *cjose_jwk_name_for_kty(cjose_jwk_kty_t kty, cjose_err *err)
153 {
154 if (0 == kty || CJOSE_JWK_KTY_OCT < kty)
155 {
156 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
157 return NULL;
158 }
159
160 return JWK_KTY_NAMES[kty - CJOSE_JWK_KTY_RSA];
161 }
162
cjose_jwk_retain(cjose_jwk_t * jwk,cjose_err * err)163 cjose_jwk_t *cjose_jwk_retain(cjose_jwk_t *jwk, cjose_err *err)
164 {
165 if (!jwk)
166 {
167 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
168 return NULL;
169 }
170
171 ++(jwk->retained);
172 // TODO: check for overflow
173
174 return jwk;
175 }
176
cjose_jwk_release(cjose_jwk_t * jwk)177 bool cjose_jwk_release(cjose_jwk_t *jwk)
178 {
179 if (!jwk)
180 {
181 return false;
182 }
183
184 --(jwk->retained);
185 if (0 == jwk->retained)
186 {
187 cjose_get_dealloc()(jwk->kid);
188 jwk->kid = NULL;
189
190 // assumes freefunc is set
191 assert(NULL != jwk->fns->free);
192 jwk->fns->free(jwk);
193 jwk = NULL;
194 }
195
196 return (NULL != jwk);
197 }
198
cjose_jwk_get_kty(const cjose_jwk_t * jwk,cjose_err * err)199 cjose_jwk_kty_t cjose_jwk_get_kty(const cjose_jwk_t *jwk, cjose_err *err)
200 {
201 if (!jwk)
202 {
203 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
204 return -1;
205 }
206
207 return jwk->kty;
208 }
cjose_jwk_get_keysize(const cjose_jwk_t * jwk,cjose_err * err)209 size_t cjose_jwk_get_keysize(const cjose_jwk_t *jwk, cjose_err *err)
210 {
211 if (!jwk)
212 {
213 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
214 return 0;
215 }
216 return jwk->keysize;
217 }
218
cjose_jwk_get_keydata(const cjose_jwk_t * jwk,cjose_err * err)219 void *cjose_jwk_get_keydata(const cjose_jwk_t *jwk, cjose_err *err)
220 {
221 if (!jwk)
222 {
223 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
224 return NULL;
225 }
226 return jwk->keydata;
227 }
228
cjose_jwk_get_kid(const cjose_jwk_t * jwk,cjose_err * err)229 const char *cjose_jwk_get_kid(const cjose_jwk_t *jwk, cjose_err *err)
230 {
231 if (!jwk)
232 {
233 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
234 return NULL;
235 }
236
237 return jwk->kid;
238 }
239
cjose_jwk_set_kid(cjose_jwk_t * jwk,const char * kid,size_t len,cjose_err * err)240 bool cjose_jwk_set_kid(cjose_jwk_t *jwk, const char *kid, size_t len, cjose_err *err)
241 {
242 if (!jwk || !kid)
243 {
244 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
245 return false;
246 }
247 if (jwk->kid)
248 {
249 cjose_get_dealloc()(jwk->kid);
250 }
251 jwk->kid = (char *)cjose_get_alloc()(len + 1);
252 if (!jwk->kid)
253 {
254 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
255 return false;
256 }
257 strncpy(jwk->kid, kid, len + 1);
258 return true;
259 }
260
cjose_jwk_to_json(const cjose_jwk_t * jwk,bool priv,cjose_err * err)261 char *cjose_jwk_to_json(const cjose_jwk_t *jwk, bool priv, cjose_err *err)
262 {
263 char *result = NULL;
264
265 if (!jwk)
266 {
267 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
268 return NULL;
269 }
270
271 json_t *json = json_object(), *field = NULL;
272 if (!json)
273 {
274 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
275 goto to_json_cleanup;
276 }
277
278 // set kty
279 const char *kty = cjose_jwk_name_for_kty(jwk->kty, err);
280 field = json_string(kty);
281 if (!field)
282 {
283 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
284 goto to_json_cleanup;
285 }
286 json_object_set(json, "kty", field);
287 json_decref(field);
288 field = NULL;
289
290 // set kid
291 if (NULL != jwk->kid)
292 {
293 field = json_string(jwk->kid);
294 if (!field)
295 {
296 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
297 goto to_json_cleanup;
298 }
299 json_object_set(json, CJOSE_JWK_KID_STR, field);
300 json_decref(field);
301 field = NULL;
302 }
303
304 // set public fields
305 if (jwk->fns->public_json && !jwk->fns->public_json(jwk, json, err))
306 {
307 goto to_json_cleanup;
308 }
309
310 // set private fields
311 if (priv && jwk->fns->private_json && !jwk->fns->private_json(jwk, json, err))
312 {
313 goto to_json_cleanup;
314 }
315
316 // generate the string ...
317 char *str_jwk = json_dumps(json, JSON_ENCODE_ANY | JSON_COMPACT | JSON_PRESERVE_ORDER);
318 if (!str_jwk)
319 {
320 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
321 goto to_json_cleanup;
322 }
323 result = _cjose_strndup(str_jwk, -1, err);
324 if (!result)
325 {
326 cjose_get_dealloc()(str_jwk);
327 goto to_json_cleanup;
328 }
329 cjose_get_dealloc()(str_jwk);
330
331 to_json_cleanup:
332 if (json)
333 {
334 json_decref(json);
335 json = NULL;
336 }
337 if (field)
338 {
339 json_decref(field);
340 field = NULL;
341 }
342
343 return result;
344 }
345
346 //////////////// Octet String ////////////////
347 // internal data & functions -- Octet String
348
349 static void _oct_free(cjose_jwk_t *jwk);
350 static bool _oct_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
351 static bool _oct_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
352
353 static const key_fntable OCT_FNTABLE = { _oct_free, _oct_public_fields, _oct_private_fields };
354
_oct_new(uint8_t * buffer,size_t keysize,cjose_err * err)355 static cjose_jwk_t *_oct_new(uint8_t *buffer, size_t keysize, cjose_err *err)
356 {
357 cjose_jwk_t *jwk = (cjose_jwk_t *)cjose_get_alloc()(sizeof(cjose_jwk_t));
358 if (NULL == jwk)
359 {
360 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
361 }
362 else
363 {
364 memset(jwk, 0, sizeof(cjose_jwk_t));
365 jwk->retained = 1;
366 jwk->kty = CJOSE_JWK_KTY_OCT;
367 jwk->keysize = keysize;
368 jwk->keydata = buffer;
369 jwk->fns = &OCT_FNTABLE;
370 }
371
372 return jwk;
373 }
374
_oct_free(cjose_jwk_t * jwk)375 static void _oct_free(cjose_jwk_t *jwk)
376 {
377 uint8_t *buffer = (uint8_t *)jwk->keydata;
378 jwk->keydata = NULL;
379 if (buffer)
380 {
381 cjose_get_dealloc()(buffer);
382 }
383 cjose_get_dealloc()(jwk);
384 }
385
_oct_public_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)386 static bool _oct_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err) { return true; }
387
_oct_private_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)388 static bool _oct_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
389 {
390 json_t *field = NULL;
391 char *k = NULL;
392 size_t klen = 0;
393 uint8_t *keydata = (uint8_t *)jwk->keydata;
394 size_t keysize = jwk->keysize / 8;
395
396 if (!cjose_base64url_encode(keydata, keysize, &k, &klen, err))
397 {
398 return false;
399 }
400
401 field = _cjose_json_stringn(k, klen, err);
402 cjose_get_dealloc()(k);
403 k = NULL;
404 if (!field)
405 {
406 return false;
407 }
408 json_object_set(json, "k", field);
409 json_decref(field);
410
411 return true;
412 }
413
414 // interface functions -- Octet String
415
cjose_jwk_create_oct_random(size_t keysize,cjose_err * err)416 cjose_jwk_t *cjose_jwk_create_oct_random(size_t keysize, cjose_err *err)
417 {
418 cjose_jwk_t *jwk = NULL;
419 uint8_t *buffer = NULL;
420
421 if (0 == keysize)
422 {
423 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
424 goto create_oct_failed;
425 }
426
427 // resize to bytes
428 size_t buffersize = sizeof(uint8_t) * (keysize / 8);
429
430 buffer = (uint8_t *)cjose_get_alloc()(buffersize);
431 if (NULL == buffer)
432 {
433 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
434 goto create_oct_failed;
435 }
436 if (1 != RAND_bytes(buffer, buffersize))
437 {
438 goto create_oct_failed;
439 }
440
441 jwk = _oct_new(buffer, keysize, err);
442 if (NULL == jwk)
443 {
444 goto create_oct_failed;
445 }
446 return jwk;
447
448 create_oct_failed:
449 if (buffer)
450 {
451 cjose_get_dealloc()(buffer);
452 buffer = NULL;
453 }
454
455 return NULL;
456 }
457
cjose_jwk_create_oct_spec(const uint8_t * data,size_t len,cjose_err * err)458 cjose_jwk_t *cjose_jwk_create_oct_spec(const uint8_t *data, size_t len, cjose_err *err)
459 {
460 cjose_jwk_t *jwk = NULL;
461 uint8_t *buffer = NULL;
462
463 if (NULL == data || 0 == len)
464 {
465 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
466 goto create_oct_failed;
467 }
468
469 buffer = (uint8_t *)cjose_get_alloc()(len);
470 if (!buffer)
471 {
472 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
473 goto create_oct_failed;
474 }
475 memcpy(buffer, data, len);
476
477 jwk = _oct_new(buffer, len * 8, err);
478 if (NULL == jwk)
479 {
480 goto create_oct_failed;
481 }
482
483 return jwk;
484
485 create_oct_failed:
486 if (buffer)
487 {
488 cjose_get_dealloc()(buffer);
489 buffer = NULL;
490 }
491
492 return NULL;
493 }
494
495 //////////////// Elliptic Curve ////////////////
496 // internal data & functions -- Elliptic Curve
497
498 static void _EC_free(cjose_jwk_t *jwk);
499 static bool _EC_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
500 static bool _EC_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
501
502 static const key_fntable EC_FNTABLE = { _EC_free, _EC_public_fields, _EC_private_fields };
503
_ec_size_for_curve(cjose_jwk_ec_curve crv,cjose_err * err)504 static inline uint8_t _ec_size_for_curve(cjose_jwk_ec_curve crv, cjose_err *err)
505 {
506 switch (crv)
507 {
508 case CJOSE_JWK_EC_P_256:
509 return 32;
510 case CJOSE_JWK_EC_P_384:
511 return 48;
512 case CJOSE_JWK_EC_P_521:
513 return 66;
514 case CJOSE_JWK_EC_INVALID:
515 return 0;
516 }
517
518 return 0;
519 }
520
_ec_name_for_curve(cjose_jwk_ec_curve crv,cjose_err * err)521 static inline const char *_ec_name_for_curve(cjose_jwk_ec_curve crv, cjose_err *err)
522 {
523 switch (crv)
524 {
525 case CJOSE_JWK_EC_P_256:
526 return CJOSE_JWK_EC_P_256_STR;
527 case CJOSE_JWK_EC_P_384:
528 return CJOSE_JWK_EC_P_384_STR;
529 case CJOSE_JWK_EC_P_521:
530 return CJOSE_JWK_EC_P_521_STR;
531 case CJOSE_JWK_EC_INVALID:
532 return NULL;
533 }
534
535 return NULL;
536 }
537
_ec_curve_from_name(const char * name,cjose_jwk_ec_curve * crv,cjose_err * err)538 static inline bool _ec_curve_from_name(const char *name, cjose_jwk_ec_curve *crv, cjose_err *err)
539 {
540 bool retval = true;
541 if (strncmp(name, CJOSE_JWK_EC_P_256_STR, sizeof(CJOSE_JWK_EC_P_256_STR)) == 0)
542 {
543 *crv = CJOSE_JWK_EC_P_256;
544 }
545 else if (strncmp(name, CJOSE_JWK_EC_P_384_STR, sizeof(CJOSE_JWK_EC_P_384_STR)) == 0)
546 {
547 *crv = CJOSE_JWK_EC_P_384;
548 }
549 else if (strncmp(name, CJOSE_JWK_EC_P_521_STR, sizeof(CJOSE_JWK_EC_P_521_STR)) == 0)
550 {
551 *crv = CJOSE_JWK_EC_P_521;
552 }
553 else
554 {
555 retval = false;
556 }
557 return retval;
558 }
559
_kty_from_name(const char * name,cjose_jwk_kty_t * kty,cjose_err * err)560 static inline bool _kty_from_name(const char *name, cjose_jwk_kty_t *kty, cjose_err *err)
561 {
562 bool retval = true;
563 if (strncmp(name, CJOSE_JWK_KTY_EC_STR, sizeof(CJOSE_JWK_KTY_EC_STR)) == 0)
564 {
565 *kty = CJOSE_JWK_KTY_EC;
566 }
567 else if (strncmp(name, CJOSE_JWK_KTY_RSA_STR, sizeof(CJOSE_JWK_KTY_RSA_STR)) == 0)
568 {
569 *kty = CJOSE_JWK_KTY_RSA;
570 }
571 else if (strncmp(name, CJOSE_JWK_KTY_OCT_STR, sizeof(CJOSE_JWK_KTY_OCT_STR)) == 0)
572 {
573 *kty = CJOSE_JWK_KTY_OCT;
574 }
575 else
576 {
577 retval = false;
578 }
579 return retval;
580 }
581
_EC_new(cjose_jwk_ec_curve crv,EC_KEY * ec,cjose_err * err)582 static cjose_jwk_t *_EC_new(cjose_jwk_ec_curve crv, EC_KEY *ec, cjose_err *err)
583 {
584 ec_keydata *keydata = cjose_get_alloc()(sizeof(ec_keydata));
585 if (!keydata)
586 {
587 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
588 return NULL;
589 }
590 keydata->crv = crv;
591 keydata->key = ec;
592
593 cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
594 if (!jwk)
595 {
596 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
597 cjose_get_dealloc()(keydata);
598 return NULL;
599 }
600 memset(jwk, 0, sizeof(cjose_jwk_t));
601 jwk->retained = 1;
602 jwk->kty = CJOSE_JWK_KTY_EC;
603 switch (crv)
604 {
605 case CJOSE_JWK_EC_P_256:
606 jwk->keysize = 256;
607 break;
608 case CJOSE_JWK_EC_P_384:
609 jwk->keysize = 384;
610 break;
611 case CJOSE_JWK_EC_P_521:
612 jwk->keysize = 521;
613 break;
614 case CJOSE_JWK_EC_INVALID:
615 // should never happen
616 jwk->keysize = 0;
617 break;
618 }
619 jwk->keydata = keydata;
620 jwk->fns = &EC_FNTABLE;
621
622 return jwk;
623 }
624
_EC_free(cjose_jwk_t * jwk)625 static void _EC_free(cjose_jwk_t *jwk)
626 {
627 ec_keydata *keydata = (ec_keydata *)jwk->keydata;
628 jwk->keydata = NULL;
629
630 if (keydata)
631 {
632 EC_KEY *ec = keydata->key;
633 keydata->key = NULL;
634 if (ec)
635 {
636 EC_KEY_free(ec);
637 }
638 cjose_get_dealloc()(keydata);
639 }
640 cjose_get_dealloc()(jwk);
641 }
642
_EC_public_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)643 static bool _EC_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
644 {
645 ec_keydata *keydata = (ec_keydata *)jwk->keydata;
646 const EC_GROUP *params = NULL;
647 const EC_POINT *pub = NULL;
648 BIGNUM *bnX = NULL, *bnY = NULL;
649 uint8_t *buffer = NULL;
650 char *b64u = NULL;
651 size_t len = 0, offset = 0;
652 json_t *field = NULL;
653 bool result = false;
654
655 // track expected binary data size
656 uint8_t numsize = _ec_size_for_curve(keydata->crv, err);
657
658 // output the curve
659 field = json_string(_ec_name_for_curve(keydata->crv, err));
660 if (!field)
661 {
662 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
663 goto _ec_to_string_cleanup;
664 }
665 json_object_set(json, "crv", field);
666 json_decref(field);
667 field = NULL;
668
669 // obtain the public key
670 pub = EC_KEY_get0_public_key(keydata->key);
671 params = EC_KEY_get0_group(keydata->key);
672 if (!pub || !params)
673 {
674 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
675 goto _ec_to_string_cleanup;
676 }
677
678 buffer = cjose_get_alloc()(numsize);
679 bnX = BN_new();
680 bnY = BN_new();
681 if (!buffer || !bnX || !bnY)
682 {
683 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
684 goto _ec_to_string_cleanup;
685 }
686 if (1 != EC_POINT_get_affine_coordinates_GFp(params, pub, bnX, bnY, NULL))
687 {
688 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
689 goto _ec_to_string_cleanup;
690 }
691
692 // output the x coordinate
693 offset = numsize - BN_num_bytes(bnX);
694 memset(buffer, 0, numsize);
695 BN_bn2bin(bnX, (buffer + offset));
696 if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
697 {
698 goto _ec_to_string_cleanup;
699 }
700 field = _cjose_json_stringn(b64u, len, err);
701 if (!field)
702 {
703 goto _ec_to_string_cleanup;
704 }
705 json_object_set(json, "x", field);
706 json_decref(field);
707 field = NULL;
708 cjose_get_dealloc()(b64u);
709 b64u = NULL;
710
711 // output the y coordinate
712 offset = numsize - BN_num_bytes(bnY);
713 memset(buffer, 0, numsize);
714 BN_bn2bin(bnY, (buffer + offset));
715 if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
716 {
717 goto _ec_to_string_cleanup;
718 }
719 field = _cjose_json_stringn(b64u, len, err);
720 if (!field)
721 {
722 goto _ec_to_string_cleanup;
723 }
724 json_object_set(json, "y", field);
725 json_decref(field);
726 field = NULL;
727 cjose_get_dealloc()(b64u);
728 b64u = NULL;
729
730 result = true;
731
732 _ec_to_string_cleanup:
733 if (field)
734 {
735 json_decref(field);
736 }
737 if (bnX)
738 {
739 BN_free(bnX);
740 }
741 if (bnY)
742 {
743 BN_free(bnY);
744 }
745 if (buffer)
746 {
747 cjose_get_dealloc()(buffer);
748 }
749 if (b64u)
750 {
751 cjose_get_dealloc()(b64u);
752 }
753
754 return result;
755 }
756
_EC_private_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)757 static bool _EC_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
758 {
759 ec_keydata *keydata = (ec_keydata *)jwk->keydata;
760 const BIGNUM *bnD = EC_KEY_get0_private_key(keydata->key);
761 uint8_t *buffer = NULL;
762 char *b64u = NULL;
763 size_t len = 0, offset = 0;
764 json_t *field = NULL;
765 bool result = false;
766
767 // track expected binary data size
768 uint8_t numsize = _ec_size_for_curve(keydata->crv, err);
769
770 // short circuit if 'd' is NULL or 0
771 if (!bnD || BN_is_zero(bnD))
772 {
773 return true;
774 }
775
776 buffer = cjose_get_alloc()(numsize);
777 if (!buffer)
778 {
779 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
780 goto _ec_to_string_cleanup;
781 }
782
783 offset = numsize - BN_num_bytes(bnD);
784 memset(buffer, 0, numsize);
785 BN_bn2bin(bnD, (buffer + offset));
786 if (!cjose_base64url_encode(buffer, numsize, &b64u, &len, err))
787 {
788 goto _ec_to_string_cleanup;
789 }
790 field = _cjose_json_stringn(b64u, len, err);
791 if (!field)
792 {
793 goto _ec_to_string_cleanup;
794 }
795 json_object_set(json, "d", field);
796 json_decref(field);
797 field = NULL;
798 cjose_get_dealloc()(b64u);
799 b64u = NULL;
800
801 result = true;
802
803 _ec_to_string_cleanup:
804 if (buffer)
805 {
806 cjose_get_dealloc()(buffer);
807 }
808
809 return result;
810 }
811
812 // interface functions -- Elliptic Curve
813
cjose_jwk_create_EC_random(cjose_jwk_ec_curve crv,cjose_err * err)814 cjose_jwk_t *cjose_jwk_create_EC_random(cjose_jwk_ec_curve crv, cjose_err *err)
815 {
816 cjose_jwk_t *jwk = NULL;
817 EC_KEY *ec = NULL;
818
819 ec = EC_KEY_new_by_curve_name(crv);
820 if (!ec)
821 {
822 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
823 goto create_EC_failed;
824 }
825
826 if (1 != EC_KEY_generate_key(ec))
827 {
828 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
829 goto create_EC_failed;
830 }
831
832 jwk = _EC_new(crv, ec, err);
833 if (!jwk)
834 {
835 goto create_EC_failed;
836 }
837
838 return jwk;
839
840 create_EC_failed:
841 if (jwk)
842 {
843 cjose_get_dealloc()(jwk);
844 jwk = NULL;
845 }
846 if (ec)
847 {
848 EC_KEY_free(ec);
849 ec = NULL;
850 }
851
852 return NULL;
853 }
854
cjose_jwk_create_EC_spec(const cjose_jwk_ec_keyspec * spec,cjose_err * err)855 cjose_jwk_t *cjose_jwk_create_EC_spec(const cjose_jwk_ec_keyspec *spec, cjose_err *err)
856 {
857 cjose_jwk_t *jwk = NULL;
858 EC_KEY *ec = NULL;
859 EC_GROUP *params = NULL;
860 EC_POINT *Q = NULL;
861 BIGNUM *bnD = NULL;
862 BIGNUM *bnX = NULL;
863 BIGNUM *bnY = NULL;
864
865 if (!spec)
866 {
867 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
868 return NULL;
869 }
870
871 bool hasPriv = (NULL != spec->d && 0 < spec->dlen);
872 bool hasPub = ((NULL != spec->x && 0 < spec->xlen) && (NULL != spec->y && 0 < spec->ylen));
873 if (!hasPriv && !hasPub)
874 {
875 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
876 return NULL;
877 }
878
879 ec = EC_KEY_new_by_curve_name(spec->crv);
880 if (NULL == ec)
881 {
882 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
883 goto create_EC_failed;
884 }
885
886 params = (EC_GROUP *)EC_KEY_get0_group(ec);
887 if (NULL == params)
888 {
889 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
890 goto create_EC_failed;
891 }
892
893 // convert d from octet string to BIGNUM
894 if (hasPriv)
895 {
896 bnD = BN_bin2bn(spec->d, spec->dlen, NULL);
897 if (NULL == bnD)
898 {
899 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
900 goto create_EC_failed;
901 }
902 if (1 != EC_KEY_set_private_key(ec, bnD))
903 {
904 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
905 goto create_EC_failed;
906 }
907
908 // calculate public key from private
909 Q = EC_POINT_new(params);
910 if (NULL == Q)
911 {
912 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
913 goto create_EC_failed;
914 }
915 if (1 != EC_POINT_mul(params, Q, bnD, NULL, NULL, NULL))
916 {
917 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
918 goto create_EC_failed;
919 }
920
921 // public key is set below
922 // ignore provided public key!
923 hasPub = false;
924 }
925 if (hasPub)
926 {
927 Q = EC_POINT_new(params);
928 if (NULL == Q)
929 {
930 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
931 goto create_EC_failed;
932 }
933
934 bnX = BN_bin2bn(spec->x, spec->xlen, NULL);
935 bnY = BN_bin2bn(spec->y, spec->ylen, NULL);
936 if (!bnX || !bnY)
937 {
938 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
939 goto create_EC_failed;
940 }
941
942 if (1 != EC_POINT_set_affine_coordinates_GFp(params, Q, bnX, bnY, NULL))
943 {
944 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
945 goto create_EC_failed;
946 }
947 }
948
949 // always set the public key
950 if (1 != EC_KEY_set_public_key(ec, Q))
951 {
952 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
953 goto create_EC_failed;
954 }
955
956 jwk = _EC_new(spec->crv, ec, err);
957 if (!jwk)
958 {
959 goto create_EC_failed;
960 }
961
962 // jump to cleanup
963 goto create_EC_cleanup;
964
965 create_EC_failed:
966 if (jwk)
967 {
968 cjose_get_dealloc()(jwk);
969 jwk = NULL;
970 }
971 if (ec)
972 {
973 EC_KEY_free(ec);
974 ec = NULL;
975 }
976
977 create_EC_cleanup:
978 if (Q)
979 {
980 EC_POINT_free(Q);
981 Q = NULL;
982 }
983 if (bnD)
984 {
985 BN_free(bnD);
986 bnD = NULL;
987 }
988 if (bnX)
989 {
990 BN_free(bnX);
991 bnX = NULL;
992 }
993 if (bnY)
994 {
995 BN_free(bnY);
996 bnY = NULL;
997 }
998
999 return jwk;
1000 }
1001
cjose_jwk_EC_get_curve(const cjose_jwk_t * jwk,cjose_err * err)1002 const cjose_jwk_ec_curve cjose_jwk_EC_get_curve(const cjose_jwk_t *jwk, cjose_err *err)
1003 {
1004 if (NULL == jwk || CJOSE_JWK_KTY_EC != cjose_jwk_get_kty(jwk, err))
1005 {
1006 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1007 return CJOSE_JWK_EC_INVALID;
1008 }
1009
1010 ec_keydata *keydata = jwk->keydata;
1011 return keydata->crv;
1012 }
1013
1014 //////////////// RSA ////////////////
1015 // internal data & functions -- RSA
1016
1017 static void _RSA_free(cjose_jwk_t *jwk);
1018 static bool _RSA_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1019 static bool _RSA_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err);
1020
1021 static const key_fntable RSA_FNTABLE = { _RSA_free, _RSA_public_fields, _RSA_private_fields };
1022
_RSA_new(RSA * rsa,cjose_err * err)1023 static inline cjose_jwk_t *_RSA_new(RSA *rsa, cjose_err *err)
1024 {
1025 cjose_jwk_t *jwk = cjose_get_alloc()(sizeof(cjose_jwk_t));
1026 if (!jwk)
1027 {
1028 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1029 return NULL;
1030 }
1031 memset(jwk, 0, sizeof(cjose_jwk_t));
1032 jwk->retained = 1;
1033 jwk->kty = CJOSE_JWK_KTY_RSA;
1034 jwk->keysize = RSA_size(rsa) * 8;
1035 jwk->keydata = rsa;
1036 jwk->fns = &RSA_FNTABLE;
1037
1038 return jwk;
1039 }
1040
_RSA_free(cjose_jwk_t * jwk)1041 static void _RSA_free(cjose_jwk_t *jwk)
1042 {
1043 RSA *rsa = (RSA *)jwk->keydata;
1044 jwk->keydata = NULL;
1045 if (rsa)
1046 {
1047 RSA_free(rsa);
1048 }
1049 cjose_get_dealloc()(jwk);
1050 }
1051
_RSA_json_field(BIGNUM * param,const char * name,json_t * json,cjose_err * err)1052 static inline bool _RSA_json_field(BIGNUM *param, const char *name, json_t *json, cjose_err *err)
1053 {
1054 json_t *field = NULL;
1055 uint8_t *data = NULL;
1056 char *b64u = NULL;
1057 size_t datalen = 0, b64ulen = 0;
1058 bool result = false;
1059
1060 if (!param)
1061 {
1062 return true;
1063 }
1064
1065 datalen = BN_num_bytes(param);
1066 data = cjose_get_alloc()(sizeof(uint8_t) * datalen);
1067 if (!data)
1068 {
1069 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1070 goto RSA_json_field_cleanup;
1071 }
1072 BN_bn2bin(param, data);
1073 if (!cjose_base64url_encode(data, datalen, &b64u, &b64ulen, err))
1074 {
1075 goto RSA_json_field_cleanup;
1076 }
1077 field = _cjose_json_stringn(b64u, b64ulen, err);
1078 if (!field)
1079 {
1080 goto RSA_json_field_cleanup;
1081 }
1082 json_object_set(json, name, field);
1083 json_decref(field);
1084 field = NULL;
1085 result = true;
1086
1087 RSA_json_field_cleanup:
1088 if (b64u)
1089 {
1090 cjose_get_dealloc()(b64u);
1091 b64u = NULL;
1092 }
1093 if (data)
1094 {
1095 cjose_get_dealloc()(data);
1096 data = NULL;
1097 }
1098
1099 return result;
1100 }
1101
_RSA_public_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)1102 static bool _RSA_public_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1103 {
1104 RSA *rsa = (RSA *)jwk->keydata;
1105
1106 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
1107 _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d);
1108
1109 if (!_RSA_json_field(rsa_e, "e", json, err))
1110 {
1111 return false;
1112 }
1113 if (!_RSA_json_field(rsa_n, "n", json, err))
1114 {
1115 return false;
1116 }
1117
1118 return true;
1119 }
1120
_RSA_private_fields(const cjose_jwk_t * jwk,json_t * json,cjose_err * err)1121 static bool _RSA_private_fields(const cjose_jwk_t *jwk, json_t *json, cjose_err *err)
1122 {
1123 RSA *rsa = (RSA *)jwk->keydata;
1124
1125 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
1126 _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d);
1127
1128 BIGNUM *rsa_p = NULL, *rsa_q;
1129 _cjose_jwk_rsa_get_factors(rsa, &rsa_p, &rsa_q);
1130
1131 BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL, *rsa_iqmp = NULL;
1132 _cjose_jwk_rsa_get_crt(rsa, &rsa_dmp1, &rsa_dmq1, &rsa_iqmp);
1133
1134 if (!_RSA_json_field(rsa_d, "d", json, err))
1135 {
1136 return false;
1137 }
1138 if (!_RSA_json_field(rsa_p, "p", json, err))
1139 {
1140 return false;
1141 }
1142 if (!_RSA_json_field(rsa_q, "q", json, err))
1143 {
1144 return false;
1145 }
1146 if (!_RSA_json_field(rsa_dmp1, "dp", json, err))
1147 {
1148 return false;
1149 }
1150 if (!_RSA_json_field(rsa_dmq1, "dq", json, err))
1151 {
1152 return false;
1153 }
1154 if (!_RSA_json_field(rsa_iqmp, "qi", json, err))
1155 {
1156 return false;
1157 }
1158
1159 return true;
1160 }
1161
1162 // interface functions -- RSA
1163 static const uint8_t *DEFAULT_E_DAT = (const uint8_t *)"\x01\x00\x01";
1164 static const size_t DEFAULT_E_LEN = 3;
1165
cjose_jwk_create_RSA_random(size_t keysize,const uint8_t * e,size_t elen,cjose_err * err)1166 cjose_jwk_t *cjose_jwk_create_RSA_random(size_t keysize, const uint8_t *e, size_t elen, cjose_err *err)
1167 {
1168 if (0 == keysize)
1169 {
1170 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1171 return NULL;
1172 }
1173 if (NULL == e || 0 >= elen)
1174 {
1175 e = DEFAULT_E_DAT;
1176 elen = DEFAULT_E_LEN;
1177 }
1178
1179 RSA *rsa = NULL;
1180 BIGNUM *bn = NULL;
1181
1182 rsa = RSA_new();
1183 if (!rsa)
1184 {
1185 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1186 goto create_RSA_random_failed;
1187 }
1188
1189 bn = BN_bin2bn(e, elen, NULL);
1190 if (!bn)
1191 {
1192 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1193 goto create_RSA_random_failed;
1194 }
1195
1196 if (0 == RSA_generate_key_ex(rsa, keysize, bn, NULL))
1197 {
1198 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1199 goto create_RSA_random_failed;
1200 }
1201
1202 BN_free(bn);
1203 return _RSA_new(rsa, err);
1204
1205 create_RSA_random_failed:
1206 if (bn)
1207 {
1208 BN_free(bn);
1209 }
1210 if (rsa)
1211 {
1212 RSA_free(rsa);
1213 }
1214 return NULL;
1215 }
1216
cjose_jwk_create_RSA_spec(const cjose_jwk_rsa_keyspec * spec,cjose_err * err)1217 cjose_jwk_t *cjose_jwk_create_RSA_spec(const cjose_jwk_rsa_keyspec *spec, cjose_err *err)
1218 {
1219 if (NULL == spec)
1220 {
1221 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1222 return NULL;
1223 }
1224
1225 bool hasPub = (NULL != spec->n && 0 < spec->nlen) && (NULL != spec->e && 0 < spec->elen);
1226 bool hasPriv = (NULL != spec->n && 0 < spec->nlen) && (NULL != spec->d && 0 < spec->dlen);
1227 if (!hasPub && !hasPriv)
1228 {
1229 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1230 return NULL;
1231 }
1232
1233 RSA *rsa = NULL;
1234 rsa = RSA_new();
1235 if (!rsa)
1236 {
1237 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1238 return NULL;
1239 }
1240
1241 if (hasPriv)
1242 {
1243 if (!_cjose_jwk_rsa_set(rsa, spec->n, spec->nlen, spec->e, spec->elen, spec->d, spec->dlen))
1244 {
1245 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1246 goto create_RSA_spec_failed;
1247 }
1248 _cjose_jwk_rsa_set_factors(rsa, spec->p, spec->plen, spec->q, spec->qlen);
1249 _cjose_jwk_rsa_set_crt(rsa, spec->dp, spec->dplen, spec->dq, spec->dqlen, spec->qi, spec->qilen);
1250 }
1251 else if (hasPub)
1252 {
1253 if (!_cjose_jwk_rsa_set(rsa, spec->n, spec->nlen, spec->e, spec->elen, NULL, 0))
1254 {
1255 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1256 goto create_RSA_spec_failed;
1257 }
1258 }
1259
1260 return _RSA_new(rsa, err);
1261
1262 create_RSA_spec_failed:
1263 if (rsa)
1264 {
1265 RSA_free(rsa);
1266 }
1267
1268 return NULL;
1269 }
1270
1271 //////////////// Import ////////////////
1272 // internal data & functions -- JWK key import
1273
_get_json_object_string_attribute(json_t * json,const char * key,cjose_err * err)1274 static const char *_get_json_object_string_attribute(json_t *json, const char *key, cjose_err *err)
1275 {
1276 const char *attr_str = NULL;
1277 json_t *attr_json = json_object_get(json, key);
1278 if (NULL != attr_json)
1279 {
1280 attr_str = json_string_value(attr_json);
1281 }
1282 return attr_str;
1283 }
1284
1285 /**
1286 * Internal helper function for extracing an octet string from a base64url
1287 * encoded field. Caller provides the json object, the attribute key,
1288 * and an expected length for the octet string. On successful decoding,
1289 * this will return a newly allocated buffer with the decoded octet string
1290 * of the expected length.
1291 *
1292 * Note: caller is responsible for freeing the buffer returned by this function.
1293 *
1294 * \param[in] json the JSON object from which to read the attribute.
1295 * \param[in] key the name of the attribute to be decoded.
1296 * \param[out] pointer to buffer of octet string (if decoding succeeds).
1297 * \param[in/out] in as the expected length of the attribute, out as the
1298 * actual decoded length. Note, this method succeeds only
1299 * if the actual decoded length matches the expected length.
1300 * If the in-value is 0 this indicates there is no particular
1301 * expected length (i.e. any length is ok).
1302 * \returns true if attribute is either not present or successfully decoded.
1303 * false otherwise.
1304 */
1305 static bool
_decode_json_object_base64url_attribute(json_t * jwk_json,const char * key,uint8_t ** buffer,size_t * buflen,cjose_err * err)1306 _decode_json_object_base64url_attribute(json_t *jwk_json, const char *key, uint8_t **buffer, size_t *buflen, cjose_err *err)
1307 {
1308 // get the base64url encoded string value of the attribute (if any)
1309 const char *str = _get_json_object_string_attribute(jwk_json, key, err);
1310 if (str == NULL || strlen(str) == 0)
1311 {
1312 *buflen = 0;
1313 *buffer = NULL;
1314 return true;
1315 }
1316
1317 // if a particular decoded length is expected, check for that
1318 if (*buflen != 0)
1319 {
1320 const char *end = NULL;
1321 for (end = str + strlen(str) - 1; *end == '=' && end > str; --end)
1322 ;
1323 size_t unpadded_len = end + 1 - str - ((*end == '=') ? 1 : 0);
1324 size_t expected_len = ceil(4 * ((float)*buflen / 3));
1325
1326 if (expected_len != unpadded_len)
1327 {
1328 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1329 *buflen = 0;
1330 *buffer = NULL;
1331 return false;
1332 }
1333 }
1334
1335 // decode the base64url encoded string to the allocated buffer
1336 if (!cjose_base64url_decode(str, strlen(str), buffer, buflen, err))
1337 {
1338 *buflen = 0;
1339 *buffer = NULL;
1340 return false;
1341 }
1342
1343 return true;
1344 }
1345
_cjose_jwk_import_EC(json_t * jwk_json,cjose_err * err)1346 static cjose_jwk_t *_cjose_jwk_import_EC(json_t *jwk_json, cjose_err *err)
1347 {
1348 cjose_jwk_t *jwk = NULL;
1349 uint8_t *x_buffer = NULL;
1350 uint8_t *y_buffer = NULL;
1351 uint8_t *d_buffer = NULL;
1352
1353 // get the value of the crv attribute
1354 const char *crv_str = _get_json_object_string_attribute(jwk_json, CJOSE_JWK_CRV_STR, err);
1355 if (crv_str == NULL)
1356 {
1357 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1358 goto import_EC_cleanup;
1359 }
1360
1361 // get the curve identifer for the curve named by crv
1362 cjose_jwk_ec_curve crv;
1363 if (!_ec_curve_from_name(crv_str, &crv, err))
1364 {
1365 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1366 goto import_EC_cleanup;
1367 }
1368
1369 // get the decoded value of the x coordinate
1370 size_t x_buflen = (size_t)_ec_size_for_curve(crv, err);
1371 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_X_STR, &x_buffer, &x_buflen, err))
1372 {
1373 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1374 goto import_EC_cleanup;
1375 }
1376
1377 // get the decoded value of the y coordinate
1378 size_t y_buflen = (size_t)_ec_size_for_curve(crv, err);
1379 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_Y_STR, &y_buffer, &y_buflen, err))
1380 {
1381 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1382 goto import_EC_cleanup;
1383 }
1384
1385 // get the decoded value of the private key d
1386 size_t d_buflen = (size_t)_ec_size_for_curve(crv, err);
1387 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err))
1388 {
1389 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1390 goto import_EC_cleanup;
1391 }
1392
1393 // create an ec keyspec
1394 cjose_jwk_ec_keyspec ec_keyspec;
1395 memset(&ec_keyspec, 0, sizeof(cjose_jwk_ec_keyspec));
1396 ec_keyspec.crv = crv;
1397 ec_keyspec.x = x_buffer;
1398 ec_keyspec.xlen = x_buflen;
1399 ec_keyspec.y = y_buffer;
1400 ec_keyspec.ylen = y_buflen;
1401 ec_keyspec.d = d_buffer;
1402 ec_keyspec.dlen = d_buflen;
1403
1404 // create the jwk
1405 jwk = cjose_jwk_create_EC_spec(&ec_keyspec, err);
1406
1407 import_EC_cleanup:
1408 if (NULL != x_buffer)
1409 {
1410 cjose_get_dealloc()(x_buffer);
1411 }
1412 if (NULL != y_buffer)
1413 {
1414 cjose_get_dealloc()(y_buffer);
1415 }
1416 if (NULL != d_buffer)
1417 {
1418 cjose_get_dealloc()(d_buffer);
1419 }
1420
1421 return jwk;
1422 }
1423
_cjose_jwk_import_RSA(json_t * jwk_json,cjose_err * err)1424 static cjose_jwk_t *_cjose_jwk_import_RSA(json_t *jwk_json, cjose_err *err)
1425 {
1426 cjose_jwk_t *jwk = NULL;
1427 uint8_t *n_buffer = NULL;
1428 uint8_t *e_buffer = NULL;
1429 uint8_t *d_buffer = NULL;
1430 uint8_t *p_buffer = NULL;
1431 uint8_t *q_buffer = NULL;
1432 uint8_t *dp_buffer = NULL;
1433 uint8_t *dq_buffer = NULL;
1434 uint8_t *qi_buffer = NULL;
1435
1436 // get the decoded value of n (buflen = 0 means no particular expected len)
1437 size_t n_buflen = 0;
1438 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_N_STR, &n_buffer, &n_buflen, err))
1439 {
1440 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1441 goto import_RSA_cleanup;
1442 }
1443
1444 // get the decoded value of e
1445 size_t e_buflen = 0;
1446 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_E_STR, &e_buffer, &e_buflen, err))
1447 {
1448 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1449 goto import_RSA_cleanup;
1450 }
1451
1452 // get the decoded value of d
1453 size_t d_buflen = 0;
1454 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_D_STR, &d_buffer, &d_buflen, err))
1455 {
1456 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1457 goto import_RSA_cleanup;
1458 }
1459
1460 // get the decoded value of p
1461 size_t p_buflen = 0;
1462 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_P_STR, &p_buffer, &p_buflen, err))
1463 {
1464 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1465 goto import_RSA_cleanup;
1466 }
1467
1468 // get the decoded value of q
1469 size_t q_buflen = 0;
1470 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_Q_STR, &q_buffer, &q_buflen, err))
1471 {
1472 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1473 goto import_RSA_cleanup;
1474 }
1475
1476 // get the decoded value of dp
1477 size_t dp_buflen = 0;
1478 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_DP_STR, &dp_buffer, &dp_buflen, err))
1479 {
1480 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1481 goto import_RSA_cleanup;
1482 }
1483
1484 // get the decoded value of dq
1485 size_t dq_buflen = 0;
1486 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_DQ_STR, &dq_buffer, &dq_buflen, err))
1487 {
1488 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1489 goto import_RSA_cleanup;
1490 }
1491
1492 // get the decoded value of qi
1493 size_t qi_buflen = 0;
1494 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_QI_STR, &qi_buffer, &qi_buflen, err))
1495 {
1496 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1497 goto import_RSA_cleanup;
1498 }
1499
1500 // create an rsa keyspec
1501 cjose_jwk_rsa_keyspec rsa_keyspec;
1502 memset(&rsa_keyspec, 0, sizeof(cjose_jwk_rsa_keyspec));
1503 rsa_keyspec.n = n_buffer;
1504 rsa_keyspec.nlen = n_buflen;
1505 rsa_keyspec.e = e_buffer;
1506 rsa_keyspec.elen = e_buflen;
1507 rsa_keyspec.d = d_buffer;
1508 rsa_keyspec.dlen = d_buflen;
1509 rsa_keyspec.p = p_buffer;
1510 rsa_keyspec.plen = p_buflen;
1511 rsa_keyspec.q = q_buffer;
1512 rsa_keyspec.qlen = q_buflen;
1513 rsa_keyspec.dp = dp_buffer;
1514 rsa_keyspec.dplen = dp_buflen;
1515 rsa_keyspec.dq = dq_buffer;
1516 rsa_keyspec.dqlen = dq_buflen;
1517 rsa_keyspec.qi = qi_buffer;
1518 rsa_keyspec.qilen = qi_buflen;
1519
1520 // create the jwk
1521 jwk = cjose_jwk_create_RSA_spec(&rsa_keyspec, err);
1522
1523 import_RSA_cleanup:
1524 cjose_get_dealloc()(n_buffer);
1525 cjose_get_dealloc()(e_buffer);
1526 cjose_get_dealloc()(d_buffer);
1527 cjose_get_dealloc()(p_buffer);
1528 cjose_get_dealloc()(q_buffer);
1529 cjose_get_dealloc()(dp_buffer);
1530 cjose_get_dealloc()(dq_buffer);
1531 cjose_get_dealloc()(qi_buffer);
1532
1533 return jwk;
1534 }
1535
_cjose_jwk_import_oct(json_t * jwk_json,cjose_err * err)1536 static cjose_jwk_t *_cjose_jwk_import_oct(json_t *jwk_json, cjose_err *err)
1537 {
1538 cjose_jwk_t *jwk = NULL;
1539 uint8_t *k_buffer = NULL;
1540
1541 // get the decoded value of k (buflen = 0 means no particular expected len)
1542 size_t k_buflen = 0;
1543 if (!_decode_json_object_base64url_attribute(jwk_json, CJOSE_JWK_K_STR, &k_buffer, &k_buflen, err))
1544 {
1545 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1546 goto import_oct_cleanup;
1547 }
1548
1549 // create the jwk
1550 jwk = cjose_jwk_create_oct_spec(k_buffer, k_buflen, err);
1551
1552 import_oct_cleanup:
1553 if (NULL != k_buffer)
1554 {
1555 cjose_get_dealloc()(k_buffer);
1556 }
1557
1558 return jwk;
1559 }
1560
cjose_jwk_import(const char * jwk_str,size_t len,cjose_err * err)1561 cjose_jwk_t *cjose_jwk_import(const char *jwk_str, size_t len, cjose_err *err)
1562 {
1563 cjose_jwk_t *jwk = NULL;
1564
1565 // check params
1566 if ((NULL == jwk_str) || (0 == len))
1567 {
1568 return NULL;
1569 }
1570
1571 // parse json content from the given string
1572 json_t *jwk_json = json_loadb(jwk_str, len, 0, NULL);
1573 if (NULL == jwk_json)
1574 {
1575 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1576 goto import_cleanup;
1577 }
1578
1579 jwk = cjose_jwk_import_json((cjose_header_t *)jwk_json, err);
1580
1581 // poor man's "finally"
1582 import_cleanup:
1583 if (NULL != jwk_json)
1584 {
1585 json_decref(jwk_json);
1586 }
1587
1588 return jwk;
1589 }
1590
cjose_jwk_import_json(cjose_header_t * json,cjose_err * err)1591 cjose_jwk_t *cjose_jwk_import_json(cjose_header_t *json, cjose_err *err)
1592 {
1593 cjose_jwk_t *jwk = NULL;
1594
1595 json_t *jwk_json = (json_t *)json;
1596
1597 if (NULL == jwk_json || JSON_OBJECT != json_typeof(jwk_json))
1598 {
1599 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1600 return NULL;
1601 }
1602
1603 // get the string value of the kty attribute of the jwk
1604 const char *kty_str = _get_json_object_string_attribute(jwk_json, CJOSE_JWK_KTY_STR, err);
1605 if (NULL == kty_str)
1606 {
1607 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1608 return NULL;
1609 }
1610
1611 // get kty corresponding to kty_str (kty is required)
1612 cjose_jwk_kty_t kty;
1613 if (!_kty_from_name(kty_str, &kty, err))
1614 {
1615 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1616 return NULL;
1617 }
1618
1619 // create a cjose_jwt_t based on the kty
1620 switch (kty)
1621 {
1622 case CJOSE_JWK_KTY_EC:
1623 jwk = _cjose_jwk_import_EC(jwk_json, err);
1624 break;
1625
1626 case CJOSE_JWK_KTY_RSA:
1627 jwk = _cjose_jwk_import_RSA(jwk_json, err);
1628 break;
1629
1630 case CJOSE_JWK_KTY_OCT:
1631 jwk = _cjose_jwk_import_oct(jwk_json, err);
1632 break;
1633
1634 default:
1635 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1636 return NULL;
1637 }
1638 if (NULL == jwk)
1639 {
1640 // helper function will have already set err
1641 return NULL;
1642 }
1643
1644 // get the value of the kid attribute (kid is optional)
1645 const char *kid_str = _get_json_object_string_attribute(jwk_json, CJOSE_JWK_KID_STR, err);
1646 if (kid_str != NULL)
1647 {
1648 jwk->kid = _cjose_strndup(kid_str, -1, err);
1649 if (!jwk->kid)
1650 {
1651 cjose_jwk_release(jwk);
1652 return NULL;
1653 }
1654 }
1655
1656 return jwk;
1657 }
1658
1659 //////////////// ECDH ////////////////
1660 // internal data & functions -- ECDH derivation
1661
_cjose_jwk_evp_key_from_ec_key(const cjose_jwk_t * jwk,EVP_PKEY ** key,cjose_err * err)1662 static bool _cjose_jwk_evp_key_from_ec_key(const cjose_jwk_t *jwk, EVP_PKEY **key, cjose_err *err)
1663 {
1664 // validate that the jwk is of type EC and we have a valid out-param
1665 if (NULL == jwk || CJOSE_JWK_KTY_EC != jwk->kty || NULL == jwk->keydata || NULL == key || NULL != *key)
1666 {
1667 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1668 goto _cjose_jwk_evp_key_from_ec_key_fail;
1669 }
1670
1671 // create a blank EVP_PKEY
1672 *key = EVP_PKEY_new();
1673 if (NULL == key)
1674 {
1675 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1676 goto _cjose_jwk_evp_key_from_ec_key_fail;
1677 }
1678
1679 // assign the EVP_PKEY to reference the jwk's internal EC_KEY structure
1680 if (1 != EVP_PKEY_set1_EC_KEY(*key, ((struct _ec_keydata_int *)(jwk->keydata))->key))
1681 {
1682 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1683 goto _cjose_jwk_evp_key_from_ec_key_fail;
1684 }
1685
1686 // happy path
1687 return true;
1688
1689 // fail path
1690 _cjose_jwk_evp_key_from_ec_key_fail:
1691
1692 EVP_PKEY_free(*key);
1693 *key = NULL;
1694
1695 return false;
1696 }
1697
cjose_jwk_derive_ecdh_secret(const cjose_jwk_t * jwk_self,const cjose_jwk_t * jwk_peer,cjose_err * err)1698 cjose_jwk_t *cjose_jwk_derive_ecdh_secret(const cjose_jwk_t *jwk_self, const cjose_jwk_t *jwk_peer, cjose_err *err)
1699 {
1700 return cjose_jwk_derive_ecdh_ephemeral_key(jwk_self, jwk_peer, err);
1701 }
1702
cjose_jwk_derive_ecdh_ephemeral_key(const cjose_jwk_t * jwk_self,const cjose_jwk_t * jwk_peer,cjose_err * err)1703 cjose_jwk_t *cjose_jwk_derive_ecdh_ephemeral_key(const cjose_jwk_t *jwk_self, const cjose_jwk_t *jwk_peer, cjose_err *err)
1704 {
1705 uint8_t *secret = NULL;
1706 size_t secret_len = 0;
1707 uint8_t *ephemeral_key = NULL;
1708 size_t ephemeral_key_len = 0;
1709 cjose_jwk_t *jwk_ephemeral_key = NULL;
1710
1711 if (!cjose_jwk_derive_ecdh_bits(jwk_self, jwk_peer, &secret, &secret_len, err))
1712 {
1713 goto _cjose_jwk_derive_shared_secret_fail;
1714 }
1715
1716 // HKDF of the DH shared secret (SHA256, no salt, no info, 256 bit expand)
1717 ephemeral_key_len = 32;
1718 ephemeral_key = (uint8_t *)cjose_get_alloc()(ephemeral_key_len);
1719 if (!cjose_jwk_hkdf(EVP_sha256(), (uint8_t *)"", 0, (uint8_t *)"", 0, secret, secret_len, ephemeral_key, ephemeral_key_len,
1720 err))
1721 {
1722 goto _cjose_jwk_derive_shared_secret_fail;
1723 }
1724
1725 // create a JWK of the shared secret
1726 jwk_ephemeral_key = cjose_jwk_create_oct_spec(ephemeral_key, ephemeral_key_len, err);
1727 if (NULL == jwk_ephemeral_key)
1728 {
1729 goto _cjose_jwk_derive_shared_secret_fail;
1730 }
1731
1732 // happy path
1733 cjose_get_dealloc()(secret);
1734 cjose_get_dealloc()(ephemeral_key);
1735
1736 return jwk_ephemeral_key;
1737
1738 // fail path
1739 _cjose_jwk_derive_shared_secret_fail:
1740
1741 if (NULL != jwk_ephemeral_key)
1742 {
1743 cjose_jwk_release(jwk_ephemeral_key);
1744 }
1745 cjose_get_dealloc()(secret);
1746 cjose_get_dealloc()(ephemeral_key);
1747 return NULL;
1748 }
1749
cjose_jwk_derive_ecdh_bits(const cjose_jwk_t * jwk_self,const cjose_jwk_t * jwk_peer,uint8_t ** output,size_t * output_len,cjose_err * err)1750 bool cjose_jwk_derive_ecdh_bits(const cjose_jwk_t *jwk_self,
1751 const cjose_jwk_t *jwk_peer,
1752 uint8_t **output,
1753 size_t *output_len,
1754 cjose_err *err)
1755 {
1756 EVP_PKEY_CTX *ctx = NULL;
1757 EVP_PKEY *pkey_self = NULL;
1758 EVP_PKEY *pkey_peer = NULL;
1759 uint8_t *secret = NULL;
1760 size_t secret_len = 0;
1761
1762 // get EVP_KEY from jwk_self
1763 if (!_cjose_jwk_evp_key_from_ec_key(jwk_self, &pkey_self, err))
1764 {
1765 goto _cjose_jwk_derive_bits_fail;
1766 }
1767
1768 // get EVP_KEY from jwk_peer
1769 if (!_cjose_jwk_evp_key_from_ec_key(jwk_peer, &pkey_peer, err))
1770 {
1771 goto _cjose_jwk_derive_bits_fail;
1772 }
1773
1774 // create derivation context based on local key pair
1775 ctx = EVP_PKEY_CTX_new(pkey_self, NULL);
1776 if (NULL == ctx)
1777 {
1778 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1779 goto _cjose_jwk_derive_bits_fail;
1780 }
1781
1782 // initialize derivation context
1783 if (1 != EVP_PKEY_derive_init(ctx))
1784 {
1785 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1786 goto _cjose_jwk_derive_bits_fail;
1787 }
1788
1789 // provide the peer public key
1790 if (1 != EVP_PKEY_derive_set_peer(ctx, pkey_peer))
1791 {
1792 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1793 goto _cjose_jwk_derive_bits_fail;
1794 }
1795
1796 // determine buffer length for shared secret
1797 if (1 != EVP_PKEY_derive(ctx, NULL, &secret_len))
1798 {
1799 CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
1800 goto _cjose_jwk_derive_bits_fail;
1801 }
1802
1803 // allocate buffer for shared secret
1804 secret = (uint8_t *)cjose_get_alloc()(secret_len);
1805 if (NULL == output)
1806 {
1807 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1808 goto _cjose_jwk_derive_bits_fail;
1809 }
1810 memset(secret, 0, secret_len);
1811
1812 // derive the shared secret
1813 if (1 != (EVP_PKEY_derive(ctx, secret, &secret_len)))
1814 {
1815 CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY);
1816 goto _cjose_jwk_derive_bits_fail;
1817 }
1818
1819 // happy path
1820 EVP_PKEY_CTX_free(ctx);
1821 EVP_PKEY_free(pkey_self);
1822 EVP_PKEY_free(pkey_peer);
1823
1824 *output = secret;
1825 *output_len = secret_len;
1826 return true;
1827
1828 _cjose_jwk_derive_bits_fail:
1829
1830 if (NULL != ctx)
1831 {
1832 EVP_PKEY_CTX_free(ctx);
1833 }
1834 if (NULL != pkey_self)
1835 {
1836 EVP_PKEY_free(pkey_self);
1837 }
1838 if (NULL != pkey_peer)
1839 {
1840 EVP_PKEY_free(pkey_peer);
1841 }
1842 cjose_get_dealloc()(secret);
1843
1844 return false;
1845 }
1846
cjose_jwk_hkdf(const EVP_MD * md,const uint8_t * salt,size_t salt_len,const uint8_t * info,size_t info_len,const uint8_t * ikm,size_t ikm_len,uint8_t * okm,unsigned int okm_len,cjose_err * err)1847 bool cjose_jwk_hkdf(const EVP_MD *md,
1848 const uint8_t *salt,
1849 size_t salt_len,
1850 const uint8_t *info,
1851 size_t info_len,
1852 const uint8_t *ikm,
1853 size_t ikm_len,
1854 uint8_t *okm,
1855 unsigned int okm_len,
1856 cjose_err *err)
1857 {
1858 // current impl. is very limited: SHA256, 256 bit output, and no info
1859 if ((EVP_sha256() != md) || (0 != info_len) || (32 != okm_len))
1860 {
1861 CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
1862 return false;
1863 }
1864
1865 // HKDF-Extract, HMAC-SHA256(salt, IKM) -> PRK
1866 unsigned int prk_len;
1867 unsigned char prk[EVP_MAX_MD_SIZE];
1868 HMAC(md, salt, salt_len, ikm, ikm_len, prk, &prk_len);
1869
1870 // HKDF-Expand, HMAC-SHA256(PRK,0x01) -> OKM
1871 const unsigned char t[] = { 0x01 };
1872 HMAC(md, prk, prk_len, t, sizeof(t), okm, NULL);
1873
1874 return true;
1875 }
1876