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_ATTRIBUTE_ClaimList *attrs, 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_ATTRIBUTE_ClaimList *attrs, 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_ATTRIBUTE_ClaimList **attrs, 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_ATTRIBUTE_ClaimList attrs,
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 119 of file oidc_helper.c.

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry::attest, GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry::claim, create_jwt_header(), GNUNET_RECLAIM_ATTRIBUTE_Claim::data, GNUNET_RECLAIM_ATTESTATION_Claim::data, GNUNET_RECLAIM_ATTRIBUTE_Claim::data_size, GNUNET_RECLAIM_ATTESTATION_Claim::data_size, fix_base64(), GNUNET_asprintf(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_CRYPTO_hmac_raw(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_RECLAIM_ATTESTATION_value_to_string(), GNUNET_RECLAIM_ATTRIBUTE_list_count_attest(), GNUNET_RECLAIM_ATTRIBUTE_value_to_string(), GNUNET_STRINGS_base64_encode(), GNUNET_STRINGS_data_to_string_alloc(), GNUNET_TIME_absolute_add(), GNUNET_TIME_absolute_get(), GNUNET_RECLAIM_ATTESTATION_Claim::id, GNUNET_RECLAIM_ATTESTATION_REFERENCE::id_attest, GNUNET_RECLAIM_ATTRIBUTE_ClaimList::list_head, GNUNET_RECLAIM_ATTRIBUTE_ClaimList::list_tail, GNUNET_RECLAIM_ATTRIBUTE_Claim::name, GNUNET_RECLAIM_ATTESTATION_REFERENCE::name, GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry::next, GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry::reference, result, SERVER_ADDRESS, subject, GNUNET_RECLAIM_ATTRIBUTE_Claim::type, and GNUNET_RECLAIM_ATTESTATION_Claim::type.

Referenced by token_endpoint().

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 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
const char * name
The name of the attribute.
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.
size_t data_size
Number of bytes in data.
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
struct GNUNET_RECLAIM_ATTESTATION_REFERENCE * reference
The reference.
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
uint64_t id_attest
Referenced ID of Attestation.
#define SERVER_ADDRESS
Definition: oidc_helper.h:39
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.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
size_t data_size
Number of bytes in data.
static int result
Global testing status.
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:98
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1855
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static GNUNET_NETWORK_STRUCT_END char * create_jwt_header(void)
Definition: oidc_helper.c:68
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.
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...
const char * name
The name of the attribute/attestation reference value.
#define GNUNET_log(kind,...)
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
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * next
DLL.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_head
List head.
#define GNUNET_free(ptr)
Wrapper around free.
const void * data
Binary value stored as attribute value.
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_ATTRIBUTE_ClaimList attrs,
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 573 of file oidc_helper.c.

References OIDC_Parameters::attr_list_len, GNUNET_RECLAIM_Ticket::audience, base64_and_urlencode(), 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_ATTRIBUTE_list_serialize(), GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size(), GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, GNUNET_SYSERR, OIDC_Parameters::nonce, payload, GNUNET_CRYPTO_EccSignaturePurpose::purpose, GNUNET_CRYPTO_EccSignaturePurpose::size, and OIDC_Parameters::ticket.

Referenced by oidc_ticket_issue_cb().

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
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,
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 }
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
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...
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
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)
static char * base64_and_urlencode(const char *data, size_t data_size)
Returns base64 encoded string urlencoded.
Definition: oidc_helper.c:434
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_ATTRIBUTE_ClaimList *attrs)
Get required size for serialization buffer.
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.
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_ATTRIBUTE_ClaimList **  attrs,
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 708 of file oidc_helper.c.

References OIDC_Parameters::attr_list_len, GNUNET_RECLAIM_Ticket::audience, base64url_encode(), 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_base64_decode(), GNUNET_SYSERR, GNUNET_RECLAIM_Ticket::identity, OIDC_Parameters::nonce, GNUNET_CRYPTO_EccSignaturePurpose::purpose, and OIDC_Parameters::ticket.

Referenced by token_endpoint().

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 }
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
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:531
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
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1920
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...
static char * base64url_encode(const char *data, size_t data_size)
Returns base64 encoded string urlencoded.
Definition: oidc_helper.c:453
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
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * GNUNET_RECLAIM_ATTRIBUTE_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
#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 851 of file oidc_helper.c.

References GNUNET_assert, and GNUNET_TIME_Relative::rel_value_us.

Referenced by token_endpoint().

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 }
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 879 of file oidc_helper.c.

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

Referenced by token_endpoint().

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 }
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:1855
Here is the call graph for this function:
Here is the caller graph for this function: