aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/oidc_helper.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2020-08-05 11:35:05 +0200
committerMartin Schanzenbach <mschanzenbach@posteo.de>2020-08-05 11:35:05 +0200
commit6e764f4abd8a3f14f03a5a167af7d5cb703fd1d5 (patch)
treed5efbc30c698cdf191bf3ffa96e6c80ee5e9154c /src/reclaim/oidc_helper.c
parentade9b5e5248a97438ecb979f3be353f565a27ba1 (diff)
downloadgnunet-6e764f4abd8a3f14f03a5a167af7d5cb703fd1d5.tar.gz
gnunet-6e764f4abd8a3f14f03a5a167af7d5cb703fd1d5.zip
reclaim: Make SPAs work with public clients. No longer encrypt code.
Diffstat (limited to 'src/reclaim/oidc_helper.c')
-rw-r--r--src/reclaim/oidc_helper.c185
1 files changed, 39 insertions, 146 deletions
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index b48738cc4..4da387564 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
@@ -326,89 +326,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
326} 326}
327 327
328 328
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/** 329/**
413 * Builds an OIDC authorization code including 330 * Builds an OIDC authorization code including
414 * a reclaim ticket and nonce 331 * a reclaim ticket and nonce
@@ -439,34 +356,21 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
439 size_t attr_list_len = 0; 356 size_t attr_list_len = 0;
440 size_t attests_list_len = 0; 357 size_t attests_list_len = 0;
441 size_t code_challenge_len = 0; 358 size_t code_challenge_len = 0;
442 uint32_t nonce; 359 uint32_t nonce_len = 0;
443 uint32_t nonce_tmp;
444 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 360 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
445 struct GNUNET_CRYPTO_EcdhePrivateKey ecdh_priv;
446 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
447 361
448 /** PLAINTEXT **/ 362 /** PLAINTEXT **/
449 // Assign ticket 363 // Assign ticket
450 memset (&params, 0, sizeof(params)); 364 memset (&params, 0, sizeof(params));
451 params.ticket = *ticket; 365 params.ticket = *ticket;
452 // Assign nonce 366 // Assign nonce
453 nonce = 0;
454 payload_len = sizeof(struct OIDC_Parameters); 367 payload_len = sizeof(struct OIDC_Parameters);
455 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0)) 368 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
456 { 369 {
457 if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) 370 nonce_len = strlen (nonce_str);
458 { 371 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 } 372 }
468 nonce_tmp = htonl (nonce); 373 params.nonce_len = htonl (nonce_len);
469 params.nonce = nonce_tmp;
470 // Assign code challenge 374 // Assign code challenge
471 if (NULL != code_challenge) 375 if (NULL != code_challenge)
472 code_challenge_len = strlen (code_challenge); 376 code_challenge_len = strlen (code_challenge);
@@ -506,6 +410,11 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
506 memcpy (tmp, code_challenge, code_challenge_len); 410 memcpy (tmp, code_challenge, code_challenge_len);
507 tmp += code_challenge_len; 411 tmp += code_challenge_len;
508 } 412 }
413 if (0 < nonce_len)
414 {
415 memcpy (tmp, nonce_str, nonce_len);
416 tmp += nonce_len;
417 }
509 if (0 < attr_list_len) 418 if (0 < attr_list_len)
510 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp); 419 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
511 if (0 < attests_list_len) 420 if (0 < attests_list_len)
@@ -513,36 +422,24 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
513 422
514 /** END **/ 423 /** END **/
515 424
516 /** ENCRYPT **/
517 // Get length 425 // Get length
518 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 426 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
519 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
520 + payload_len + sizeof(struct 427 + payload_len + sizeof(struct
521 GNUNET_CRYPTO_EcdsaSignature); 428 GNUNET_CRYPTO_EcdsaSignature);
522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
523 "Length of data to encode: %lu\n", 430 "Length of data to encode: %lu\n",
524 code_payload_len); 431 code_payload_len);
525 432
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 433 // Initialize code payload
530 code_payload = GNUNET_malloc (code_payload_len); 434 code_payload = GNUNET_malloc (code_payload_len);
531 GNUNET_assert (NULL != code_payload); 435 GNUNET_assert (NULL != code_payload);
532 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload; 436 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
533 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 437 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
534 + sizeof(ecdh_pub) + payload_len); 438 + payload_len);
535 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); 439 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
536 // Store pubkey 440 // Store pubkey
537 buf_ptr = (char *) &purpose[1]; 441 buf_ptr = (char *) &purpose[1];
538 memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub)); 442 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); 443 GNUNET_free (payload);
547 buf_ptr += payload_len; 444 buf_ptr += payload_len;
548 // Sign and store signature 445 // Sign and store signature
@@ -570,14 +467,16 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
570 * 467 *
571 * @param audience the expected audience of the code 468 * @param audience the expected audience of the code
572 * @param code the string representation of the code 469 * @param code the string representation of the code
573 * @param code_verfier PKCE code verifier 470 * @param code_verfier PKCE code verifier. Optional, must be provided
471 * if used in request.
574 * @param ticket where to store the ticket 472 * @param ticket where to store the ticket
575 * @param attrs the attributes in the code 473 * @param attrs the attributes in the code
576 * @param nonce where to store the nonce 474 * @param attests the attestations in the code (if any)
475 * @param nonce_str where to store the nonce (if contained)
577 * @return GNUNET_OK if successful, else GNUNET_SYSERR 476 * @return GNUNET_OK if successful, else GNUNET_SYSERR
578 */ 477 */
579int 478int
580OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, 479OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
581 const char *code, 480 const char *code,
582 const char *code_verifier, 481 const char *code_verifier,
583 struct GNUNET_RECLAIM_Ticket *ticket, 482 struct GNUNET_RECLAIM_Ticket *ticket,
@@ -595,14 +494,12 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
595 char *code_verifier_hash; 494 char *code_verifier_hash;
596 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 495 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
597 struct GNUNET_CRYPTO_EcdsaSignature *signature; 496 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; 497 uint32_t code_challenge_len;
601 uint32_t attrs_ser_len; 498 uint32_t attrs_ser_len;
602 uint32_t attests_ser_len; 499 uint32_t attests_ser_len;
603 size_t plaintext_len; 500 size_t plaintext_len;
604 size_t code_payload_len; 501 size_t code_payload_len;
605 uint32_t nonce = 0; 502 uint32_t nonce_len = 0;
606 struct OIDC_Parameters *params; 503 struct OIDC_Parameters *params;
607 504
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); 505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
@@ -624,16 +521,10 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
624 plaintext_len = code_payload_len; 521 plaintext_len = code_payload_len;
625 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose); 522 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
626 ptr = (char *) &purpose[1]; 523 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); 524 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
631 525
632 // Decrypt ciphertext
633 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature); 526 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
634 plaintext = GNUNET_malloc (plaintext_len); 527 plaintext = ptr;
635 decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
636 // ptr = plaintext;
637 ptr += plaintext_len; 528 ptr += plaintext_len;
638 signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr; 529 signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
639 params = (struct OIDC_Parameters *) plaintext; 530 params = (struct OIDC_Parameters *) plaintext;
@@ -658,11 +549,10 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
658 // encode code verifier 549 // encode code verifier
659 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8, 550 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
660 &expected_code_challenge); 551 &expected_code_challenge);
661 code_challenge = (char *) &params[1]; 552 code_challenge = ((char *) &params[1]);
662 GNUNET_free (code_verifier_hash); 553 GNUNET_free (code_verifier_hash);
663 if ((strlen (expected_code_challenge) != code_challenge_len) || 554 if (0 !=
664 (0 != 555 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
665 strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
666 { 556 {
667 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 557 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
668 "Invalid code verifier! Expected: %s, Got: %.*s\n", 558 "Invalid code verifier! Expected: %s, Got: %.*s\n",
@@ -675,17 +565,23 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
675 } 565 }
676 GNUNET_free (expected_code_challenge); 566 GNUNET_free (expected_code_challenge);
677 } 567 }
568 nonce_len = ntohl (params->nonce_len);
569 if (0 != nonce_len)
570 {
571 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
572 nonce_len);
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
574 }
575
678 // Ticket 576 // Ticket
679 memcpy (ticket, &params->ticket, sizeof(params->ticket)); 577 memcpy (ticket, &params->ticket, sizeof(params->ticket));
680 // Nonce 578 // Signature
681 nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr)); 579 //GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce); 580 if (0 != GNUNET_memcmp (audience, &ticket->audience))
683 // Signature
684 GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
685 if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
686 { 581 {
687 GNUNET_free (code_payload); 582 GNUNET_free (code_payload);
688 GNUNET_free (plaintext); 583 if (NULL != nonce_str)
584 GNUNET_free (nonce_str);
689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 585 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
690 "Audience in ticket does not match client!\n"); 586 "Audience in ticket does not match client!\n");
691 return GNUNET_SYSERR; 587 return GNUNET_SYSERR;
@@ -697,12 +593,13 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
697 &ticket->identity)) 593 &ticket->identity))
698 { 594 {
699 GNUNET_free (code_payload); 595 GNUNET_free (code_payload);
700 GNUNET_free (plaintext); 596 if (NULL != nonce_str)
597 GNUNET_free (nonce_str);
701 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n"); 598 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
702 return GNUNET_SYSERR; 599 return GNUNET_SYSERR;
703 } 600 }
704 // Attributes 601 // Attributes
705 attrs_ser = ((char *) &params[1]) + code_challenge_len; 602 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
706 attrs_ser_len = ntohl (params->attr_list_len); 603 attrs_ser_len = ntohl (params->attr_list_len);
707 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len); 604 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
708 attests_ser = ((char*) attrs_ser) + attrs_ser_len; 605 attests_ser = ((char*) attrs_ser) + attrs_ser_len;
@@ -710,11 +607,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
710 *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser, 607 *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser,
711 attests_ser_len); 608 attests_ser_len);
712 609
713 *nonce_str = NULL;
714 if (nonce != 0)
715 GNUNET_asprintf (nonce_str, "%u", nonce);
716 GNUNET_free (code_payload); 610 GNUNET_free (code_payload);
717 GNUNET_free (plaintext);
718 return GNUNET_OK; 611 return GNUNET_OK;
719} 612}
720 613