GNUnet  0.11.x
Data Structures | Functions
oidc_helper.c File Reference

helper library for OIDC related functions More...

#include "platform.h"
#include <inttypes.h>
#include <jansson.h>
#include "gnunet_util_lib.h"
#include "gnunet_reclaim_attribute_lib.h"
#include "gnunet_reclaim_service.h"
#include "gnunet_signatures.h"
#include "oidc_helper.h"
#include <gcrypt.h>
Include dependency graph for oidc_helper.c:

Go to the source code of this file.

Data Structures

struct  OIDC_Parameters
 The signature used to generate the authorization code. More...
 

Functions

static GNUNET_NETWORK_STRUCT_END char * create_jwt_header (void)
 
static void replace_char (char *str, char find, char replace)
 
static void fix_base64 (char *str)
 
char * OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const 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...
 
static char from_hex (char ch)
 
static char to_hex (char code)
 
static char * url_encode (const char *str)
 
static char * url_decode (const char *str)
 
static char * base64_and_urlencode (const char *data, size_t data_size)
 Returns base64 encoded string urlencoded. More...
 
static char * base64url_encode (const char *data, size_t data_size)
 Returns base64 encoded string urlencoded. More...
 
static void derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_HashCode *key_material)
 
static void calculate_key_priv (struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
 
static void calculate_key_pub (struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
 
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)
 
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)
 
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. 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_str)
 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.c.

Function Documentation

◆ create_jwt_header()

static GNUNET_NETWORK_STRUCT_END char* create_jwt_header ( void  )
static

Definition at line 68 of file oidc_helper.c.

References JWT_ALG, JWT_ALG_VALUE, JWT_TYP, and JWT_TYP_VALUE.

Referenced by OIDC_id_token_new().

69 {
70  json_t *root;
71  char *json_str;
72 
73  root = json_object ();
74  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
75  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
76 
77  json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
78  json_decref (root);
79  return json_str;
80 }
#define JWT_ALG_VALUE
Definition: oidc_helper.h:33
#define JWT_TYP
Definition: oidc_helper.h:35
#define JWT_ALG
Definition: oidc_helper.h:30
#define JWT_TYP_VALUE
Definition: oidc_helper.h:37
Here is the caller graph for this function:

◆ replace_char()

static void replace_char ( char *  str,
char  find,
char  replace 
)
static

Definition at line 84 of file oidc_helper.c.

Referenced by fix_base64().

85 {
86  char *current_pos = strchr (str, find);
87 
88  while (current_pos)
89  {
90  *current_pos = replace;
91  current_pos = strchr (current_pos, find);
92  }
93 }
Here is the caller graph for this function:

◆ fix_base64()

static void fix_base64 ( char *  str)
static

Definition at line 98 of file oidc_helper.c.

References replace_char().

Referenced by OIDC_id_token_new().

99 {
100  // Replace + with -
101  replace_char (str, '+', '-');
102 
103  // Replace / with _
104  replace_char (str, '/', '_');
105 }
static void replace_char(char *str, char find, char replace)
Definition: oidc_helper.c:84
Here is the call graph for this function:
Here is the caller graph for this function:

◆ OIDC_id_token_new()

char* OIDC_id_token_new ( const struct GNUNET_CRYPTO_EcdsaPublicKey aud_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey sub_key,
const 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::claim, create_jwt_header(), GNUNET_RECLAIM_ATTRIBUTE_Claim::data, GNUNET_RECLAIM_ATTRIBUTE_Claim::data_size, fix_base64(), GNUNET_asprintf(), GNUNET_CRYPTO_hmac_raw(), GNUNET_free, 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_ATTRIBUTE_ClaimList::list_head, GNUNET_RECLAIM_ATTRIBUTE_Claim::name, GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry::next, result, SERVER_ADDRESS, subject, and GNUNET_RECLAIM_ATTRIBUTE_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 *result;
135  char *header_base64;
136  char *body_base64;
137  char *signature_target;
138  char *signature_base64;
139  char *attr_val_str;
140  json_t *body;
141 
142  // iat REQUIRED time now
143  time_now = GNUNET_TIME_absolute_get ();
144  // exp REQUIRED time expired from config
145  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
146  // auth_time only if max_age
147  // nonce only if nonce
148  // OPTIONAL acr,amr,azp
149  subject =
151  sizeof(struct
153  audience =
155  sizeof(struct
157  header = create_jwt_header ();
158  body = json_object ();
159 
160  // iss REQUIRED case sensitive server uri with https
161  // The issuer is the local reclaim instance (e.g.
162  // https://reclaim.id/api/openid)
163  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
164  // sub REQUIRED public key identity, not exceed 255 ASCII length
165  json_object_set_new (body, "sub", json_string (subject));
166  // aud REQUIRED public key client_id must be there
167  json_object_set_new (body, "aud", json_string (audience));
168  // iat
169  json_object_set_new (body,
170  "iat",
171  json_integer (time_now.abs_value_us / (1000 * 1000)));
172  // exp
173  json_object_set_new (body,
174  "exp",
175  json_integer (exp_time.abs_value_us / (1000 * 1000)));
176  // nbf
177  json_object_set_new (body,
178  "nbf",
179  json_integer (time_now.abs_value_us / (1000 * 1000)));
180  // nonce
181  if (NULL != nonce)
182  json_object_set_new (body, "nonce", json_string (nonce));
183 
184  for (le = attrs->list_head; NULL != le; le = le->next)
185  {
186  attr_val_str =
188  le->claim->data,
189  le->claim->data_size);
190  json_object_set_new (body, le->claim->name, json_string (attr_val_str));
191  GNUNET_free (attr_val_str);
192  }
193  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
194  json_decref (body);
195 
196  GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64);
197  fix_base64 (header_base64);
198 
199  GNUNET_STRINGS_base64_encode (body_str, strlen (body_str), &body_base64);
200  fix_base64 (body_base64);
201 
202  GNUNET_free (subject);
203  GNUNET_free (audience);
204 
209  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
210  GNUNET_CRYPTO_hmac_raw (secret_key,
211  strlen (secret_key),
212  signature_target,
213  strlen (signature_target),
214  &signature);
215  GNUNET_STRINGS_base64_encode ((const char *) &signature,
216  sizeof(struct GNUNET_HashCode),
217  &signature_base64);
218  fix_base64 (signature_base64);
219 
220  GNUNET_asprintf (&result,
221  "%s.%s.%s",
222  header_base64,
223  body_base64,
224  signature_base64);
225 
226  GNUNET_free (signature_target);
227  GNUNET_free (header);
228  GNUNET_free (body_str);
229  GNUNET_free (signature_base64);
230  GNUNET_free (body_base64);
231  GNUNET_free (header_base64);
232  return result;
233 }
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.
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_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
const void * data
Binary value stored as attribute value.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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
static GNUNET_NETWORK_STRUCT_END char * create_jwt_header(void)
Definition: oidc_helper.c:68
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...
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ from_hex()

static char from_hex ( char  ch)
static

Definition at line 238 of file oidc_helper.c.

Referenced by url_decode().

239 {
240  return isdigit (ch) ? ch - '0' : tolower (ch) - 'a' + 10;
241 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
Here is the caller graph for this function:

◆ to_hex()

static char to_hex ( char  code)
static

Definition at line 246 of file oidc_helper.c.

Referenced by url_encode().

247 {
248  static char hex[] = "0123456789abcdef";
249 
250  return hex[code & 15];
251 }
Here is the caller graph for this function:

◆ url_encode()

static char* url_encode ( const char *  str)
static

Definition at line 257 of file oidc_helper.c.

References buf, GNUNET_malloc, and to_hex().

Referenced by base64_and_urlencode().

258 {
259  char *pstr = (char *) str;
260  char *buf = GNUNET_malloc (strlen (str) * 3 + 1);
261  char *pbuf = buf;
262 
263  while (*pstr)
264  {
265  if (isalnum (*pstr) || (*pstr == '-') || (*pstr == '_') || (*pstr == '.') ||
266  (*pstr == '~') )
267  *pbuf++ = *pstr;
268  else if (*pstr == ' ')
269  *pbuf++ = '+';
270  else
271  {
272  *pbuf++ = '%';
273  *pbuf++ = to_hex (*pstr >> 4);
274  *pbuf++ = to_hex (*pstr & 15);
275  }
276  pstr++;
277  }
278  *pbuf = '\0';
279  return buf;
280 }
static char to_hex(char code)
Definition: oidc_helper.c:246
static char buf[2048]
#define GNUNET_malloc(size)
Wrapper around malloc.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ url_decode()

static char* url_decode ( const char *  str)
static

Definition at line 286 of file oidc_helper.c.

References buf, from_hex(), and GNUNET_malloc.

287 {
288  char *pstr = (char *) str;
289  char *buf = GNUNET_malloc (strlen (str) + 1);
290  char *pbuf = buf;
291 
292  while (*pstr)
293  {
294  if (*pstr == '%')
295  {
296  if (pstr[1] && pstr[2])
297  {
298  *pbuf++ = from_hex (pstr[1]) << 4 | from_hex (pstr[2]);
299  pstr += 2;
300  }
301  }
302  else if (*pstr == '+')
303  {
304  *pbuf++ = ' ';
305  }
306  else
307  {
308  *pbuf++ = *pstr;
309  }
310  pstr++;
311  }
312  *pbuf = '\0';
313  return buf;
314 }
static char buf[2048]
static char from_hex(char ch)
Definition: oidc_helper.c:238
#define GNUNET_malloc(size)
Wrapper around malloc.
Here is the call graph for this function:

◆ base64_and_urlencode()

static char* base64_and_urlencode ( const char *  data,
size_t  data_size 
)
static

Returns base64 encoded string urlencoded.

Parameters
stringthe string to encode
Returns
base64 encoded string

Definition at line 324 of file oidc_helper.c.

References enc, GNUNET_free, GNUNET_STRINGS_base64_encode(), and url_encode().

Referenced by OIDC_build_authz_code().

325 {
326  char *enc;
327  char *urlenc;
328 
330  urlenc = url_encode (enc);
331  GNUNET_free (enc);
332  return urlenc;
333 }
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1855
static char * url_encode(const char *str)
Definition: oidc_helper.c:257
static OpusEncoder * enc
OPUS encoder.
uint32_t data
The data value.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ base64url_encode()

static char* base64url_encode ( const char *  data,
size_t  data_size 
)
static

Returns base64 encoded string urlencoded.

Parameters
stringthe string to encode
Returns
base64 encoded string

Definition at line 343 of file oidc_helper.c.

References enc, and GNUNET_STRINGS_base64_encode().

Referenced by OIDC_parse_authz_code().

344 {
345  char *enc;
346  size_t pos;
347 
349  // Replace with correct characters for base64url
350  pos = 0;
351  while ('\0' != enc[pos])
352  {
353  if ('+' == enc[pos])
354  enc[pos] = '-';
355  if ('/' == enc[pos])
356  enc[pos] = '_';
357  if ('=' == enc[pos])
358  {
359  enc[pos] = '\0';
360  break;
361  }
362  pos++;
363  }
364  return enc;
365 }
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1855
static OpusEncoder * enc
OPUS encoder.
uint32_t data
The data value.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_aes_key()

static void derive_aes_key ( struct GNUNET_CRYPTO_SymmetricSessionKey key,
struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
struct GNUNET_HashCode key_material 
)
static

Definition at line 369 of file oidc_helper.c.

References GNUNET_CRYPTO_kdf().

Referenced by calculate_key_priv(), and calculate_key_pub().

372 {
373  static const char ctx_key[] = "reclaim-aes-ctx-key";
374  static const char ctx_iv[] = "reclaim-aes-ctx-iv";
375 
376  GNUNET_CRYPTO_kdf (key,
377  sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
378  ctx_key,
379  strlen (ctx_key),
380  key_material,
381  sizeof(struct GNUNET_HashCode),
382  NULL);
383  GNUNET_CRYPTO_kdf (iv,
384  sizeof(
386  ctx_iv,
387  strlen (ctx_iv),
388  key_material,
389  sizeof(struct GNUNET_HashCode),
390  NULL);
391 }
A 512-bit hashcode.
int GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:89
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_key_priv()

static void calculate_key_priv ( struct GNUNET_CRYPTO_SymmetricSessionKey key,
struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const struct GNUNET_CRYPTO_EcdsaPrivateKey ecdsa_priv,
const struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub 
)
static

Definition at line 395 of file oidc_helper.c.

References derive_aes_key(), and GNUNET_CRYPTO_ecdsa_ecdh().

Referenced by decrypt_payload().

399 {
400  struct GNUNET_HashCode key_material;
401 
402  GNUNET_CRYPTO_ecdsa_ecdh (ecdsa_priv, ecdh_pub, &key_material);
403  derive_aes_key (key, iv, &key_material);
404 }
int GNUNET_CRYPTO_ecdsa_ecdh(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
Derive key material from a ECDH public key and a private ECDSA key.
Definition: crypto_ecc.c:1560
static void derive_aes_key(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_HashCode *key_material)
Definition: oidc_helper.c:369
A 512-bit hashcode.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_key_pub()

static void calculate_key_pub ( struct GNUNET_CRYPTO_SymmetricSessionKey key,
struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub,
const struct GNUNET_CRYPTO_EcdhePrivateKey ecdh_priv 
)
static

Definition at line 408 of file oidc_helper.c.

References derive_aes_key(), and GNUNET_CRYPTO_ecdh_ecdsa().

Referenced by encrypt_payload().

412 {
413  struct GNUNET_HashCode key_material;
414 
415  GNUNET_CRYPTO_ecdh_ecdsa (ecdh_priv, ecdsa_pub, &key_material);
416  derive_aes_key (key, iv, &key_material);
417 }
int GNUNET_CRYPTO_ecdh_ecdsa(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, struct GNUNET_HashCode *key_material)
Derive key material from a EcDSA public key and a private ECDH key.
Definition: crypto_ecc.c:1666
static void derive_aes_key(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_HashCode *key_material)
Definition: oidc_helper.c:369
A 512-bit hashcode.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ decrypt_payload()

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 
)
static

Definition at line 421 of file oidc_helper.c.

References calculate_key_priv(), GNUNET_break, and GNUNET_CRYPTO_symmetric_decrypt().

Referenced by OIDC_parse_authz_code().

426 {
429 
430  calculate_key_priv (&key, &iv, ecdsa_priv, ecdh_pub);
431  GNUNET_break (GNUNET_CRYPTO_symmetric_decrypt (ct, ct_len, &key, &iv, buf));
432 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static char buf[2048]
struct GNUNET_HashCode key
The key used in the DHT.
static void calculate_key_priv(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
Definition: oidc_helper.c:395
ssize_t GNUNET_CRYPTO_symmetric_decrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Decrypt a given block using a symmetric sessionkey.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ encrypt_payload()

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 
)
static

Definition at line 436 of file oidc_helper.c.

References calculate_key_pub(), GNUNET_break, and GNUNET_CRYPTO_symmetric_encrypt().

Referenced by OIDC_build_authz_code().

441 {
444 
445  calculate_key_pub (&key, &iv, ecdsa_pub, ecdh_priv);
446  GNUNET_break (
447  GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf));
448 }
static void calculate_key_pub(struct GNUNET_CRYPTO_SymmetricSessionKey *key, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
Definition: oidc_helper.c:408
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
ssize_t GNUNET_CRYPTO_symmetric_encrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Encrypt a block using a symmetric sessionkey.
static char buf[2048]
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned long long payload
How much data are we currently storing in the database?
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 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 463 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().

468 {
469  struct OIDC_Parameters params;
470  char *code_payload;
471  char *payload;
472  char *tmp;
473  char *code_str;
474  char *buf_ptr = NULL;
475  size_t payload_len;
476  size_t code_payload_len;
477  size_t attr_list_len = 0;
478  size_t code_challenge_len = 0;
479  uint32_t nonce;
480  uint32_t nonce_tmp;
482  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv;
483  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
484 
486  // Assign ticket
487  memset (&params, 0, sizeof(params));
488  params.ticket = *ticket;
489  // Assign nonce
490  nonce = 0;
491  payload_len = sizeof(struct OIDC_Parameters);
492  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
493  {
494  if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX))
495  {
496  GNUNET_break (0);
497  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
498  return NULL;
499  }
501  "Got nonce: %u from %s\n",
502  nonce,
503  nonce_str);
504  }
505  nonce_tmp = htonl (nonce);
506  params.nonce = nonce_tmp;
507  // Assign code challenge
508  if (NULL != code_challenge)
509  code_challenge_len = strlen (code_challenge);
510  payload_len += code_challenge_len;
511  params.code_challenge_len = htonl (code_challenge_len);
512  // Assign attributes
513  if (NULL != attrs)
514  {
515  // Get length
516  attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
517  params.attr_list_len = htonl (attr_list_len);
519  "Length of serialized attributes: %lu\n",
520  attr_list_len);
521  // Get serialized attributes
522  payload_len += attr_list_len;
523  }
524  // Get plaintext length
525  payload = GNUNET_malloc (payload_len);
526  memcpy (payload, &params, sizeof(params));
527  tmp = payload + sizeof(params);
528  if (0 < code_challenge_len)
529  {
530  memcpy (tmp, code_challenge, code_challenge_len);
531  tmp += code_challenge_len;
532  }
533  if (0 < attr_list_len)
538  // Get length
539  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
540  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
541  + payload_len + sizeof(struct
544  "Length of data to encode: %lu\n",
545  code_payload_len);
546 
547  // Generate ECDH key
548  ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create ();
549  GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub);
550  // Initialize code payload
551  code_payload = GNUNET_malloc (code_payload_len);
552  GNUNET_assert (NULL != code_payload);
553  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
554  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
555  + sizeof(ecdh_pub) + payload_len);
557  // Store pubkey
558  buf_ptr = (char *) &purpose[1];
559  memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub));
560  buf_ptr += sizeof(ecdh_pub);
561  // Encrypt plaintext and store
562  encrypt_payload (&ticket->audience, ecdh_priv, payload, payload_len, buf_ptr);
563  GNUNET_free (ecdh_priv);
564  GNUNET_free (payload);
565  buf_ptr += payload_len;
566  // Sign and store signature
567  if (GNUNET_SYSERR ==
568  GNUNET_CRYPTO_ecdsa_sign (issuer,
569  purpose,
571  buf_ptr))
572  {
573  GNUNET_break (0);
574  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
575  GNUNET_free (code_payload);
576  return NULL;
577  }
578  code_str = base64_and_urlencode (code_payload, code_payload_len);
579  GNUNET_free (code_payload);
580  return code_str;
581 }
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:436
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:608
#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:929
#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:76
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:301
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:324
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
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 598 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().

604 {
605  char *code_payload;
606  char *ptr;
607  char *plaintext;
608  char *attrs_ser;
609  char *expected_code_challenge;
610  char *code_challenge;
611  char *code_verifier_hash;
613  struct GNUNET_CRYPTO_EcdsaSignature *signature;
614  struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
615  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
616  uint32_t code_challenge_len;
617  uint32_t attrs_ser_len;
618  size_t plaintext_len;
619  size_t code_payload_len;
620  uint32_t nonce = 0;
621  struct OIDC_Parameters *params;
622 
623  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
624  code_payload = NULL;
625  code_payload_len =
626  GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload);
627  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
628  + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
629  + sizeof(struct OIDC_Parameters)
630  + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
631  {
632  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
633  GNUNET_free_non_null (code_payload);
634  return GNUNET_SYSERR;
635  }
636 
637  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
638  plaintext_len = code_payload_len;
639  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
640  ptr = (char *) &purpose[1];
641  // Public ECDH key
642  ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
643  ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
644  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
645 
646  // Decrypt ciphertext
647  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
648  plaintext = GNUNET_malloc (plaintext_len);
649  decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
650  // ptr = plaintext;
651  ptr += plaintext_len;
652  signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
653  params = (struct OIDC_Parameters *) plaintext;
654 
655  // cmp code_challenge code_verifier
656  code_challenge_len = ntohl (params->code_challenge_len);
657  if (0 != code_challenge_len) /* Only check if this code requires a CV */
658  {
659  if (NULL == code_verifier)
660  {
662  "Expected code verifier!\n");
663  GNUNET_free_non_null (code_payload);
664  return GNUNET_SYSERR;
665  }
666  code_verifier_hash = GNUNET_malloc (256 / 8);
667  // hash code verifier
668  gcry_md_hash_buffer (GCRY_MD_SHA256,
669  code_verifier_hash,
670  code_verifier,
671  strlen (code_verifier));
672  // encode code verifier
673  expected_code_challenge = base64url_encode (code_verifier_hash, 256 / 8);
674  code_challenge = (char *) &params[1];
675  GNUNET_free (code_verifier_hash);
676  if ((strlen (expected_code_challenge) != code_challenge_len) ||
677  (0 !=
678  strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
679  {
681  "Invalid code verifier! Expected: %s, Got: %.*s\n",
682  expected_code_challenge,
683  code_challenge_len,
684  code_challenge);
685  GNUNET_free_non_null (code_payload);
686  GNUNET_free (expected_code_challenge);
687  return GNUNET_SYSERR;
688  }
689  GNUNET_free (expected_code_challenge);
690  }
691  // Ticket
692  memcpy (ticket, &params->ticket, sizeof(params->ticket));
693  // Nonce
694  nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr));
695  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
696  // Signature
697  GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
698  if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
699  {
700  GNUNET_free (code_payload);
701  GNUNET_free (plaintext);
703  "Audience in ticket does not match client!\n");
704  return GNUNET_SYSERR;
705  }
706  if (GNUNET_OK !=
708  purpose,
709  signature,
710  &ticket->identity))
711  {
712  GNUNET_free (code_payload);
713  GNUNET_free (plaintext);
714  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
715  return GNUNET_SYSERR;
716  }
717  // Attributes
718  attrs_ser = ((char *) &params[1]) + code_challenge_len;
719  attrs_ser_len = ntohl (params->attr_list_len);
720  *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, attrs_ser_len);
721 
722  *nonce_str = NULL;
723  if (nonce != 0)
724  GNUNET_asprintf (nonce_str, "%u", nonce);
725  GNUNET_free (code_payload);
726  GNUNET_free (plaintext);
727  return GNUNET_OK;
728 }
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:1046
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:75
#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:421
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:76
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:239
#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:343
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 741 of file oidc_helper.c.

References GNUNET_assert, and GNUNET_TIME_Relative::rel_value_us.

Referenced by token_endpoint().

745 {
746  json_t *root_json;
747 
748  root_json = json_object ();
749 
750  GNUNET_assert (NULL != access_token);
751  GNUNET_assert (NULL != id_token);
752  GNUNET_assert (NULL != expiration_time);
753  json_object_set_new (root_json, "access_token", json_string (access_token));
754  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
755  json_object_set_new (root_json,
756  "expires_in",
757  json_integer (expiration_time->rel_value_us
758  / (1000 * 1000)));
759  json_object_set_new (root_json, "id_token", json_string (id_token));
760  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
761  json_decref (root_json);
762 }
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 769 of file oidc_helper.c.

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

Referenced by token_endpoint().

770 {
771  char *access_token;
772  uint64_t random_number;
773 
774  random_number =
776  GNUNET_STRINGS_base64_encode (&random_number,
777  sizeof(uint64_t),
778  &access_token);
779  return access_token;
780 }
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: