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 *source_name;
144  char *result;
145  char *header_base64;
146  char *body_base64;
147  char *signature_target;
148  char *signature_base64;
149  char *attr_val_str;
150  char *attest_val_str;
151  json_t *body;
152  json_t *aggr_names;
153  json_t *aggr_sources;
154  json_t *aggr_sources_jwt;
155  int num_attestations = 0;
156  for (le = attrs->list_head; NULL != le; le = le->next)
157  {
159  num_attestations++;
160  }
161 
162  // iat REQUIRED time now
163  time_now = GNUNET_TIME_absolute_get ();
164  // exp REQUIRED time expired from config
165  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
166  // auth_time only if max_age
167  // nonce only if nonce
168  // OPTIONAL acr,amr,azp
169  subject =
171  sizeof(struct
173  audience =
175  sizeof(struct
177  header = create_jwt_header ();
178  body = json_object ();
179  aggr_names = json_object ();
180  aggr_sources = json_object ();
181 
182  // iss REQUIRED case sensitive server uri with https
183  // The issuer is the local reclaim instance (e.g.
184  // https://reclaim.id/api/openid)
185  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
186  // sub REQUIRED public key identity, not exceed 255 ASCII length
187  json_object_set_new (body, "sub", json_string (subject));
188  // aud REQUIRED public key client_id must be there
189  json_object_set_new (body, "aud", json_string (audience));
190  // iat
191  json_object_set_new (body,
192  "iat",
193  json_integer (time_now.abs_value_us / (1000 * 1000)));
194  // exp
195  json_object_set_new (body,
196  "exp",
197  json_integer (exp_time.abs_value_us / (1000 * 1000)));
198  // nbf
199  json_object_set_new (body,
200  "nbf",
201  json_integer (time_now.abs_value_us / (1000 * 1000)));
202  // nonce
203  if (NULL != nonce)
204  json_object_set_new (body, "nonce", json_string (nonce));
205  attest_val_str = NULL;
206  aggr_names_str = NULL;
207  aggr_sources_str = NULL;
208  source_name = NULL;
209  int i = 0;
210  for (ale = attests->list_head; NULL != ale; ale = ale->next)
211  {
212  // New Attestation
213  GNUNET_asprintf (&source_name,
214  "src%d",
215  i);
216  aggr_sources_jwt = json_object ();
217  attest_val_str =
219  ale->attestation->data,
220  ale->attestation->data_size);
221  json_object_set_new (aggr_sources_jwt, "JWT",
222  json_string (attest_val_str) );
223  json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
224  GNUNET_free (source_name);
225  source_name = NULL;
226  i++;
227  }
228 
229  for (le = attrs->list_head; NULL != le; le = le->next)
230  {
231 
233  {
234 
235  attr_val_str =
237  le->attribute->data,
238  le->attribute->data_size);
239  json_object_set_new (body, le->attribute->name,
240  json_string (attr_val_str));
241  GNUNET_free (attr_val_str);
242  }
243  else
244  {
245  // Check if attest is there
246  int j = 0;
247  for (ale = attests->list_head; NULL != ale; ale = ale->next)
248  {
249  if (GNUNET_YES ==
251  &le->attribute->attestation))
252  break;
253  j++;
254  }
255  GNUNET_assert (NULL != ale);
256  // Attestation is existing, hence take the respective source str
257  GNUNET_asprintf (&source_name,
258  "src%d",
259  j);
260  json_object_set_new (aggr_names, le->attribute->data,
261  json_string (source_name));
262  GNUNET_free (source_name);
263  }
264  }
265 
266  if (NULL != attest_val_str)
267  GNUNET_free (attest_val_str);
268  if (0 != i)
269  {
270  aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
271  aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
272  | JSON_COMPACT);
273  json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
274  json_object_set_new (body, "_claim_sources", json_string (
275  aggr_sources_str));
276  }
277 
278  json_decref (aggr_names);
279  json_decref (aggr_sources);
280 
281  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
282  json_decref (body);
283  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
284 
285  GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
286  fix_base64 (header_base64);
287 
288  GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
289  fix_base64 (body_base64);
290 
291  GNUNET_free (subject);
292  GNUNET_free (audience);
293 
298  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
299  GNUNET_CRYPTO_hmac_raw (secret_key,
300  strlen (secret_key),
301  signature_target,
302  strlen (signature_target),
303  &signature);
304  GNUNET_STRINGS_base64url_encode ((const char *) &signature,
305  sizeof(struct GNUNET_HashCode),
306  &signature_base64);
307  fix_base64 (signature_base64);
308 
309  GNUNET_asprintf (&result,
310  "%s.%s.%s",
311  header_base64,
312  body_base64,
313  signature_base64);
314 
315  GNUNET_free (signature_target);
316  GNUNET_free (header);
317  GNUNET_free (body_str);
318  if (NULL != aggr_sources_str)
319  GNUNET_free (aggr_sources_str);
320  if (NULL != aggr_names_str)
321  GNUNET_free (aggr_names_str);
322  GNUNET_free (signature_base64);
323  GNUNET_free (body_base64);
324  GNUNET_free (header_base64);
325  return result;
326 }
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:420
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.
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.
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 424 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().

430 {
431  struct OIDC_Parameters params;
432  char *code_payload;
433  char *payload;
434  char *tmp;
435  char *code_str;
436  char *buf_ptr = NULL;
437  size_t payload_len;
438  size_t code_payload_len;
439  size_t attr_list_len = 0;
440  size_t attests_list_len = 0;
441  size_t code_challenge_len = 0;
442  uint32_t nonce;
443  uint32_t nonce_tmp;
445  struct GNUNET_CRYPTO_EcdhePrivateKey ecdh_priv;
446  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
447 
449  // Assign ticket
450  memset (&params, 0, sizeof(params));
451  params.ticket = *ticket;
452  // Assign nonce
453  nonce = 0;
454  payload_len = sizeof(struct OIDC_Parameters);
455  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
456  {
457  if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX))
458  {
459  GNUNET_break (0);
460  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
461  return NULL;
462  }
464  "Got nonce: %u from %s\n",
465  nonce,
466  nonce_str);
467  }
468  nonce_tmp = htonl (nonce);
469  params.nonce = nonce_tmp;
470  // Assign code challenge
471  if (NULL != code_challenge)
472  code_challenge_len = strlen (code_challenge);
473  payload_len += code_challenge_len;
474  params.code_challenge_len = htonl (code_challenge_len);
475  // Assign attributes
476  if (NULL != attrs)
477  {
478  // Get length
479  attr_list_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
480  params.attr_list_len = htonl (attr_list_len);
482  "Length of serialized attributes: %lu\n",
483  attr_list_len);
484  // Get serialized attributes
485  payload_len += attr_list_len;
486  }
487  if (NULL != attests)
488  {
489  // Get length
490  attests_list_len =
492  params.attest_list_len = htonl (attests_list_len);
494  "Length of serialized attestations: %lu\n",
495  attests_list_len);
496  // Get serialized attributes
497  payload_len += attests_list_len;
498  }
499 
500  // Get plaintext length
501  payload = GNUNET_malloc (payload_len);
502  memcpy (payload, &params, sizeof(params));
503  tmp = payload + sizeof(params);
504  if (0 < code_challenge_len)
505  {
506  memcpy (tmp, code_challenge, code_challenge_len);
507  tmp += code_challenge_len;
508  }
509  if (0 < attr_list_len)
511  if (0 < attests_list_len)
513 
517  // Get length
518  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
519  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
520  + payload_len + sizeof(struct
523  "Length of data to encode: %lu\n",
524  code_payload_len);
525 
526  // Generate ECDH key
527  GNUNET_CRYPTO_ecdhe_key_create (&ecdh_priv);
528  GNUNET_CRYPTO_ecdhe_key_get_public (&ecdh_priv, &ecdh_pub);
529  // Initialize code payload
530  code_payload = GNUNET_malloc (code_payload_len);
531  GNUNET_assert (NULL != code_payload);
532  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
533  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
534  + sizeof(ecdh_pub) + payload_len);
536  // Store pubkey
537  buf_ptr = (char *) &purpose[1];
538  memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub));
539  buf_ptr += sizeof(ecdh_pub);
540  // Encrypt plaintext and store
541  encrypt_payload (&ticket->audience,
542  &ecdh_priv,
543  payload,
544  payload_len,
545  buf_ptr);
546  GNUNET_free (payload);
547  buf_ptr += payload_len;
548  // Sign and store signature
549  if (GNUNET_SYSERR ==
551  purpose,
553  buf_ptr))
554  {
555  GNUNET_break (0);
556  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
557  GNUNET_free (code_payload);
558  return NULL;
559  }
560  GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
561  GNUNET_free (code_payload);
562  return code_str;
563 }
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:397
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
#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.
void GNUNET_CRYPTO_ecdhe_key_create(struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
Create a new private key.
Definition: crypto_ecc.c:508
#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.
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:215
size_t GNUNET_RECLAIM_attribute_list_serialize(const struct GNUNET_RECLAIM_AttributeList *attrs, char *result)
Serialize an attribute list.
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:645
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 580 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, 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_log, GNUNET_malloc, GNUNET_memcmp, GNUNET_OK, GNUNET_RECLAIM_attestation_list_deserialize(), 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().

587 {
588  char *code_payload;
589  char *ptr;
590  char *plaintext;
591  char *attrs_ser;
592  char *attests_ser;
593  char *expected_code_challenge;
594  char *code_challenge;
595  char *code_verifier_hash;
597  struct GNUNET_CRYPTO_EcdsaSignature *signature;
598  struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
599  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
600  uint32_t code_challenge_len;
601  uint32_t attrs_ser_len;
602  uint32_t attests_ser_len;
603  size_t plaintext_len;
604  size_t code_payload_len;
605  uint32_t nonce = 0;
606  struct OIDC_Parameters *params;
607 
608  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
609  code_payload = NULL;
610  code_payload_len =
611  GNUNET_STRINGS_base64url_decode (code, strlen (code),
612  (void **) &code_payload);
613  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
614  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
615  + sizeof(struct OIDC_Parameters)
616  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
617  {
618  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
619  GNUNET_free (code_payload);
620  return GNUNET_SYSERR;
621  }
622 
623  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
624  plaintext_len = code_payload_len;
625  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
626  ptr = (char *) &purpose[1];
627  // Public ECDH key
628  ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
629  ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
630  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
631 
632  // Decrypt ciphertext
633  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
634  plaintext = GNUNET_malloc (plaintext_len);
635  decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
636  // ptr = plaintext;
637  ptr += plaintext_len;
638  signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
639  params = (struct OIDC_Parameters *) plaintext;
640 
641  // cmp code_challenge code_verifier
642  code_challenge_len = ntohl (params->code_challenge_len);
643  if (0 != code_challenge_len) /* Only check if this code requires a CV */
644  {
645  if (NULL == code_verifier)
646  {
648  "Expected code verifier!\n");
649  GNUNET_free (code_payload);
650  return GNUNET_SYSERR;
651  }
652  code_verifier_hash = GNUNET_malloc (256 / 8);
653  // hash code verifier
654  gcry_md_hash_buffer (GCRY_MD_SHA256,
655  code_verifier_hash,
656  code_verifier,
657  strlen (code_verifier));
658  // encode code verifier
659  GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
660  &expected_code_challenge);
661  code_challenge = (char *) &params[1];
662  GNUNET_free (code_verifier_hash);
663  if ((strlen (expected_code_challenge) != code_challenge_len) ||
664  (0 !=
665  strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
666  {
668  "Invalid code verifier! Expected: %s, Got: %.*s\n",
669  expected_code_challenge,
670  code_challenge_len,
671  code_challenge);
672  GNUNET_free (code_payload);
673  GNUNET_free (expected_code_challenge);
674  return GNUNET_SYSERR;
675  }
676  GNUNET_free (expected_code_challenge);
677  }
678  // Ticket
679  memcpy (ticket, &params->ticket, sizeof(params->ticket));
680  // Nonce
681  nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr));
682  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
683  // Signature
684  GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
685  if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
686  {
687  GNUNET_free (code_payload);
688  GNUNET_free (plaintext);
690  "Audience in ticket does not match client!\n");
691  return GNUNET_SYSERR;
692  }
693  if (GNUNET_OK !=
695  purpose,
696  signature,
697  &ticket->identity))
698  {
699  GNUNET_free (code_payload);
700  GNUNET_free (plaintext);
701  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
702  return GNUNET_SYSERR;
703  }
704  // Attributes
705  attrs_ser = ((char *) &params[1]) + code_challenge_len;
706  attrs_ser_len = ntohl (params->attr_list_len);
707  *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
708  attests_ser = ((char*) attrs_ser) + attrs_ser_len;
709  attests_ser_len = ntohl (params->attest_list_len);
710  *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser,
711  attests_ser_len);
712 
713  *nonce_str = NULL;
714  if (nonce != 0)
715  GNUNET_asprintf (nonce_str, "%u", nonce);
716  GNUNET_free (code_payload);
717  GNUNET_free (plaintext);
718  return GNUNET_OK;
719 }
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
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:382
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)
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:176
uint32_t attest_list_len
The length of the attestation list.
Definition: oidc_helper.c:67
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
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:745
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_AttestationList * GNUNET_RECLAIM_attestation_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
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 732 of file oidc_helper.c.

References GNUNET_assert, and GNUNET_TIME_Relative::rel_value_us.

Referenced by token_endpoint().

736 {
737  json_t *root_json;
738 
739  root_json = json_object ();
740 
741  GNUNET_assert (NULL != access_token);
742  GNUNET_assert (NULL != id_token);
743  GNUNET_assert (NULL != expiration_time);
744  json_object_set_new (root_json, "access_token", json_string (access_token));
745  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
746  json_object_set_new (root_json,
747  "expires_in",
748  json_integer (expiration_time->rel_value_us
749  / (1000 * 1000)));
750  json_object_set_new (root_json, "id_token", json_string (id_token));
751  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
752  json_decref (root_json);
753 }
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 760 of file oidc_helper.c.

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

Referenced by token_endpoint().

761 {
762  char *access_token;
763  uint64_t random_number;
764 
765  random_number =
767  GNUNET_STRINGS_base64_encode (&random_number,
768  sizeof(uint64_t),
769  &access_token);
770  return access_token;
771 }
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: