aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2020-02-06 22:34:11 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2020-02-09 20:38:11 +0100
commitd06446f143610790d9a0530d524d8e9db2a03b8c (patch)
treed42cdc3c342922b56a41487d5ed49fc1c981066a /src
parenta80090ffcc10a2a2c188313e997d16802f2777f1 (diff)
downloadgnunet-d06446f143610790d9a0530d524d8e9db2a03b8c.tar.gz
gnunet-d06446f143610790d9a0530d524d8e9db2a03b8c.zip
add base64url encoding to util (RFC7515)
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_strings_lib.h26
-rw-r--r--src/reclaim/oidc_helper.c149
-rw-r--r--src/util/strings.c85
3 files changed, 119 insertions, 141 deletions
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 5e8892c0d..4003590fc 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -349,6 +349,19 @@ GNUNET_STRINGS_base64_encode (const void *in,
349 349
350 350
351/** 351/**
352 * Encode into Base64url. RFC7515
353 *
354 * @param in the data to encode
355 * @param len the length of the input
356 * @param output where to write the output (*output should be NULL,
357 * is allocated)
358 * @return the size of the output
359 */
360size_t
361GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output);
362
363
364/**
352 * Decode from Base64. 365 * Decode from Base64.
353 * 366 *
354 * @param data the data to encode 367 * @param data the data to encode
@@ -364,6 +377,19 @@ GNUNET_STRINGS_base64_decode (const char *data,
364 377
365 378
366/** 379/**
380 * Decode from Base64url. RFC7515
381 *
382 * @param data the data to decode
383 * @param len the length of the input
384 * @param output where to write the output (*output should be NULL,
385 * is allocated)
386 * @return the size of the output
387 */
388size_t
389GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out);
390
391
392/**
367 * Convert a peer path to a human-readable string. 393 * Convert a peer path to a human-readable string.
368 * 394 *
369 * @param pids array of PIDs to convert to a string 395 * @param pids array of PIDs to convert to a string
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 487aa5695..92b4b69cc 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -287,10 +287,10 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
287 json_decref (body); 287 json_decref (body);
288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str); 288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
289 289
290 GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64); 290 GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
291 fix_base64 (header_base64); 291 fix_base64 (header_base64);
292 292
293 GNUNET_STRINGS_base64_encode (body_str, strlen (body_str), &body_base64); 293 GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
294 fix_base64 (body_base64); 294 fix_base64 (body_base64);
295 295
296 GNUNET_free (subject); 296 GNUNET_free (subject);
@@ -306,9 +306,9 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
306 signature_target, 306 signature_target,
307 strlen (signature_target), 307 strlen (signature_target),
308 &signature); 308 &signature);
309 GNUNET_STRINGS_base64_encode ((const char *) &signature, 309 GNUNET_STRINGS_base64url_encode ((const char *) &signature,
310 sizeof(struct GNUNET_HashCode), 310 sizeof(struct GNUNET_HashCode),
311 &signature_base64); 311 &signature_base64);
312 fix_base64 (signature_base64); 312 fix_base64 (signature_base64);
313 313
314 GNUNET_asprintf (&result, 314 GNUNET_asprintf (&result,
@@ -333,138 +333,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
333} 333}
334 334
335 335
336/* Converts a hex character to its integer value */
337static char
338from_hex (char ch)
339{
340 return isdigit (ch) ? ch - '0' : tolower (ch) - 'a' + 10;
341}
342
343
344/* Converts an integer value to its hex character*/
345static char
346to_hex (char code)
347{
348 static char hex[] = "0123456789abcdef";
349
350 return hex[code & 15];
351}
352
353
354/* Returns a url-encoded version of str */
355/* IMPORTANT: be sure to free() the returned string after use */
356static char *
357url_encode (const char *str)
358{
359 char *pstr = (char *) str;
360 char *buf = GNUNET_malloc (strlen (str) * 3 + 1);
361 char *pbuf = buf;
362
363 while (*pstr)
364 {
365 if (isalnum (*pstr) || (*pstr == '-') || (*pstr == '_') || (*pstr == '.') ||
366 (*pstr == '~') )
367 *pbuf++ = *pstr;
368 else if (*pstr == ' ')
369 *pbuf++ = '+';
370 else
371 {
372 *pbuf++ = '%';
373 *pbuf++ = to_hex (*pstr >> 4);
374 *pbuf++ = to_hex (*pstr & 15);
375 }
376 pstr++;
377 }
378 *pbuf = '\0';
379 return buf;
380}
381
382
383/* Returns a url-decoded version of str */
384/* IMPORTANT: be sure to free() the returned string after use */
385static char *
386url_decode (const char *str)
387{
388 char *pstr = (char *) str;
389 char *buf = GNUNET_malloc (strlen (str) + 1);
390 char *pbuf = buf;
391
392 while (*pstr)
393 {
394 if (*pstr == '%')
395 {
396 if (pstr[1] && pstr[2])
397 {
398 *pbuf++ = from_hex (pstr[1]) << 4 | from_hex (pstr[2]);
399 pstr += 2;
400 }
401 }
402 else if (*pstr == '+')
403 {
404 *pbuf++ = ' ';
405 }
406 else
407 {
408 *pbuf++ = *pstr;
409 }
410 pstr++;
411 }
412 *pbuf = '\0';
413 return buf;
414}
415
416
417/**
418 * Returns base64 encoded string urlencoded
419 *
420 * @param string the string to encode
421 * @return base64 encoded string
422 */
423static char *
424base64_and_urlencode (const char *data, size_t data_size)
425{
426 char *enc;
427 char *urlenc;
428
429 GNUNET_STRINGS_base64_encode (data, data_size, &enc);
430 urlenc = url_encode (enc);
431 GNUNET_free (enc);
432 return urlenc;
433}
434
435
436/**
437 * Returns base64 encoded string urlencoded
438 *
439 * @param string the string to encode
440 * @return base64 encoded string
441 */
442static char *
443base64url_encode (const char *data, size_t data_size)
444{
445 char *enc;
446 size_t pos;
447
448 GNUNET_STRINGS_base64_encode (data, data_size, &enc);
449 // Replace with correct characters for base64url
450 pos = 0;
451 while ('\0' != enc[pos])
452 {
453 if ('+' == enc[pos])
454 enc[pos] = '-';
455 if ('/' == enc[pos])
456 enc[pos] = '_';
457 if ('=' == enc[pos])
458 {
459 enc[pos] = '\0';
460 break;
461 }
462 pos++;
463 }
464 return enc;
465}
466
467
468static void 336static void
469derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key, 337derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
470 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, 338 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
@@ -693,7 +561,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
693 GNUNET_free (code_payload); 561 GNUNET_free (code_payload);
694 return NULL; 562 return NULL;
695 } 563 }
696 code_str = base64_and_urlencode (code_payload, code_payload_len); 564 GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
697 GNUNET_free (code_payload); 565 GNUNET_free (code_payload);
698 return code_str; 566 return code_str;
699} 567}
@@ -742,7 +610,8 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); 610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
743 code_payload = NULL; 611 code_payload = NULL;
744 code_payload_len = 612 code_payload_len =
745 GNUNET_STRINGS_base64_decode (code, strlen (code), (void **) &code_payload); 613 GNUNET_STRINGS_base64url_decode (code, strlen (code),
614 (void **) &code_payload);
746 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 615 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
747 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) 616 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
748 + sizeof(struct OIDC_Parameters) 617 + sizeof(struct OIDC_Parameters)
@@ -789,7 +658,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
789 code_verifier, 658 code_verifier,
790 strlen (code_verifier)); 659 strlen (code_verifier));
791 // encode code verifier 660 // encode code verifier
792 expected_code_challenge = base64url_encode (code_verifier_hash, 256 / 8); 661 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8, &expected_code_challenge);
793 code_challenge = (char *) &params[1]; 662 code_challenge = (char *) &params[1];
794 GNUNET_free (code_verifier_hash); 663 GNUNET_free (code_verifier_hash);
795 if ((strlen (expected_code_challenge) != code_challenge_len) || 664 if ((strlen (expected_code_challenge) != code_challenge_len) ||
diff --git a/src/util/strings.c b/src/util/strings.c
index 4e7451283..a291dc4e1 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -1897,6 +1897,41 @@ GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output)
1897} 1897}
1898 1898
1899 1899
1900/**
1901 * Encode into Base64url. RFC7515
1902 *
1903 * @param in the data to encode
1904 * @param len the length of the input
1905 * @param output where to write the output (*output should be NULL,
1906 * is allocated)
1907 * @return the size of the output
1908 */
1909size_t
1910GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output)
1911{
1912 char *enc;
1913 size_t pos;
1914
1915 GNUNET_STRINGS_base64_encode (in, len, output);
1916 enc = *output;
1917 // Replace with correct characters for base64url
1918 pos = 0;
1919 while ('\0' != enc[pos])
1920 {
1921 if ('+' == enc[pos])
1922 enc[pos] = '-';
1923 if ('/' == enc[pos])
1924 enc[pos] = '_';
1925 if ('=' == enc[pos])
1926 {
1927 enc[pos] = '\0';
1928 break;
1929 }
1930 pos++;
1931 }
1932 return strlen (enc);
1933}
1934
1900#define cvtfind(a) \ 1935#define cvtfind(a) \
1901 ((((a) >= 'A') && ((a) <= 'Z')) \ 1936 ((((a) >= 'A') && ((a) <= 'Z')) \
1902 ? (a) - 'A' \ 1937 ? (a) - 'A' \
@@ -1929,7 +1964,7 @@ GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out)
1929 "ignoring CR/LF\n"); \ 1964 "ignoring CR/LF\n"); \
1930 i++; \ 1965 i++; \
1931 if (i >= len) \ 1966 if (i >= len) \
1932 goto END; \ 1967 goto END; \
1933 } 1968 }
1934 1969
1935 output = GNUNET_malloc ((len * 3 / 4) + 8); 1970 output = GNUNET_malloc ((len * 3 / 4) + 8);
@@ -1978,4 +2013,52 @@ END:
1978} 2013}
1979 2014
1980 2015
2016/**
2017 * Decode from Base64url. RFC7515
2018 *
2019 * @param data the data to decode
2020 * @param len the length of the input
2021 * @param output where to write the output (*output should be NULL,
2022 * is allocated)
2023 * @return the size of the output
2024 */
2025size_t
2026GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2027{
2028 char *s;
2029 int padding;
2030 size_t ret;
2031
2032 /* make enough space for padding */
2033 s = GNUNET_malloc (len + 3);
2034 memcpy (s, data, len);
2035
2036 for (int i = 0; i < strlen (s); i++)
2037 {
2038 if (s[i] == '-')
2039 s[i] = '+';
2040 if (s[i] == '_')
2041 s[i] = '/';
2042 }
2043 padding = len % 4;
2044 switch (padding) // Pad with trailing '='s
2045 {
2046 case 0:
2047 break; // No pad chars in this case
2048 case 2:
2049 strncpy (&s[len], "==", 2);
2050 break; // Two pad chars
2051 case 3:
2052 s[len] = '=';
2053 break; // One pad char
2054 default:
2055 GNUNET_assert (0);
2056 break;
2057 }
2058 ret = GNUNET_STRINGS_base64_decode (s, strlen (s), out);
2059 GNUNET_free (s);
2060 return ret;
2061}
2062
2063
1981/* end of strings.c */ 2064/* end of strings.c */