GNUnet  0.11.x
Macros | Functions
oidc_helper.h File Reference

helper library for OIDC related functions More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define JWT_ALG   "alg"
 
#define JWT_ALG_VALUE   "HS512"
 
#define JWT_TYP   "typ"
 
#define JWT_TYP_VALUE   "jwt"
 
#define SERVER_ADDRESS   "https://api.reclaim"
 

Functions

char * OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, struct GNUNET_RECLAIM_AttributeList *attrs, struct GNUNET_RECLAIM_AttestationList *attests, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
 Create a JWT from attributes. More...
 
char * OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList *attrs, struct GNUNET_RECLAIM_AttestationList *attests, const char *nonce, const char *code_challenge)
 Builds an OIDC authorization code including a reclaim ticket and nonce. More...
 
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_AttributeList **attrs, struct GNUNET_RECLAIM_AttestationList **attests, char **nonce)
 Parse reclaim ticket and nonce from authorization code. More...
 
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? More...
 
char * OIDC_access_token_new ()
 Generate a new access token. More...
 

Detailed Description

helper library for OIDC related functions

Author
Martin Schanzenbach

Definition in file oidc_helper.h.

Macro Definition Documentation

◆ JWT_ALG

#define JWT_ALG   "alg"

Definition at line 30 of file oidc_helper.h.

Referenced by create_jwt_header().

◆ JWT_ALG_VALUE

#define JWT_ALG_VALUE   "HS512"

Definition at line 33 of file oidc_helper.h.

Referenced by create_jwt_header().

◆ JWT_TYP

#define JWT_TYP   "typ"

Definition at line 35 of file oidc_helper.h.

Referenced by create_jwt_header().

◆ JWT_TYP_VALUE

#define JWT_TYP_VALUE   "jwt"

Definition at line 37 of file oidc_helper.h.

Referenced by create_jwt_header().

◆ SERVER_ADDRESS

#define SERVER_ADDRESS   "https://api.reclaim"

Definition at line 39 of file oidc_helper.h.

Referenced by OIDC_id_token_new().

Function Documentation

◆ OIDC_id_token_new()

char* OIDC_id_token_new ( const struct GNUNET_CRYPTO_EcdsaPublicKey aud_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey sub_key,
struct GNUNET_RECLAIM_AttributeList attrs,
struct GNUNET_RECLAIM_AttestationList attests,
const struct GNUNET_TIME_Relative expiration_time,
const char *  nonce,
const char *  secret_key 
)

Create a JWT from attributes.

Parameters
aud_keythe public of the audience
sub_keythe public key of the subject
attrsthe attribute list
expiration_timethe validity of the token
secret_keythe key used to sign the JWT
Returns
a new base64-encoded JWT string.

Creating the JWT signature. This might not be standards compliant, check.

Definition at line 124 of file oidc_helper.c.

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_RECLAIM_Attribute::attestation, GNUNET_RECLAIM_AttestationListEntry::attestation, GNUNET_RECLAIM_AttributeListEntry::attribute, create_jwt_header(), GNUNET_RECLAIM_Attribute::data, GNUNET_RECLAIM_Attestation::data, GNUNET_RECLAIM_Attribute::data_size, GNUNET_RECLAIM_Attestation::data_size, fix_base64(), GNUNET_asprintf(), GNUNET_assert, GNUNET_CRYPTO_hmac_raw(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_RECLAIM_attestation_value_to_string(), GNUNET_RECLAIM_attribute_value_to_string(), GNUNET_RECLAIM_id_is_equal, GNUNET_RECLAIM_id_is_zero, GNUNET_STRINGS_base64url_encode(), GNUNET_STRINGS_data_to_string_alloc(), GNUNET_TIME_absolute_add(), GNUNET_TIME_absolute_get(), GNUNET_YES, GNUNET_RECLAIM_Attestation::id, GNUNET_RECLAIM_AttributeList::list_head, GNUNET_RECLAIM_AttestationList::list_head, GNUNET_RECLAIM_Attribute::name, GNUNET_RECLAIM_AttributeListEntry::next, GNUNET_RECLAIM_AttestationListEntry::next, result, SERVER_ADDRESS, subject, GNUNET_RECLAIM_Attribute::type, and GNUNET_RECLAIM_Attestation::type.

Referenced by token_endpoint().

131 {
134  struct GNUNET_HashCode signature;
135  struct GNUNET_TIME_Absolute exp_time;
136  struct GNUNET_TIME_Absolute time_now;
137  char *audience;
138  char *subject;
139  char *header;
140  char *body_str;
141  char *aggr_names_str;
142  char *aggr_sources_str;
143  char *aggr_sources_jwt_str;
144  char *source_name;
145  char *result;
146  char *header_base64;
147  char *body_base64;
148  char *signature_target;
149  char *signature_base64;
150  char *attr_val_str;
151  char *attest_val_str;
152  json_t *body;
153  json_t *aggr_names;
154  json_t *aggr_sources;
155  json_t *aggr_sources_jwt;
156  int num_attestations = 0;
157  for (le = attrs->list_head; NULL != le; le = le->next)
158  {
160  num_attestations++;
161  }
162 
163  // iat REQUIRED time now
164  time_now = GNUNET_TIME_absolute_get ();
165  // exp REQUIRED time expired from config
166  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
167  // auth_time only if max_age
168  // nonce only if nonce
169  // OPTIONAL acr,amr,azp
170  subject =
172  sizeof(struct
174  audience =
176  sizeof(struct
178  header = create_jwt_header ();
179  body = json_object ();
180  aggr_names = json_object ();
181  aggr_sources = json_object ();
182 
183  // iss REQUIRED case sensitive server uri with https
184  // The issuer is the local reclaim instance (e.g.
185  // https://reclaim.id/api/openid)
186  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
187  // sub REQUIRED public key identity, not exceed 255 ASCII length
188  json_object_set_new (body, "sub", json_string (subject));
189  // aud REQUIRED public key client_id must be there
190  json_object_set_new (body, "aud", json_string (audience));
191  // iat
192  json_object_set_new (body,
193  "iat",
194  json_integer (time_now.abs_value_us / (1000 * 1000)));
195  // exp
196  json_object_set_new (body,
197  "exp",
198  json_integer (exp_time.abs_value_us / (1000 * 1000)));
199  // nbf
200  json_object_set_new (body,
201  "nbf",
202  json_integer (time_now.abs_value_us / (1000 * 1000)));
203  // nonce
204  if (NULL != nonce)
205  json_object_set_new (body, "nonce", json_string (nonce));
206  attest_val_str = NULL;
207  aggr_names_str = NULL;
208  aggr_sources_str = NULL;
209  aggr_sources_jwt_str = NULL;
210  source_name = NULL;
211  int i = 0;
212  for (ale = attests->list_head; NULL != ale; ale = ale->next)
213  {
214  // New Attestation
215  GNUNET_asprintf (&source_name,
216  "src%d",
217  i);
218  aggr_sources_jwt = json_object ();
219  attest_val_str =
221  ale->attestation->data,
222  ale->attestation->data_size);
223  json_object_set_new (aggr_sources_jwt, "JWT",
224  json_string (attest_val_str) );
225  aggr_sources_jwt_str = json_dumps (aggr_sources_jwt, JSON_INDENT (0)
226  | JSON_COMPACT);
227  json_object_set_new (aggr_sources, source_name,json_string (
228  aggr_sources_jwt_str));
229  i++;
230  }
231 
232  for (le = attrs->list_head; NULL != le; le = le->next)
233  {
234 
236  {
237 
238  attr_val_str =
240  le->attribute->data,
241  le->attribute->data_size);
242  json_object_set_new (body, le->attribute->name,
243  json_string (attr_val_str));
244  GNUNET_free (attr_val_str);
245  }
246  else
247  {
248  // Check if attest is there
249  int j = 0;
250  for (ale = attests->list_head; NULL != ale; ale = ale->next)
251  {
252  if (GNUNET_YES ==
254  &le->attribute->attestation))
255  break;
256  j++;
257  }
258  GNUNET_assert (NULL != ale);
259  // Attestation is existing, hence take the respective source str
260  GNUNET_asprintf (&source_name,
261  "src%d",
262  j);
263  json_object_set_new (aggr_names, le->attribute->data,
264  json_string (source_name));
265  }
266  }
267 
268  if (NULL != attest_val_str)
269  GNUNET_free (attest_val_str);
270  if (NULL != source_name)
271  GNUNET_free (source_name);
272  if (0 != i)
273  {
274  aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
275  aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
276  | JSON_COMPACT);
277  json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
278  json_object_set_new (body, "_claim_sources", json_string (
279  aggr_sources_str));
280  }
281 
282  json_decref (aggr_names);
283  json_decref (aggr_sources);
284  json_decref (aggr_sources_jwt);
285 
286  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
287  json_decref (body);
288  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
289 
290  GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
291  fix_base64 (header_base64);
292 
293  GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
294  fix_base64 (body_base64);
295 
296  GNUNET_free (subject);
297  GNUNET_free (audience);
298 
303  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
304  GNUNET_CRYPTO_hmac_raw (secret_key,
305  strlen (secret_key),
306  signature_target,
307  strlen (signature_target),
308  &signature);
309  GNUNET_STRINGS_base64url_encode ((const char *) &signature,
310  sizeof(struct GNUNET_HashCode),
311  &signature_base64);
312  fix_base64 (signature_base64);
313 
314  GNUNET_asprintf (&result,
315  "%s.%s.%s",
316  header_base64,
317  body_base64,
318  signature_base64);
319 
320  GNUNET_free (signature_target);
321  GNUNET_free (header);
322  GNUNET_free (body_str);
323  if (NULL != aggr_sources_str)
324  GNUNET_free (aggr_sources_str);
325  if (NULL != aggr_names_str)
326  GNUNET_free (aggr_names_str);
327  if (NULL != aggr_sources_jwt_str)
328  GNUNET_free (aggr_sources_jwt_str);
329  GNUNET_free (signature_base64);
330  GNUNET_free (body_base64);
331  GNUNET_free (header_base64);
332  return result;
333 }
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' this be the standard hmac function and the abov...
Definition: crypto_hash.c:403
const char * name
The name of the attribute.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_RECLAIM_Attestation * attestation
The attestation.
#define GNUNET_NO
Definition: gnunet_common.h:86
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
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1930
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
char * GNUNET_RECLAIM_attestation_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'claim' of an attestation to a string.
struct GNUNET_RECLAIM_Identifier attestation
Referenced ID of Attestation (may be 0 if self-attested)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
static int result
Global testing status.
size_t data_size
Number of bytes in data.
size_t data_size
Number of bytes in data.
A 512-bit hashcode.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void fix_base64(char *str)
Definition: oidc_helper.c:103
struct GNUNET_RECLAIM_Identifier id
ID.
uint32_t type
Type/Format of Claim.
struct GNUNET_RECLAIM_AttestationListEntry * list_head
List head.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
static GNUNET_NETWORK_STRUCT_END char * create_jwt_header(void)
Definition: oidc_helper.c:73
const void * data
Binary value stored as attribute value.
static char * subject
Subject pubkey string.
Definition: gnunet-abd.c:86
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
#define GNUNET_RECLAIM_id_is_equal(a, b)
#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 'claim' of an attribute to a string.
uint32_t type
Type of Claim.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:85
struct GNUNET_RECLAIM_AttestationListEntry * next
DLL.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:935
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_RECLAIM_id_is_zero(a)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ OIDC_build_authz_code()

char* OIDC_build_authz_code ( const struct GNUNET_CRYPTO_EcdsaPrivateKey issuer,
const struct GNUNET_RECLAIM_Ticket ticket,
struct GNUNET_RECLAIM_AttributeList attrs,
struct GNUNET_RECLAIM_AttestationList attests,
const char *  nonce_str,
const char *  code_challenge 
)

Builds an OIDC authorization code including a reclaim ticket and nonce.

Parameters
issuerthe issuer of the ticket, used to sign the ticket and nonce
ticketthe ticket to include in the code
attrslist of attributes to share
noncethe nonce to include in the code
code_challengePKCE code challenge
Returns
a new authorization code (caller must free)
Parameters
issuerthe issuer of the ticket, used to sign the ticket and nonce
ticketthe ticket to include in the code
attrslist of attributes which are shared
noncethe nonce to include in the code
code_challengePKCE code challenge
Returns
a new authorization code (caller must free)

PLAINTEXT

END

ENCRYPT

Definition at line 431 of file oidc_helper.c.

References OIDC_Parameters::attest_list_len, OIDC_Parameters::attr_list_len, GNUNET_RECLAIM_Ticket::audience, OIDC_Parameters::code_challenge_len, encrypt_payload(), GNUNET_assert, GNUNET_break, GNUNET_CRYPTO_ecdhe_key_create(), GNUNET_CRYPTO_ecdhe_key_get_public(), GNUNET_CRYPTO_ecdsa_sign(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_RECLAIM_attestation_list_serialize(), GNUNET_RECLAIM_attestation_list_serialize_get_size(), GNUNET_RECLAIM_attribute_list_serialize(), GNUNET_RECLAIM_attribute_list_serialize_get_size(), GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, GNUNET_STRINGS_base64url_encode(), GNUNET_SYSERR, OIDC_Parameters::nonce, payload, GNUNET_CRYPTO_EccSignaturePurpose::purpose, GNUNET_CRYPTO_EccSignaturePurpose::size, and OIDC_Parameters::ticket.

Referenced by oidc_ticket_issue_cb().

437 {
438  struct OIDC_Parameters params;
439  char *code_payload;
440  char *payload;
441  char *tmp;
442  char *code_str;
443  char *buf_ptr = NULL;
444  size_t payload_len;
445  size_t code_payload_len;
446  size_t attr_list_len = 0;
447  size_t attests_list_len = 0;
448  size_t code_challenge_len = 0;
449  uint32_t nonce;
450  uint32_t nonce_tmp;
452  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv;
453  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
454 
456  // Assign ticket
457  memset (&params, 0, sizeof(params));
458  params.ticket = *ticket;
459  // Assign nonce
460  nonce = 0;
461  payload_len = sizeof(struct OIDC_Parameters);
462  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
463  {
464  if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX))
465  {
466  GNUNET_break (0);
467  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
468  return NULL;
469  }
471  "Got nonce: %u from %s\n",
472  nonce,
473  nonce_str);
474  }
475  nonce_tmp = htonl (nonce);
476  params.nonce = nonce_tmp;
477  // Assign code challenge
478  if (NULL != code_challenge)
479  code_challenge_len = strlen (code_challenge);
480  payload_len += code_challenge_len;
481  params.code_challenge_len = htonl (code_challenge_len);
482  // Assign attributes
483  if (NULL != attrs)
484  {
485  // Get length
486  attr_list_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
487  params.attr_list_len = htonl (attr_list_len);
489  "Length of serialized attributes: %lu\n",
490  attr_list_len);
491  // Get serialized attributes
492  payload_len += attr_list_len;
493  }
494  if (NULL != attests)
495  {
496  // Get length
497  attests_list_len =
499  params.attest_list_len = htonl (attests_list_len);
501  "Length of serialized attestations: %lu\n",
502  attests_list_len);
503  // Get serialized attributes
504  payload_len += attests_list_len;
505  }
506 
507  // Get plaintext length
508  payload = GNUNET_malloc (payload_len);
509  memcpy (payload, &params, sizeof(params));
510  tmp = payload + sizeof(params);
511  if (0 < code_challenge_len)
512  {
513  memcpy (tmp, code_challenge, code_challenge_len);
514  tmp += code_challenge_len;
515  }
516  if (0 < attr_list_len)
518  if (0 < attests_list_len)
520 
524  // Get length
525  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
526  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
527  + payload_len + sizeof(struct
530  "Length of data to encode: %lu\n",
531  code_payload_len);
532 
533  // Generate ECDH key
534  ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create ();
535  GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub);
536  // Initialize code payload
537  code_payload = GNUNET_malloc (code_payload_len);
538  GNUNET_assert (NULL != code_payload);
539  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
540  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
541  + sizeof(ecdh_pub) + payload_len);
543  // Store pubkey
544  buf_ptr = (char *) &purpose[1];
545  memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub));
546  buf_ptr += sizeof(ecdh_pub);
547  // Encrypt plaintext and store
548  encrypt_payload (&ticket->audience, ecdh_priv, payload, payload_len, buf_ptr);
549  GNUNET_free (ecdh_priv);
550  GNUNET_free (payload);
551  buf_ptr += payload_len;
552  // Sign and store signature
553  if (GNUNET_SYSERR ==
554  GNUNET_CRYPTO_ecdsa_sign (issuer,
555  purpose,
557  buf_ptr))
558  {
559  GNUNET_break (0);
560  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
561  GNUNET_free (code_payload);
562  return NULL;
563  }
564  GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
565  GNUNET_free (code_payload);
566  return code_str;
567 }
size_t GNUNET_RECLAIM_attestation_list_serialize(const struct GNUNET_RECLAIM_AttestationList *attrs, char *result)
Serialize an attribute list.
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:404
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t nonce
The nonce.
Definition: oidc_helper.c:52
#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
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1930
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
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
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket.
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition: oidc_helper.c:57
an ECC signature using ECDSA
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
Private ECC key encoded for transmission.
#define GNUNET_SYSERR
Definition: gnunet_common.h:84
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
size_t GNUNET_RECLAIM_attribute_list_serialize(const struct GNUNET_RECLAIM_AttributeList *attrs, char *result)
Serialize an attribute list.
static unsigned long long payload
How much data are we currently storing in the database?
struct GNUNET_CRYPTO_EcdsaPublicKey audience
The ticket audience (= relying party)
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
#define GNUNET_log(kind,...)
size_t GNUNET_RECLAIM_attribute_list_serialize_get_size(const struct GNUNET_RECLAIM_AttributeList *attrs)
Get required size for serialization buffer.
size_t GNUNET_RECLAIM_attestation_list_serialize_get_size(const struct GNUNET_RECLAIM_AttestationList *attestations)
Get required size for serialization buffer.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
The signature used to generate the authorization code.
Definition: oidc_helper.c:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ OIDC_parse_authz_code()

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_AttributeList **  attrs,
struct GNUNET_RECLAIM_AttestationList **  attests,
char **  nonce_str 
)

Parse reclaim ticket and nonce from authorization code.

This also verifies the signature in the code.

Parameters
ecdsa_privthe audience of the ticket
codethe string representation of the code
code_verfierPKCE code verifier
ticketwhere to store the ticket
attrsthe attributes found in the code
noncewhere to store the nonce
Returns
GNUNET_OK if successful, else GNUNET_SYSERR

This also verifies the signature in the code.

Parameters
audiencethe expected audience of the code
codethe string representation of the code
code_verfierPKCE code verifier
ticketwhere to store the ticket
attrsthe attributes in the code
noncewhere to store the nonce
Returns
GNUNET_OK if successful, else GNUNET_SYSERR

Definition at line 584 of file oidc_helper.c.

References OIDC_Parameters::attr_list_len, GNUNET_RECLAIM_Ticket::audience, OIDC_Parameters::code_challenge_len, decrypt_payload(), GNUNET_asprintf(), GNUNET_CRYPTO_ecdsa_key_get_public(), GNUNET_CRYPTO_ecdsa_verify(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_free_non_null, GNUNET_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_OK, GNUNET_RECLAIM_attribute_list_deserialize(), GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, GNUNET_STRINGS_base64url_decode(), GNUNET_STRINGS_base64url_encode(), GNUNET_SYSERR, GNUNET_RECLAIM_Ticket::identity, OIDC_Parameters::nonce, GNUNET_CRYPTO_EccSignaturePurpose::purpose, and OIDC_Parameters::ticket.

Referenced by token_endpoint().

591 {
592  char *code_payload;
593  char *ptr;
594  char *plaintext;
595  char *attrs_ser;
596  char *expected_code_challenge;
597  char *code_challenge;
598  char *code_verifier_hash;
600  struct GNUNET_CRYPTO_EcdsaSignature *signature;
601  struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
602  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
603  uint32_t code_challenge_len;
604  uint32_t attrs_ser_len;
605  size_t plaintext_len;
606  size_t code_payload_len;
607  uint32_t nonce = 0;
608  struct OIDC_Parameters *params;
609 
610  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
611  code_payload = NULL;
612  code_payload_len =
613  GNUNET_STRINGS_base64url_decode (code, strlen (code),
614  (void **) &code_payload);
615  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
616  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
617  + sizeof(struct OIDC_Parameters)
618  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
619  {
620  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
621  GNUNET_free_non_null (code_payload);
622  return GNUNET_SYSERR;
623  }
624 
625  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
626  plaintext_len = code_payload_len;
627  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
628  ptr = (char *) &purpose[1];
629  // Public ECDH key
630  ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
631  ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
632  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
633 
634  // Decrypt ciphertext
635  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
636  plaintext = GNUNET_malloc (plaintext_len);
637  decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
638  // ptr = plaintext;
639  ptr += plaintext_len;
640  signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
641  params = (struct OIDC_Parameters *) plaintext;
642 
643  // cmp code_challenge code_verifier
644  code_challenge_len = ntohl (params->code_challenge_len);
645  if (0 != code_challenge_len) /* Only check if this code requires a CV */
646  {
647  if (NULL == code_verifier)
648  {
650  "Expected code verifier!\n");
651  GNUNET_free_non_null (code_payload);
652  return GNUNET_SYSERR;
653  }
654  code_verifier_hash = GNUNET_malloc (256 / 8);
655  // hash code verifier
656  gcry_md_hash_buffer (GCRY_MD_SHA256,
657  code_verifier_hash,
658  code_verifier,
659  strlen (code_verifier));
660  // encode code verifier
661  GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8, &expected_code_challenge);
662  code_challenge = (char *) &params[1];
663  GNUNET_free (code_verifier_hash);
664  if ((strlen (expected_code_challenge) != code_challenge_len) ||
665  (0 !=
666  strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
667  {
669  "Invalid code verifier! Expected: %s, Got: %.*s\n",
670  expected_code_challenge,
671  code_challenge_len,
672  code_challenge);
673  GNUNET_free_non_null (code_payload);
674  GNUNET_free (expected_code_challenge);
675  return GNUNET_SYSERR;
676  }
677  GNUNET_free (expected_code_challenge);
678  }
679  // Ticket
680  memcpy (ticket, &params->ticket, sizeof(params->ticket));
681  // Nonce
682  nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr));
683  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
684  // Signature
685  GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
686  if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
687  {
688  GNUNET_free (code_payload);
689  GNUNET_free (plaintext);
691  "Audience in ticket does not match client!\n");
692  return GNUNET_SYSERR;
693  }
694  if (GNUNET_OK !=
696  purpose,
697  signature,
698  &ticket->identity))
699  {
700  GNUNET_free (code_payload);
701  GNUNET_free (plaintext);
702  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
703  return GNUNET_SYSERR;
704  }
705  // Attributes
706  attrs_ser = ((char *) &params[1]) + code_challenge_len;
707  attrs_ser_len = ntohl (params->attr_list_len);
708  *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
709 
710  *nonce_str = NULL;
711  if (nonce != 0)
712  GNUNET_asprintf (nonce_str, "%u", nonce);
713  GNUNET_free (code_payload);
714  GNUNET_free (plaintext);
715  return GNUNET_OK;
716 }
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
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t nonce
The nonce.
Definition: oidc_helper.c:52
struct GNUNET_RECLAIM_AttributeList * GNUNET_RECLAIM_attribute_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
uint32_t attr_list_len
The length of the attributes list.
Definition: oidc_helper.c:62
#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.
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:389
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1930
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket.
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition: oidc_helper.c:57
an ECC signature using ECDSA
struct GNUNET_CRYPTO_EcdsaPublicKey identity
The ticket issuer (= the user)
#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
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_CRYPTO_EcdsaPublicKey audience
The ticket audience (= relying party)
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
#define GNUNET_log(kind,...)
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
Definition: oidc_helper.c:47
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:2048
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
The signature used to generate the authorization code.
Definition: oidc_helper.c:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ OIDC_build_token_response()

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?

Parameters
access_tokenthe access token to include
id_tokenthe id_token to include
expiration_timethe expiration time of the token(s)
token_responsewhere to store the response

Definition at line 729 of file oidc_helper.c.

References GNUNET_assert, and GNUNET_TIME_Relative::rel_value_us.

Referenced by token_endpoint().

733 {
734  json_t *root_json;
735 
736  root_json = json_object ();
737 
738  GNUNET_assert (NULL != access_token);
739  GNUNET_assert (NULL != id_token);
740  GNUNET_assert (NULL != expiration_time);
741  json_object_set_new (root_json, "access_token", json_string (access_token));
742  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
743  json_object_set_new (root_json,
744  "expires_in",
745  json_integer (expiration_time->rel_value_us
746  / (1000 * 1000)));
747  json_object_set_new (root_json, "id_token", json_string (id_token));
748  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
749  json_decref (root_json);
750 }
uint64_t rel_value_us
The actual value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Here is the caller graph for this function:

◆ OIDC_access_token_new()

char* OIDC_access_token_new ( )

Generate a new access token.

Definition at line 757 of file oidc_helper.c.

References GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_u64(), and GNUNET_STRINGS_base64_encode().

Referenced by token_endpoint().

758 {
759  char *access_token;
760  uint64_t random_number;
761 
762  random_number =
764  GNUNET_STRINGS_base64_encode (&random_number,
765  sizeof(uint64_t),
766  &access_token);
767  return access_token;
768 }
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
Randomness for IVs etc.
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1874
Here is the call graph for this function:
Here is the caller graph for this function: