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