1 /*!
2  *
3  */
4 
5 #include "check_cjose.h"
6 
7 #include <stdlib.h>
8 #include <openssl/evp.h>
9 #include <jansson.h>
10 #include <check.h>
11 #include <cjose/jwk.h>
12 #include <cjose/base64.h>
13 #include <cjose/util.h>
14 #include "include/jwk_int.h"
15 
16 /**
17  * Convenience function for comparing multiple string attributes of two
18  * json objects.
19  *
20  * \param left_json a json object to be compared.
21  * \param right_json a json object to be compared.
22  * \param null terminated array of attribute names.
23  * \returns true if string values of all named attributes are identical in both
24  *         json objects or are both missing from each, false otherwise.
25  */
_match_string_attrs(json_t * left_json,json_t * right_json,const char ** attrs)26 static bool _match_string_attrs(json_t *left_json, json_t *right_json, const char **attrs)
27 {
28     for (int i = 0; NULL != attrs[i]; ++i)
29     {
30         const char *left_attr_str = NULL;
31         json_t *left_attr_json = NULL;
32         left_attr_json = json_object_get(left_json, attrs[i]);
33         if (NULL != left_attr_json)
34         {
35             left_attr_str = json_string_value(left_attr_json);
36         }
37 
38         const char *right_attr_str = NULL;
39         json_t *right_attr_json = json_object_get(right_json, attrs[i]);
40         if (NULL != right_attr_json)
41         {
42             right_attr_str = json_string_value(right_attr_json);
43         }
44 
45         // return false if strings don't match (consider NULL==NULL a match)
46         if ((left_attr_str != right_attr_str)
47             && (left_attr_str == NULL || right_attr_str == NULL || strcmp(left_attr_str, right_attr_str) != 0))
48         {
49             return false;
50         }
51     }
52     return true;
53 }
54 
START_TEST(test_cjose_jwk_name_for_kty)55 START_TEST(test_cjose_jwk_name_for_kty)
56 {
57     cjose_err err;
58     ck_assert_str_eq("RSA", cjose_jwk_name_for_kty(CJOSE_JWK_KTY_RSA, &err));
59     ck_assert_str_eq("EC", cjose_jwk_name_for_kty(CJOSE_JWK_KTY_EC, &err));
60     ck_assert_str_eq("oct", cjose_jwk_name_for_kty(CJOSE_JWK_KTY_OCT, &err));
61     ck_assert(NULL == cjose_jwk_name_for_kty(0, &err));
62     ck_assert(NULL == cjose_jwk_name_for_kty(99, &err));
63 }
64 END_TEST
65 
66 const char *RSA_e = "AQAB";
67 const char *RSA_n = "2Rgbvu_cGMpvVl8DE6aGGX7IE2lKn5c9ZtexriFrCLqBbKt2TBOZkoCn_AbcDjUVk23CxsIj9Z1VfsL_0UeVA_AeOLUWw0F5-"
68                     "JhoK6NBeLpYZOz7HYieTOSJjSxYhoCYtVbLKI27e3NEvckxTs-90CdKl71P7YwrdSrY59hR-u2etyNCRGAPcoDH5xYJxrG2p5FH_Dh_"
69                     "MQ0ugDnJY2_b_-w9NS2Y2atIkzXZDjtcSpjImKpL0eIFF69ptiF8vd4q2j-"
70                     "ougipFBGP9U5bSVzeZ7FyGkJ5Qa2DYc0osYi1QFs3YZKzkKfcblx14u-yZYhUkZHlb_jbfulnUHxDdO_r8Q";
71 const char *RSA_d = "P9N6tNRIXXGG8lnUyb43xt8ja7GVIv6QKuBXeN6SXWqYCp8OlKdei1gQC2To5bRtt36ZuV3yvI-ZRz-"
72                     "Ffr4Q7at29y0mmBl0BsaoOcwxv5Dp1CJoYfJ8uBao6jyTelfsjcQKzs18xXrKRxIT0Rv6rmwe3iXmjeycCkKiqudKkv8m9RtbvdWH8AFd2ZsCL"
73                     "NblVRrOZ9ZPQQCMVJLf65pF_cBfux-Zz_CJCfq93gFcN3h1tPFLX8UPBMqvqkBZzDx8PGoYgrydz-T8tcqtkDriyEL3mGYe9b2uH_"
74                     "8JnzMMNMFheVPDdNBhyQQVOmQqPj7idv7677eSle4LJZANUYZdwQ";
75 const char *RSA_p = "8Yhaq4UMiFptSuUMcLUqOJdZ9Jr0z2KG_ZrPaaHIX8gfbtp5DGjhXEE--SwoX9ukEzR6vCewSFcEl20wnT0uTwrVs-Bf2J1L-"
76                     "5tKKeiiwLQxXtk1cG5-PI-ECkqX0AP2K2Xa0wpIjldBE5SBR0S7whANpKxhVFMtNgKog4xNvxU";
77 const char *RSA_q = "5hkENNaWQSJ5qWXVJYh0LAHddr1NXwkKIfKNjK8vCYfOHXDgKxW4UbAIu7wIU9iZcVjTdN2UcaJMe5fBQR9ZEP8bcuY9ZpeUCkv-"
78                     "g9IGw69HUXE7ERBz1es_lZOuJzENwL85Al7jOtVJ2y26g4r30q4jqaL7CcgUZjBKAytjUG0";
79 const char *RSA_dp = "pAn1epQsRNcVb05Muqdv-2tfnu824TqLb-YahCVqjxK9tm4O1EzO8fcmK9i_uwrTTm_QA8X4xcjDx4xS_"
80                      "he1Qd2b8kSrE9UQ69s17WygTLyU41QmJSwF9F-MT-kFXjOylxrgGYDccj_0ZLXxb1PRKSX5_iNNHxY2mH4JsP4zN1k";
81 const char *RSA_dq = "gTTxAL6y9vZl_PKa4w2htoiBlMiuJryLvQ5X3_ULY72nxy54Ipl6vBwue0UWJAcP-u8XJpu6XKj3a7uGoIv61ql5_2Y8elyJm9Kao-"
82                      "kPNVk6oggEVAu6EBiext57v7Qy9dYrLCKeVI4qf_JIts8VZG-2xO4pK4_3rH5XQTpe9W0";
83 const char *RSA_qi = "xTJ_ON_6kc9g3ZbunSSt_oqJBguxH2x8HVl2KQXafW-F0_DOv09P1e0fbSdOLhR-V9lLjq8DxOcvCMxkpQr2G8lTaBRVTF_-szu9adi9bgb_-"
84                      "egvc_NAvRkuGE9fUmB2_nAyU-j4VUh1MMSP5qqQhMYvFdAF5y36MpI-pV1SLFQ";
START_TEST(test_cjose_jwk_create_RSA_spec)85 START_TEST(test_cjose_jwk_create_RSA_spec)
86 {
87     cjose_err err;
88     cjose_jwk_rsa_keyspec specPub;
89     cjose_jwk_rsa_keyspec specPriv;
90 
91     memset(&specPriv, 0, sizeof(cjose_jwk_rsa_keyspec));
92     cjose_base64url_decode(RSA_e, strlen(RSA_e), &specPriv.e, &specPriv.elen, &err);
93     cjose_base64url_decode(RSA_n, strlen(RSA_n), &specPriv.n, &specPriv.nlen, &err);
94     cjose_base64url_decode(RSA_d, strlen(RSA_d), &specPriv.d, &specPriv.dlen, &err);
95     cjose_base64url_decode(RSA_p, strlen(RSA_p), &specPriv.p, &specPriv.plen, &err);
96     cjose_base64url_decode(RSA_q, strlen(RSA_q), &specPriv.q, &specPriv.qlen, &err);
97     cjose_base64url_decode(RSA_dp, strlen(RSA_dp), &specPriv.dp, &specPriv.dplen, &err);
98     cjose_base64url_decode(RSA_dq, strlen(RSA_dq), &specPriv.dq, &specPriv.dqlen, &err);
99     cjose_base64url_decode(RSA_qi, strlen(RSA_qi), &specPriv.qi, &specPriv.qilen, &err);
100 
101     // everything
102     cjose_jwk_t *jwk = NULL;
103     jwk = cjose_jwk_create_RSA_spec(&specPriv, &err);
104     ck_assert(NULL != jwk);
105     ck_assert(1 == jwk->retained);
106     ck_assert(CJOSE_JWK_KTY_RSA == jwk->kty);
107     ck_assert(2048 == jwk->keysize);
108     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
109     ck_assert(NULL != jwk->keydata);
110     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
111     cjose_jwk_release(jwk);
112 
113     // only private is not possible after the OpenSSL 1.1.x changes because e & n always need to be set
114 
115     // minimal private
116     cjose_get_dealloc()(specPriv.p);
117     specPriv.p = NULL;
118     cjose_get_dealloc()(specPriv.q);
119     specPriv.q = NULL;
120     cjose_get_dealloc()(specPriv.dp);
121     specPriv.dp = NULL;
122     cjose_get_dealloc()(specPriv.dq);
123     specPriv.dq = NULL;
124     cjose_get_dealloc()(specPriv.qi);
125     specPriv.qi = NULL;
126     jwk = cjose_jwk_create_RSA_spec(&specPriv, &err);
127     ck_assert(NULL != jwk);
128     ck_assert(1 == jwk->retained);
129     ck_assert(CJOSE_JWK_KTY_RSA == jwk->kty);
130     ck_assert(2048 == jwk->keysize);
131     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
132     ck_assert(NULL != jwk->keydata);
133     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
134     cjose_jwk_release(jwk);
135 
136     cjose_get_dealloc()(specPriv.n);
137     specPriv.n = NULL;
138     cjose_get_dealloc()(specPriv.d);
139     specPriv.d = NULL;
140     cjose_get_dealloc()(specPriv.e);
141     specPriv.e = NULL;
142 
143     // public only
144     memset(&specPub, 0, sizeof(cjose_jwk_rsa_keyspec));
145     cjose_base64url_decode(RSA_e, strlen(RSA_e), &specPub.e, &specPub.elen, &err);
146     cjose_base64url_decode(RSA_n, strlen(RSA_n), &specPub.n, &specPub.nlen, &err);
147 
148     jwk = cjose_jwk_create_RSA_spec(&specPub, &err);
149     ck_assert(NULL != jwk);
150     ck_assert(1 == jwk->retained);
151     ck_assert(CJOSE_JWK_KTY_RSA == jwk->kty);
152     ck_assert(2048 == jwk->keysize);
153     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
154     ck_assert(NULL != jwk->keydata);
155     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
156     cjose_jwk_release(jwk);
157 
158     cjose_get_dealloc()(specPub.n);
159     specPub.n = NULL;
160     cjose_get_dealloc()(specPub.e);
161     specPub.e = NULL;
162 }
163 END_TEST
164 
START_TEST(test_cjose_jwk_create_RSA_random)165 START_TEST(test_cjose_jwk_create_RSA_random)
166 {
167     cjose_err err;
168     cjose_jwk_t *jwk = NULL;
169     uint8_t *e = NULL;
170     size_t elen = 0;
171 
172     e = (uint8_t *)"\x01\x00\x01";
173     elen = 3;
174     jwk = cjose_jwk_create_RSA_random(2048, e, elen, &err);
175     ck_assert(NULL != jwk);
176     ck_assert(1 == jwk->retained);
177     ck_assert(CJOSE_JWK_KTY_RSA == jwk->kty);
178     ck_assert(2048 == jwk->keysize);
179     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
180     ck_assert(NULL != jwk->keydata);
181     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
182 
183     cjose_jwk_release(jwk);
184 
185     e = NULL;
186     elen = 0;
187     jwk = cjose_jwk_create_RSA_random(2048, e, elen, &err);
188     ck_assert(NULL != jwk);
189     ck_assert(1 == jwk->retained);
190     ck_assert(CJOSE_JWK_KTY_RSA == jwk->kty);
191     ck_assert(2048 == jwk->keysize);
192     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
193     ck_assert(NULL != jwk->keydata);
194     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
195 
196     cjose_jwk_release(jwk);
197 }
198 END_TEST
199 
200 const char *EC_P256_d = "RSSjcBQW_EBxm1gzYhejCdWtj3Id_GuwldwEgSuKCEM";
201 const char *EC_P256_x = "ii8jCnvs4FLc0rteSWxanup22pNDhzizmlGN-bfTcFk";
202 const char *EC_P256_y = "KbkZ7r_DQ-t67pnxPnFDHObTLBqn44BSjcqn0STUkaM";
START_TEST(test_cjose_jwk_create_EC_P256_spec)203 START_TEST(test_cjose_jwk_create_EC_P256_spec)
204 {
205     cjose_err err;
206     cjose_jwk_t *jwk = NULL;
207     cjose_jwk_ec_keyspec spec;
208 
209     memset(&spec, 0, sizeof(cjose_jwk_ec_keyspec));
210     spec.crv = CJOSE_JWK_EC_P_256;
211     cjose_base64url_decode(EC_P256_d, strlen(EC_P256_d), &spec.d, &spec.dlen, &err);
212     cjose_base64url_decode(EC_P256_x, strlen(EC_P256_x), &spec.x, &spec.xlen, &err);
213     cjose_base64url_decode(EC_P256_y, strlen(EC_P256_y), &spec.y, &spec.ylen, &err);
214 
215     jwk = cjose_jwk_create_EC_spec(&spec, &err);
216     ck_assert(NULL != jwk);
217     ck_assert(1 == jwk->retained);
218     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
219     ck_assert(256 == jwk->keysize);
220     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
221     ck_assert(NULL != jwk->keydata);
222     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
223     ck_assert(CJOSE_JWK_EC_P_256 == cjose_jwk_EC_get_curve(jwk, &err));
224     cjose_get_dealloc()(spec.d);
225     cjose_get_dealloc()(spec.x);
226     cjose_get_dealloc()(spec.y);
227 
228     // cleanup
229     cjose_jwk_release(jwk);
230 }
231 END_TEST
START_TEST(test_cjose_jwk_create_EC_P256_random)232 START_TEST(test_cjose_jwk_create_EC_P256_random)
233 {
234     cjose_err err;
235     cjose_jwk_t *jwk = NULL;
236 
237     jwk = cjose_jwk_create_EC_random(CJOSE_JWK_EC_P_256, &err);
238     ck_assert(1 == jwk->retained);
239     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
240     ck_assert(256 == jwk->keysize);
241     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
242     ck_assert(NULL != jwk->keydata);
243     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
244     ck_assert(CJOSE_JWK_EC_P_256 == cjose_jwk_EC_get_curve(jwk, &err));
245 
246     // cleanup
247     cjose_jwk_release(jwk);
248 }
249 END_TEST
250 
251 const char *EC_384_d = "vpwFfxYfV7Ftm3fuidQsK-l_tGxqqnUUG6R5QZStJAeZy7qQiHAo7rZumFslws38";
252 const char *EC_384_x = "ulIwcMpG6gbi9Bo_CeVFDIu7RT-AFxu5NRiH9Wm39lYQOAcZTlHJM8Tz4Fwbtu-0";
253 const char *EC_384_y = "WOZtl6a6x_ukWquJbd_sF18zivwVq26HhJbnmwEKuab7zvZ3sGzOX7LJCHl4zmXa";
START_TEST(test_cjose_jwk_create_EC_P384_spec)254 START_TEST(test_cjose_jwk_create_EC_P384_spec)
255 {
256     cjose_err err;
257     cjose_jwk_t *jwk = NULL;
258     cjose_jwk_ec_keyspec spec;
259 
260     memset(&spec, 0, sizeof(cjose_jwk_ec_keyspec));
261     spec.crv = CJOSE_JWK_EC_P_384;
262     cjose_base64url_decode(EC_384_d, strlen(EC_384_d), &spec.d, &spec.dlen, &err);
263     cjose_base64url_decode(EC_384_x, strlen(EC_384_x), &spec.x, &spec.xlen, &err);
264     cjose_base64url_decode(EC_384_y, strlen(EC_384_y), &spec.y, &spec.ylen, &err);
265 
266     jwk = cjose_jwk_create_EC_spec(&spec, &err);
267     ck_assert(NULL != jwk);
268     ck_assert(1 == jwk->retained);
269     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
270     ck_assert(384 == jwk->keysize);
271     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
272     ck_assert(NULL != jwk->keydata);
273     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
274     ck_assert(CJOSE_JWK_EC_P_384 == cjose_jwk_EC_get_curve(jwk, &err));
275     cjose_get_dealloc()(spec.d);
276     cjose_get_dealloc()(spec.x);
277     cjose_get_dealloc()(spec.y);
278 
279     // cleanup
280     cjose_jwk_release(jwk);
281 }
282 END_TEST
START_TEST(test_cjose_jwk_create_EC_P384_random)283 START_TEST(test_cjose_jwk_create_EC_P384_random)
284 {
285     cjose_err err;
286     cjose_jwk_t *jwk = NULL;
287 
288     jwk = cjose_jwk_create_EC_random(CJOSE_JWK_EC_P_384, &err);
289     ck_assert(1 == jwk->retained);
290     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
291     ck_assert(384 == jwk->keysize);
292     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
293     ck_assert(NULL != jwk->keydata);
294     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
295     ck_assert(CJOSE_JWK_EC_P_384 == cjose_jwk_EC_get_curve(jwk, &err));
296 
297     // cleanup
298     cjose_jwk_release(jwk);
299 }
300 END_TEST
301 
302 const char *EC_521_d = "E-0dXEk-bh2Fb08ge8_kNCiSSLiWu7zAR-4SVxH_SfqX2vPimGlF8cU-RFxb64zjW599vsULwvE62MzFWtK63Y4";
303 const char *EC_521_x = "C3LEPuVWTeIQ7KGNibjAdUyHYyapCE6GAQ_oEs7P49yA8AWyJhxIVGWuc1punIsi5WjzHRoNhj0TqEBN4LsW0-g";
304 const char *EC_521_y = "AeMjLFBhdk-lBiaFc8QKYZYziRIS_8q-3ziwXm5zfREdzVv9GUm-l-APSv4gIq-0-G0oSyFf6j6oh7KTf4aYGTV6";
START_TEST(test_cjose_jwk_create_EC_P521_spec)305 START_TEST(test_cjose_jwk_create_EC_P521_spec)
306 {
307     cjose_err err;
308     cjose_jwk_t *jwk = NULL;
309     cjose_jwk_ec_keyspec spec;
310 
311     memset(&spec, 0, sizeof(cjose_jwk_ec_keyspec));
312     spec.crv = CJOSE_JWK_EC_P_521;
313     cjose_base64url_decode(EC_521_d, strlen(EC_521_d), &spec.d, &spec.dlen, &err);
314     cjose_base64url_decode(EC_521_x, strlen(EC_521_x), &spec.x, &spec.xlen, &err);
315     cjose_base64url_decode(EC_521_y, strlen(EC_521_y), &spec.y, &spec.ylen, &err);
316 
317     jwk = cjose_jwk_create_EC_spec(&spec, &err);
318     ck_assert(NULL != jwk);
319     ck_assert(1 == jwk->retained);
320     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
321     ck_assert(521 == jwk->keysize);
322     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
323     ck_assert(NULL != jwk->keydata);
324     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
325     ck_assert(CJOSE_JWK_EC_P_521 == cjose_jwk_EC_get_curve(jwk, &err));
326     free(spec.d);
327     free(spec.x);
328     free(spec.y);
329 
330     // cleanup
331     cjose_jwk_release(jwk);
332 }
333 END_TEST
START_TEST(test_cjose_jwk_create_EC_P521_random)334 START_TEST(test_cjose_jwk_create_EC_P521_random)
335 {
336     cjose_err err;
337     cjose_jwk_t *jwk = NULL;
338 
339     jwk = cjose_jwk_create_EC_random(CJOSE_JWK_EC_P_521, &err);
340     ck_assert(1 == jwk->retained);
341     ck_assert(CJOSE_JWK_KTY_EC == jwk->kty);
342     ck_assert(521 == jwk->keysize);
343     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
344     ck_assert(NULL != jwk->keydata);
345     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
346     ck_assert(CJOSE_JWK_EC_P_521 == cjose_jwk_EC_get_curve(jwk, &err));
347 
348     // cleanup
349     cjose_jwk_release(jwk);
350 }
351 END_TEST
352 
353 const uint8_t *OCT_KEY = "pKE-eSbyFqPdtA5WzazKFg";
START_TEST(test_cjose_jwk_create_oct_spec)354 START_TEST(test_cjose_jwk_create_oct_spec)
355 {
356     cjose_err err;
357     cjose_jwk_t *jwk = NULL;
358     uint8_t *k = NULL;
359     size_t klen = 0;
360 
361     cjose_base64url_decode(OCT_KEY, strlen(OCT_KEY), &k, &klen, &err);
362 
363     jwk = cjose_jwk_create_oct_spec(k, klen, &err);
364     ck_assert(1 == jwk->retained);
365     ck_assert(CJOSE_JWK_KTY_OCT == jwk->kty);
366     ck_assert(klen * 8 == jwk->keysize);
367     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
368     ck_assert(NULL != jwk->keydata);
369     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
370     ck_assert_bin_eq(k, jwk->keydata, klen);
371     cjose_get_dealloc()(k);
372 
373     // cleanup
374     cjose_jwk_release(jwk);
375 }
376 END_TEST
START_TEST(test_cjose_jwk_create_oct_random)377 START_TEST(test_cjose_jwk_create_oct_random)
378 {
379     cjose_err err;
380     cjose_jwk_t *jwk = NULL;
381 
382     jwk = cjose_jwk_create_oct_random(128, &err);
383     ck_assert(1 == jwk->retained);
384     ck_assert(CJOSE_JWK_KTY_OCT == jwk->kty);
385     ck_assert(128 == jwk->keysize);
386     ck_assert(cjose_jwk_get_keysize(jwk, &err) == jwk->keysize);
387     ck_assert(NULL != jwk->keydata);
388     ck_assert(cjose_jwk_get_keydata(jwk, &err) == jwk->keydata);
389 
390     // cleanup
391     cjose_jwk_release(jwk);
392 }
393 END_TEST
START_TEST(test_cjose_jwk_create_oct_random_inval)394 START_TEST(test_cjose_jwk_create_oct_random_inval)
395 {
396     cjose_err err;
397     cjose_jwk_t *jwk = NULL;
398 
399     jwk = cjose_jwk_create_oct_random(0, &err);
400     ck_assert(NULL == jwk);
401     ck_assert(CJOSE_ERR_INVALID_ARG == err.code);
402 }
403 END_TEST
404 
START_TEST(test_cjose_jwk_retain_release)405 START_TEST(test_cjose_jwk_retain_release)
406 {
407     cjose_err err;
408     // create some type of key
409     cjose_jwk_t *jwk = cjose_jwk_create_oct_random(128, &err);
410     ck_assert(1 == jwk->retained);
411 
412     cjose_jwk_t *retained = NULL;
413     retained = cjose_jwk_retain(jwk, &err);
414     ck_assert(jwk == retained);
415     ck_assert(2 == jwk->retained);
416 
417     bool result = false;
418     result = cjose_jwk_release(jwk);
419     ck_assert(result);
420     ck_assert(1 == jwk->retained);
421 
422     retained = cjose_jwk_retain(jwk, &err);
423     ck_assert(jwk == retained);
424     ck_assert(2 == jwk->retained);
425 
426     result = cjose_jwk_release(jwk);
427     ck_assert(result);
428     ck_assert(1 == jwk->retained);
429 
430     result = cjose_jwk_release(jwk);
431     ck_assert(!result);
432 
433     result = cjose_jwk_release(NULL);
434     ck_assert(!result);
435 
436     retained = cjose_jwk_retain(NULL, &err);
437     ck_assert(retained == NULL);
438 }
439 END_TEST
440 
START_TEST(test_cjose_jwk_get_kty)441 START_TEST(test_cjose_jwk_get_kty)
442 {
443     cjose_err err;
444     cjose_jwk_t *jwk = NULL;
445     jwk = cjose_jwk_create_oct_random(128, &err);
446     ck_assert(CJOSE_JWK_KTY_OCT == cjose_jwk_get_kty(jwk, &err));
447     cjose_jwk_release(jwk);
448 
449     jwk = cjose_jwk_create_EC_random(CJOSE_JWK_EC_P_256, &err);
450     ck_assert(CJOSE_JWK_KTY_EC == cjose_jwk_get_kty(jwk, &err));
451     cjose_jwk_release(jwk);
452 }
453 END_TEST
454 
START_TEST(test_cjose_jwk_to_json_oct)455 START_TEST(test_cjose_jwk_to_json_oct)
456 {
457     cjose_err err;
458     cjose_jwk_t *jwk = NULL;
459     uint8_t *k = NULL;
460     size_t klen = 0;
461 
462     cjose_base64url_decode(OCT_KEY, strlen(OCT_KEY), &k, &klen, &err);
463     jwk = cjose_jwk_create_oct_spec(k, klen, &err);
464     cjose_get_dealloc()(k);
465 
466     char *json;
467     json = cjose_jwk_to_json(jwk, false, &err);
468     ck_assert(NULL != json);
469     ck_assert_str_eq("{\"kty\":\"oct\"}", json);
470     free(json);
471 
472     json = cjose_jwk_to_json(jwk, true, &err);
473     ck_assert(NULL != json);
474     ck_assert_str_eq("{\"kty\":\"oct\",\"k\":\"pKE-eSbyFqPdtA5WzazKFg\"}", json);
475     free(json);
476 
477     cjose_jwk_release(jwk);
478 }
479 END_TEST
START_TEST(test_cjose_jwk_to_json_ec)480 START_TEST(test_cjose_jwk_to_json_ec)
481 {
482     cjose_err err;
483     cjose_jwk_t *jwk = NULL;
484     cjose_jwk_ec_keyspec spec;
485 
486     memset(&spec, 0, sizeof(cjose_jwk_ec_keyspec));
487     spec.crv = CJOSE_JWK_EC_P_256;
488     cjose_base64url_decode(EC_P256_d, strlen(EC_P256_d), &spec.d, &spec.dlen, &err);
489     cjose_base64url_decode(EC_P256_x, strlen(EC_P256_x), &spec.x, &spec.xlen, &err);
490     cjose_base64url_decode(EC_P256_y, strlen(EC_P256_y), &spec.y, &spec.ylen, &err);
491 
492     jwk = cjose_jwk_create_EC_spec(&spec, &err);
493     cjose_get_dealloc()(spec.d);
494     cjose_get_dealloc()(spec.x);
495     cjose_get_dealloc()(spec.y);
496 
497     char *json;
498     json = cjose_jwk_to_json(jwk, false, &err);
499     ck_assert(NULL != json);
500     ck_assert_str_eq("{\"kty\":\"EC\",\"crv\":\"P-256\""
501                      ",\"x\":\"ii8jCnvs4FLc0rteSWxanup22pNDhzizmlGN-bfTcFk\""
502                      ",\"y\":\"KbkZ7r_DQ-t67pnxPnFDHObTLBqn44BSjcqn0STUkaM\"}",
503                      json);
504     free(json);
505 
506     json = cjose_jwk_to_json(jwk, true, &err);
507     ck_assert(NULL != json);
508     ck_assert_str_eq("{\"kty\":\"EC\",\"crv\":\"P-256\""
509                      ",\"x\":\"ii8jCnvs4FLc0rteSWxanup22pNDhzizmlGN-bfTcFk\""
510                      ",\"y\":\"KbkZ7r_DQ-t67pnxPnFDHObTLBqn44BSjcqn0STUkaM\""
511                      ",\"d\":\"RSSjcBQW_EBxm1gzYhejCdWtj3Id_GuwldwEgSuKCEM\"}",
512                      json);
513     free(json);
514 
515     cjose_jwk_release(jwk);
516 }
517 END_TEST
518 
519 const char *RSA_PUBLIC_JSON = "{\"kty\":\"RSA\","
520                               "\"e\":\"AQAB\""
521                               ",\"n\":\"2Rgbvu_cGMpvVl8DE6aGGX7IE2lKn5c9ZtexriFrCLqBbKt2TBOZkoCn_AbcDjUVk23CxsIj9Z1VfsL_0UeVA_"
522                               "AeOLUWw0F5-JhoK6NBeLpYZOz7HYieTOSJjSxYhoCYtVbLKI27e3NEvckxTs-90CdKl71P7YwrdSrY59hR-"
523                               "u2etyNCRGAPcoDH5xYJxrG2p5FH_Dh_MQ0ugDnJY2_b_-w9NS2Y2atIkzXZDjtcSpjImKpL0eIFF69ptiF8vd4q2j-"
524                               "ougipFBGP9U5bSVzeZ7FyGkJ5Qa2DYc0osYi1QFs3YZKzkKfcblx14u-yZYhUkZHlb_jbfulnUHxDdO_r8Q\""
525                               "}";
START_TEST(test_cjose_jwk_to_json_rsa)526 START_TEST(test_cjose_jwk_to_json_rsa)
527 {
528     cjose_err err;
529     cjose_jwk_t *jwk = NULL;
530     cjose_jwk_rsa_keyspec spec;
531 
532     memset(&spec, 0, sizeof(cjose_jwk_rsa_keyspec));
533     cjose_base64url_decode(RSA_e, strlen(RSA_e), &spec.e, &spec.elen, &err);
534     cjose_base64url_decode(RSA_n, strlen(RSA_n), &spec.n, &spec.nlen, &err);
535     cjose_base64url_decode(RSA_d, strlen(RSA_d), &spec.d, &spec.dlen, &err);
536     cjose_base64url_decode(RSA_p, strlen(RSA_p), &spec.p, &spec.plen, &err);
537     cjose_base64url_decode(RSA_q, strlen(RSA_q), &spec.q, &spec.qlen, &err);
538     cjose_base64url_decode(RSA_dp, strlen(RSA_dp), &spec.dp, &spec.dplen, &err);
539     cjose_base64url_decode(RSA_dq, strlen(RSA_dq), &spec.dq, &spec.dqlen, &err);
540     cjose_base64url_decode(RSA_qi, strlen(RSA_qi), &spec.qi, &spec.qilen, &err);
541 
542     jwk = cjose_jwk_create_RSA_spec(&spec, &err);
543     cjose_get_dealloc()(spec.e);
544     cjose_get_dealloc()(spec.n);
545     cjose_get_dealloc()(spec.d);
546     cjose_get_dealloc()(spec.p);
547     cjose_get_dealloc()(spec.q);
548     cjose_get_dealloc()(spec.dp);
549     cjose_get_dealloc()(spec.dq);
550     cjose_get_dealloc()(spec.qi);
551 
552     char *json;
553     json = cjose_jwk_to_json(jwk, false, &err);
554     ck_assert(NULL != json);
555     ck_assert_str_eq(RSA_PUBLIC_JSON, json);
556     free(json);
557 
558     json = cjose_jwk_to_json(jwk, true, &err);
559     ck_assert(NULL != json);
560     ck_assert_str_eq("{\"kty\":\"RSA\",\"e\":\"AQAB\""
561                      ",\"n\":\"2Rgbvu_cGMpvVl8DE6aGGX7IE2lKn5c9ZtexriFrCLqBbKt2TBOZkoCn_AbcDjUVk23CxsIj9Z1VfsL_0UeVA_AeOLUWw0F5-"
562                      "JhoK6NBeLpYZOz7HYieTOSJjSxYhoCYtVbLKI27e3NEvckxTs-90CdKl71P7YwrdSrY59hR-u2etyNCRGAPcoDH5xYJxrG2p5FH_Dh_"
563                      "MQ0ugDnJY2_b_-w9NS2Y2atIkzXZDjtcSpjImKpL0eIFF69ptiF8vd4q2j-"
564                      "ougipFBGP9U5bSVzeZ7FyGkJ5Qa2DYc0osYi1QFs3YZKzkKfcblx14u-yZYhUkZHlb_jbfulnUHxDdO_r8Q\""
565                      ",\"d\":\"P9N6tNRIXXGG8lnUyb43xt8ja7GVIv6QKuBXeN6SXWqYCp8OlKdei1gQC2To5bRtt36ZuV3yvI-ZRz-"
566                      "Ffr4Q7at29y0mmBl0BsaoOcwxv5Dp1CJoYfJ8uBao6jyTelfsjcQKzs18xXrKRxIT0Rv6rmwe3iXmjeycCkKiqudKkv8m9RtbvdWH8AFd2ZsC"
567                      "LNblVRrOZ9ZPQQCMVJLf65pF_cBfux-Zz_CJCfq93gFcN3h1tPFLX8UPBMqvqkBZzDx8PGoYgrydz-T8tcqtkDriyEL3mGYe9b2uH_"
568                      "8JnzMMNMFheVPDdNBhyQQVOmQqPj7idv7677eSle4LJZANUYZdwQ\""
569                      ",\"p\":\"8Yhaq4UMiFptSuUMcLUqOJdZ9Jr0z2KG_ZrPaaHIX8gfbtp5DGjhXEE--SwoX9ukEzR6vCewSFcEl20wnT0uTwrVs-Bf2J1L-"
570                      "5tKKeiiwLQxXtk1cG5-PI-ECkqX0AP2K2Xa0wpIjldBE5SBR0S7whANpKxhVFMtNgKog4xNvxU\""
571                      ",\"q\":\"5hkENNaWQSJ5qWXVJYh0LAHddr1NXwkKIfKNjK8vCYfOHXDgKxW4UbAIu7wIU9iZcVjTdN2UcaJMe5fBQR9ZEP8bcuY9ZpeUCkv-"
572                      "g9IGw69HUXE7ERBz1es_lZOuJzENwL85Al7jOtVJ2y26g4r30q4jqaL7CcgUZjBKAytjUG0\""
573                      ",\"dp\":\"pAn1epQsRNcVb05Muqdv-2tfnu824TqLb-YahCVqjxK9tm4O1EzO8fcmK9i_uwrTTm_QA8X4xcjDx4xS_"
574                      "he1Qd2b8kSrE9UQ69s17WygTLyU41QmJSwF9F-MT-kFXjOylxrgGYDccj_0ZLXxb1PRKSX5_iNNHxY2mH4JsP4zN1k\""
575                      ",\"dq\":\"gTTxAL6y9vZl_PKa4w2htoiBlMiuJryLvQ5X3_ULY72nxy54Ipl6vBwue0UWJAcP-u8XJpu6XKj3a7uGoIv61ql5_"
576                      "2Y8elyJm9Kao-kPNVk6oggEVAu6EBiext57v7Qy9dYrLCKeVI4qf_JIts8VZG-2xO4pK4_3rH5XQTpe9W0\""
577                      ",\"qi\":\"xTJ_ON_6kc9g3ZbunSSt_oqJBguxH2x8HVl2KQXafW-F0_DOv09P1e0fbSdOLhR-V9lLjq8DxOcvCMxkpQr2G8lTaBRVTF_-"
578                      "szu9adi9bgb_-egvc_NAvRkuGE9fUmB2_nAyU-j4VUh1MMSP5qqQhMYvFdAF5y36MpI-pV1SLFQ\""
579                      "}",
580                      json);
581     free(json);
582 
583     cjose_jwk_release(jwk);
584 }
585 END_TEST
586 
START_TEST(test_cjose_jwk_import_json_valid)587 START_TEST(test_cjose_jwk_import_json_valid)
588 {
589     cjose_err err;
590     static const char *JWK[] = {
591         // EC P-256
592         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
593         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
594         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
595         "\"kid\": \"4E34BAFD-E5D9-479C-964D-009C419C38DB\" }",
596 
597         // EC P-256, attributes rearranged
598         "{ \"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
599         "\"kid\": \"05A9BE36-CBBD-43F4-ACC2-8C7823B2DE23\", "
600         "\"kty\": \"EC\", \"crv\": \"P-256\", "
601         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\"}",
602 
603         // EC P-256, no 'kid'
604         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
605         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
606         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\"}",
607 
608         // EC P-256, empty 'kid'
609         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
610         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
611         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
612         "\"kid\": \"\" }",
613 
614         // EC P-256, empty 'kid'
615         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
616         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
617         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
618         "\"kid\": null }",
619 
620         // EC P-256 with private key 'd'
621         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
622         "\"x\": \"ccXrxIe0aS32y9kBkZFfAh6f7UvdcowtGH5uxCIo7eY\", "
623         "\"y\": \"GGQACnDgoiQvdQTsv1KxNUzOjZgnNoO4wQe_F75-bb0\", "
624         "\"kid\": \"F2BF329A-151B-4066-AB92-1CCA0C0F9DB5\", "
625         "\"d\": \"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\" }",
626 
627         // EC P-384
628         "{ \"kty\": \"EC\", \"crv\": \"P-384\", "
629         "\"x\": \"pO1SWmH7uOJfrtU1ibqVVK7VHffbpZtGfPYMPP_5KLQO9Dtsy41UEkMlL3BWHJDH\", "
630         "\"y\": \"RdBNoaV42bRE55V8PJR3Toeo8omQAIHPboOa7LlbQSGPYp6H6zW0tKroPquJYr3w\", "
631         "\"kid\": \"55680752-989A-4C5C-BC6E-48602489865C\" }",
632 
633         // EC P-521
634         "{ \"kty\": \"EC\", \"crv\": \"P-521\", "
635         "\"x\": \"AC8xogZa6uKAPU8086yAlG_inL3BaRyTB0pQUIJMENsPV_4S32DxIEEellMzQ_ts1Egp6OyS3ewjCUKHv5CTF7IV\", "
636         "\"y\": \"AIR1I2rUew5WyetOHYC-arEDDk2R30Yto6TTot92l4aY0DL8pSYxPVwv9beFUJEl95o_1Vv5y1453nFZW1Ca0uUj\", "
637         "\"kid\": \"A3EAB438-EBF8-4FEC-B605-A67C3A0D2313\" }",
638 
639         // RSA 2048 public params only
640         "{ \"kty\": \"RSA\", "
641         "\"e\": \"AQAB\", "
642         "\"n\": "
643         "\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Imt4EkILfPfZPeUYV6lElCjoY_4GBtQOy_"
644         "e4RvDSMC0pqt5X4e6mjQvLsaAClkBmhhCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_"
645         "ekEBUsm0Xq4p6N5DjC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8VFR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0Xv"
646         "WEMXj_zk0YnVTGAGdZeDPwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\", "
647         "\"kid\": \"05F24DC3-59F4-4AC5-9849-F2F5EA8A6F3E\" }",
648 
649         // RSA 2048 public and private params with CRT params
650         "{ \"kty\": \"RSA\", "
651         "\"e\": \"AQAB\", "
652         "\"n\": "
653         "\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Imt4EkILfPfZPeUYV6lElCjoY_4GBtQOy_"
654         "e4RvDSMC0pqt5X4e6mjQvLsaAClkBmhhCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_"
655         "ekEBUsm0Xq4p6N5DjC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8VFR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0Xv"
656         "WEMXj_zk0YnVTGAGdZeDPwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\", "
657         "\"kid\": \"F7D90C71-6671-4064-A0AA-379AD1862D19\", "
658         "\"d\": "
659         "\"bixuZapp0PYFXp98gXWTT1CQlycR61lvmFf0RFyWYo9n8H7gE7KcG7AmIHVY3UVDT7jgikMIqQOCPn1SI7BXsNIPBBujEGnfHDywHSyKfdNVG-"
660         "wkTGptP9OTo3kvpP5uSCwY6btBU-1JLyWggJC_RgmaKNNYIyUlny0Q-gOx0x0I-6ipWyLQVdKZBkw6erSODM244sPU9qEmyzVW7Nbmo5PKC1U4w-"
661         "Dt4nBe19TIUHG-ggN_UDRauljbegIIcnEWWeXdJZDdPUHgmIRa2ODN0mfSKl1CB4LJ2eyKlmddGLFiHys44OVwA8LVzrodUixIQP6wQ02AUwlaYU_"
662         "BWLEVoQ\", "
663         "\"p\": "
664         "\"9GRrzfmxrL_WgSKXexO6uc2hWh-lV9bPfBU735uHUFBS2_OOUjtQSYSqm-HK2ND1EIlPZBEEu9ccdshaEVYx79eP5fRnpF8EKEo1W-eeinmn7pQsfR-"
665         "6kFzkKmdBVhUyfpZvWtNuIwNZLu-HEvF2eIVVauQtJCPnjeYFbDyveqk\", "
666         "\"q\": "
667         "\"1uGXUwk052ayLvpYx3-L272X5srOyme3PCS2W1AZBXnXK06jqFp_KqUDpPnL3MNYZlfoYW5HIQBNpGCcZaTwfdLnSZroSbkQk-"
668         "9w3zfsOiJplDbZb77mG6xbw7m7AqcNQA6szoGlCrxluE74apKg4dUOg5rEx8-LOeK90rz-So8\", "
669         "\"dp\": "
670         "\"D36KYy2weQ5UkC1cQz5V-U-zKh6VggMpdml2OVAH_SyKhE1luYrvJSoXEvj2vlZJIzpBYUu-7BXQRSugoja_xb_57I9ZPs-"
671         "TWOaTiXce0xKxdevJAknPrzVkddfECawgXmw1NSHweqHMtrAS9T1_0FZLuxIqVn88P__UWi9ixLk\", "
672         "\"dq\": "
673         "\"J733d-MXBslGoUuqCdO8MTsCkivmTScbi6Mamw7YYdvkAN19hVCffmqgnu2YV89FVUBi-UolG6Rrt8AqjN4RoKPWJRXiamgw-"
674         "btqO86jASmGL2RpmLJM6sdY_X0nalktKTDNoy_1L2QiyBDK_yL5YGtAUPTZ-j6XeHBIPWa4_V8\", "
675         "\"qi\": "
676         "\"DJcZFEvdjynkwHEOrTSXLezReXT8bj73eo7Yoadtbln27nD_8q5yAobHVOO9ZzrwSoDCeepW_fVotgMuqxdGIBXZB_"
677         "DboRvjWW0QuBZ7Lg2SwwQqi9Ve8w31Z36gvOr1fR-Bd12B5STepC4SYBn1u5uMG5AIgfgzoa-FXEEBgB8\" }",
678 
679         // RSA 4096 public and private params, without CRT params
680         "{ \"kty\": \"RSA\", "
681         "\"e\": \"AQAB\", "
682         "\"n\": "
683         "\"vlbWUA9HUDHB5MDotmXObtE_Y4zKtGNtmPHUy_xkp_fSr0BxNdSOUzvzoAhK3sxTqpzVujKC245RHJ84Hhbl-KDj-"
684         "n7Ee8EV3nKpnsqiBgHyc3rBpxpIi0J8kYmpiPGXu7k4xnCWCeiu_gfFGzvPdLHzlV7WOfYIHvymtbS7WOyTQLBgDjUKfHdJzH75vogy35h_mEcS-pde-"
685         "EIi7u4OqD3bNW7iLbf2JVLtSNUYNCMMu23GsOEcBAsdf4QMq5gU-AEFK4Aib8mSPi_tXoohembr-"
686         "JkzByRAkHbdzoGXssj0EHESt4reDfY8enVo5ACKmzbqlIJ1jmPVV6EKPBPzcQiN9dUA43xei2gmRAswdUKnexVPAPFPfKMpLqr24h1e7jHFBQL23-QqZX-"
687         "gASbEDiYa9GusSY4kRn80hZRqCq4sgIRVEiu3ofjVdo4YzzESAkmfgFayUThhakqP82_wr9_Uc2vw3ZtlaTC_"
688         "0LY70ne9yTy3SD3yEOa649nOTBfSh156YGtxvaHHidFojVHpPHBmjGAlak--mONHXHn00l_CVivUcuBqIGcZXRfiO6YwVDH_4ZTVzAkDov1C-"
689         "4SNJK0XKeIwvGSspaSQrTmH_pT66L7tIhdZLTMVMh2ahnInVZP2G_-motugLq-x962JLQuLLeuh_r_Rk4VHZYhOgoc\", "
690         "\"kid\": \"2940921e-3646-451c-8510-971552754e74\", "
691         "\"d\": "
692         "\"oMyvxXcC4icHDQBEGUOswEYabTmWTgrpnho_kg0p5BUjclbYzYdCreKqEPqwdcTcsfhJP0JI9r8mmy2PtSvXINKbhxXtXDdlCEaKMdIySyz97L06OLelrbB_"
693         "mFxaU4z2iOsToeGff8OJgqaByF4hBw8HH5u9E75cYgFDvaJv29IRHMdkftwkfb4xJIfo6SQbBnbI5Ja22-"
694         "lhnA4TgRKwY0XOmTeR8NnHIwUJ3UvZZMJvkTBOeUPT7T6OrxmZsqWKoXILMhLQBOyfldXbjNDZM5UbqSuTxmbD_"
695         "MfO3xTwWWQXfIRqMZEpw1XRBguGj4g9kJ82Ujxcn-yLYbp08QhR0ijBY13HzFVMZ2jxqckrvp3uYgfJjcCN9QXZ6qlv40s_"
696         "vJRRgv4wxdDc035eoymqGQby0UnDTmhijRV_-eAJQvdl3bv-R5dH9IzhxoJA8xAqZfVtlehPuGaXDAsa4pIWSg9hZkMdDEjW15g3zTQi3ba8_"
697         "MfmnKuDe4GXYBjrH69z7epxbhnTmKQ-fZIxboA9sYuJHj6pEGT8D485QmrnmLjvqmQUzcxnpU6E3awksTp_"
698         "HeBYLLbmrv4DPGNyVri2yPPTTRrNBtbWkuvEGVnMhvL2ed9uqLSnH8zOfgWqstqjxadxKADidYEZzmiYfEjYTDZGd9VDIUdKNGHWGFRB7UE\", "
699         "\"p\": "
700         "\"6VtjaNMD_VKTbs7sUQk-qjPTn6mCI8_3loqrOOy32b1G0HfIzCijuV-"
701         "L7g7RxmMszEEfEILxRpJnOZRehN8etsIEuCdhU6VAdhBsBH5hIA9ZtX8GIs0sPrhc4kzPiwJ6JcLytUc6HCTICf2FIU7SI8I17-"
702         "p53d35VItYiC1sGLZ2yN61VoKYNTncUSwboP2zXmGv4FPB5wQogryA_bEn-"
703         "1U12FFSRd75Ku9GAEVxbTk3OaQqYgqfo9LnAWvunTDu31D4uyC6rze77NCo8UguqCpFjvF0ihOryQI6C3d0e8kxcM1vJbMvZNfrDN65btzqWi4m-"
704         "CnqGYkl6BXQtS5UVw\", "
705         "\"q\": "
706         "\"0M7h_gtxoVoNPLRjYA5zBUD8qmyWiAzjloFOrDRLJwiD4OPHgImUx2WPTiSCjouvGqwfJh1jEEryJV_d0e4iVGyKYbFeXfzadwYXXR2jK4QwO1V_"
707         "JDHI7HUYwNl6qzZqATi2zNKunPgIwY55gWBKjP2aUvPUBAcTeCsUPvrN_SajPVfc2wSlA2TvEnjmweNvgSTNqtBlMpmpwvEb9WXfv4pl3BfRvoTk3VR4icyvl-"
708         "PLFedp2y0Fs0aQ4LRQ2ZMKWyGQEam_uAoa1tXrRJ_yQRvtWm1K8GpRZGKwN3TvtAg649PxQ7tJ8cvh3BwQROJyQBZDrlR04wqvDK4SNezlUQ\" }",
709 
710         // oct 256
711         "{ \"kty\": \"oct\", "
712         "\"kid\": \"b779034d-2e9b-44a8-8334-55d6b7a0ef59\", "
713         "\"k\": \"wsL6R8uXG4RnsckLggj9Lg-kE5MMSJ8luzIBA8j7WXE\" }",
714 
715         // oct 512
716         "{ \"kty\": \"oct\", "
717         "\"kid\": \"0c17c6d8-307d-4e4a-a860-a14788ee1110\", "
718         "\"k\": \"qKcFDl6VSS7CgMpdF9we9JFEenMQniO-8lQ0DvFI1jzfTb93H2Gc0YzO4iNEZ7VPN6p0l-PyA4vlOrn0hPS5qA\" }",
719 
720         // oct 1024
721         "{ \"kty\": \"oct\", "
722         "\"kid\": \"3dfc3c58-74fd-4b8a-88d6-5321b30b554c\", "
723         "\"k\": "
724         "\"dCDW6NH5DkKtH6dTsRm_yJchQtrVxD_ZjDob3UquMBoAwdtVIjKvMztbP4XQE7Gf_QjzEa58_UrI80QzBxG_UpFxzpjTOBfWz8Do1BHZak_"
725         "W1KBWDyfnEqc8RtxZmc4yE1dko5B8GUyfplMrEFa2tO899hnGe7pqRVdiwFF5QkY\" }",
726 
727         NULL,
728     };
729 
730     cjose_jwk_t *jwk = NULL;
731     for (int i = 0; JWK[i] != NULL; ++i)
732     {
733         // get json representation of "before"
734         json_t *left_json = json_loads(JWK[i], 0, NULL);
735         ck_assert(NULL != left_json);
736 
737         // do import
738         jwk = cjose_jwk_import_json((cjose_header_t *)left_json, &err);
739         ck_assert_msg(NULL != jwk,
740                       "expected a cjose_jwk_t, but got NULL (%s) : "
741                       "%s, file: %s, function: %s, line: %ld",
742                       JWK[i], err.message, err.file, err.function, err.line);
743 
744         // get json representation of "after"
745         char *jwk_str = cjose_jwk_to_json(jwk, true, &err);
746         json_t *right_json = json_loads(jwk_str, 0, NULL);
747         ck_assert(NULL != right_json);
748 
749         // check that cooresponding attributes match up
750         const char *attrs[] = { "kty", "crv", "x", "y", "d", "kid", "e", "n", "p", "q", "dp", "dq", "qi", NULL };
751         if (!_match_string_attrs(left_json, right_json, attrs))
752         {
753             ck_assert_str_eq(JWK[i], jwk_str);
754         }
755 
756         free(jwk_str);
757         json_decref(left_json);
758         json_decref(right_json);
759         cjose_jwk_release(jwk);
760     }
761 }
762 END_TEST
763 
START_TEST(test_cjose_jwk_import_json_invalid)764 START_TEST(test_cjose_jwk_import_json_invalid)
765 {
766     cjose_err err;
767     static const char *JWK[] = {
768         // EC P-256 invalid 'kty'
769         "{ \"kty\": \"EMC\", \"crv\": \"P-256\", "
770         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
771         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
772         "\"kid\": \"0406E98B-CE84-4C78-965A-84C53BA73A1E\" }",
773 
774         // EC P-256 missing 'kty'
775         "{ \"crv\": \"P-256\", "
776         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
777         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
778         "\"kid\": \"EE05B07C-22ED-4059-A50B-4AD0A48E28D4\" }",
779 
780         // EC P-256 invalid 'crv'
781         "{ \"kty\": \"EC\", \"crv\": \"P-257\", "
782         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
783         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
784         "\"kid\": \"BB70E4BD-9547-4566-9195-1C45777D368B\" }",
785 
786         // EC P-256 missing 'crv'
787         "{ \"kty\": \"EC\", "
788         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
789         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
790         "\"kid\": \"928D103F-8DF2-41D5-A42B-7A72508FC70E\" }",
791 
792         // EC P-256 invalid 'x' (truncated)
793         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
794         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20\", "
795         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
796         "\"kid\": \"685A7314-EBE1-4E1A-A81D-8AB4A1B56452\" }",
797 
798         // EC P-256 invalid 'x' (a number)
799         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
800         "\"x\": 42, "
801         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
802         "\"kid\": \"5B3F3AB3-E716-4D85-8E4A-4BAC0D7D64E8\" }",
803 
804         // EC P-256 missing 'x'
805         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
806         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
807         "\"kid\": \"9354D170-5FA4-46B5-901D-38098716E28A\" }",
808 
809         // EC P-256 invalid 'y' (truncated)
810         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
811         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
812         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRg\", "
813         "\"kid\": \"262DDF7E-1AB5-43D1-91EA-13B99779DF16\" }",
814 
815         // EC P-256 invalid 'y' (an object)
816         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
817         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
818         "\"y\": {}, "
819         "\"kid\": \"1BEFD34C-A86E-4512-B206-7A2B94D82D27\" }",
820 
821         // EC P-256 missing 'y'
822         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
823         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
824         "\"kid\": \"CBA61EED-3C61-45B3-9A35-9DE03F247720\" }",
825 
826         // EC P-384 invalid 'x' (truncated)
827         "{ \"kty\": \"EC\", \"crv\": \"P-384\", "
828         "\"x\": \"pO1SWmH7uOJfrtU1ibqVVK7VHffbpZtGfPYMPP_5KLQO9Dtsy41UEkMlL3BWHJD\", "
829         "\"y\": \"RdBNoaV42bRE55V8PJR3Toeo8omQAIHPboOa7LlbQSGPYp6H6zW0tKroPquJYr3w\", "
830         "\"kid\": \"FFC23684-88C8-4783-BBA3-ABF29971943B\" }",
831 
832         // EC P-521 invalid 'x' (truncated)
833         "{ \"kty\": \"EC\", \"crv\": \"P-521\", "
834         "\"x\": \"AVq9Y0jEvSINQJzcExSIUWYjo73cJcVTz_QHXCU7p9rbmC8chFdACiGLKDKlzdgW6lhZzA5qnp8mkpS2qJO_EVxU\", "
835         "\"y\": \"AQHcQF8s_dhS_84CKLll0vkr0xCqWLp5XXdb79coYWI7Ev9SwZ4UZZVPxgu7ZGyp_2WdtaWw68uYeUVU4WiyKfP\", "
836         "\"kid\": \"3930AC1C-C02F-46DA-9730-87785F405FE8\" }",
837 
838         // RSA 2048 missing 'n' (needed for both public and private)
839         "{ \"kty\": \"RSA\", "
840         "\"e\": \"AQAB\", "
841         "\"kid\": \"05F24DC3-59F4-4AC5-9849-F2F5EA8A6F3E\" }",
842 
843         // empty object
844         "{}",
845 
846         // empty string
847         "\"\"",
848 
849         // a number
850         "5",
851 
852         // null JWK
853         "null",
854 
855         NULL,
856     };
857 
858     cjose_jwk_t *jwk = NULL;
859     for (int i = 0; JWK[i] != NULL; ++i)
860     {
861         json_t *left_json = json_loads(JWK[i], 0, NULL);
862         jwk = cjose_jwk_import_json((cjose_header_t *)left_json, &err);
863         ck_assert_msg(NULL == jwk, "expected NULL, received a cjose_jwk_t");
864         ck_assert_int_eq(err.code, CJOSE_ERR_INVALID_ARG);
865         cjose_jwk_release(jwk);
866     }
867 }
868 END_TEST
869 
START_TEST(test_cjose_jwk_import_valid)870 START_TEST(test_cjose_jwk_import_valid)
871 {
872     cjose_err err;
873     static const char *JWK[] = {
874         // EC P-256
875         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
876         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
877         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
878         "\"kid\": \"4E34BAFD-E5D9-479C-964D-009C419C38DB\" }",
879 
880         // EC P-256, attributes rearranged
881         "{ \"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
882         "\"kid\": \"05A9BE36-CBBD-43F4-ACC2-8C7823B2DE23\", "
883         "\"kty\": \"EC\", \"crv\": \"P-256\", "
884         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\"}",
885 
886         // EC P-256, no 'kid'
887         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
888         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
889         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\"}",
890 
891         // EC P-256, empty 'kid'
892         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
893         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
894         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
895         "\"kid\": \"\" }",
896 
897         // EC P-256, empty 'kid'
898         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
899         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
900         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
901         "\"kid\": null }",
902 
903         // EC P-256 with private key 'd'
904         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
905         "\"x\": \"ccXrxIe0aS32y9kBkZFfAh6f7UvdcowtGH5uxCIo7eY\", "
906         "\"y\": \"GGQACnDgoiQvdQTsv1KxNUzOjZgnNoO4wQe_F75-bb0\", "
907         "\"kid\": \"F2BF329A-151B-4066-AB92-1CCA0C0F9DB5\", "
908         "\"d\": \"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\" }",
909 
910         // EC P-384
911         "{ \"kty\": \"EC\", \"crv\": \"P-384\", "
912         "\"x\": \"pO1SWmH7uOJfrtU1ibqVVK7VHffbpZtGfPYMPP_5KLQO9Dtsy41UEkMlL3BWHJDH\", "
913         "\"y\": \"RdBNoaV42bRE55V8PJR3Toeo8omQAIHPboOa7LlbQSGPYp6H6zW0tKroPquJYr3w\", "
914         "\"kid\": \"55680752-989A-4C5C-BC6E-48602489865C\" }",
915 
916         // EC P-521
917         "{ \"kty\": \"EC\", \"crv\": \"P-521\", "
918         "\"x\": \"AC8xogZa6uKAPU8086yAlG_inL3BaRyTB0pQUIJMENsPV_4S32DxIEEellMzQ_ts1Egp6OyS3ewjCUKHv5CTF7IV\", "
919         "\"y\": \"AIR1I2rUew5WyetOHYC-arEDDk2R30Yto6TTot92l4aY0DL8pSYxPVwv9beFUJEl95o_1Vv5y1453nFZW1Ca0uUj\", "
920         "\"kid\": \"A3EAB438-EBF8-4FEC-B605-A67C3A0D2313\" }",
921 
922         // RSA 2048 public params only
923         "{ \"kty\": \"RSA\", "
924         "\"e\": \"AQAB\", "
925         "\"n\": "
926         "\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Imt4EkILfPfZPeUYV6lElCjoY_4GBtQOy_"
927         "e4RvDSMC0pqt5X4e6mjQvLsaAClkBmhhCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_"
928         "ekEBUsm0Xq4p6N5DjC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8VFR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0Xv"
929         "WEMXj_zk0YnVTGAGdZeDPwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\", "
930         "\"kid\": \"05F24DC3-59F4-4AC5-9849-F2F5EA8A6F3E\" }",
931 
932         // RSA 2048 public and private params with CRT params
933         "{ \"kty\": \"RSA\", "
934         "\"e\": \"AQAB\", "
935         "\"n\": "
936         "\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Imt4EkILfPfZPeUYV6lElCjoY_4GBtQOy_"
937         "e4RvDSMC0pqt5X4e6mjQvLsaAClkBmhhCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_"
938         "ekEBUsm0Xq4p6N5DjC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8VFR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0Xv"
939         "WEMXj_zk0YnVTGAGdZeDPwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\", "
940         "\"kid\": \"F7D90C71-6671-4064-A0AA-379AD1862D19\", "
941         "\"d\": "
942         "\"bixuZapp0PYFXp98gXWTT1CQlycR61lvmFf0RFyWYo9n8H7gE7KcG7AmIHVY3UVDT7jgikMIqQOCPn1SI7BXsNIPBBujEGnfHDywHSyKfdNVG-"
943         "wkTGptP9OTo3kvpP5uSCwY6btBU-1JLyWggJC_RgmaKNNYIyUlny0Q-gOx0x0I-6ipWyLQVdKZBkw6erSODM244sPU9qEmyzVW7Nbmo5PKC1U4w-"
944         "Dt4nBe19TIUHG-ggN_UDRauljbegIIcnEWWeXdJZDdPUHgmIRa2ODN0mfSKl1CB4LJ2eyKlmddGLFiHys44OVwA8LVzrodUixIQP6wQ02AUwlaYU_"
945         "BWLEVoQ\", "
946         "\"p\": "
947         "\"9GRrzfmxrL_WgSKXexO6uc2hWh-lV9bPfBU735uHUFBS2_OOUjtQSYSqm-HK2ND1EIlPZBEEu9ccdshaEVYx79eP5fRnpF8EKEo1W-eeinmn7pQsfR-"
948         "6kFzkKmdBVhUyfpZvWtNuIwNZLu-HEvF2eIVVauQtJCPnjeYFbDyveqk\", "
949         "\"q\": "
950         "\"1uGXUwk052ayLvpYx3-L272X5srOyme3PCS2W1AZBXnXK06jqFp_KqUDpPnL3MNYZlfoYW5HIQBNpGCcZaTwfdLnSZroSbkQk-"
951         "9w3zfsOiJplDbZb77mG6xbw7m7AqcNQA6szoGlCrxluE74apKg4dUOg5rEx8-LOeK90rz-So8\", "
952         "\"dp\": "
953         "\"D36KYy2weQ5UkC1cQz5V-U-zKh6VggMpdml2OVAH_SyKhE1luYrvJSoXEvj2vlZJIzpBYUu-7BXQRSugoja_xb_57I9ZPs-"
954         "TWOaTiXce0xKxdevJAknPrzVkddfECawgXmw1NSHweqHMtrAS9T1_0FZLuxIqVn88P__UWi9ixLk\", "
955         "\"dq\": "
956         "\"J733d-MXBslGoUuqCdO8MTsCkivmTScbi6Mamw7YYdvkAN19hVCffmqgnu2YV89FVUBi-UolG6Rrt8AqjN4RoKPWJRXiamgw-"
957         "btqO86jASmGL2RpmLJM6sdY_X0nalktKTDNoy_1L2QiyBDK_yL5YGtAUPTZ-j6XeHBIPWa4_V8\", "
958         "\"qi\": "
959         "\"DJcZFEvdjynkwHEOrTSXLezReXT8bj73eo7Yoadtbln27nD_8q5yAobHVOO9ZzrwSoDCeepW_fVotgMuqxdGIBXZB_"
960         "DboRvjWW0QuBZ7Lg2SwwQqi9Ve8w31Z36gvOr1fR-Bd12B5STepC4SYBn1u5uMG5AIgfgzoa-FXEEBgB8\" }",
961 
962         // RSA 4096 public and private params, without CRT params
963         "{ \"kty\": \"RSA\", "
964         "\"e\": \"AQAB\", "
965         "\"n\": "
966         "\"vlbWUA9HUDHB5MDotmXObtE_Y4zKtGNtmPHUy_xkp_fSr0BxNdSOUzvzoAhK3sxTqpzVujKC245RHJ84Hhbl-KDj-"
967         "n7Ee8EV3nKpnsqiBgHyc3rBpxpIi0J8kYmpiPGXu7k4xnCWCeiu_gfFGzvPdLHzlV7WOfYIHvymtbS7WOyTQLBgDjUKfHdJzH75vogy35h_mEcS-pde-"
968         "EIi7u4OqD3bNW7iLbf2JVLtSNUYNCMMu23GsOEcBAsdf4QMq5gU-AEFK4Aib8mSPi_tXoohembr-"
969         "JkzByRAkHbdzoGXssj0EHESt4reDfY8enVo5ACKmzbqlIJ1jmPVV6EKPBPzcQiN9dUA43xei2gmRAswdUKnexVPAPFPfKMpLqr24h1e7jHFBQL23-QqZX-"
970         "gASbEDiYa9GusSY4kRn80hZRqCq4sgIRVEiu3ofjVdo4YzzESAkmfgFayUThhakqP82_wr9_Uc2vw3ZtlaTC_"
971         "0LY70ne9yTy3SD3yEOa649nOTBfSh156YGtxvaHHidFojVHpPHBmjGAlak--mONHXHn00l_CVivUcuBqIGcZXRfiO6YwVDH_4ZTVzAkDov1C-"
972         "4SNJK0XKeIwvGSspaSQrTmH_pT66L7tIhdZLTMVMh2ahnInVZP2G_-motugLq-x962JLQuLLeuh_r_Rk4VHZYhOgoc\", "
973         "\"kid\": \"2940921e-3646-451c-8510-971552754e74\", "
974         "\"d\": "
975         "\"oMyvxXcC4icHDQBEGUOswEYabTmWTgrpnho_kg0p5BUjclbYzYdCreKqEPqwdcTcsfhJP0JI9r8mmy2PtSvXINKbhxXtXDdlCEaKMdIySyz97L06OLelrbB_"
976         "mFxaU4z2iOsToeGff8OJgqaByF4hBw8HH5u9E75cYgFDvaJv29IRHMdkftwkfb4xJIfo6SQbBnbI5Ja22-"
977         "lhnA4TgRKwY0XOmTeR8NnHIwUJ3UvZZMJvkTBOeUPT7T6OrxmZsqWKoXILMhLQBOyfldXbjNDZM5UbqSuTxmbD_"
978         "MfO3xTwWWQXfIRqMZEpw1XRBguGj4g9kJ82Ujxcn-yLYbp08QhR0ijBY13HzFVMZ2jxqckrvp3uYgfJjcCN9QXZ6qlv40s_"
979         "vJRRgv4wxdDc035eoymqGQby0UnDTmhijRV_-eAJQvdl3bv-R5dH9IzhxoJA8xAqZfVtlehPuGaXDAsa4pIWSg9hZkMdDEjW15g3zTQi3ba8_"
980         "MfmnKuDe4GXYBjrH69z7epxbhnTmKQ-fZIxboA9sYuJHj6pEGT8D485QmrnmLjvqmQUzcxnpU6E3awksTp_"
981         "HeBYLLbmrv4DPGNyVri2yPPTTRrNBtbWkuvEGVnMhvL2ed9uqLSnH8zOfgWqstqjxadxKADidYEZzmiYfEjYTDZGd9VDIUdKNGHWGFRB7UE\", "
982         "\"p\": "
983         "\"6VtjaNMD_VKTbs7sUQk-qjPTn6mCI8_3loqrOOy32b1G0HfIzCijuV-"
984         "L7g7RxmMszEEfEILxRpJnOZRehN8etsIEuCdhU6VAdhBsBH5hIA9ZtX8GIs0sPrhc4kzPiwJ6JcLytUc6HCTICf2FIU7SI8I17-"
985         "p53d35VItYiC1sGLZ2yN61VoKYNTncUSwboP2zXmGv4FPB5wQogryA_bEn-"
986         "1U12FFSRd75Ku9GAEVxbTk3OaQqYgqfo9LnAWvunTDu31D4uyC6rze77NCo8UguqCpFjvF0ihOryQI6C3d0e8kxcM1vJbMvZNfrDN65btzqWi4m-"
987         "CnqGYkl6BXQtS5UVw\", "
988         "\"q\": "
989         "\"0M7h_gtxoVoNPLRjYA5zBUD8qmyWiAzjloFOrDRLJwiD4OPHgImUx2WPTiSCjouvGqwfJh1jEEryJV_d0e4iVGyKYbFeXfzadwYXXR2jK4QwO1V_"
990         "JDHI7HUYwNl6qzZqATi2zNKunPgIwY55gWBKjP2aUvPUBAcTeCsUPvrN_SajPVfc2wSlA2TvEnjmweNvgSTNqtBlMpmpwvEb9WXfv4pl3BfRvoTk3VR4icyvl-"
991         "PLFedp2y0Fs0aQ4LRQ2ZMKWyGQEam_uAoa1tXrRJ_yQRvtWm1K8GpRZGKwN3TvtAg649PxQ7tJ8cvh3BwQROJyQBZDrlR04wqvDK4SNezlUQ\" }",
992 
993         // oct 256
994         "{ \"kty\": \"oct\", "
995         "\"kid\": \"b779034d-2e9b-44a8-8334-55d6b7a0ef59\", "
996         "\"k\": \"wsL6R8uXG4RnsckLggj9Lg-kE5MMSJ8luzIBA8j7WXE\" }",
997 
998         // oct 512
999         "{ \"kty\": \"oct\", "
1000         "\"kid\": \"0c17c6d8-307d-4e4a-a860-a14788ee1110\", "
1001         "\"k\": \"qKcFDl6VSS7CgMpdF9we9JFEenMQniO-8lQ0DvFI1jzfTb93H2Gc0YzO4iNEZ7VPN6p0l-PyA4vlOrn0hPS5qA\" }",
1002 
1003         // oct 1024
1004         "{ \"kty\": \"oct\", "
1005         "\"kid\": \"3dfc3c58-74fd-4b8a-88d6-5321b30b554c\", "
1006         "\"k\": "
1007         "\"dCDW6NH5DkKtH6dTsRm_yJchQtrVxD_ZjDob3UquMBoAwdtVIjKvMztbP4XQE7Gf_QjzEa58_UrI80QzBxG_UpFxzpjTOBfWz8Do1BHZak_"
1008         "W1KBWDyfnEqc8RtxZmc4yE1dko5B8GUyfplMrEFa2tO899hnGe7pqRVdiwFF5QkY\" }",
1009 
1010         NULL,
1011     };
1012 
1013     cjose_jwk_t *jwk = NULL;
1014     for (int i = 0; JWK[i] != NULL; ++i)
1015     {
1016         // do import
1017         jwk = cjose_jwk_import(JWK[i], strlen(JWK[i]), &err);
1018         ck_assert_msg(NULL != jwk, "expected a cjose_jwk_t, but got NULL (%s) : "
1019                                    "%s, file: %s, function: %s, line: %ld",
1020                       JWK[i], err.message, err.file, err.function, err.line);
1021 
1022         // get json representation of "before"
1023         json_t *left_json = json_loads(JWK[i], 0, NULL);
1024         ck_assert(NULL != left_json);
1025 
1026         // get json representation of "after"
1027         char *jwk_str = cjose_jwk_to_json(jwk, true, &err);
1028         json_t *right_json = json_loads(jwk_str, 0, NULL);
1029         ck_assert(NULL != right_json);
1030 
1031         // check that cooresponding attributes match up
1032         const char *attrs[] = { "kty", "crv", "x", "y", "d", "kid", "e", "n", "p", "q", "dp", "dq", "qi", NULL };
1033         if (!_match_string_attrs(left_json, right_json, attrs))
1034         {
1035             ck_assert_str_eq(JWK[i], jwk_str);
1036         }
1037 
1038         free(jwk_str);
1039         json_decref(left_json);
1040         json_decref(right_json);
1041         cjose_jwk_release(jwk);
1042     }
1043 }
1044 END_TEST
1045 
START_TEST(test_cjose_jwk_import_invalid)1046 START_TEST(test_cjose_jwk_import_invalid)
1047 {
1048     cjose_err err;
1049     static const char *JWK[] = {
1050         // EC P-256 invalid 'kty'
1051         "{ \"kty\": \"EMC\", \"crv\": \"P-256\", "
1052         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1053         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1054         "\"kid\": \"0406E98B-CE84-4C78-965A-84C53BA73A1E\" }",
1055 
1056         // EC P-256 missing 'kty'
1057         "{ \"crv\": \"P-256\", "
1058         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1059         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1060         "\"kid\": \"EE05B07C-22ED-4059-A50B-4AD0A48E28D4\" }",
1061 
1062         // EC P-256 invalid 'crv'
1063         "{ \"kty\": \"EC\", \"crv\": \"P-257\", "
1064         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1065         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1066         "\"kid\": \"BB70E4BD-9547-4566-9195-1C45777D368B\" }",
1067 
1068         // EC P-256 missing 'crv'
1069         "{ \"kty\": \"EC\", "
1070         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1071         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1072         "\"kid\": \"928D103F-8DF2-41D5-A42B-7A72508FC70E\" }",
1073 
1074         // EC P-256 invalid 'x' (truncated)
1075         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1076         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20\", "
1077         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1078         "\"kid\": \"685A7314-EBE1-4E1A-A81D-8AB4A1B56452\" }",
1079 
1080         // EC P-256 invalid 'x' (a number)
1081         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1082         "\"x\": 42, "
1083         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1084         "\"kid\": \"5B3F3AB3-E716-4D85-8E4A-4BAC0D7D64E8\" }",
1085 
1086         // EC P-256 missing 'x'
1087         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1088         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1089         "\"kid\": \"9354D170-5FA4-46B5-901D-38098716E28A\" }",
1090 
1091         // EC P-256 invalid 'y' (truncated)
1092         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1093         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1094         "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRg\", "
1095         "\"kid\": \"262DDF7E-1AB5-43D1-91EA-13B99779DF16\" }",
1096 
1097         // EC P-256 invalid 'y' (an object)
1098         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1099         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1100         "\"y\": {}, "
1101         "\"kid\": \"1BEFD34C-A86E-4512-B206-7A2B94D82D27\" }",
1102 
1103         // EC P-256 missing 'y'
1104         "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1105         "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1106         "\"kid\": \"CBA61EED-3C61-45B3-9A35-9DE03F247720\" }",
1107 
1108         // EC P-384 invalid 'x' (truncated)
1109         "{ \"kty\": \"EC\", \"crv\": \"P-384\", "
1110         "\"x\": \"pO1SWmH7uOJfrtU1ibqVVK7VHffbpZtGfPYMPP_5KLQO9Dtsy41UEkMlL3BWHJD\", "
1111         "\"y\": \"RdBNoaV42bRE55V8PJR3Toeo8omQAIHPboOa7LlbQSGPYp6H6zW0tKroPquJYr3w\", "
1112         "\"kid\": \"FFC23684-88C8-4783-BBA3-ABF29971943B\" }",
1113 
1114         // EC P-521 invalid 'x' (truncated)
1115         "{ \"kty\": \"EC\", \"crv\": \"P-521\", "
1116         "\"x\": \"AVq9Y0jEvSINQJzcExSIUWYjo73cJcVTz_QHXCU7p9rbmC8chFdACiGLKDKlzdgW6lhZzA5qnp8mkpS2qJO_EVxU\", "
1117         "\"y\": \"AQHcQF8s_dhS_84CKLll0vkr0xCqWLp5XXdb79coYWI7Ev9SwZ4UZZVPxgu7ZGyp_2WdtaWw68uYeUVU4WiyKfP\", "
1118         "\"kid\": \"3930AC1C-C02F-46DA-9730-87785F405FE8\" }",
1119 
1120         // RSA 2048 missing 'n' (needed for both public and private)
1121         "{ \"kty\": \"RSA\", "
1122         "\"e\": \"AQAB\", "
1123         "\"kid\": \"05F24DC3-59F4-4AC5-9849-F2F5EA8A6F3E\" }",
1124 
1125         // empty object
1126         "{}",
1127 
1128         // empty string
1129         "\"\"",
1130 
1131         // null JWK
1132         "null",
1133 
1134         // a number
1135         "5",
1136 
1137         // nothing
1138         "",
1139 
1140         // junk
1141         "!@#$%^&*()",
1142 
1143         NULL,
1144     };
1145 
1146     cjose_jwk_t *jwk = NULL;
1147     for (int i = 0; JWK[i] != NULL; ++i)
1148     {
1149         jwk = cjose_jwk_import(JWK[i], strlen(JWK[i]), &err);
1150         ck_assert_msg(NULL == jwk, "expected NULL, received a cjose_jwk_t");
1151         ck_assert_int_eq(err.code, CJOSE_ERR_INVALID_ARG);
1152         cjose_jwk_release(jwk);
1153     }
1154 }
1155 END_TEST
1156 
START_TEST(test_cjose_jwk_import_underflow_length)1157 START_TEST(test_cjose_jwk_import_underflow_length)
1158 {
1159     cjose_err err;
1160     static const char *JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1161                              "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1162                              "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1163                              "\"kid\": \"CF21823B-D7C3-4C7F-BBE9-F11745E6BD21\" }";
1164 
1165     cjose_jwk_t *jwk = NULL;
1166 
1167     // test zero json doc length
1168     jwk = cjose_jwk_import(JWK, 0, &err);
1169     ck_assert_msg(NULL == jwk, "expected NULL, received a cjose_jwk_t");
1170     cjose_jwk_release(jwk);
1171 
1172     // test truncated length
1173     jwk = cjose_jwk_import(JWK, 10, &err);
1174     ck_assert_msg(NULL == jwk, "expected NULL, received a cjose_jwk_t");
1175     cjose_jwk_release(jwk);
1176 }
1177 END_TEST
1178 
START_TEST(test_cjose_jwk_import_no_zero_termination)1179 START_TEST(test_cjose_jwk_import_no_zero_termination)
1180 {
1181     cjose_err err;
1182     static const char *JWK = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1183                              "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1184                              "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1185                              "\"kid\": \"7CD876ED-6404-443A-8BBD-D4C1C99B6F71\" }, "
1186                              "{ \"kty\": \"EC\", \"crv\": \"P-384\", "
1187                              "\"x\": \"pO1SWmH7uOJfrtU1ibqVVK7VHffbpZtGfPYMPP_5KLQO9Dtsy41UEkMlL3BWHJD\", "
1188                              "\"y\": \"RdBNoaV42bRE55V8PJR3Toeo8omQAIHPboOa7LlbQSGPYp6H6zW0tKroPquJYr3w\", "
1189                              "\"kid\": \"7CD876ED-6404-443A-8BBD-D4C1C99B6F71\" }";
1190 
1191     cjose_jwk_t *jwk = NULL;
1192 
1193     // do import providing length of just the first key (which is length 182)
1194     jwk = cjose_jwk_import(JWK, 182, &err);
1195     ck_assert_msg(NULL != jwk, "expected a cjose_jwk_t, but got NULL");
1196 
1197     // get json representation of "before"
1198     json_t *left_json = json_loads(JWK, JSON_DISABLE_EOF_CHECK, NULL);
1199     ck_assert(NULL != left_json);
1200 
1201     // get json representation of "after"
1202     char *jwk_str = cjose_jwk_to_json(jwk, true, &err);
1203     json_t *right_json = json_loads(jwk_str, 0, NULL);
1204     ck_assert(NULL != right_json);
1205 
1206     // check that cooresponding attributes match up
1207     const char *attrs[] = { "kty", "crv", "x", "y", "d", "kid", NULL };
1208     if (!_match_string_attrs(left_json, right_json, attrs))
1209     {
1210         ck_assert_str_eq(JWK, jwk_str);
1211     }
1212 
1213     free(jwk_str);
1214     json_decref(left_json);
1215     json_decref(right_json);
1216     cjose_jwk_release(jwk);
1217 }
1218 END_TEST
1219 
START_TEST(test_cjose_jwk_import_with_base64url_padding)1220 START_TEST(test_cjose_jwk_import_with_base64url_padding)
1221 {
1222     cjose_err err;
1223     static const char *JWK_IN = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1224                                 "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M=\", "
1225                                 "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ=\", "
1226                                 "\"kid\": \"BEB14BFF-1D35-4AC0-9D0A-3FD44D1C834D\" }";
1227 
1228     static const char *JWK_OUT = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1229                                  "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", "
1230                                  "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", "
1231                                  "\"kid\": \"BEB14BFF-1D35-4AC0-9D0A-3FD44D1C834D\" }";
1232 
1233     cjose_jwk_t *jwk = NULL;
1234 
1235     // do import
1236     jwk = cjose_jwk_import(JWK_IN, strlen(JWK_IN), &err);
1237     ck_assert_msg(NULL != jwk, "expected a cjose_jwk_t, but got NULL");
1238 
1239     // get json representation of "expected" (i.e. no padding)
1240     json_t *left_json = json_loads(JWK_OUT, 0, NULL);
1241     ck_assert(NULL != left_json);
1242 
1243     // get json representation of "actual" (i.e. reserialized original)
1244     char *jwk_str = cjose_jwk_to_json(jwk, true, &err);
1245     json_t *right_json = json_loads(jwk_str, 0, NULL);
1246     ck_assert(NULL != right_json);
1247 
1248     // check that cooresponding attributes match up
1249     const char *attrs[] = { "kty", "crv", "x", "y", "d", "kid", NULL };
1250     if (!_match_string_attrs(left_json, right_json, attrs))
1251     {
1252         ck_assert_str_eq(JWK_OUT, jwk_str);
1253     }
1254 
1255     free(jwk_str);
1256     json_decref(left_json);
1257     json_decref(right_json);
1258     cjose_jwk_release(jwk);
1259 }
1260 END_TEST
1261 
START_TEST(test_cjose_jwk_EC_import_with_priv_export_with_pub)1262 START_TEST(test_cjose_jwk_EC_import_with_priv_export_with_pub)
1263 {
1264     cjose_err err;
1265     static const char *JWK_IN = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1266                                 "\"kid\": \"7302734F-A854-40BC-A44F-93F6F72B0D34\", "
1267                                 "\"d\": \"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\" }";
1268 
1269     static const char *JWK_OUT = "{ \"kty\": \"EC\", \"crv\": \"P-256\", "
1270                                  "\"x\": \"ccXrxIe0aS32y9kBkZFfAh6f7UvdcowtGH5uxCIo7eY\", "
1271                                  "\"y\": \"GGQACnDgoiQvdQTsv1KxNUzOjZgnNoO4wQe_F75-bb0\", "
1272                                  "\"kid\": \"7302734F-A854-40BC-A44F-93F6F72B0D34\", "
1273                                  "\"d\": \"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\" }";
1274 
1275     cjose_jwk_t *jwk = NULL;
1276 
1277     // do import which includes just the private key 'd'
1278     jwk = cjose_jwk_import(JWK_IN, strlen(JWK_IN), &err);
1279     ck_assert_msg(NULL != jwk, "expected a cjose_jwk_t, but got NULL");
1280 
1281     // get json representation of "expected" (i.e. includes 'x' and 'y')
1282     json_t *left_json = json_loads(JWK_OUT, 0, NULL);
1283     ck_assert(NULL != left_json);
1284 
1285     // get json representation of "actual" (i.e. reserialized original)
1286     char *jwk_str = cjose_jwk_to_json(jwk, true, &err);
1287     json_t *right_json = json_loads(jwk_str, 0, NULL);
1288     ck_assert(NULL != right_json);
1289 
1290     // check that cooresponding attributes match up
1291     const char *attrs[] = { "kty", "crv", "x", "y", "d", "kid", NULL };
1292     if (!_match_string_attrs(left_json, right_json, attrs))
1293     {
1294         ck_assert_str_eq(JWK_OUT, jwk_str);
1295     }
1296 
1297     free(jwk_str);
1298     json_decref(left_json);
1299     json_decref(right_json);
1300     cjose_jwk_release(jwk);
1301 }
1302 END_TEST
1303 
START_TEST(test_cjose_jwk_hkdf)1304 START_TEST(test_cjose_jwk_hkdf)
1305 {
1306     cjose_err err;
1307 
1308     const char *ikm = "source key material";
1309     size_t ikm_len = strlen(ikm);
1310 
1311     size_t ephemeral_key_len = 32;
1312     uint8_t *ephemeral_key = (uint8_t *)malloc(ephemeral_key_len);
1313     bool ok
1314         = cjose_jwk_hkdf(EVP_sha256(), (uint8_t *)"", 0, (uint8_t *)"", 0, ikm, ikm_len, ephemeral_key, ephemeral_key_len, &err);
1315     ck_assert_msg(ok, "Failed to compute HKDF");
1316 
1317     // the following is the expected output of HKDF with the ikm given above,
1318     // SHA256, no salt, no info, and an extend length of 256 bits, as provided
1319     // by the Ruby impl. of HKDF found here: https://github.com/jtdowney/hkdf
1320     const uint8_t expected[] = { 0x0C, 0x23, 0xF4, 0x62, 0x98, 0x9B, 0x7F, 0x77, 0x3E, 0x7C, 0x2F, 0x7C, 0x6B, 0xF4, 0x6B, 0xB7,
1321                                  0xB9, 0x11, 0x65, 0xC5, 0x92, 0xD1, 0x0C, 0x48, 0xFD, 0x47, 0x94, 0x76, 0x74, 0xB4, 0x14, 0xCE };
1322     for (int i = 0; i < ephemeral_key_len; i++)
1323     {
1324         ck_assert_msg(ephemeral_key[i] == expected[i], "HKDF failed on byte: %d", i);
1325     }
1326     free(ephemeral_key);
1327 }
1328 END_TEST
1329 
START_TEST(test_cjose_jwk_get_and_set_kid)1330 START_TEST(test_cjose_jwk_get_and_set_kid)
1331 {
1332     cjose_err err;
1333 
1334     const char *oldKid = "725cad72-23c6-4bf7-84c3-4583a6cf5fe9";
1335     const char *newKid = "aec1cebf-ddec-4d5f-8a61-f29e2f68dc41";
1336 
1337     static const char *JWK_BEFORE[] = { // OCT key
1338                                         "{\"kty\":\"oct\","
1339                                         "\"kid\":\"725cad72-23c6-4bf7-84c3-4583a6cf5fe9\","
1340                                         "\"k\":\"wsL6R8uXG4RnsckLggj9Lg-kE5MMSJ8luzIBA8j7WXE\"}",
1341 
1342                                         // EC key
1343                                         "{\"kty\":\"EC\","
1344                                         "\"kid\":\"725cad72-23c6-4bf7-84c3-4583a6cf5fe9\","
1345                                         "\"crv\":\"P-256\","
1346                                         "\"x\":\"ccXrxIe0aS32y9kBkZFfAh6f7UvdcowtGH5uxCIo7eY\","
1347                                         "\"y\":\"GGQACnDgoiQvdQTsv1KxNUzOjZgnNoO4wQe_F75-bb0\","
1348                                         "\"d\":\"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\"}",
1349 
1350                                         // RSA key
1351                                         "{\"kty\":\"RSA\","
1352                                         "\"kid\":\"725cad72-23c6-4bf7-84c3-4583a6cf5fe9\","
1353                                         "\"e\":\"AQAB\","
1354                                         "\"n\":\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Im"
1355                                         "t4EkILfPfZPeUYV6lElCjoY_4GBtQOy_e4RvDSMC0pqt5X4e6mjQvLsaAClkBmh"
1356                                         "hCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_ekEBUsm0Xq4p6N5D"
1357                                         "jC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8V"
1358                                         "FR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0XvWEMXj_zk0YnVTGAGdZeD"
1359                                         "PwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\"}",
1360 
1361                                         NULL
1362 
1363     };
1364 
1365     static const char *JWK_AFTER[] = { // OCT key
1366                                        "{\"kty\":\"oct\","
1367                                        "\"kid\":\"aec1cebf-ddec-4d5f-8a61-f29e2f68dc41\","
1368                                        "\"k\":\"wsL6R8uXG4RnsckLggj9Lg-kE5MMSJ8luzIBA8j7WXE\"}",
1369 
1370                                        // EC key
1371                                        "{\"kty\":\"EC\","
1372                                        "\"kid\":\"aec1cebf-ddec-4d5f-8a61-f29e2f68dc41\","
1373                                        "\"crv\":\"P-256\","
1374                                        "\"x\":\"ccXrxIe0aS32y9kBkZFfAh6f7UvdcowtGH5uxCIo7eY\","
1375                                        "\"y\":\"GGQACnDgoiQvdQTsv1KxNUzOjZgnNoO4wQe_F75-bb0\","
1376                                        "\"d\":\"hWdoUQvCWta1UQhC0nkTG0fHLFjWpDLv5wucVyq4-HY\"}",
1377 
1378                                        // RSA key
1379                                        "{\"kty\":\"RSA\","
1380                                        "\"kid\":\"aec1cebf-ddec-4d5f-8a61-f29e2f68dc41\","
1381                                        "\"e\":\"AQAB\","
1382                                        "\"n\":\"zSNO12-ydrm-bheszVm2ZvycKrSV2CN0xqQHPxB4yT8MFlWfopMA2Im"
1383                                        "t4EkILfPfZPeUYV6lElCjoY_4GBtQOy_e4RvDSMC0pqt5X4e6mjQvLsaAClkBmh"
1384                                        "hCYd-Vn9XIC3rSeAmBpSJDuwq_RTweXSG0hb_bn5FHf1Bl_ekEBUsm0Xq4p6N5D"
1385                                        "jC0ImNP74G0qxBVJzu07qsCJzYpifYYoEYkwIY7S4jqyHv55wiuMt89VTl37y8V"
1386                                        "FR3ll6RPiPFa4Raiminw5wKNJEmrGEukabibspiC0XvWEMXj_zk0YnVTGAGdZeD"
1387                                        "PwnjYY6JUOJ9KgcYkiQYb9SXetsjSbyheZw\"}",
1388 
1389                                        NULL
1390     };
1391 
1392     // because stuff happens
1393     ck_assert(sizeof(JWK_BEFORE) == sizeof(JWK_AFTER));
1394 
1395     const char *kid = NULL;
1396     char *json = NULL;
1397     for (int i = 0; JWK_BEFORE[i] != NULL; ++i)
1398     {
1399         // import the before state
1400         cjose_jwk_t *jwk = cjose_jwk_import(JWK_BEFORE[i], strlen(JWK_BEFORE[i]), &err);
1401         ck_assert_msg(NULL != jwk, "expected a cjose_jwk_t, but got NULL");
1402 
1403         // check that kid was imported correctly
1404         kid = cjose_jwk_get_kid(jwk, &err);
1405         ck_assert_msg(!strcmp(kid, oldKid), "match on imported JWK kid failed: %d", i);
1406 
1407         // change the kid
1408         ck_assert(cjose_jwk_set_kid(jwk, newKid, strlen(newKid), &err));
1409 
1410         // check that the kid was changed
1411         kid = cjose_jwk_get_kid(jwk, &err);
1412         ck_assert_msg(!strcmp(kid, newKid), "match on modified JWK kid failed: %d", i);
1413 
1414         // check that the kid is exported correctly
1415         json = cjose_jwk_to_json(jwk, true, &err);
1416         ck_assert_msg(!strcmp(json, JWK_AFTER[i]), "match on modified JWK JSON failed: %d", i);
1417 
1418         // freedom!
1419         cjose_jwk_release(jwk);
1420         free(json);
1421     }
1422 }
1423 END_TEST
1424 
cjose_jwk_suite()1425 Suite *cjose_jwk_suite()
1426 {
1427     Suite *suite = suite_create("jwk");
1428 
1429     TCase *tc_jwk = tcase_create("core");
1430     tcase_set_timeout(tc_jwk, 120.0);
1431     tcase_add_test(tc_jwk, test_cjose_jwk_name_for_kty);
1432     tcase_add_test(tc_jwk, test_cjose_jwk_create_RSA_spec);
1433     tcase_add_test(tc_jwk, test_cjose_jwk_create_RSA_random);
1434     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P256_spec);
1435     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P256_random);
1436     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P384_spec);
1437     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P384_random);
1438     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P521_spec);
1439     tcase_add_test(tc_jwk, test_cjose_jwk_create_EC_P521_random);
1440     tcase_add_test(tc_jwk, test_cjose_jwk_create_oct_spec);
1441     tcase_add_test(tc_jwk, test_cjose_jwk_create_oct_random);
1442     tcase_add_test(tc_jwk, test_cjose_jwk_create_oct_random_inval);
1443     tcase_add_test(tc_jwk, test_cjose_jwk_retain_release);
1444     tcase_add_test(tc_jwk, test_cjose_jwk_get_kty);
1445     tcase_add_test(tc_jwk, test_cjose_jwk_to_json_oct);
1446     tcase_add_test(tc_jwk, test_cjose_jwk_to_json_ec);
1447     tcase_add_test(tc_jwk, test_cjose_jwk_to_json_rsa);
1448     tcase_add_test(tc_jwk, test_cjose_jwk_import_json_valid);
1449     tcase_add_test(tc_jwk, test_cjose_jwk_import_json_invalid);
1450     tcase_add_test(tc_jwk, test_cjose_jwk_import_valid);
1451     tcase_add_test(tc_jwk, test_cjose_jwk_import_invalid);
1452     tcase_add_test(tc_jwk, test_cjose_jwk_import_underflow_length);
1453     tcase_add_test(tc_jwk, test_cjose_jwk_import_no_zero_termination);
1454     tcase_add_test(tc_jwk, test_cjose_jwk_import_with_base64url_padding);
1455     tcase_add_test(tc_jwk, test_cjose_jwk_EC_import_with_priv_export_with_pub);
1456     tcase_add_test(tc_jwk, test_cjose_jwk_hkdf);
1457     tcase_add_test(tc_jwk, test_cjose_jwk_get_and_set_kid);
1458     suite_add_tcase(suite, tc_jwk);
1459 
1460     return suite;
1461 }
1462