aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/oidc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/oidc_helper.c')
-rw-r--r--src/reclaim/oidc_helper.c532
1 files changed, 301 insertions, 231 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index ad2839200..9b5938c43 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -47,9 +47,9 @@ struct OIDC_Parameters
47 struct GNUNET_RECLAIM_Ticket ticket; 47 struct GNUNET_RECLAIM_Ticket ticket;
48 48
49 /** 49 /**
50 * The nonce 50 * The nonce length
51 */ 51 */
52 uint32_t nonce GNUNET_PACKED; 52 uint32_t nonce_len GNUNET_PACKED;
53 53
54 /** 54 /**
55 * The length of the PKCE code_challenge 55 * The length of the PKCE code_challenge
@@ -69,6 +69,51 @@ struct OIDC_Parameters
69 69
70GNUNET_NETWORK_STRUCT_END 70GNUNET_NETWORK_STRUCT_END
71 71
72/**
73 * Standard claims represented by the "profile" scope in OIDC
74 */
75static char OIDC_profile_claims[14][32] = {
76 "name", "family_name", "given_name", "middle_name", "nickname",
77 "preferred_username", "profile", "picture", "website", "gender", "birthdate",
78 "zoneinfo", "locale", "updated_at"
79};
80
81/**
82 * Standard claims represented by the "email" scope in OIDC
83 */
84static char OIDC_email_claims[2][16] = {
85 "email", "email_verified"
86};
87
88/**
89 * Standard claims represented by the "phone" scope in OIDC
90 */
91static char OIDC_phone_claims[2][32] = {
92 "phone_number", "phone_number_verified"
93};
94
95/**
96 * Standard claims represented by the "address" scope in OIDC
97 */
98static char OIDC_address_claims[5][32] = {
99 "street_address", "locality", "region", "postal_code", "country"
100};
101
102static enum GNUNET_GenericReturnValue
103is_claim_in_address_scope (const char *claim)
104{
105 int i;
106 for (i = 0; i < 5; i++)
107 {
108 if (0 == strcmp (claim, OIDC_address_claims[i]))
109 {
110 return GNUNET_YES;
111 }
112 }
113 return GNUNET_NO;
114}
115
116
72static char * 117static char *
73create_jwt_header (void) 118create_jwt_header (void)
74{ 119{
@@ -109,49 +154,22 @@ fix_base64 (char *str)
109 replace_char (str, '/', '_'); 154 replace_char (str, '/', '_');
110} 155}
111 156
112 157static json_t*
113/** 158generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
114 * Create a JWT from attributes 159 struct GNUNET_RECLAIM_AttributeList *attrs,
115 * 160 struct GNUNET_RECLAIM_AttestationList *attests)
116 * @param aud_key the public of the audience
117 * @param sub_key the public key of the subject
118 * @param attrs the attribute list
119 * @param expiration_time the validity of the token
120 * @param secret_key the key used to sign the JWT
121 * @return a new base64-encoded JWT string.
122 */
123char *
124OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
125 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
126 struct GNUNET_RECLAIM_AttributeList *attrs,
127 struct GNUNET_RECLAIM_AttestationList *attests,
128 const struct GNUNET_TIME_Relative *expiration_time,
129 const char *nonce,
130 const char *secret_key)
131{ 161{
132 struct GNUNET_RECLAIM_AttributeListEntry *le; 162 struct GNUNET_RECLAIM_AttributeListEntry *le;
133 struct GNUNET_RECLAIM_AttestationListEntry *ale; 163 struct GNUNET_RECLAIM_AttestationListEntry *ale;
134 struct GNUNET_HashCode signature;
135 struct GNUNET_TIME_Absolute exp_time;
136 struct GNUNET_TIME_Absolute time_now;
137 char *audience;
138 char *subject; 164 char *subject;
139 char *header;
140 char *body_str;
141 char *aggr_names_str;
142 char *aggr_sources_str;
143 char *source_name; 165 char *source_name;
144 char *result;
145 char *header_base64;
146 char *body_base64;
147 char *signature_target;
148 char *signature_base64;
149 char *attr_val_str; 166 char *attr_val_str;
150 char *attest_val_str; 167 char *attest_val_str;
151 json_t *body; 168 json_t *body;
152 json_t *aggr_names; 169 json_t *aggr_names;
153 json_t *aggr_sources; 170 json_t *aggr_sources;
154 json_t *aggr_sources_jwt; 171 json_t *aggr_sources_jwt;
172 json_t *addr_claim = NULL;
155 int num_attestations = 0; 173 int num_attestations = 0;
156 for (le = attrs->list_head; NULL != le; le = le->next) 174 for (le = attrs->list_head; NULL != le; le = le->next)
157 { 175 {
@@ -159,22 +177,10 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
159 num_attestations++; 177 num_attestations++;
160 } 178 }
161 179
162 // iat REQUIRED time now
163 time_now = GNUNET_TIME_absolute_get ();
164 // exp REQUIRED time expired from config
165 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
166 // auth_time only if max_age
167 // nonce only if nonce
168 // OPTIONAL acr,amr,azp
169 subject = 180 subject =
170 GNUNET_STRINGS_data_to_string_alloc (sub_key, 181 GNUNET_STRINGS_data_to_string_alloc (sub_key,
171 sizeof(struct 182 sizeof(struct
172 GNUNET_CRYPTO_EcdsaPublicKey)); 183 GNUNET_CRYPTO_EcdsaPublicKey));
173 audience =
174 GNUNET_STRINGS_data_to_string_alloc (aud_key,
175 sizeof(struct
176 GNUNET_CRYPTO_EcdsaPublicKey));
177 header = create_jwt_header ();
178 body = json_object (); 184 body = json_object ();
179 aggr_names = json_object (); 185 aggr_names = json_object ();
180 aggr_sources = json_object (); 186 aggr_sources = json_object ();
@@ -185,26 +191,7 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
185 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS)); 191 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
186 // sub REQUIRED public key identity, not exceed 255 ASCII length 192 // sub REQUIRED public key identity, not exceed 255 ASCII length
187 json_object_set_new (body, "sub", json_string (subject)); 193 json_object_set_new (body, "sub", json_string (subject));
188 // aud REQUIRED public key client_id must be there
189 json_object_set_new (body, "aud", json_string (audience));
190 // iat
191 json_object_set_new (body,
192 "iat",
193 json_integer (time_now.abs_value_us / (1000 * 1000)));
194 // exp
195 json_object_set_new (body,
196 "exp",
197 json_integer (exp_time.abs_value_us / (1000 * 1000)));
198 // nbf
199 json_object_set_new (body,
200 "nbf",
201 json_integer (time_now.abs_value_us / (1000 * 1000)));
202 // nonce
203 if (NULL != nonce)
204 json_object_set_new (body, "nonce", json_string (nonce));
205 attest_val_str = NULL; 194 attest_val_str = NULL;
206 aggr_names_str = NULL;
207 aggr_sources_str = NULL;
208 source_name = NULL; 195 source_name = NULL;
209 int i = 0; 196 int i = 0;
210 for (ale = attests->list_head; NULL != ale; ale = ale->next) 197 for (ale = attests->list_head; NULL != ale; ale = ale->next)
@@ -236,8 +223,26 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
236 GNUNET_RECLAIM_attribute_value_to_string (le->attribute->type, 223 GNUNET_RECLAIM_attribute_value_to_string (le->attribute->type,
237 le->attribute->data, 224 le->attribute->data,
238 le->attribute->data_size); 225 le->attribute->data_size);
239 json_object_set_new (body, le->attribute->name, 226 /**
240 json_string (attr_val_str)); 227 * There is this wierd quirk that the individual address claim(s) must be
228 * inside a JSON object of the "address" claim.
229 * FIXME: Possibly include formatted claim here
230 */
231 if (GNUNET_YES == is_claim_in_address_scope (le->attribute->name))
232 {
233 if (NULL == addr_claim)
234 {
235 addr_claim = json_object ();
236 }
237 json_object_set_new (addr_claim, le->attribute->name,
238 json_string (attr_val_str));
239
240 }
241 else
242 {
243 json_object_set_new (body, le->attribute->name,
244 json_string (attr_val_str));
245 }
241 GNUNET_free (attr_val_str); 246 GNUNET_free (attr_val_str);
242 } 247 }
243 else 248 else
@@ -262,21 +267,113 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
262 GNUNET_free (source_name); 267 GNUNET_free (source_name);
263 } 268 }
264 } 269 }
270 if (NULL != addr_claim)
271 json_object_set_new (body, "address", addr_claim);
265 272
266 if (NULL != attest_val_str) 273 if (NULL != attest_val_str)
267 GNUNET_free (attest_val_str); 274 GNUNET_free (attest_val_str);
268 if (0 != i) 275 if (0 != i)
269 { 276 {
270 aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT); 277 json_object_set_new (body, "_claim_names", aggr_names);
271 aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0) 278 json_object_set_new (body, "_claim_sources", aggr_sources);
272 | JSON_COMPACT);
273 json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
274 json_object_set_new (body, "_claim_sources", json_string (
275 aggr_sources_str));
276 } 279 }
277 280
278 json_decref (aggr_names); 281 return body;
279 json_decref (aggr_sources); 282}
283
284/**
285 * Generate userinfo JSON as string
286 *
287 * @param sub_key the subject (user)
288 * @param attrs user attribute list
289 * @param attests user attribute attestation list (may be empty)
290 * @return Userinfo JSON
291 */
292char *
293OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
294 struct GNUNET_RECLAIM_AttributeList *attrs,
295 struct GNUNET_RECLAIM_AttestationList *attests)
296{
297 char *body_str;
298 json_t* body = generate_userinfo_json (sub_key,
299 attrs,
300 attests);
301 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
302 json_decref (body);
303 return body_str;
304}
305
306
307/**
308 * Create a JWT from attributes
309 *
310 * @param aud_key the public of the audience
311 * @param sub_key the public key of the subject
312 * @param attrs the attribute list
313 * @param expiration_time the validity of the token
314 * @param secret_key the key used to sign the JWT
315 * @return a new base64-encoded JWT string.
316 */
317char *
318OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
319 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
320 struct GNUNET_RECLAIM_AttributeList *attrs,
321 struct GNUNET_RECLAIM_AttestationList *attests,
322 const struct GNUNET_TIME_Relative *expiration_time,
323 const char *nonce,
324 const char *secret_key)
325{
326 struct GNUNET_HashCode signature;
327 struct GNUNET_TIME_Absolute exp_time;
328 struct GNUNET_TIME_Absolute time_now;
329 char *audience;
330 char *subject;
331 char *header;
332 char *body_str;
333 char *result;
334 char *header_base64;
335 char *body_base64;
336 char *signature_target;
337 char *signature_base64;
338 json_t *body;
339
340 body = generate_userinfo_json (sub_key,
341 attrs,
342 attests);
343 // iat REQUIRED time now
344 time_now = GNUNET_TIME_absolute_get ();
345 // exp REQUIRED time expired from config
346 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
347 // auth_time only if max_age
348 // nonce only if nonce
349 // OPTIONAL acr,amr,azp
350 subject =
351 GNUNET_STRINGS_data_to_string_alloc (sub_key,
352 sizeof(struct
353 GNUNET_CRYPTO_EcdsaPublicKey));
354 audience =
355 GNUNET_STRINGS_data_to_string_alloc (aud_key,
356 sizeof(struct
357 GNUNET_CRYPTO_EcdsaPublicKey));
358 header = create_jwt_header ();
359
360 // aud REQUIRED public key client_id must be there
361 json_object_set_new (body, "aud", json_string (audience));
362 // iat
363 json_object_set_new (body,
364 "iat",
365 json_integer (time_now.abs_value_us / (1000 * 1000)));
366 // exp
367 json_object_set_new (body,
368 "exp",
369 json_integer (exp_time.abs_value_us / (1000 * 1000)));
370 // nbf
371 json_object_set_new (body,
372 "nbf",
373 json_integer (time_now.abs_value_us / (1000 * 1000)));
374 // nonce
375 if (NULL != nonce)
376 json_object_set_new (body, "nonce", json_string (nonce));
280 377
281 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT); 378 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
282 json_decref (body); 379 json_decref (body);
@@ -315,10 +412,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
315 GNUNET_free (signature_target); 412 GNUNET_free (signature_target);
316 GNUNET_free (header); 413 GNUNET_free (header);
317 GNUNET_free (body_str); 414 GNUNET_free (body_str);
318 if (NULL != aggr_sources_str)
319 GNUNET_free (aggr_sources_str);
320 if (NULL != aggr_names_str)
321 GNUNET_free (aggr_names_str);
322 GNUNET_free (signature_base64); 415 GNUNET_free (signature_base64);
323 GNUNET_free (body_base64); 416 GNUNET_free (body_base64);
324 GNUNET_free (header_base64); 417 GNUNET_free (header_base64);
@@ -326,89 +419,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
326} 419}
327 420
328 421
329static void
330derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
331 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
332 struct GNUNET_HashCode *key_material)
333{
334 static const char ctx_key[] = "reclaim-aes-ctx-key";
335 static const char ctx_iv[] = "reclaim-aes-ctx-iv";
336
337 GNUNET_CRYPTO_kdf (key,
338 sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
339 ctx_key,
340 strlen (ctx_key),
341 key_material,
342 sizeof(struct GNUNET_HashCode),
343 NULL);
344 GNUNET_CRYPTO_kdf (iv,
345 sizeof(
346 struct GNUNET_CRYPTO_SymmetricInitializationVector),
347 ctx_iv,
348 strlen (ctx_iv),
349 key_material,
350 sizeof(struct GNUNET_HashCode),
351 NULL);
352}
353
354
355static void
356calculate_key_priv (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
357 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
358 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
359 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
360{
361 struct GNUNET_HashCode key_material;
362
363 GNUNET_CRYPTO_ecdsa_ecdh (ecdsa_priv, ecdh_pub, &key_material);
364 derive_aes_key (key, iv, &key_material);
365}
366
367
368static void
369calculate_key_pub (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
370 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
371 const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
372 const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
373{
374 struct GNUNET_HashCode key_material;
375
376 GNUNET_CRYPTO_ecdh_ecdsa (ecdh_priv, ecdsa_pub, &key_material);
377 derive_aes_key (key, iv, &key_material);
378}
379
380
381static void
382decrypt_payload (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
383 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub,
384 const char *ct,
385 size_t ct_len,
386 char *buf)
387{
388 struct GNUNET_CRYPTO_SymmetricSessionKey key;
389 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
390
391 calculate_key_priv (&key, &iv, ecdsa_priv, ecdh_pub);
392 GNUNET_break (GNUNET_CRYPTO_symmetric_decrypt (ct, ct_len, &key, &iv, buf));
393}
394
395
396static void
397encrypt_payload (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
398 const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv,
399 const char *payload,
400 size_t payload_len,
401 char *buf)
402{
403 struct GNUNET_CRYPTO_SymmetricSessionKey key;
404 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
405
406 calculate_key_pub (&key, &iv, ecdsa_pub, ecdh_priv);
407 GNUNET_break (
408 GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf));
409}
410
411
412/** 422/**
413 * Builds an OIDC authorization code including 423 * Builds an OIDC authorization code including
414 * a reclaim ticket and nonce 424 * a reclaim ticket and nonce
@@ -439,34 +449,21 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
439 size_t attr_list_len = 0; 449 size_t attr_list_len = 0;
440 size_t attests_list_len = 0; 450 size_t attests_list_len = 0;
441 size_t code_challenge_len = 0; 451 size_t code_challenge_len = 0;
442 uint32_t nonce; 452 uint32_t nonce_len = 0;
443 uint32_t nonce_tmp;
444 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 453 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
445 struct GNUNET_CRYPTO_EcdhePrivateKey ecdh_priv;
446 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
447 454
448 /** PLAINTEXT **/ 455 /** PLAINTEXT **/
449 // Assign ticket 456 // Assign ticket
450 memset (&params, 0, sizeof(params)); 457 memset (&params, 0, sizeof(params));
451 params.ticket = *ticket; 458 params.ticket = *ticket;
452 // Assign nonce 459 // Assign nonce
453 nonce = 0;
454 payload_len = sizeof(struct OIDC_Parameters); 460 payload_len = sizeof(struct OIDC_Parameters);
455 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0)) 461 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
456 { 462 {
457 if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) 463 nonce_len = strlen (nonce_str);
458 { 464 payload_len += nonce_len;
459 GNUNET_break (0);
460 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
461 return NULL;
462 }
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Got nonce: %u from %s\n",
465 nonce,
466 nonce_str);
467 } 465 }
468 nonce_tmp = htonl (nonce); 466 params.nonce_len = htonl (nonce_len);
469 params.nonce = nonce_tmp;
470 // Assign code challenge 467 // Assign code challenge
471 if (NULL != code_challenge) 468 if (NULL != code_challenge)
472 code_challenge_len = strlen (code_challenge); 469 code_challenge_len = strlen (code_challenge);
@@ -506,6 +503,11 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
506 memcpy (tmp, code_challenge, code_challenge_len); 503 memcpy (tmp, code_challenge, code_challenge_len);
507 tmp += code_challenge_len; 504 tmp += code_challenge_len;
508 } 505 }
506 if (0 < nonce_len)
507 {
508 memcpy (tmp, nonce_str, nonce_len);
509 tmp += nonce_len;
510 }
509 if (0 < attr_list_len) 511 if (0 < attr_list_len)
510 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp); 512 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
511 if (0 < attests_list_len) 513 if (0 < attests_list_len)
@@ -513,36 +515,24 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
513 515
514 /** END **/ 516 /** END **/
515 517
516 /** ENCRYPT **/
517 // Get length 518 // Get length
518 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 519 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
519 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
520 + payload_len + sizeof(struct 520 + payload_len + sizeof(struct
521 GNUNET_CRYPTO_EcdsaSignature); 521 GNUNET_CRYPTO_EcdsaSignature);
522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
523 "Length of data to encode: %lu\n", 523 "Length of data to encode: %lu\n",
524 code_payload_len); 524 code_payload_len);
525 525
526 // Generate ECDH key
527 GNUNET_CRYPTO_ecdhe_key_create (&ecdh_priv);
528 GNUNET_CRYPTO_ecdhe_key_get_public (&ecdh_priv, &ecdh_pub);
529 // Initialize code payload 526 // Initialize code payload
530 code_payload = GNUNET_malloc (code_payload_len); 527 code_payload = GNUNET_malloc (code_payload_len);
531 GNUNET_assert (NULL != code_payload); 528 GNUNET_assert (NULL != code_payload);
532 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload; 529 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
533 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 530 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
534 + sizeof(ecdh_pub) + payload_len); 531 + payload_len);
535 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); 532 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
536 // Store pubkey 533 // Store pubkey
537 buf_ptr = (char *) &purpose[1]; 534 buf_ptr = (char *) &purpose[1];
538 memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub)); 535 memcpy (buf_ptr, payload, payload_len);
539 buf_ptr += sizeof(ecdh_pub);
540 // Encrypt plaintext and store
541 encrypt_payload (&ticket->audience,
542 &ecdh_priv,
543 payload,
544 payload_len,
545 buf_ptr);
546 GNUNET_free (payload); 536 GNUNET_free (payload);
547 buf_ptr += payload_len; 537 buf_ptr += payload_len;
548 // Sign and store signature 538 // Sign and store signature
@@ -570,14 +560,16 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
570 * 560 *
571 * @param audience the expected audience of the code 561 * @param audience the expected audience of the code
572 * @param code the string representation of the code 562 * @param code the string representation of the code
573 * @param code_verfier PKCE code verifier 563 * @param code_verfier PKCE code verifier. Optional, must be provided
564 * if used in request.
574 * @param ticket where to store the ticket 565 * @param ticket where to store the ticket
575 * @param attrs the attributes in the code 566 * @param attrs the attributes in the code
576 * @param nonce where to store the nonce 567 * @param attests the attestations in the code (if any)
568 * @param nonce_str where to store the nonce (if contained)
577 * @return GNUNET_OK if successful, else GNUNET_SYSERR 569 * @return GNUNET_OK if successful, else GNUNET_SYSERR
578 */ 570 */
579int 571int
580OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, 572OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
581 const char *code, 573 const char *code,
582 const char *code_verifier, 574 const char *code_verifier,
583 struct GNUNET_RECLAIM_Ticket *ticket, 575 struct GNUNET_RECLAIM_Ticket *ticket,
@@ -595,14 +587,12 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
595 char *code_verifier_hash; 587 char *code_verifier_hash;
596 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 588 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
597 struct GNUNET_CRYPTO_EcdsaSignature *signature; 589 struct GNUNET_CRYPTO_EcdsaSignature *signature;
598 struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
599 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
600 uint32_t code_challenge_len; 590 uint32_t code_challenge_len;
601 uint32_t attrs_ser_len; 591 uint32_t attrs_ser_len;
602 uint32_t attests_ser_len; 592 uint32_t attests_ser_len;
603 size_t plaintext_len; 593 size_t plaintext_len;
604 size_t code_payload_len; 594 size_t code_payload_len;
605 uint32_t nonce = 0; 595 uint32_t nonce_len = 0;
606 struct OIDC_Parameters *params; 596 struct OIDC_Parameters *params;
607 597
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); 598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
@@ -611,7 +601,6 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
611 GNUNET_STRINGS_base64url_decode (code, strlen (code), 601 GNUNET_STRINGS_base64url_decode (code, strlen (code),
612 (void **) &code_payload); 602 (void **) &code_payload);
613 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 603 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
614 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
615 + sizeof(struct OIDC_Parameters) 604 + sizeof(struct OIDC_Parameters)
616 + sizeof(struct GNUNET_CRYPTO_EcdsaSignature)) 605 + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
617 { 606 {
@@ -624,16 +613,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
624 plaintext_len = code_payload_len; 613 plaintext_len = code_payload_len;
625 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose); 614 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
626 ptr = (char *) &purpose[1]; 615 ptr = (char *) &purpose[1];
627 // Public ECDH key
628 ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
629 ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
630 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
631
632 // Decrypt ciphertext
633 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature); 616 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
634 plaintext = GNUNET_malloc (plaintext_len); 617 plaintext = ptr;
635 decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
636 // ptr = plaintext;
637 ptr += plaintext_len; 618 ptr += plaintext_len;
638 signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr; 619 signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
639 params = (struct OIDC_Parameters *) plaintext; 620 params = (struct OIDC_Parameters *) plaintext;
@@ -658,11 +639,10 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
658 // encode code verifier 639 // encode code verifier
659 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8, 640 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
660 &expected_code_challenge); 641 &expected_code_challenge);
661 code_challenge = (char *) &params[1]; 642 code_challenge = ((char *) &params[1]);
662 GNUNET_free (code_verifier_hash); 643 GNUNET_free (code_verifier_hash);
663 if ((strlen (expected_code_challenge) != code_challenge_len) || 644 if (0 !=
664 (0 != 645 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
665 strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
666 { 646 {
667 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 647 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
668 "Invalid code verifier! Expected: %s, Got: %.*s\n", 648 "Invalid code verifier! Expected: %s, Got: %.*s\n",
@@ -675,17 +655,23 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
675 } 655 }
676 GNUNET_free (expected_code_challenge); 656 GNUNET_free (expected_code_challenge);
677 } 657 }
658 nonce_len = ntohl (params->nonce_len);
659 if (0 != nonce_len)
660 {
661 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
662 nonce_len);
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
664 }
665
678 // Ticket 666 // Ticket
679 memcpy (ticket, &params->ticket, sizeof(params->ticket)); 667 memcpy (ticket, &params->ticket, sizeof(params->ticket));
680 // Nonce
681 nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr));
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
683 // Signature 668 // Signature
684 GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub); 669 // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
685 if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience)) 670 if (0 != GNUNET_memcmp (audience, &ticket->audience))
686 { 671 {
687 GNUNET_free (code_payload); 672 GNUNET_free (code_payload);
688 GNUNET_free (plaintext); 673 if (NULL != *nonce_str)
674 GNUNET_free (*nonce_str);
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 675 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Audience in ticket does not match client!\n"); 676 "Audience in ticket does not match client!\n");
691 return GNUNET_SYSERR; 677 return GNUNET_SYSERR;
@@ -697,12 +683,13 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
697 &ticket->identity)) 683 &ticket->identity))
698 { 684 {
699 GNUNET_free (code_payload); 685 GNUNET_free (code_payload);
700 GNUNET_free (plaintext); 686 if (NULL != *nonce_str)
687 GNUNET_free (*nonce_str);
701 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n"); 688 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
702 return GNUNET_SYSERR; 689 return GNUNET_SYSERR;
703 } 690 }
704 // Attributes 691 // Attributes
705 attrs_ser = ((char *) &params[1]) + code_challenge_len; 692 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
706 attrs_ser_len = ntohl (params->attr_list_len); 693 attrs_ser_len = ntohl (params->attr_list_len);
707 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len); 694 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
708 attests_ser = ((char*) attrs_ser) + attrs_ser_len; 695 attests_ser = ((char*) attrs_ser) + attrs_ser_len;
@@ -710,11 +697,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
710 *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser, 697 *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser,
711 attests_ser_len); 698 attests_ser_len);
712 699
713 *nonce_str = NULL;
714 if (nonce != 0)
715 GNUNET_asprintf (nonce_str, "%u", nonce);
716 GNUNET_free (code_payload); 700 GNUNET_free (code_payload);
717 GNUNET_free (plaintext);
718 return GNUNET_OK; 701 return GNUNET_OK;
719} 702}
720 703
@@ -757,15 +740,102 @@ OIDC_build_token_response (const char *access_token,
757 * Generate a new access token 740 * Generate a new access token
758 */ 741 */
759char * 742char *
760OIDC_access_token_new () 743OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket)
761{ 744{
762 char *access_token; 745 char *access_token;
763 uint64_t random_number;
764 746
765 random_number = 747 GNUNET_STRINGS_base64_encode (ticket,
766 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); 748 sizeof(*ticket),
767 GNUNET_STRINGS_base64_encode (&random_number,
768 sizeof(uint64_t),
769 &access_token); 749 &access_token);
770 return access_token; 750 return access_token;
771} 751}
752
753
754/**
755 * Parse an access token
756 */
757int
758OIDC_access_token_parse (const char *token,
759 struct GNUNET_RECLAIM_Ticket **ticket)
760{
761 if (sizeof (struct GNUNET_RECLAIM_Ticket) !=
762 GNUNET_STRINGS_base64_decode (token,
763 strlen (token),
764 (void**) ticket))
765 return GNUNET_SYSERR;
766 return GNUNET_OK;
767}
768
769
770/**
771 * Checks if a claim is implicitly requested through standard
772 * scope(s)
773 *
774 * @param scopes the scopes which have been requested
775 * @param attr the attribute name to check
776 * @return GNUNET_YES if attribute is implcitly requested
777 */
778enum GNUNET_GenericReturnValue
779OIDC_check_scopes_for_claim_request (const char*scopes,
780 const char*attr)
781{
782 char *scope_variables;
783 char *scope_variable;
784 char delimiter[] = " ";
785 int i;
786
787 scope_variables = GNUNET_strdup (scopes);
788 scope_variable = strtok (scope_variables, delimiter);
789 while (NULL != scope_variable)
790 {
791 if (0 == strcmp ("profile", scope_variable))
792 {
793 for (i = 0; i < 14; i++)
794 {
795 if (0 == strcmp (attr, OIDC_profile_claims[i]))
796 {
797 GNUNET_free (scope_variables);
798 return GNUNET_YES;
799 }
800 }
801 }
802 else if (0 == strcmp ("address", scope_variable))
803 {
804 for (i = 0; i < 5; i++)
805 {
806 if (0 == strcmp (attr, OIDC_address_claims[i]))
807 {
808 GNUNET_free (scope_variables);
809 return GNUNET_YES;
810 }
811 }
812 }
813 else if (0 == strcmp ("email", scope_variable))
814 {
815 for (i = 0; i < 2; i++)
816 {
817 if (0 == strcmp (attr, OIDC_email_claims[i]))
818 {
819 GNUNET_free (scope_variables);
820 return GNUNET_YES;
821 }
822 }
823 }
824 else if (0 == strcmp ("phone", scope_variable))
825 {
826 for (i = 0; i < 2; i++)
827 {
828 if (0 == strcmp (attr, OIDC_phone_claims[i]))
829 {
830 GNUNET_free (scope_variables);
831 return GNUNET_YES;
832 }
833 }
834
835 }
836 scope_variable = strtok (NULL, delimiter);
837 }
838 GNUNET_free (scope_variables);
839 return GNUNET_NO;
840
841}