GNUnet  0.11.x
oidc_helper.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2015 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include <inttypes.h>
28 #include <jansson.h>
29 #include "gnunet_util_lib.h"
30 #include "gnunet_reclaim_lib.h"
31 #include "gnunet_reclaim_service.h"
32 #include "gnunet_signatures.h"
33 #include "oidc_helper.h"
34 // #include "benchmark.h"
35 #include <gcrypt.h>
36 
38 
43 {
48 
53 
58 
63 
68 };
69 
71 
75 static 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 
84 static char OIDC_email_claims[2][16] = {
85  "email", "email_verified"
86 };
87 
91 static char OIDC_phone_claims[2][32] = {
92  "phone_number", "phone_number_verified"
93 };
94 
98 static char OIDC_address_claims[5][32] = {
99  "street_address", "locality", "region", "postal_code", "country"
100 };
101 
102 static enum GNUNET_GenericReturnValue
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 
117 static char *
119 {
120  json_t *root;
121  char *json_str;
122 
123  root = json_object ();
124  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
125  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
126 
127  json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
128  json_decref (root);
129  return json_str;
130 }
131 
132 
133 static void
134 replace_char (char *str, char find, char replace)
135 {
136  char *current_pos = strchr (str, find);
137 
138  while (current_pos)
139  {
140  *current_pos = replace;
141  current_pos = strchr (current_pos, find);
142  }
143 }
144 
145 
146 // RFC4648
147 static void
148 fix_base64 (char *str)
149 {
150  // Replace + with -
151  replace_char (str, '+', '-');
152 
153  // Replace / with _
154  replace_char (str, '/', '_');
155 }
156 
157 
158 static json_t*
160  const struct GNUNET_RECLAIM_AttributeList *attrs,
161  const struct
162  GNUNET_RECLAIM_PresentationList *presentations)
163 {
166  char *subject;
167  char *source_name;
168  char *attr_val_str;
169  char *pres_val_str;
170  json_t *body;
171  json_t *aggr_names;
172  json_t *aggr_sources;
173  json_t *aggr_sources_jwt;
174  json_t *addr_claim = NULL;
175  int num_presentations = 0;
176  for (le = attrs->list_head; NULL != le; le = le->next)
177  {
179  num_presentations++;
180  }
181 
182  subject =
184  sizeof(struct
186  body = json_object ();
187  aggr_names = json_object ();
188  aggr_sources = json_object ();
189 
190  // iss REQUIRED case sensitive server uri with https
191  // The issuer is the local reclaim instance (e.g.
192  // https://reclaim.id/api/openid)
193  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
194  // sub REQUIRED public key identity, not exceed 255 ASCII length
195  json_object_set_new (body, "sub", json_string (subject));
196  GNUNET_free (subject);
197  pres_val_str = NULL;
198  source_name = NULL;
199  int i = 0;
200  for (ple = presentations->list_head; NULL != ple; ple = ple->next)
201  {
202  // New presentation
203  GNUNET_asprintf (&source_name,
204  "src%d",
205  i);
207  "Adding new presentation source #%d\n", i);
208  aggr_sources_jwt = json_object ();
209  pres_val_str =
211  ple->presentation->data,
212  ple->presentation->data_size);
214  "Presentation is: %s\n", pres_val_str);
215  json_object_set_new (aggr_sources_jwt,
217  ple->presentation->type),
218  json_string (pres_val_str) );
219  json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
220  GNUNET_free (pres_val_str);
221  GNUNET_free (source_name);
222  source_name = NULL;
223  i++;
224  }
225 
226  int addr_is_aggregated = GNUNET_NO;
227  int addr_is_normal = GNUNET_NO;
228  for (le = attrs->list_head; NULL != le; le = le->next)
229  {
231  "Processing %s for userinfo body\n",
232  le->attribute->name);
234  {
235  attr_val_str =
237  le->attribute->data,
238  le->attribute->data_size);
244  {
245  if (GNUNET_YES == addr_is_aggregated)
246  {
248  "Address is set as aggregated claim. Skipping self-issued value...\n");
249  GNUNET_free (attr_val_str);
250  continue;
251  }
252  addr_is_normal = GNUNET_YES;
253 
254  if (NULL == addr_claim)
255  {
256  addr_claim = json_object ();
257  json_object_set_new (body, "address", addr_claim);
258  }
259  json_object_set_new (addr_claim, le->attribute->name,
260  json_string (attr_val_str));
261 
262  }
263  else
264  {
265  json_object_set_new (body, le->attribute->name,
266  json_string (attr_val_str));
267  }
268  GNUNET_free (attr_val_str);
269  }
270  else
271  {
272  // Check if presentation is there
273  int j = 0;
274  for (ple = presentations->list_head; NULL != ple; ple = ple->next)
275  {
276  if (GNUNET_YES ==
278  &le->attribute->credential))
279  break;
280  j++;
281  }
282  if (NULL == ple)
283  {
285  "Presentation for `%s' missing...\n",
286  le->attribute->name);
287  continue;
288  }
294  {
295  if (GNUNET_YES == addr_is_normal)
296  {
298  "Address is already set as normal claim. Skipping attested value...\n");
299  continue;
300  }
301  addr_is_aggregated = GNUNET_YES;
303  if (NULL != addr_claim)
304  continue;
305  addr_claim = json_object ();
306  GNUNET_asprintf (&source_name,
307  "src%d",
308  j);
309  json_object_set_new (aggr_names, "address",
310  json_string (source_name));
311  GNUNET_free (source_name);
312  }
313  else
314  {
315  // Presentation exists, hence take the respective source str
316  GNUNET_asprintf (&source_name,
317  "src%d",
318  j);
319  json_object_set_new (aggr_names, le->attribute->name,
320  json_string (source_name));
321  GNUNET_free (source_name);
322  }
323  }
324  }
325  if (0 != i)
326  {
327  json_object_set_new (body, "_claim_names", aggr_names);
328  json_object_set_new (body, "_claim_sources", aggr_sources);
329  }
330 
331  return body;
332 }
333 
334 
343 char *
345  const struct GNUNET_RECLAIM_AttributeList *attrs,
346  const struct
347  GNUNET_RECLAIM_PresentationList *presentations)
348 {
349  char *body_str;
350  json_t*body = generate_userinfo_json (sub_key,
351  attrs,
352  presentations);
353  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
354  json_decref (body);
355  return body_str;
356 }
357 
358 
370 char *
372  const struct GNUNET_IDENTITY_PublicKey *sub_key,
373  const struct GNUNET_RECLAIM_AttributeList *attrs,
374  const struct
375  GNUNET_RECLAIM_PresentationList *presentations,
376  const struct GNUNET_TIME_Relative *expiration_time,
377  const char *nonce,
378  const char *secret_key)
379 {
380  struct GNUNET_HashCode signature;
381  struct GNUNET_TIME_Absolute exp_time;
382  struct GNUNET_TIME_Absolute time_now;
383  char *audience;
384  char *subject;
385  char *header;
386  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 
394  body = generate_userinfo_json (sub_key,
395  attrs,
396  presentations);
397  // iat REQUIRED time now
398  time_now = GNUNET_TIME_absolute_get ();
399  // exp REQUIRED time expired from config
400  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
401  // auth_time only if max_age
402  // nonce only if nonce
403  // OPTIONAL acr,amr,azp
404  subject =
406  sizeof(struct
408  audience =
410  sizeof(struct
412  header = create_jwt_header ();
413 
414  // aud REQUIRED public key client_id must be there
415  json_object_set_new (body, "aud", json_string (audience));
416  // iat
417  json_object_set_new (body,
418  "iat",
419  json_integer (time_now.abs_value_us / (1000 * 1000)));
420  // exp
421  json_object_set_new (body,
422  "exp",
423  json_integer (exp_time.abs_value_us / (1000 * 1000)));
424  // nbf
425  json_object_set_new (body,
426  "nbf",
427  json_integer (time_now.abs_value_us / (1000 * 1000)));
428  // nonce
429  if (NULL != nonce)
430  json_object_set_new (body, "nonce", json_string (nonce));
431 
432  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
433  json_decref (body);
434  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
435 
436  GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
437  fix_base64 (header_base64);
438 
439  GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
440  fix_base64 (body_base64);
441 
442  GNUNET_free (subject);
443  GNUNET_free (audience);
444 
449  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
450  GNUNET_CRYPTO_hmac_raw (secret_key,
451  strlen (secret_key),
452  signature_target,
453  strlen (signature_target),
454  &signature);
455  GNUNET_STRINGS_base64url_encode ((const char *) &signature,
456  sizeof(struct GNUNET_HashCode),
457  &signature_base64);
458  fix_base64 (signature_base64);
459 
460  GNUNET_asprintf (&result,
461  "%s.%s.%s",
462  header_base64,
463  body_base64,
464  signature_base64);
465 
466  GNUNET_free (signature_target);
467  GNUNET_free (header);
468  GNUNET_free (body_str);
469  GNUNET_free (signature_base64);
470  GNUNET_free (body_base64);
471  GNUNET_free (header_base64);
472  return result;
473 }
474 
475 
488 char *
490  const struct GNUNET_RECLAIM_Ticket *ticket,
491  const struct GNUNET_RECLAIM_AttributeList *attrs,
492  const struct
493  GNUNET_RECLAIM_PresentationList *presentations,
494  const char *nonce_str,
495  const char *code_challenge)
496 {
497  struct OIDC_Parameters params;
498  char *code_payload;
499  char *payload;
500  char *tmp;
501  char *code_str;
502  char *buf_ptr = NULL;
503  size_t payload_len;
504  size_t code_payload_len;
505  size_t attr_list_len = 0;
506  size_t pres_list_len = 0;
507  size_t code_challenge_len = 0;
508  uint32_t nonce_len = 0;
510 
512  // Assign ticket
513  memset (&params, 0, sizeof(params));
514  params.ticket = *ticket;
515  // Assign nonce
516  payload_len = sizeof(struct OIDC_Parameters);
517  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
518  {
519  nonce_len = strlen (nonce_str);
520  payload_len += nonce_len;
521  }
522  params.nonce_len = htonl (nonce_len);
523  // Assign code challenge
524  if (NULL != code_challenge)
525  code_challenge_len = strlen (code_challenge);
526  payload_len += code_challenge_len;
527  params.code_challenge_len = htonl (code_challenge_len);
528  // Assign attributes
529  if (NULL != attrs)
530  {
531  // Get length
532  attr_list_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
533  params.attr_list_len = htonl (attr_list_len);
535  "Length of serialized attributes: %lu\n",
536  attr_list_len);
537  // Get serialized attributes
538  payload_len += attr_list_len;
539  }
540  if (NULL != presentations)
541  {
542  // Get length
543  // FIXME only add presentations relevant for attribute list!!!
544  // This is important because of the distinction between id_token and
545  // userinfo in OIDC
546  pres_list_len =
548  params.pres_list_len = htonl (pres_list_len);
550  "Length of serialized presentations: %lu\n",
551  pres_list_len);
552  // Get serialized attributes
553  payload_len += pres_list_len;
554  }
555 
556  // Get plaintext length
557  payload = GNUNET_malloc (payload_len);
558  memcpy (payload, &params, sizeof(params));
559  tmp = payload + sizeof(params);
560  if (0 < code_challenge_len)
561  {
562  memcpy (tmp, code_challenge, code_challenge_len);
563  tmp += code_challenge_len;
564  }
565  if (0 < nonce_len)
566  {
567  memcpy (tmp, nonce_str, nonce_len);
568  tmp += nonce_len;
569  }
570  if (0 < attr_list_len)
572  tmp += attr_list_len;
573  if (0 < pres_list_len)
574  GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
575  tmp += pres_list_len;
576 
579  // Get length
580  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
581  + payload_len + sizeof(struct
582  GNUNET_IDENTITY_Signature);
584  "Length of data to encode: %lu\n",
585  code_payload_len);
586 
587  // Initialize code payload
588  code_payload = GNUNET_malloc (code_payload_len);
589  GNUNET_assert (NULL != code_payload);
590  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
591  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
592  + payload_len);
594  // Store pubkey
595  buf_ptr = (char *) &purpose[1];
596  memcpy (buf_ptr, payload, payload_len);
597  GNUNET_free (payload);
598  buf_ptr += payload_len;
599  // Sign and store signature
600  if (GNUNET_SYSERR ==
601  GNUNET_IDENTITY_sign_ (issuer,
602  purpose,
603  (struct GNUNET_IDENTITY_Signature *)
604  buf_ptr))
605  {
606  GNUNET_break (0);
607  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
608  GNUNET_free (code_payload);
609  return NULL;
610  }
611  GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
612  GNUNET_free (code_payload);
613  return code_str;
614 }
615 
616 
618 check_code_challenge (const char *code_challenge,
619  uint32_t code_challenge_len,
620  const char *code_verifier)
621 {
622  char *code_verifier_hash;
623  char *expected_code_challenge;
624 
625  if (0 == code_challenge_len) /* Only check if this code requires a CV */
626  return GNUNET_OK;
627  if (NULL == code_verifier)
628  {
630  "Expected code verifier!\n");
631  return GNUNET_SYSERR;
632  }
633  code_verifier_hash = GNUNET_malloc (256 / 8);
634  // hash code verifier
635  gcry_md_hash_buffer (GCRY_MD_SHA256,
636  code_verifier_hash,
637  code_verifier,
638  strlen (code_verifier));
639  // encode code verifier
640  GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
641  &expected_code_challenge);
642  GNUNET_free (code_verifier_hash);
643  if (0 !=
644  strncmp (expected_code_challenge, code_challenge, code_challenge_len))
645  {
647  "Invalid code verifier! Expected: %s, Got: %.*s\n",
648  expected_code_challenge,
649  code_challenge_len,
650  code_challenge);
651  GNUNET_free (expected_code_challenge);
652  return GNUNET_SYSERR;
653  }
654  GNUNET_free (expected_code_challenge);
655  return GNUNET_OK;
656 }
657 
658 
674 int
676  const char *code,
677  const char *code_verifier,
679  struct GNUNET_RECLAIM_AttributeList **attrs,
680  struct GNUNET_RECLAIM_PresentationList **presentations,
681  char **nonce_str,
683 {
684  char *code_payload;
685  char *ptr;
686  char *plaintext;
687  char *attrs_ser;
688  char *presentations_ser;
689  char *code_challenge;
691  struct GNUNET_IDENTITY_Signature *signature;
692  uint32_t code_challenge_len;
693  uint32_t attrs_ser_len;
694  uint32_t pres_ser_len;
695  size_t plaintext_len;
696  size_t code_payload_len;
697  uint32_t nonce_len = 0;
698  struct OIDC_Parameters *params;
699 
700  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
701  code_payload = NULL;
702  code_payload_len =
703  GNUNET_STRINGS_base64url_decode (code, strlen (code),
704  (void **) &code_payload);
705  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
706  + sizeof(struct OIDC_Parameters)
707  + sizeof(struct GNUNET_IDENTITY_Signature))
708  {
709  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
710  GNUNET_free (code_payload);
711  return GNUNET_SYSERR;
712  }
713 
714  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
715  plaintext_len = code_payload_len;
716  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
717  ptr = (char *) &purpose[1];
718  plaintext_len -= sizeof(struct GNUNET_IDENTITY_Signature);
719  plaintext = ptr;
720  ptr += plaintext_len;
721  signature = (struct GNUNET_IDENTITY_Signature *) ptr;
722  params = (struct OIDC_Parameters *) plaintext;
723 
724  // cmp code_challenge code_verifier
725  code_challenge_len = ntohl (params->code_challenge_len);
726  code_challenge = ((char *) &params[1]);
727  if (! (opts & OIDC_VERIFICATION_NO_CODE_VERIFIER))
728  {
729  if (GNUNET_OK != check_code_challenge (code_challenge,
730  code_challenge_len,
731  code_verifier))
732  {
733  GNUNET_free (code_payload);
734  return GNUNET_SYSERR;
735  }
736  }
737  nonce_len = ntohl (params->nonce_len);
738  if (0 != nonce_len)
739  {
740  *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
741  nonce_len);
742  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
743  }
744 
745  // Ticket
746  memcpy (ticket, &params->ticket, sizeof(params->ticket));
747  // Signature
748  // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
749  if (0 != GNUNET_memcmp (audience, &ticket->audience))
750  {
751  GNUNET_free (code_payload);
752  if (NULL != *nonce_str)
753  GNUNET_free (*nonce_str);
755  "Audience in ticket does not match client!\n");
756  return GNUNET_SYSERR;
757  }
758  if (GNUNET_OK !=
761  purpose,
762  signature,
763  &(ticket->identity)))
764  {
765  GNUNET_free (code_payload);
766  if (NULL != *nonce_str)
767  GNUNET_free (*nonce_str);
768  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
769  return GNUNET_SYSERR;
770  }
771  // Attributes
772  attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
773  attrs_ser_len = ntohl (params->attr_list_len);
774  *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
775  presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
776  pres_ser_len = ntohl (params->pres_list_len);
777  *presentations =
779  pres_ser_len);
780 
781  GNUNET_free (code_payload);
782  return GNUNET_OK;
783 }
784 
785 
795 void
796 OIDC_build_token_response (const char *access_token,
797  const char *id_token,
798  const struct GNUNET_TIME_Relative *expiration_time,
799  char **token_response)
800 {
801  json_t *root_json;
802 
803  root_json = json_object ();
804 
805  GNUNET_assert (NULL != access_token);
806  GNUNET_assert (NULL != id_token);
807  GNUNET_assert (NULL != expiration_time);
808  json_object_set_new (root_json, "access_token", json_string (access_token));
809  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
810  json_object_set_new (root_json,
811  "expires_in",
812  json_integer (expiration_time->rel_value_us
813  / (1000 * 1000)));
814  json_object_set_new (root_json, "id_token", json_string (id_token));
815  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
816  json_decref (root_json);
817 }
818 
819 
823 char *
825 {
826  char *access_token;
827 
829  sizeof(*ticket),
830  &access_token);
831  return access_token;
832 }
833 
834 
838 int
839 OIDC_access_token_parse (const char *token,
840  struct GNUNET_RECLAIM_Ticket **ticket)
841 {
842  if (sizeof (struct GNUNET_RECLAIM_Ticket) !=
844  strlen (token),
845  (void**) ticket))
846  return GNUNET_SYSERR;
847  return GNUNET_OK;
848 }
849 
850 
861  const char*attr)
862 {
863  char *scope_variables;
864  char *scope_variable;
865  char delimiter[] = " ";
866  int i;
867 
868  scope_variables = GNUNET_strdup (scopes);
869  scope_variable = strtok (scope_variables, delimiter);
870  while (NULL != scope_variable)
871  {
872  if (0 == strcmp ("profile", scope_variable))
873  {
874  for (i = 0; i < 14; i++)
875  {
876  if (0 == strcmp (attr, OIDC_profile_claims[i]))
877  {
878  GNUNET_free (scope_variables);
879  return GNUNET_YES;
880  }
881  }
882  }
883  else if (0 == strcmp ("address", scope_variable))
884  {
885  for (i = 0; i < 5; i++)
886  {
887  if (0 == strcmp (attr, OIDC_address_claims[i]))
888  {
889  GNUNET_free (scope_variables);
890  return GNUNET_YES;
891  }
892  }
893  }
894  else if (0 == strcmp ("email", scope_variable))
895  {
896  for (i = 0; i < 2; i++)
897  {
898  if (0 == strcmp (attr, OIDC_email_claims[i]))
899  {
900  GNUNET_free (scope_variables);
901  return GNUNET_YES;
902  }
903  }
904  }
905  else if (0 == strcmp ("phone", scope_variable))
906  {
907  for (i = 0; i < 2; i++)
908  {
909  if (0 == strcmp (attr, OIDC_phone_claims[i]))
910  {
911  GNUNET_free (scope_variables);
912  return GNUNET_YES;
913  }
914  }
915 
916  }
917  else if (0 == strcmp (attr, scope_variable))
918  {
920  GNUNET_free (scope_variables);
921  return GNUNET_YES;
922  }
923  scope_variable = strtok (NULL, delimiter);
924  }
925  GNUNET_free (scope_variables);
926  return GNUNET_NO;
927 
928 }
Do not check code verifier even if expected.
Definition: oidc_helper.h:51
int GNUNET_IDENTITY_signature_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_IDENTITY_Signature *sig, const struct GNUNET_IDENTITY_PublicKey *pub)
Verify a given signature.
The authorization ticket.
static enum GNUNET_GenericReturnValue is_claim_in_address_scope(const char *claim)
Definition: oidc_helper.c:103
uint64_t rel_value_us
The actual value.
uint32_t type
Type/Format of Claim.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
#define JWT_ALG_VALUE
Definition: oidc_helper.h:33
struct GNUNET_RECLAIM_Attribute * claim
Claim to store.
void GNUNET_CRYPTO_hmac_raw(const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104) TODO: Shouldn&#39; this be the standard hmac function and the abov...
Definition: crypto_hash.c:274
const char * name
The name of the attribute.
OIDC_VerificationOptions
Definition: oidc_helper.h:41
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_RECLAIM_AttributeList * GNUNET_RECLAIM_attribute_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
uint32_t attr_list_len
The length of the attributes list.
Definition: oidc_helper.c:62
enum GNUNET_GenericReturnValue check_code_challenge(const char *code_challenge, uint32_t code_challenge_len, const char *code_verifier)
Definition: oidc_helper.c:618
uint32_t pres_list_len
The length of the presentation list.
Definition: oidc_helper.c:67
static char * create_jwt_header(void)
Definition: oidc_helper.c:118
A private key for an identity as per LSD0001.
struct GNUNET_RECLAIM_PresentationListEntry * list_head
List head.
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:675
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
helper library for OIDC related functions
A list of GNUNET_RECLAIM_Attribute structures.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:395
#define SERVER_ADDRESS
Definition: oidc_helper.h:39
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
void OIDC_build_token_response(const char *access_token, const char *id_token, const struct GNUNET_TIME_Relative *expiration_time, char **token_response)
Build a token response for a token request TODO: Maybe we should add the scope here?
Definition: oidc_helper.c:796
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32.
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
Definition: oidc_helper.c:860
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1932
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
static char OIDC_email_claims[2][16]
Standard claims represented by the "email" scope in OIDC.
Definition: oidc_helper.c:84
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket.
struct GNUNET_IDENTITY_PublicKey identity
The ticket issuer (= the user)
static void replace_char(char *str, char find, char replace)
Definition: oidc_helper.c:134
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition: oidc_helper.c:57
An identity signature as per LSD0001.
const char * GNUNET_RECLAIM_presentation_number_to_typename(uint32_t type)
Convert a presentation type number to the corresponding credential type string.
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:824
#define JWT_TYP
Definition: oidc_helper.h:35
static int result
Global testing status.
size_t GNUNET_RECLAIM_presentation_list_serialize_get_size(const struct GNUNET_RECLAIM_PresentationList *presentations)
Get required size for serialization buffer.
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
const void * data
Binary value stored as presentation value.
size_t data_size
Number of bytes in data.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
static GNUNET_NETWORK_STRUCT_END char OIDC_profile_claims[14][32]
Standard claims represented by the "profile" scope in OIDC.
Definition: oidc_helper.c:75
A 512-bit hashcode.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1978
char * OIDC_generate_id_token(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT from attributes.
Definition: oidc_helper.c:371
static void fix_base64(char *str)
Definition: oidc_helper.c:148
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1876
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:489
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
size_t data_size
Number of bytes in data.
size_t GNUNET_RECLAIM_attribute_list_serialize(const struct GNUNET_RECLAIM_AttributeList *attrs, char *result)
Serialize an attribute list.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
static unsigned long long payload
How much data are we currently storing in the database?
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
static char OIDC_phone_claims[2][32]
Standard claims represented by the "phone" scope in OIDC.
Definition: oidc_helper.c:91
char * GNUNET_RECLAIM_presentation_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;claim&#39; of a presentation to a string.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
static json_t * generate_userinfo_json(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Definition: oidc_helper.c:159
static char * subject
Subject pubkey string.
Definition: gnunet-abd.c:86
An identity key as per LSD0001.
A list of GNUNET_RECLAIM_Presentation structures.
#define GNUNET_PACKED
gcc-ism to get packed structs.
int GNUNET_IDENTITY_sign_(const struct GNUNET_IDENTITY_PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_IDENTITY_Signature *sig)
Sign a given block.
static char OIDC_address_claims[5][32]
Standard claims represented by the "address" scope in OIDC.
Definition: oidc_helper.c:98
#define GNUNET_RECLAIM_id_is_equal(a, b)
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
#define GNUNET_log(kind,...)
const void * data
Binary value stored as attribute value.
char * GNUNET_RECLAIM_attribute_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;claim&#39; of an attribute to a string.
size_t GNUNET_RECLAIM_attribute_list_serialize_get_size(const struct GNUNET_RECLAIM_AttributeList *attrs)
Get required size for serialization buffer.
uint32_t type
Type of Claim.
#define JWT_ALG
Definition: oidc_helper.h:30
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:839
Time for absolute times used by GNUnet, in microseconds.
uint32_t nonce_len
The nonce length.
Definition: oidc_helper.c:52
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:937
#define JWT_TYP_VALUE
Definition: oidc_helper.h:37
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
Definition: oidc_helper.c:47
size_t GNUNET_RECLAIM_presentation_list_serialize(const struct GNUNET_RECLAIM_PresentationList *presentations, char *result)
Serialize a presentation list.
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:344
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:2050
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_RECLAIM_PresentationList * GNUNET_RECLAIM_presentation_list_deserialize(const char *data, size_t data_size)
Deserialize a presentation list.
Time for relative time used by GNUnet, in microseconds.
The signature used to generate the authorization code.
Definition: oidc_helper.c:42
#define GNUNET_RECLAIM_id_is_zero(a)