From 97164b43a8b69cc1bf07c3384586f58c99873ce8 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 17 Sep 2019 16:10:56 +0200 Subject: gracely handle missing PKCE params in token request --- src/reclaim/oidc_helper.c | 725 +++++++++++++++++++++++----------------------- 1 file changed, 367 insertions(+), 358 deletions(-) (limited to 'src/reclaim/oidc_helper.c') diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index 83b8e8cb3..6bcae21d4 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c @@ -31,7 +31,7 @@ #include "gnunet_reclaim_service.h" #include "gnunet_signatures.h" #include "oidc_helper.h" -//#include "benchmark.h" +// #include "benchmark.h" #include GNUNET_NETWORK_STRUCT_BEGIN @@ -39,7 +39,8 @@ GNUNET_NETWORK_STRUCT_BEGIN /** * The signature used to generate the authorization code */ -struct OIDC_Parameters { +struct OIDC_Parameters +{ /** * The reclaim ticket */ @@ -64,41 +65,41 @@ struct OIDC_Parameters { GNUNET_NETWORK_STRUCT_END static char * -create_jwt_header(void) +create_jwt_header (void) { json_t *root; char *json_str; - root = json_object(); - json_object_set_new(root, JWT_ALG, json_string(JWT_ALG_VALUE)); - json_object_set_new(root, JWT_TYP, json_string(JWT_TYP_VALUE)); + root = json_object (); + json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE)); + json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE)); - json_str = json_dumps(root, JSON_INDENT(0) | JSON_COMPACT); - json_decref(root); + json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT); + json_decref (root); return json_str; } static void -replace_char(char *str, char find, char replace) +replace_char (char *str, char find, char replace) { - char *current_pos = strchr(str, find); + char *current_pos = strchr (str, find); while (current_pos) - { - *current_pos = replace; - current_pos = strchr(current_pos, find); - } + { + *current_pos = replace; + current_pos = strchr (current_pos, find); + } } // RFC4648 static void -fix_base64(char *str) +fix_base64 (char *str) { // Replace + with - - replace_char(str, '+', '-'); + replace_char (str, '+', '-'); // Replace / with _ - replace_char(str, '/', '_'); + replace_char (str, '/', '_'); } /** @@ -112,12 +113,12 @@ fix_base64(char *str) * @return a new base64-encoded JWT string. */ 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) +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) { struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; struct GNUNET_HashCode signature; @@ -136,108 +137,108 @@ OIDC_id_token_new(const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, json_t *body; // iat REQUIRED time now - time_now = GNUNET_TIME_absolute_get(); + time_now = GNUNET_TIME_absolute_get (); // exp REQUIRED time expired from config - exp_time = GNUNET_TIME_absolute_add(time_now, *expiration_time); + exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time); // auth_time only if max_age // nonce only if nonce // OPTIONAL acr,amr,azp subject = - GNUNET_STRINGS_data_to_string_alloc(sub_key, - sizeof(struct - GNUNET_CRYPTO_EcdsaPublicKey)); + GNUNET_STRINGS_data_to_string_alloc (sub_key, + sizeof(struct + GNUNET_CRYPTO_EcdsaPublicKey)); audience = - GNUNET_STRINGS_data_to_string_alloc(aud_key, - sizeof(struct - GNUNET_CRYPTO_EcdsaPublicKey)); - header = create_jwt_header(); - body = json_object(); + GNUNET_STRINGS_data_to_string_alloc (aud_key, + sizeof(struct + GNUNET_CRYPTO_EcdsaPublicKey)); + header = create_jwt_header (); + body = json_object (); // iss REQUIRED case sensitive server uri with https // The issuer is the local reclaim instance (e.g. // https://reclaim.id/api/openid) - json_object_set_new(body, "iss", json_string(SERVER_ADDRESS)); + json_object_set_new (body, "iss", json_string (SERVER_ADDRESS)); // sub REQUIRED public key identity, not exceed 255 ASCII length - json_object_set_new(body, "sub", json_string(subject)); + json_object_set_new (body, "sub", json_string (subject)); // aud REQUIRED public key client_id must be there - json_object_set_new(body, "aud", json_string(audience)); + json_object_set_new (body, "aud", json_string (audience)); // iat - json_object_set_new(body, - "iat", - json_integer(time_now.abs_value_us / (1000 * 1000))); + json_object_set_new (body, + "iat", + json_integer (time_now.abs_value_us / (1000 * 1000))); // exp - json_object_set_new(body, - "exp", - json_integer(exp_time.abs_value_us / (1000 * 1000))); + json_object_set_new (body, + "exp", + json_integer (exp_time.abs_value_us / (1000 * 1000))); // nbf - json_object_set_new(body, - "nbf", - json_integer(time_now.abs_value_us / (1000 * 1000))); + json_object_set_new (body, + "nbf", + json_integer (time_now.abs_value_us / (1000 * 1000))); // nonce if (NULL != nonce) - json_object_set_new(body, "nonce", json_string(nonce)); + json_object_set_new (body, "nonce", json_string (nonce)); for (le = attrs->list_head; NULL != le; le = le->next) - { - attr_val_str = - GNUNET_RECLAIM_ATTRIBUTE_value_to_string(le->claim->type, - le->claim->data, - le->claim->data_size); - json_object_set_new(body, le->claim->name, json_string(attr_val_str)); - GNUNET_free(attr_val_str); - } - body_str = json_dumps(body, JSON_INDENT(0) | JSON_COMPACT); - json_decref(body); - - GNUNET_STRINGS_base64_encode(header, strlen(header), &header_base64); - fix_base64(header_base64); - - GNUNET_STRINGS_base64_encode(body_str, strlen(body_str), &body_base64); - fix_base64(body_base64); - - GNUNET_free(subject); - GNUNET_free(audience); + { + attr_val_str = + GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type, + le->claim->data, + le->claim->data_size); + json_object_set_new (body, le->claim->name, json_string (attr_val_str)); + GNUNET_free (attr_val_str); + } + body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT); + json_decref (body); + + GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64); + fix_base64 (header_base64); + + GNUNET_STRINGS_base64_encode (body_str, strlen (body_str), &body_base64); + fix_base64 (body_base64); + + GNUNET_free (subject); + GNUNET_free (audience); /** * Creating the JWT signature. This might not be * standards compliant, check. */ - GNUNET_asprintf(&signature_target, "%s.%s", header_base64, body_base64); - GNUNET_CRYPTO_hmac_raw(secret_key, - strlen(secret_key), - signature_target, - strlen(signature_target), - &signature); - GNUNET_STRINGS_base64_encode((const char *)&signature, - sizeof(struct GNUNET_HashCode), - &signature_base64); - fix_base64(signature_base64); - - GNUNET_asprintf(&result, - "%s.%s.%s", - header_base64, - body_base64, - signature_base64); - - GNUNET_free(signature_target); - GNUNET_free(header); - GNUNET_free(body_str); - GNUNET_free(signature_base64); - GNUNET_free(body_base64); - GNUNET_free(header_base64); + GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64); + GNUNET_CRYPTO_hmac_raw (secret_key, + strlen (secret_key), + signature_target, + strlen (signature_target), + &signature); + GNUNET_STRINGS_base64_encode ((const char *) &signature, + sizeof(struct GNUNET_HashCode), + &signature_base64); + fix_base64 (signature_base64); + + GNUNET_asprintf (&result, + "%s.%s.%s", + header_base64, + body_base64, + signature_base64); + + GNUNET_free (signature_target); + GNUNET_free (header); + GNUNET_free (body_str); + GNUNET_free (signature_base64); + GNUNET_free (body_base64); + GNUNET_free (header_base64); return result; } /* Converts a hex character to its integer value */ static char -from_hex(char ch) +from_hex (char ch) { - return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; + return isdigit (ch) ? ch - '0' : tolower (ch) - 'a' + 10; } /* Converts an integer value to its hex character*/ static char -to_hex(char code) +to_hex (char code) { static char hex[] = "0123456789abcdef"; @@ -247,27 +248,27 @@ to_hex(char code) /* Returns a url-encoded version of str */ /* IMPORTANT: be sure to free() the returned string after use */ static char * -url_encode(const char *str) +url_encode (const char *str) { - char *pstr = (char *)str; - char *buf = GNUNET_malloc(strlen(str) * 3 + 1); + char *pstr = (char *) str; + char *buf = GNUNET_malloc (strlen (str) * 3 + 1); char *pbuf = buf; while (*pstr) + { + if (isalnum (*pstr) || (*pstr == '-') || (*pstr == '_') || (*pstr == '.') || + (*pstr == '~') ) + *pbuf++ = *pstr; + else if (*pstr == ' ') + *pbuf++ = '+'; + else { - if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || - *pstr == '~') - *pbuf++ = *pstr; - else if (*pstr == ' ') - *pbuf++ = '+'; - else - { - *pbuf++ = '%'; - *pbuf++ = to_hex(*pstr >> 4); - *pbuf++ = to_hex(*pstr & 15); - } - pstr++; + *pbuf++ = '%'; + *pbuf++ = to_hex (*pstr >> 4); + *pbuf++ = to_hex (*pstr & 15); } + pstr++; + } *pbuf = '\0'; return buf; } @@ -276,32 +277,32 @@ url_encode(const char *str) /* Returns a url-decoded version of str */ /* IMPORTANT: be sure to free() the returned string after use */ static char * -url_decode(const char *str) +url_decode (const char *str) { - char *pstr = (char *)str; - char *buf = GNUNET_malloc(strlen(str) + 1); + char *pstr = (char *) str; + char *buf = GNUNET_malloc (strlen (str) + 1); char *pbuf = buf; while (*pstr) + { + if (*pstr == '%') + { + if (pstr[1] && pstr[2]) + { + *pbuf++ = from_hex (pstr[1]) << 4 | from_hex (pstr[2]); + pstr += 2; + } + } + else if (*pstr == '+') + { + *pbuf++ = ' '; + } + else { - if (*pstr == '%') - { - if (pstr[1] && pstr[2]) - { - *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); - pstr += 2; - } - } - else if (*pstr == '+') - { - *pbuf++ = ' '; - } - else - { - *pbuf++ = *pstr; - } - pstr++; + *pbuf++ = *pstr; } + pstr++; + } *pbuf = '\0'; return buf; } @@ -313,14 +314,14 @@ url_decode(const char *str) * @return base64 encoded string */ static char * -base64_and_urlencode(const char *data, size_t data_size) +base64_and_urlencode (const char *data, size_t data_size) { char *enc; char *urlenc; - GNUNET_STRINGS_base64_encode(data, data_size, &enc); - urlenc = url_encode(enc); - GNUNET_free(enc); + GNUNET_STRINGS_base64_encode (data, data_size, &enc); + urlenc = url_encode (enc); + GNUNET_free (enc); return urlenc; } @@ -332,111 +333,111 @@ base64_and_urlencode(const char *data, size_t data_size) * @return base64 encoded string */ static char * -base64url_encode(const char *data, size_t data_size) +base64url_encode (const char *data, size_t data_size) { char *enc; size_t pos; - GNUNET_STRINGS_base64_encode(data, data_size, &enc); - //Replace with correct characters for base64url + GNUNET_STRINGS_base64_encode (data, data_size, &enc); + // Replace with correct characters for base64url pos = 0; while ('\0' != enc[pos]) + { + if ('+' == enc[pos]) + enc[pos] = '-'; + if ('/' == enc[pos]) + enc[pos] = '_'; + if ('=' == enc[pos]) { - if ('+' == enc[pos]) - enc[pos] = '-'; - if ('/' == enc[pos]) - enc[pos] = '_'; - if ('=' == enc[pos]) - { - enc[pos] = '\0'; - break; - } - pos++; + enc[pos] = '\0'; + break; } + pos++; + } return enc; } static void -derive_aes_key(struct GNUNET_CRYPTO_SymmetricSessionKey *key, - struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - struct GNUNET_HashCode *key_material) +derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key, + struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + struct GNUNET_HashCode *key_material) { static const char ctx_key[] = "reclaim-aes-ctx-key"; static const char ctx_iv[] = "reclaim-aes-ctx-iv"; - GNUNET_CRYPTO_kdf(key, - sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey), - ctx_key, - strlen(ctx_key), - key_material, - sizeof(struct GNUNET_HashCode), - NULL); - GNUNET_CRYPTO_kdf(iv, - sizeof( - struct GNUNET_CRYPTO_SymmetricInitializationVector), - ctx_iv, - strlen(ctx_iv), - key_material, - sizeof(struct GNUNET_HashCode), - NULL); + GNUNET_CRYPTO_kdf (key, + sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey), + ctx_key, + strlen (ctx_key), + key_material, + sizeof(struct GNUNET_HashCode), + NULL); + GNUNET_CRYPTO_kdf (iv, + sizeof( + struct GNUNET_CRYPTO_SymmetricInitializationVector), + ctx_iv, + strlen (ctx_iv), + key_material, + sizeof(struct GNUNET_HashCode), + NULL); } 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) +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) { struct GNUNET_HashCode key_material; - GNUNET_CRYPTO_ecdsa_ecdh(ecdsa_priv, ecdh_pub, &key_material); - derive_aes_key(key, iv, &key_material); + GNUNET_CRYPTO_ecdsa_ecdh (ecdsa_priv, ecdh_pub, &key_material); + derive_aes_key (key, iv, &key_material); } 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) +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) { struct GNUNET_HashCode key_material; - GNUNET_CRYPTO_ecdh_ecdsa(ecdh_priv, ecdsa_pub, &key_material); - derive_aes_key(key, iv, &key_material); + GNUNET_CRYPTO_ecdh_ecdsa (ecdh_priv, ecdsa_pub, &key_material); + derive_aes_key (key, iv, &key_material); } 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) +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) { struct GNUNET_CRYPTO_SymmetricSessionKey key; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - calculate_key_priv(&key, &iv, ecdsa_priv, ecdh_pub); - GNUNET_break(GNUNET_CRYPTO_symmetric_decrypt(ct, ct_len, &key, &iv, buf)); + calculate_key_priv (&key, &iv, ecdsa_priv, ecdh_pub); + GNUNET_break (GNUNET_CRYPTO_symmetric_decrypt (ct, ct_len, &key, &iv, 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) +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) { struct GNUNET_CRYPTO_SymmetricSessionKey key; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - calculate_key_pub(&key, &iv, ecdsa_pub, ecdh_priv); - GNUNET_break( - GNUNET_CRYPTO_symmetric_encrypt(payload, payload_len, &key, &iv, buf)); + calculate_key_pub (&key, &iv, ecdsa_pub, ecdh_priv); + GNUNET_break ( + GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf)); } /** @@ -451,11 +452,11 @@ encrypt_payload(const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, * @return a new authorization code (caller must free) */ 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) +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) { struct OIDC_Parameters params; char *code_payload; @@ -475,98 +476,99 @@ OIDC_build_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, /** PLAINTEXT **/ // Assign ticket - memset(¶ms, 0, sizeof(params)); + memset (¶ms, 0, sizeof(params)); params.ticket = *ticket; // Assign nonce nonce = 0; payload_len = sizeof(struct OIDC_Parameters); - if (NULL != nonce_str && strcmp("", nonce_str) != 0) + if ((NULL != nonce_str)&& (strcmp ("", nonce_str) != 0)) + { + if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) { - if ((1 != sscanf(nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) - { - GNUNET_break(0); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str); - return NULL; - } - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got nonce: %u from %s\n", - nonce, - nonce_str); + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str); + return NULL; } - nonce_tmp = htonl(nonce); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got nonce: %u from %s\n", + nonce, + nonce_str); + } + nonce_tmp = htonl (nonce); params.nonce = nonce_tmp; // Assign code challenge if (NULL != code_challenge) - code_challenge_len = strlen(code_challenge); + code_challenge_len = strlen (code_challenge); payload_len += code_challenge_len; - params.code_challenge_len = htonl(code_challenge_len); + params.code_challenge_len = htonl (code_challenge_len); // Assign attributes if (NULL != attrs) - { - // Get length - attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size(attrs); - params.attr_list_len = htonl(attr_list_len); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Length of serialized attributes: %lu\n", - attr_list_len); - // Get serialized attributes - payload_len += attr_list_len; - } + { + // Get length + attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs); + params.attr_list_len = htonl (attr_list_len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Length of serialized attributes: %lu\n", + attr_list_len); + // Get serialized attributes + payload_len += attr_list_len; + } // Get plaintext length - payload = GNUNET_malloc(payload_len); - memcpy(payload, ¶ms, sizeof(params)); + payload = GNUNET_malloc (payload_len); + memcpy (payload, ¶ms, sizeof(params)); tmp = payload + sizeof(params); if (0 < code_challenge_len) - { - memcpy(tmp, code_challenge, code_challenge_len); - tmp += code_challenge_len; - } + { + memcpy (tmp, code_challenge, code_challenge_len); + tmp += code_challenge_len; + } if (0 < attr_list_len) - GNUNET_RECLAIM_ATTRIBUTE_list_serialize(attrs, tmp); + GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, tmp); /** END **/ /** ENCRYPT **/ // Get length - code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) + - payload_len + sizeof(struct GNUNET_CRYPTO_EcdsaSignature); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Length of data to encode: %lu\n", - code_payload_len); + code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) + + payload_len + sizeof(struct + GNUNET_CRYPTO_EcdsaSignature); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Length of data to encode: %lu\n", + code_payload_len); // Generate ECDH key - ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create(); - GNUNET_CRYPTO_ecdhe_key_get_public(ecdh_priv, &ecdh_pub); + ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create (); + GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub); // Initialize code payload - code_payload = GNUNET_malloc(code_payload_len); - GNUNET_assert(NULL != code_payload); - purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)code_payload; - purpose->size = htonl(sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof(ecdh_pub) + payload_len); - purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); + code_payload = GNUNET_malloc (code_payload_len); + GNUNET_assert (NULL != code_payload); + purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload; + purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof(ecdh_pub) + payload_len); + purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); // Store pubkey - buf_ptr = (char *)&purpose[1]; - memcpy(buf_ptr, &ecdh_pub, sizeof(ecdh_pub)); + buf_ptr = (char *) &purpose[1]; + memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub)); buf_ptr += sizeof(ecdh_pub); // Encrypt plaintext and store - encrypt_payload(&ticket->audience, ecdh_priv, payload, payload_len, buf_ptr); - GNUNET_free(ecdh_priv); - GNUNET_free(payload); + encrypt_payload (&ticket->audience, ecdh_priv, payload, payload_len, buf_ptr); + GNUNET_free (ecdh_priv); + GNUNET_free (payload); buf_ptr += payload_len; // Sign and store signature if (GNUNET_SYSERR == - GNUNET_CRYPTO_ecdsa_sign(issuer, - purpose, - (struct GNUNET_CRYPTO_EcdsaSignature *) - buf_ptr)) - { - GNUNET_break(0); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n"); - GNUNET_free(code_payload); - return NULL; - } - code_str = base64_and_urlencode(code_payload, code_payload_len); - GNUNET_free(code_payload); + GNUNET_CRYPTO_ecdsa_sign (issuer, + purpose, + (struct GNUNET_CRYPTO_EcdsaSignature *) + buf_ptr)) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n"); + GNUNET_free (code_payload); + return NULL; + } + code_str = base64_and_urlencode (code_payload, code_payload_len); + GNUNET_free (code_payload); return code_str; } @@ -585,12 +587,12 @@ OIDC_build_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, * @return GNUNET_OK if successful, else GNUNET_SYSERR */ 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) +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) { char *code_payload; char *ptr; @@ -610,103 +612,110 @@ OIDC_parse_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, uint32_t nonce = 0; struct OIDC_Parameters *params; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); code_payload = NULL; code_payload_len = - GNUNET_STRINGS_base64_decode(code, strlen(code), (void **)&code_payload); - if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) + - sizeof(struct OIDC_Parameters) + - sizeof(struct GNUNET_CRYPTO_EcdsaSignature)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n"); - GNUNET_free_non_null(code_payload); - return GNUNET_SYSERR; - } - - purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)code_payload; + GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload); + if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) + + sizeof(struct OIDC_Parameters) + + sizeof(struct GNUNET_CRYPTO_EcdsaSignature)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n"); + GNUNET_free_non_null (code_payload); + return GNUNET_SYSERR; + } + + purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload; plaintext_len = code_payload_len; plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose); - ptr = (char *)&purpose[1]; + ptr = (char *) &purpose[1]; // Public ECDH key - ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *)ptr; + ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr; ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey); plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey); // Decrypt ciphertext plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature); - plaintext = GNUNET_malloc(plaintext_len); - decrypt_payload(ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext); - //ptr = plaintext; + plaintext = GNUNET_malloc (plaintext_len); + decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext); + // ptr = plaintext; ptr += plaintext_len; - signature = (struct GNUNET_CRYPTO_EcdsaSignature *)ptr; - params = (struct OIDC_Parameters *)plaintext; + signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr; + params = (struct OIDC_Parameters *) plaintext; // cmp code_challenge code_verifier - code_challenge_len = ntohl(params->code_challenge_len); + code_challenge_len = ntohl (params->code_challenge_len); if (0 != code_challenge_len) /* Only check if this code requires a CV */ + { + if (NULL == code_verifier) { - code_verifier_hash = GNUNET_malloc(256 / 8); - // hash code verifier - gcry_md_hash_buffer(GCRY_MD_SHA256, - code_verifier_hash, - code_verifier, - strlen(code_verifier)); - // encode code verifier - expected_code_challenge = base64url_encode(code_verifier_hash, 256 / 8); - code_challenge = (char *)¶ms[1]; - GNUNET_free(code_verifier_hash); - if ((strlen(expected_code_challenge) != code_challenge_len) || - (0 != - strncmp(expected_code_challenge, code_challenge, code_challenge_len))) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Invalid code verifier! Expected: %s, Got: %.*s\n", - expected_code_challenge, - code_challenge_len, - code_challenge); - GNUNET_free_non_null(code_payload); - GNUNET_free(expected_code_challenge); - return GNUNET_SYSERR; - } - GNUNET_free(expected_code_challenge); - } - // Ticket - memcpy(ticket, ¶ms->ticket, sizeof(params->ticket)); - // Nonce - nonce = ntohl(params->nonce); //ntohl (*((uint32_t *) ptr)); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce); - // Signature - GNUNET_CRYPTO_ecdsa_key_get_public(ecdsa_priv, &ecdsa_pub); - if (0 != GNUNET_memcmp(&ecdsa_pub, &ticket->audience)) - { - GNUNET_free(code_payload); - GNUNET_free(plaintext); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Audience in ticket does not match client!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected code verifier!\n"); + GNUNET_free_non_null (code_payload); return GNUNET_SYSERR; } - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, - purpose, - signature, - &ticket->identity)) + code_verifier_hash = GNUNET_malloc (256 / 8); + // hash code verifier + gcry_md_hash_buffer (GCRY_MD_SHA256, + code_verifier_hash, + code_verifier, + strlen (code_verifier)); + // encode code verifier + expected_code_challenge = base64url_encode (code_verifier_hash, 256 / 8); + code_challenge = (char *) ¶ms[1]; + GNUNET_free (code_verifier_hash); + if ((strlen (expected_code_challenge) != code_challenge_len) || + (0 != + strncmp (expected_code_challenge, code_challenge, code_challenge_len))) { - GNUNET_free(code_payload); - GNUNET_free(plaintext); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid code verifier! Expected: %s, Got: %.*s\n", + expected_code_challenge, + code_challenge_len, + code_challenge); + GNUNET_free_non_null (code_payload); + GNUNET_free (expected_code_challenge); return GNUNET_SYSERR; } + GNUNET_free (expected_code_challenge); + } + // Ticket + memcpy (ticket, ¶ms->ticket, sizeof(params->ticket)); + // Nonce + nonce = ntohl (params->nonce); // ntohl (*((uint32_t *) ptr)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce); + // Signature + GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub); + if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience)) + { + GNUNET_free (code_payload); + GNUNET_free (plaintext); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Audience in ticket does not match client!\n"); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, + purpose, + signature, + &ticket->identity)) + { + GNUNET_free (code_payload); + GNUNET_free (plaintext); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n"); + return GNUNET_SYSERR; + } // Attributes - attrs_ser = ((char *)¶ms[1]) + code_challenge_len; - attrs_ser_len = ntohl(params->attr_list_len); - *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize(attrs_ser, attrs_ser_len); + attrs_ser = ((char *) ¶ms[1]) + code_challenge_len; + attrs_ser_len = ntohl (params->attr_list_len); + *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attrs_ser, attrs_ser_len); *nonce_str = NULL; if (nonce != 0) - GNUNET_asprintf(nonce_str, "%u", nonce); - GNUNET_free(code_payload); - GNUNET_free(plaintext); + GNUNET_asprintf (nonce_str, "%u", nonce); + GNUNET_free (code_payload); + GNUNET_free (plaintext); return GNUNET_OK; } @@ -721,42 +730,42 @@ OIDC_parse_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, * @param token_response where to store the response */ void -OIDC_build_token_response(const char *access_token, - const char *id_token, - const struct GNUNET_TIME_Relative *expiration_time, - char **token_response) +OIDC_build_token_response (const char *access_token, + const char *id_token, + const struct GNUNET_TIME_Relative *expiration_time, + char **token_response) { json_t *root_json; - root_json = json_object(); - - GNUNET_assert(NULL != access_token); - GNUNET_assert(NULL != id_token); - GNUNET_assert(NULL != expiration_time); - json_object_set_new(root_json, "access_token", json_string(access_token)); - json_object_set_new(root_json, "token_type", json_string("Bearer")); - json_object_set_new(root_json, - "expires_in", - json_integer(expiration_time->rel_value_us / - (1000 * 1000))); - json_object_set_new(root_json, "id_token", json_string(id_token)); - *token_response = json_dumps(root_json, JSON_INDENT(0) | JSON_COMPACT); - json_decref(root_json); + root_json = json_object (); + + GNUNET_assert (NULL != access_token); + GNUNET_assert (NULL != id_token); + GNUNET_assert (NULL != expiration_time); + json_object_set_new (root_json, "access_token", json_string (access_token)); + json_object_set_new (root_json, "token_type", json_string ("Bearer")); + json_object_set_new (root_json, + "expires_in", + json_integer (expiration_time->rel_value_us + / (1000 * 1000))); + json_object_set_new (root_json, "id_token", json_string (id_token)); + *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT); + json_decref (root_json); } /** * Generate a new access token */ char * -OIDC_access_token_new() +OIDC_access_token_new () { char *access_token; uint64_t random_number; random_number = - GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); - GNUNET_STRINGS_base64_encode(&random_number, - sizeof(uint64_t), - &access_token); + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); + GNUNET_STRINGS_base64_encode (&random_number, + sizeof(uint64_t), + &access_token); return access_token; } -- cgit v1.2.3