diff options
author | Tristan Schwieren <tristan.schwieren@tum.de> | 2022-04-11 13:29:20 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-06-09 11:43:01 +0200 |
commit | 349b4e37123368e3f03d563770d72bcbfd8109ad (patch) | |
tree | 865732d15ee62fa5c7e5d651445ea276a4d4756d /src/reclaim/oidc_helper.c | |
parent | 79eff4349f89d13a8cc707550f6bb7d5fe8c99c3 (diff) | |
download | gnunet-349b4e37123368e3f03d563770d72bcbfd8109ad.tar.gz gnunet-349b4e37123368e3f03d563770d72bcbfd8109ad.zip |
-init oidc RSA256 feature
Diffstat (limited to 'src/reclaim/oidc_helper.c')
-rw-r--r-- | src/reclaim/oidc_helper.c | 160 |
1 files changed, 128 insertions, 32 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index 9237902ce..cfa71b26c 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c | |||
@@ -22,10 +22,12 @@ | |||
22 | * @file reclaim/oidc_helper.c | 22 | * @file reclaim/oidc_helper.c |
23 | * @brief helper library for OIDC related functions | 23 | * @brief helper library for OIDC related functions |
24 | * @author Martin Schanzenbach | 24 | * @author Martin Schanzenbach |
25 | * @author Tristan Schwieren | ||
25 | */ | 26 | */ |
26 | #include "platform.h" | 27 | #include "platform.h" |
27 | #include <inttypes.h> | 28 | #include <inttypes.h> |
28 | #include <jansson.h> | 29 | #include <jansson.h> |
30 | #include <jose/jose.h> | ||
29 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_reclaim_lib.h" | 32 | #include "gnunet_reclaim_lib.h" |
31 | #include "gnunet_reclaim_service.h" | 33 | #include "gnunet_reclaim_service.h" |
@@ -115,13 +117,13 @@ is_claim_in_address_scope (const char *claim) | |||
115 | 117 | ||
116 | 118 | ||
117 | static char * | 119 | static char * |
118 | create_jwt_header (void) | 120 | create_jwt_hmac_header (void) |
119 | { | 121 | { |
120 | json_t *root; | 122 | json_t *root; |
121 | char *json_str; | 123 | char *json_str; |
122 | 124 | ||
123 | root = json_object (); | 125 | root = json_object (); |
124 | json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE)); | 126 | json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE_HMAC)); |
125 | json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE)); | 127 | json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE)); |
126 | 128 | ||
127 | json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT); | 129 | json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT); |
@@ -356,40 +358,22 @@ OIDC_generate_userinfo (const struct GNUNET_IDENTITY_PublicKey *sub_key, | |||
356 | } | 358 | } |
357 | 359 | ||
358 | 360 | ||
359 | /** | ||
360 | * Create a JWT from attributes | ||
361 | * | ||
362 | * @param aud_key the public of the audience | ||
363 | * @param sub_key the public key of the subject | ||
364 | * @param attrs the attribute list | ||
365 | * @param presentations credential presentation list (may be empty) | ||
366 | * @param expiration_time the validity of the token | ||
367 | * @param secret_key the key used to sign the JWT | ||
368 | * @return a new base64-encoded JWT string. | ||
369 | */ | ||
370 | char * | 361 | char * |
371 | OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key, | 362 | generate_id_token_body (const struct GNUNET_IDENTITY_PublicKey *aud_key, |
372 | const struct GNUNET_IDENTITY_PublicKey *sub_key, | 363 | const struct GNUNET_IDENTITY_PublicKey *sub_key, |
373 | const struct GNUNET_RECLAIM_AttributeList *attrs, | 364 | const struct GNUNET_RECLAIM_AttributeList *attrs, |
374 | const struct | 365 | const struct |
375 | GNUNET_RECLAIM_PresentationList *presentations, | 366 | GNUNET_RECLAIM_PresentationList *presentations, |
376 | const struct GNUNET_TIME_Relative *expiration_time, | 367 | const struct GNUNET_TIME_Relative *expiration_time, |
377 | const char *nonce, | 368 | const char *nonce) |
378 | const char *secret_key) | ||
379 | { | 369 | { |
380 | struct GNUNET_HashCode signature; | 370 | struct GNUNET_HashCode signature; |
381 | struct GNUNET_TIME_Absolute exp_time; | 371 | struct GNUNET_TIME_Absolute exp_time; |
382 | struct GNUNET_TIME_Absolute time_now; | 372 | struct GNUNET_TIME_Absolute time_now; |
373 | json_t *body; | ||
383 | char *audience; | 374 | char *audience; |
384 | char *subject; | 375 | char *subject; |
385 | char *header; | ||
386 | char *body_str; | 376 | char *body_str; |
387 | char *result; | ||
388 | char *header_base64; | ||
389 | char *body_base64; | ||
390 | char *signature_target; | ||
391 | char *signature_base64; | ||
392 | json_t *body; | ||
393 | 377 | ||
394 | body = generate_userinfo_json (sub_key, | 378 | body = generate_userinfo_json (sub_key, |
395 | attrs, | 379 | attrs, |
@@ -409,7 +393,6 @@ OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key, | |||
409 | GNUNET_STRINGS_data_to_string_alloc (aud_key, | 393 | GNUNET_STRINGS_data_to_string_alloc (aud_key, |
410 | sizeof(struct | 394 | sizeof(struct |
411 | GNUNET_IDENTITY_PublicKey)); | 395 | GNUNET_IDENTITY_PublicKey)); |
412 | header = create_jwt_header (); | ||
413 | 396 | ||
414 | // aud REQUIRED public key client_id must be there | 397 | // aud REQUIRED public key client_id must be there |
415 | json_object_set_new (body, "aud", json_string (audience)); | 398 | json_object_set_new (body, "aud", json_string (audience)); |
@@ -429,19 +412,132 @@ OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key, | |||
429 | if (NULL != nonce) | 412 | if (NULL != nonce) |
430 | json_object_set_new (body, "nonce", json_string (nonce)); | 413 | json_object_set_new (body, "nonce", json_string (nonce)); |
431 | 414 | ||
432 | body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT); | 415 | // Error checking |
433 | json_decref (body); | 416 | body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT); |
434 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str); | 417 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str); |
435 | 418 | ||
419 | json_decref (body); | ||
420 | GNUNET_free (subject); | ||
421 | GNUNET_free (audience); | ||
422 | |||
423 | return body_str; | ||
424 | } | ||
425 | |||
426 | |||
427 | /** | ||
428 | * Create a JWT using RSA256 algorithm from attributes | ||
429 | * | ||
430 | * @param aud_key the public of the audience | ||
431 | * @param sub_key the public key of the subject | ||
432 | * @param attrs the attribute list | ||
433 | * @param presentations credential presentation list (may be empty) | ||
434 | * @param expiration_time the validity of the token | ||
435 | * @param secret_rsa_key the key used to sign the JWT | ||
436 | * @return a new base64-encoded JWT string. | ||
437 | */ | ||
438 | char * | ||
439 | OIDC_generate_id_token_rsa (const struct GNUNET_IDENTITY_PublicKey *aud_key, | ||
440 | const struct GNUNET_IDENTITY_PublicKey *sub_key, | ||
441 | const struct GNUNET_RECLAIM_AttributeList *attrs, | ||
442 | const struct | ||
443 | GNUNET_RECLAIM_PresentationList *presentations, | ||
444 | const struct GNUNET_TIME_Relative *expiration_time, | ||
445 | const char *nonce, | ||
446 | const json_t *secret_rsa_key) | ||
447 | { | ||
448 | json_t *jws; | ||
449 | char *body_str; | ||
450 | char *result; | ||
451 | |||
452 | // Generate the body of the JSON Web Signature | ||
453 | body_str = generate_id_token_body (aud_key, | ||
454 | sub_key, | ||
455 | attrs, | ||
456 | presentations, | ||
457 | expiration_time, | ||
458 | nonce); | ||
459 | |||
460 | if (! body_str) | ||
461 | { | ||
462 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
463 | "Body for the JWS could not be generated\n"); | ||
464 | } | ||
465 | |||
466 | // Creating the JSON Web Signature. | ||
467 | jws = json_pack ("{s:o}", "payload", | ||
468 | jose_b64_enc (body_str, strlen (body_str))); | ||
469 | |||
470 | if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key)) | ||
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
473 | "Signature generation failed\n"); | ||
474 | } | ||
475 | |||
476 | // Encoding JSON as compact JSON Web Signature | ||
477 | GNUNET_asprintf (&result, "%s.%s.%s", | ||
478 | json_string_value (json_object_get (jws, "protected")), | ||
479 | json_string_value (json_object_get (jws, "payload")), | ||
480 | json_string_value (json_object_get (jws, "signature")) ); | ||
481 | |||
482 | json_decref(jws); | ||
483 | GNUNET_free(body_str); | ||
484 | return result; | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * Create a JWT using HMAC (HS256) from attributes | ||
489 | * | ||
490 | * @param aud_key the public of the audience | ||
491 | * @param sub_key the public key of the subject | ||
492 | * @param attrs the attribute list | ||
493 | * @param presentations credential presentation list (may be empty) | ||
494 | * @param expiration_time the validity of the token | ||
495 | * @param secret_key the key used to sign the JWT | ||
496 | * @return a new base64-encoded JWT string. | ||
497 | */ | ||
498 | char * | ||
499 | OIDC_generate_id_token_hmac (const struct GNUNET_IDENTITY_PublicKey *aud_key, | ||
500 | const struct GNUNET_IDENTITY_PublicKey *sub_key, | ||
501 | const struct GNUNET_RECLAIM_AttributeList *attrs, | ||
502 | const struct | ||
503 | GNUNET_RECLAIM_PresentationList *presentations, | ||
504 | const struct GNUNET_TIME_Relative *expiration_time, | ||
505 | const char *nonce, | ||
506 | const char *secret_key) | ||
507 | { | ||
508 | struct GNUNET_HashCode signature; | ||
509 | struct GNUNET_TIME_Absolute exp_time; | ||
510 | struct GNUNET_TIME_Absolute time_now; | ||
511 | char *header; | ||
512 | char *header_base64; | ||
513 | char *body_str; | ||
514 | char *body_base64; | ||
515 | char *signature_target; | ||
516 | char *signature_base64; | ||
517 | char *result; | ||
518 | |||
519 | // Generate and encode Header | ||
520 | header = create_jwt_hmac_header (); | ||
436 | GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64); | 521 | GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64); |
437 | fix_base64 (header_base64); | 522 | fix_base64 (header_base64); |
438 | 523 | ||
524 | // Generate and encode the body of the JSON Web Signature | ||
525 | body_str = generate_id_token_body (aud_key, | ||
526 | sub_key, | ||
527 | attrs, | ||
528 | presentations, | ||
529 | expiration_time, | ||
530 | nonce); | ||
531 | |||
532 | if (! body_str) | ||
533 | { | ||
534 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
535 | "Body for the JWS could not be generated\n"); | ||
536 | } | ||
537 | |||
439 | GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64); | 538 | GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64); |
440 | fix_base64 (body_base64); | 539 | fix_base64 (body_base64); |
441 | 540 | ||
442 | GNUNET_free (subject); | ||
443 | GNUNET_free (audience); | ||
444 | |||
445 | /** | 541 | /** |
446 | * Creating the JWT signature. This might not be | 542 | * Creating the JWT signature. This might not be |
447 | * standards compliant, check. | 543 | * standards compliant, check. |
@@ -463,12 +559,12 @@ OIDC_generate_id_token (const struct GNUNET_IDENTITY_PublicKey *aud_key, | |||
463 | body_base64, | 559 | body_base64, |
464 | signature_base64); | 560 | signature_base64); |
465 | 561 | ||
466 | GNUNET_free (signature_target); | ||
467 | GNUNET_free (header); | 562 | GNUNET_free (header); |
563 | GNUNET_free (header_base64); | ||
468 | GNUNET_free (body_str); | 564 | GNUNET_free (body_str); |
469 | GNUNET_free (signature_base64); | ||
470 | GNUNET_free (body_base64); | 565 | GNUNET_free (body_base64); |
471 | GNUNET_free (header_base64); | 566 | GNUNET_free (signature_target); |
567 | GNUNET_free (signature_base64); | ||
472 | return result; | 568 | return result; |
473 | } | 569 | } |
474 | 570 | ||