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"
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 
52  uint32_t nonce GNUNET_PACKED;
53 
58 
63 };
64 
66 
67 static char *
69 {
70  json_t *root;
71  char *json_str;
72 
73  root = json_object ();
74  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
75  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
76 
77  json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
78  json_decref (root);
79  return json_str;
80 }
81 
82 
83 static void
84 replace_char (char *str, char find, char replace)
85 {
86  char *current_pos = strchr (str, find);
87 
88  while (current_pos)
89  {
90  *current_pos = replace;
91  current_pos = strchr (current_pos, find);
92  }
93 }
94 
95 
96 // RFC4648
97 static void
98 fix_base64 (char *str)
99 {
100  // Replace + with -
101  replace_char (str, '+', '-');
102 
103  // Replace / with _
104  replace_char (str, '/', '_');
105 }
106 
107 
118 char *
120  const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
122  const struct GNUNET_TIME_Relative *expiration_time,
123  const char *nonce,
124  const char *secret_key)
125 {
127  struct GNUNET_HashCode signature;
128  struct GNUNET_TIME_Absolute exp_time;
129  struct GNUNET_TIME_Absolute time_now;
130  char *audience;
131  char *subject;
132  char *header;
133  char *body_str;
134  char *aggr_names_str;
135  char *aggr_sources_str;
136  char *aggr_sources_jwt_str;
137  char *source_name;
138  char *result;
139  char *header_base64;
140  char *body_base64;
141  char *signature_target;
142  char *signature_base64;
143  char *attr_val_str;
144  char *attest_val_str;
145  json_t *body;
146  json_t *aggr_names;
147  json_t *aggr_sources;
148  json_t *aggr_sources_jwt;
149  uint64_t attest_arr[GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (attrs)];
150 
151  // iat REQUIRED time now
152  time_now = GNUNET_TIME_absolute_get ();
153  // exp REQUIRED time expired from config
154  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
155  // auth_time only if max_age
156  // nonce only if nonce
157  // OPTIONAL acr,amr,azp
158  subject =
160  sizeof(struct
162  audience =
164  sizeof(struct
166  header = create_jwt_header ();
167  body = json_object ();
168  aggr_names = json_object ();
169  aggr_sources = json_object ();
170 
171  // iss REQUIRED case sensitive server uri with https
172  // The issuer is the local reclaim instance (e.g.
173  // https://reclaim.id/api/openid)
174  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
175  // sub REQUIRED public key identity, not exceed 255 ASCII length
176  json_object_set_new (body, "sub", json_string (subject));
177  // aud REQUIRED public key client_id must be there
178  json_object_set_new (body, "aud", json_string (audience));
179  // iat
180  json_object_set_new (body,
181  "iat",
182  json_integer (time_now.abs_value_us / (1000 * 1000)));
183  // exp
184  json_object_set_new (body,
185  "exp",
186  json_integer (exp_time.abs_value_us / (1000 * 1000)));
187  // nbf
188  json_object_set_new (body,
189  "nbf",
190  json_integer (time_now.abs_value_us / (1000 * 1000)));
191  // nonce
192  if (NULL != nonce)
193  json_object_set_new (body, "nonce", json_string (nonce));
194  int i = 0;
195  attest_val_str = NULL;
196  aggr_names_str = NULL;
197  aggr_sources_str = NULL;
198  aggr_sources_jwt_str = NULL;
199  source_name = NULL;
200  for (le = attrs->list_head; NULL != le; le = le->next)
201  {
202 
203  if (le->claim != NULL)
204  {
205 
206  attr_val_str =
208  le->claim->data,
209  le->claim->data_size);
210  json_object_set_new (body, le->claim->name, json_string (attr_val_str));
211  GNUNET_free (attr_val_str);
212  }
213  else if (NULL != le->reference)
214  {
215  // Check if attest is there
216  int j = 0;
217  while (j<i)
218  {
219  if (attest_arr[j] == le->reference->id_attest)
220  break;
221  j++;
222  }
223  if (j==i)
224  {
225  // Attest not yet existent. Append to the end of the list
226  GNUNET_CONTAINER_DLL_remove (attrs->list_head, attrs->list_tail, le);
228  le);
229  continue;
230  }
231  else
232  {
233  // Attestation is existing, hence take the respective source str
234  GNUNET_asprintf (&source_name,
235  "src%d",
236  j);
237  json_object_set_new (aggr_names, le->reference->name, json_string (
238  source_name));
239  }
240 
241  }
242  else if (NULL != le->attest)
243  {
244  // We assume that at max 99 different attestations
245  int j = 0;
246  while (j<i)
247  {
248  if (attest_arr[j] == le->attest->id)
249  break;
250  j++;
251  }
252  if (j==i)
253  {
254  // New Attestation
255  attest_arr[i] = le->attest->id;
256  GNUNET_asprintf (&source_name,
257  "src%d",
258  i);
259  aggr_sources_jwt = json_object ();
261  le->attest->type, le->attest->data, le->attest->data_size);
262  json_object_set_new (aggr_sources_jwt, "JWT",json_string (
263  attest_val_str) );
264  aggr_sources_jwt_str = json_dumps (aggr_sources_jwt, JSON_INDENT (0)
265  | JSON_COMPACT);
266  json_object_set_new (aggr_sources, source_name,json_string (
267  aggr_sources_jwt_str));
268  i++;
269  }
270  else
271  {
272  // Attestation already existent. Ignore
273  continue;
274  }
275 
276  }
277  }
278  if (NULL != attest_val_str)
279  GNUNET_free (attest_val_str);
280  if (NULL != source_name)
281  GNUNET_free (source_name);
282  if (0!=i)
283  {
284  aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
285  aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
286  | JSON_COMPACT);
287  json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
288  json_object_set_new (body, "_claim_sources", json_string (
289  aggr_sources_str));
290  }
291 
292  json_decref (aggr_names);
293  json_decref (aggr_sources);
294  json_decref (aggr_sources_jwt);
295 
296  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
297  json_decref (body);
298  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
299 
300  GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64);
301  fix_base64 (header_base64);
302 
303  GNUNET_STRINGS_base64_encode (body_str, strlen (body_str), &body_base64);
304  fix_base64 (body_base64);
305 
306  GNUNET_free (subject);
307  GNUNET_free (audience);
308 
313  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
314  GNUNET_CRYPTO_hmac_raw (secret_key,
315  strlen (secret_key),
316  signature_target,
317  strlen (signature_target),
318  &signature);
319  GNUNET_STRINGS_base64_encode ((const char *) &signature,
320  sizeof(struct GNUNET_HashCode),
321  &signature_base64);
322  fix_base64 (signature_base64);
323 
324  GNUNET_asprintf (&result,
325  "%s.%s.%s",
326  header_base64,
327  body_base64,
328  signature_base64);
329 
330  GNUNET_free (signature_target);
331  GNUNET_free (header);
332  GNUNET_free (body_str);
333  if (NULL != aggr_sources_str)
334  GNUNET_free (aggr_sources_str);
335  if (NULL != aggr_names_str)
336  GNUNET_free (aggr_names_str);
337  if (NULL != aggr_sources_jwt_str)
338  GNUNET_free (aggr_sources_jwt_str);
339  GNUNET_free (signature_base64);
340  GNUNET_free (body_base64);
341  GNUNET_free (header_base64);
342  return result;
343 }
344 
345 
346 /* Converts a hex character to its integer value */
347 static char
348 from_hex (char ch)
349 {
350  return isdigit (ch) ? ch - '0' : tolower (ch) - 'a' + 10;
351 }
352 
353 
354 /* Converts an integer value to its hex character*/
355 static char
356 to_hex (char code)
357 {
358  static char hex[] = "0123456789abcdef";
359 
360  return hex[code & 15];
361 }
362 
363 
364 /* Returns a url-encoded version of str */
365 /* IMPORTANT: be sure to free() the returned string after use */
366 static char *
367 url_encode (const char *str)
368 {
369  char *pstr = (char *) str;
370  char *buf = GNUNET_malloc (strlen (str) * 3 + 1);
371  char *pbuf = buf;
372 
373  while (*pstr)
374  {
375  if (isalnum (*pstr) || (*pstr == '-') || (*pstr == '_') || (*pstr == '.') ||
376  (*pstr == '~') )
377  *pbuf++ = *pstr;
378  else if (*pstr == ' ')
379  *pbuf++ = '+';
380  else
381  {
382  *pbuf++ = '%';
383  *pbuf++ = to_hex (*pstr >> 4);
384  *pbuf++ = to_hex (*pstr & 15);
385  }
386  pstr++;
387  }
388  *pbuf = '\0';
389  return buf;
390 }
391 
392 
393 /* Returns a url-decoded version of str */
394 /* IMPORTANT: be sure to free() the returned string after use */
395 static char *
396 url_decode (const char *str)
397 {
398  char *pstr = (char *) str;
399  char *buf = GNUNET_malloc (strlen (str) + 1);
400  char *pbuf = buf;
401 
402  while (*pstr)
403  {
404  if (*pstr == '%')
405  {
406  if (pstr[1] && pstr[2])
407  {
408  *pbuf++ = from_hex (pstr[1]) << 4 | from_hex (pstr[2]);
409  pstr += 2;
410  }
411  }
412  else if (*pstr == '+')
413  {
414  *pbuf++ = ' ';
415  }
416  else
417  {
418  *pbuf++ = *pstr;
419  }
420  pstr++;
421  }
422  *pbuf = '\0';
423  return buf;
424 }
425 
426 
433 static char *
434 base64_and_urlencode (const char *data, size_t data_size)
435 {
436  char *enc;
437  char *urlenc;
438 
439  GNUNET_STRINGS_base64_encode (data, data_size, &enc);
440  urlenc = url_encode (enc);
441  GNUNET_free (enc);
442  return urlenc;
443 }
444 
445 
452 static char *
453 base64url_encode (const char *data, size_t data_size)
454 {
455  char *enc;
456  size_t pos;
457 
458  GNUNET_STRINGS_base64_encode (data, data_size, &enc);
459  // Replace with correct characters for base64url
460  pos = 0;
461  while ('\0' != enc[pos])
462  {
463  if ('+' == enc[pos])
464  enc[pos] = '-';
465  if ('/' == enc[pos])
466  enc[pos] = '_';
467  if ('=' == enc[pos])
468  {
469  enc[pos] = '\0';
470  break;
471  }
472  pos++;
473  }
474  return enc;
475 }
476 
477 
478 static void
481  struct GNUNET_HashCode *key_material)
482 {
483  static const char ctx_key[] = "reclaim-aes-ctx-key";
484  static const char ctx_iv[] = "reclaim-aes-ctx-iv";
485 
486  GNUNET_CRYPTO_kdf (key,
487  sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
488  ctx_key,
489  strlen (ctx_key),
490  key_material,
491  sizeof(struct GNUNET_HashCode),
492  NULL);
493  GNUNET_CRYPTO_kdf (iv,
494  sizeof(
496  ctx_iv,
497  strlen (ctx_iv),
498  key_material,
499  sizeof(struct GNUNET_HashCode),
500  NULL);
501 }
502 
503 
504 static void
507  const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
508  const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
509 {
510  struct GNUNET_HashCode key_material;
511 
512  GNUNET_CRYPTO_ecdsa_ecdh (ecdsa_priv, ecdh_pub, &key_material);
513  derive_aes_key (key, iv, &key_material);
514 }
515 
516 
517 static void
520  const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
521  const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
522 {
523  struct GNUNET_HashCode key_material;
524 
525  GNUNET_CRYPTO_ecdh_ecdsa (ecdh_priv, ecdsa_pub, &key_material);
526  derive_aes_key (key, iv, &key_material);
527 }
528 
529 
530 static void
532  const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub,
533  const char *ct,
534  size_t ct_len,
535  char *buf)
536 {
539 
540  calculate_key_priv (&key, &iv, ecdsa_priv, ecdh_pub);
541  GNUNET_break (GNUNET_CRYPTO_symmetric_decrypt (ct, ct_len, &key, &iv, buf));
542 }
543 
544 
545 static void
547  const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv,
548  const char *payload,
549  size_t payload_len,
550  char *buf)
551 {
554 
555  calculate_key_pub (&key, &iv, ecdsa_pub, ecdh_priv);
556  GNUNET_break (
557  GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf));
558 }
559 
560 
572 char *
574  const struct GNUNET_RECLAIM_Ticket *ticket,
576  const char *nonce_str,
577  const char *code_challenge)
578 {
579  struct OIDC_Parameters params;
580  char *code_payload;
581  char *payload;
582  char *tmp;
583  char *code_str;
584  char *buf_ptr = NULL;
585  size_t payload_len;
586  size_t code_payload_len;
587  size_t attr_list_len = 0;
588  size_t code_challenge_len = 0;
589  uint32_t nonce;
590  uint32_t nonce_tmp;
592  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv;
593  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
594 
596  // Assign ticket
597  memset (&params, 0, sizeof(params));
598  params.ticket = *ticket;
599  // Assign nonce
600  nonce = 0;
601  payload_len = sizeof(struct OIDC_Parameters);
602  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
603  {
604  if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX))
605  {
606  GNUNET_break (0);
607  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
608  return NULL;
609  }
611  "Got nonce: %u from %s\n",
612  nonce,
613  nonce_str);
614  }
615  nonce_tmp = htonl (nonce);
616  params.nonce = nonce_tmp;
617  // Assign code challenge
618  if (NULL != code_challenge)
619  code_challenge_len = strlen (code_challenge);
620  payload_len += code_challenge_len;
621  params.code_challenge_len = htonl (code_challenge_len);
622  // Assign attributes
623  if (NULL != attrs)
624  {
625  // Get length
626  attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
627  params.attr_list_len = htonl (attr_list_len);
629  "Length of serialized attributes: %lu\n",
630  attr_list_len);
631  // Get serialized attributes
632  payload_len += attr_list_len;
633  }
634  // Get plaintext length
635  payload = GNUNET_malloc (payload_len);
636  memcpy (payload, &params, sizeof(params));
637  tmp = payload + sizeof(params);
638  if (0 < code_challenge_len)
639  {
640  memcpy (tmp, code_challenge, code_challenge_len);
641  tmp += code_challenge_len;
642  }
643  if (0 < attr_list_len)
648  // Get length
649  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
650  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
651  + payload_len + sizeof(struct
652  GNUNET_CRYPTO_EcdsaSignature);
654  "Length of data to encode: %lu\n",
655  code_payload_len);
656 
657  // Generate ECDH key
658  ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create ();
659  GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub);
660  // Initialize code payload
661  code_payload = GNUNET_malloc (code_payload_len);
662  GNUNET_assert (NULL != code_payload);
663  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
664  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
665  + sizeof(ecdh_pub) + payload_len);
667  // Store pubkey
668  buf_ptr = (char *) &purpose[1];
669  memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub));
670  buf_ptr += sizeof(ecdh_pub);
671  // Encrypt plaintext and store
672  encrypt_payload (&ticket->audience, ecdh_priv, payload, payload_len, buf_ptr);
673  GNUNET_free (ecdh_priv);
674  GNUNET_free (payload);
675  buf_ptr += payload_len;
676  // Sign and store signature
677  if (GNUNET_SYSERR ==
678  GNUNET_CRYPTO_ecdsa_sign (issuer,
679  purpose,
680  (struct GNUNET_CRYPTO_EcdsaSignature *)
681  buf_ptr))
682  {
683  GNUNET_break (0);
684  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
685  GNUNET_free (code_payload);
686  return NULL;
687  }
688  code_str = base64_and_urlencode (code_payload, code_payload_len);
689  GNUNET_free (code_payload);
690  return code_str;
691 }
692 
693 
707 int
709  const char *code,
710  const char *code_verifier,
712  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs,
713  char **nonce_str)
714 {
715  char *code_payload;
716  char *ptr;
717  char *plaintext;
718  char *attrs_ser;
719  char *expected_code_challenge;
720  char *code_challenge;
721  char *code_verifier_hash;
723  struct GNUNET_CRYPTO_EcdsaSignature *signature;
724  struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
725  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
726  uint32_t code_challenge_len;
727  uint32_t attrs_ser_len;
728  size_t plaintext_len;
729  size_t code_payload_len;
730  uint32_t nonce = 0;
731  struct OIDC_Parameters *params;
732 
733  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
734  code_payload = NULL;
735  code_payload_len =
736  GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload);
737  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
738  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
739  + sizeof(struct OIDC_Parameters)
740  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
741  {
742  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
743  GNUNET_free_non_null (code_payload);
744  return GNUNET_SYSERR;
745  }
746 
747  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
748  plaintext_len = code_payload_len;
749  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
750  ptr = (char *) &purpose[1];
751  // Public ECDH key
752  ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
753  ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
754  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
755 
756  // Decrypt ciphertext
757  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
758  plaintext = GNUNET_malloc (plaintext_len);
759  decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
760  // ptr = plaintext;
761  ptr += plaintext_len;
762  signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
763  params = (struct OIDC_Parameters *) plaintext;
764 
765  // cmp code_challenge code_verifier
766  code_challenge_len = ntohl (params->code_challenge_len);
767  if (0 != code_challenge_len) /* Only check if this code requires a CV */
768  {
769  if (NULL == code_verifier)
770  {
772  "Expected code verifier!\n");
773  GNUNET_free_non_null (code_payload);
774  return GNUNET_SYSERR;
775  }
776  code_verifier_hash = GNUNET_malloc (256 / 8);
777  // hash code verifier
778  gcry_md_hash_buffer (GCRY_MD_SHA256,
779  code_verifier_hash,
780  code_verifier,
781  strlen (code_verifier));
782  // encode code verifier
783  expected_code_challenge = base64url_encode (code_verifier_hash, 256 / 8);
784  code_challenge = (char *) &params[1];
785  GNUNET_free (code_verifier_hash);
786  if ((strlen (expected_code_challenge) != code_challenge_len) ||
787  (0 !=
788  strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
789  {
791  "Invalid code verifier! Expected: %s, Got: %.*s\n",
792  expected_code_challenge,
793  code_challenge_len,
794  code_challenge);
795  GNUNET_free_non_null (code_payload);
796  GNUNET_free (expected_code_challenge);
797  return GNUNET_SYSERR;
798  }
799  GNUNET_free (expected_code_challenge);
800  }
801  // Ticket
802  memcpy (ticket, &params->ticket, sizeof(params->ticket));
803  // Nonce
804  nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr));
805  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
806  // Signature
807  GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
808  if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
809  {
810  GNUNET_free (code_payload);
811  GNUNET_free (plaintext);
813  "Audience in ticket does not match client!\n");
814  return GNUNET_SYSERR;
815  }
816  if (GNUNET_OK !=
818  purpose,
819  signature,
820  &ticket->identity))
821  {
822  GNUNET_free (code_payload);
823  GNUNET_free (plaintext);
824  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
825  return GNUNET_SYSERR;
826  }
827  // Attributes
828  attrs_ser = ((char *) &params[1]) + code_challenge_len;
829  attrs_ser_len = ntohl (params->attr_list_len);
830  *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, attrs_ser_len);
831 
832  *nonce_str = NULL;
833  if (nonce != 0)
834  GNUNET_asprintf (nonce_str, "%u", nonce);
835  GNUNET_free (code_payload);
836  GNUNET_free (plaintext);
837  return GNUNET_OK;
838 }
839 
840 
850 void
851 OIDC_build_token_response (const char *access_token,
852  const char *id_token,
853  const struct GNUNET_TIME_Relative *expiration_time,
854  char **token_response)
855 {
856  json_t *root_json;
857 
858  root_json = json_object ();
859 
860  GNUNET_assert (NULL != access_token);
861  GNUNET_assert (NULL != id_token);
862  GNUNET_assert (NULL != expiration_time);
863  json_object_set_new (root_json, "access_token", json_string (access_token));
864  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
865  json_object_set_new (root_json,
866  "expires_in",
867  json_integer (expiration_time->rel_value_us
868  / (1000 * 1000)));
869  json_object_set_new (root_json, "id_token", json_string (id_token));
870  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
871  json_decref (root_json);
872 }
873 
874 
878 char *
880 {
881  char *access_token;
882  uint64_t random_number;
883 
884  random_number =
886  GNUNET_STRINGS_base64_encode (&random_number,
887  sizeof(uint64_t),
888  &access_token);
889  return access_token;
890 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
const char * name
The name of the attribute.
int GNUNET_CRYPTO_ecdsa_ecdh(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
Derive key material from a ECDH public key and a private ECDSA key.
Definition: crypto_ecc.c:1071
struct GNUNET_RECLAIM_ATTRIBUTE_Claim * claim
The attribute claim.
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.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
The authorization ticket.
static void calculate_key_pub(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
Definition: oidc_helper.c:518
uint64_t rel_value_us
The actual value.
static void encrypt_payload(const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv, const char *payload, size_t payload_len, char *buf)
Definition: oidc_helper.c:546
int GNUNET_CRYPTO_ecdh_ecdsa(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, struct GNUNET_HashCode *key_material)
Derive key material from a EcDSA public key and a private ECDH key.
Definition: crypto_ecc.c:1126
int GNUNET_CRYPTO_ecdsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EcdsaSignature *sig, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Verify ECDSA signature.
Definition: crypto_ecc.c:776
size_t data_size
Number of bytes in data.
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
static void derive_aes_key(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_HashCode *key_material)
Definition: oidc_helper.c:479
uint32_t nonce
The nonce.
Definition: oidc_helper.c:52
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_tail
List tail.
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:403
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
struct GNUNET_RECLAIM_ATTESTATION_REFERENCE * reference
The reference.
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint32_t attr_list_len
The length of the attributes list.
Definition: oidc_helper.c:62
struct GNUNET_CRYPTO_EcdhePrivateKey * GNUNET_CRYPTO_ecdhe_key_create(void)
Create a new private key.
Definition: crypto_ecc.c:499
helper library for OIDC related functions
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:83
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
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
Private ECC key encoded for transmission.
uint64_t id_attest
Referenced ID of Attestation.
#define SERVER_ADDRESS
Definition: oidc_helper.h:39
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:851
static char to_hex(char code)
Definition: oidc_helper.c:356
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.
static void decrypt_payload(const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub, const char *ct, size_t ct_len, char *buf)
Definition: oidc_helper.c:531
struct GNUNET_RECLAIM_ATTESTATION_Claim * attest
The attestation claim.
const void * data
Binary value stored as attribute value.
int GNUNET_RECLAIM_ATTRIBUTE_list_count_attest(const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
Count attestations in claim list.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
int GNUNET_CRYPTO_ecdsa_sign(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
ECDSA Sign a given block.
Definition: crypto_ecc.c:687
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket.
static void replace_char(char *str, char find, char replace)
Definition: oidc_helper.c:84
ssize_t GNUNET_CRYPTO_symmetric_encrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Encrypt a block using a symmetric sessionkey.
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition: oidc_helper.c:57
Randomness for IVs etc.
an ECC signature using ECDSA
#define JWT_TYP
Definition: oidc_helper.h:35
static char buf[2048]
size_t data_size
Number of bytes in data.
static int result
Global testing status.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
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:1920
static void fix_base64(char *str)
Definition: oidc_helper.c:98
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1855
Private ECC key encoded for transmission.
struct GNUNET_CRYPTO_EcdsaPublicKey identity
The ticket issuer (= the user)
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:84
void GNUNET_CRYPTO_ecdsa_key_get_public(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:172
void GNUNET_CRYPTO_ecdhe_key_get_public(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:206
int OIDC_parse_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, char **nonce_str)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:708
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static char from_hex(char ch)
Definition: oidc_helper.c:348
static unsigned long long payload
How much data are we currently storing in the database?
static GNUNET_NETWORK_STRUCT_END char * create_jwt_header(void)
Definition: oidc_helper.c:68
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
char * GNUNET_RECLAIM_ATTESTATION_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;claim&#39; of an attestation to a string.
char * OIDC_id_token_new(const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT from attributes.
Definition: oidc_helper.c:119
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won&#39;t work on W32;.
static char * url_decode(const char *str)
Definition: oidc_helper.c:396
static char * subject
Subject pubkey string.
Definition: gnunet-abd.c:86
char * OIDC_access_token_new()
Generate a new access token.
Definition: oidc_helper.c:879
#define GNUNET_PACKED
gcc-ism to get packed structs.
struct GNUNET_CRYPTO_EcdsaPublicKey audience
The ticket audience (= relying party)
static char * url_encode(const char *str)
Definition: oidc_helper.c:367
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
static char * base64_and_urlencode(const char *data, size_t data_size)
Returns base64 encoded string urlencoded.
Definition: oidc_helper.c:434
static OpusEncoder * enc
OPUS encoder.
const char * name
The name of the attribute/attestation reference value.
A list of GNUNET_RECLAIM_ATTRIBUTE_Claim structures.
static char * base64url_encode(const char *data, size_t data_size)
Returns base64 encoded string urlencoded.
Definition: oidc_helper.c:453
static void calculate_key_priv(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
Definition: oidc_helper.c:505
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
#define GNUNET_log(kind,...)
#define JWT_ALG
Definition: oidc_helper.h:30
Time for absolute times used by GNUnet, in microseconds.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:920
#define JWT_TYP_VALUE
Definition: oidc_helper.h:37
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:573
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
Definition: oidc_helper.c:47
ssize_t GNUNET_CRYPTO_symmetric_decrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Decrypt a given block using a symmetric sessionkey.
uint32_t data
The data value.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * next
DLL.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_head
List head.
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:89
size_t GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size(const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
Get required size for serialization buffer.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * GNUNET_RECLAIM_ATTRIBUTE_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
size_t GNUNET_RECLAIM_ATTRIBUTE_list_serialize(const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, char *result)
Serialize an attribute list.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
const void * data
Binary value stored as attribute value.
The signature used to generate the authorization code.
Definition: oidc_helper.c:42