30 #include <jose/jose.h>
34 #include "gnunet_signatures.h"
78 "name",
"family_name",
"given_name",
"middle_name",
"nickname",
79 "preferred_username",
"profile",
"picture",
"website",
"gender",
"birthdate",
80 "zoneinfo",
"locale",
"updated_at"
87 "email",
"email_verified"
94 "phone_number",
"phone_number_verified"
101 "street_address",
"locality",
"region",
"postal_code",
"country"
108 for (i = 0; i < 5; i++)
125 root = json_object ();
129 json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
138 char *current_pos = strchr (str, find);
143 current_pos = strchr (current_pos, find);
174 json_t *aggr_sources;
175 json_t *aggr_sources_jwt;
176 json_t *addr_claim = NULL;
177 int num_presentations = 0;
188 body = json_object ();
189 aggr_names = json_object ();
190 aggr_sources = json_object ();
197 json_object_set_new (body,
"sub", json_string (
subject));
202 for (ple = presentations->
list_head; NULL != ple; ple = ple->
next)
209 "Adding new presentation source #%d\n", i);
210 aggr_sources_jwt = json_object ();
216 "Presentation is: %s\n", pres_val_str);
217 json_object_set_new (aggr_sources_jwt,
220 json_string (pres_val_str) );
221 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
233 "Processing %s for userinfo body\n",
250 "Address is set as aggregated claim. Skipping self-issued value...\n");
256 if (NULL == addr_claim)
258 addr_claim = json_object ();
259 json_object_set_new (body,
"address", addr_claim);
262 json_string (attr_val_str));
268 json_string (attr_val_str));
276 for (ple = presentations->
list_head; NULL != ple; ple = ple->
next)
287 "Presentation for `%s' missing...\n",
300 "Address is already set as normal claim. Skipping attested value...\n");
305 if (NULL != addr_claim)
307 addr_claim = json_object ();
311 json_object_set_new (aggr_names,
"address",
312 json_string (source_name));
322 json_string (source_name));
329 json_object_set_new (body,
"_claim_names", aggr_names);
330 json_object_set_new (body,
"_claim_sources", aggr_sources);
355 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
397 json_object_set_new (body,
"aud", json_string (audience));
399 json_object_set_new (body,
403 json_object_set_new (body,
407 json_object_set_new (body,
412 json_object_set_new (body,
"nonce", json_string (nonce));
415 body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT);
434 const json_t *secret_rsa_key)
448 if (NULL == body_str)
451 "Body for the JWS could not be generated\n");
456 jws = json_pack (
"{s:o}",
"payload",
457 jose_b64_enc (body_str, strlen (body_str)));
460 if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
463 "Signature generation failed\n");
469 json_string_value (json_object_get (jws,
"protected")),
470 json_string_value (json_object_get (jws,
"payload")),
471 json_string_value (json_object_get (jws,
"signature")) );
496 const char *secret_key)
503 char *signature_target;
504 char *signature_base64;
512 "Header for the JWS could not be generated\n");
527 if (NULL == body_str)
530 "Body for the JWS could not be generated\n");
542 GNUNET_asprintf (&signature_target,
"%s.%s", header_base64, body_base64);
546 strlen (signature_target),
586 const char *nonce_str,
587 const char *code_challenge)
594 char *buf_ptr = NULL;
596 size_t code_payload_len;
605 memset (¶ms, 0,
sizeof(params));
609 if ((NULL != nonce_str) && (strcmp (
"", nonce_str) != 0))
616 if (NULL != code_challenge)
627 "Length of serialized attributes: %lu\n",
632 if (NULL != presentations)
642 "Length of serialized presentations: %lu\n",
650 memcpy (
payload, ¶ms,
sizeof(params));
651 tmp =
payload +
sizeof(params);
673 + payload_len + sizeof(struct
676 "Length of data to encode: %lu\n",
687 buf_ptr = (
char *) &
purpose[1];
688 memcpy (buf_ptr,
payload, payload_len);
690 buf_ptr += payload_len;
711 uint32_t code_challenge_len,
712 const char *code_verifier)
714 char *code_verifier_hash;
715 char *expected_code_challenge;
717 if (0 == code_challenge_len)
719 if (NULL == code_verifier)
722 "Expected code verifier!\n");
727 gcry_md_hash_buffer (GCRY_MD_SHA256,
730 strlen (code_verifier));
733 &expected_code_challenge);
736 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
739 "Invalid code verifier! Expected: %s, Got: %.*s\n",
740 expected_code_challenge,
769 const char *code_verifier,
780 char *presentations_ser;
781 char *code_challenge;
784 uint32_t code_challenge_len;
785 uint32_t attrs_ser_len;
786 uint32_t pres_ser_len;
787 size_t plaintext_len;
788 size_t code_payload_len;
789 uint32_t nonce_len = 0;
796 (
void **) &code_payload);
807 plaintext_len = code_payload_len;
812 ptr += plaintext_len;
818 code_challenge = ((
char *) ¶ms[1]);
844 if (NULL != *nonce_str)
847 "Audience in ticket does not match client!\n");
858 if (NULL != *nonce_str)
867 presentations_ser = ((
char*) attrs_ser) + attrs_ser_len;
889 const char *id_token,
891 char **token_response)
895 root_json = json_object ();
900 json_object_set_new (root_json,
"access_token", json_string (access_token));
901 json_object_set_new (root_json,
"token_type", json_string (
"Bearer"));
902 json_object_set_new (root_json,
906 json_object_set_new (root_json,
"id_token", json_string (id_token));
907 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
908 json_decref (root_json);
961 char *scope_variables;
962 char *scope_variable;
963 char delimiter[] =
" ";
967 scope_variable = strtok (scope_variables, delimiter);
968 while (NULL != scope_variable)
970 if (0 == strcmp (
"profile", scope_variable))
972 for (i = 0; i < 14; i++)
981 else if (0 == strcmp (
"address", scope_variable))
983 for (i = 0; i < 5; i++)
992 else if (0 == strcmp (
"email", scope_variable))
994 for (i = 0; i < 2; i++)
1003 else if (0 == strcmp (
"phone", scope_variable))
1005 for (i = 0; i < 2; i++)
1015 else if (0 == strcmp (attr, scope_variable))
1021 scope_variable = strtok (NULL, delimiter);
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket (Reclaim)
static char * subject
Subject pubkey string.
static int replace
Replace DID Document Flag.
struct GNUNET_RECLAIM_Attribute * claim
Claim to store.
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
static int result
Global testing status.
static unsigned long long payload
How much data are we currently storing in the database?
Identity attribute definitions.
reclaim service; implements identity and personal data sharing for GNUnet
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_sign_(const struct GNUNET_IDENTITY_PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_IDENTITY_Signature *sig)
Sign a given block.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_signature_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_IDENTITY_Signature *sig, const struct GNUNET_IDENTITY_PublicKey *pub)
Verify a given signature.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
GNUNET_GenericReturnValue
Named constants for return values.
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't this be the standard hmac function and the abo...
#define GNUNET_PACKED
gcc-ism to get packed structs.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_RECLAIM_id_is_equal(a, b)
#define GNUNET_RECLAIM_id_is_zero(a)
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.
char * GNUNET_RECLAIM_presentation_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'claim' of a presentation to a string.
struct GNUNET_RECLAIM_AttributeList * GNUNET_RECLAIM_attribute_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
size_t GNUNET_RECLAIM_attribute_list_serialize(const struct GNUNET_RECLAIM_AttributeList *attrs, char *result)
Serialize an attribute list.
size_t GNUNET_RECLAIM_presentation_list_serialize(const struct GNUNET_RECLAIM_PresentationList *presentations, char *result)
Serialize a presentation list.
const char * GNUNET_RECLAIM_presentation_number_to_typename(uint32_t type)
Convert a presentation type number to the corresponding credential type string.
struct GNUNET_RECLAIM_PresentationList * GNUNET_RECLAIM_presentation_list_deserialize(const char *data, size_t data_size)
Deserialize a presentation list.
size_t GNUNET_RECLAIM_presentation_list_serialize_get_size(const struct GNUNET_RECLAIM_PresentationList *presentations)
Get required size for serialization buffer.
size_t GNUNET_RECLAIM_attribute_list_serialize_get_size(const struct GNUNET_RECLAIM_AttributeList *attrs)
Get required size for serialization buffer.
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
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.
static char * create_jwt_hmac_header(void)
char * OIDC_generate_id_token_hmac(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT using HMAC (HS256) from attributes.
static void replace_char(char *str, char find, char replace)
static char OIDC_email_claims[2][16]
Standard claims represented by the "email" scope in OIDC.
static char OIDC_address_claims[5][32]
Standard claims represented by the "address" scope in OIDC.
static void fix_base64(char *str)
enum GNUNET_GenericReturnValue check_code_challenge(const char *code_challenge, uint32_t code_challenge_len, const char *code_verifier)
static json_t * generate_userinfo_json(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
static enum GNUNET_GenericReturnValue is_claim_in_address_scope(const char *claim)
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
char * generate_id_token_body(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce)
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
static char OIDC_phone_claims[2][32]
Standard claims represented by the "phone" scope in OIDC.
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
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?
static GNUNET_NETWORK_STRUCT_END char OIDC_profile_claims[14][32]
Standard claims represented by the "profile" scope in OIDC.
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
char * OIDC_generate_id_token_rsa(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const json_t *secret_rsa_key)
Create a JWT using RSA256 algorithm from attributes.
helper library for OIDC related functions
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
#define JWT_ALG_VALUE_HMAC
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
An identity signature as per LSD0001.
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
A list of GNUNET_RECLAIM_Attribute structures.
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
const char * name
The name of the attribute.
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
uint32_t type
Type of Claim.
const void * data
Binary value stored as attribute value.
size_t data_size
Number of bytes in data.
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
A list of GNUNET_RECLAIM_Presentation structures.
struct GNUNET_RECLAIM_PresentationListEntry * list_head
List head.
const void * data
Binary value stored as presentation value.
uint32_t type
Type/Format of Claim.
size_t data_size
Number of bytes in data.
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
The authorization ticket.
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
struct GNUNET_IDENTITY_PublicKey identity
The ticket issuer (= the user)
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The signature used to generate the authorization code.
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
uint32_t pres_list_len
The length of the presentation list.
uint32_t nonce_len
The nonce length.
uint32_t attr_list_len
The length of the attributes list.
uint32_t code_challenge_len
The length of the PKCE code_challenge.