aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/crypto_curve25519.c30
-rw-r--r--src/common/crypto_curve25519.h7
-rw-r--r--src/or/routerparse.c25
-rw-r--r--src/test/test_crypto.c37
4 files changed, 82 insertions, 17 deletions
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c
index a4ab65cf4..aead4f8ba 100644
--- a/src/common/crypto_curve25519.c
+++ b/src/common/crypto_curve25519.c
@@ -178,3 +178,33 @@ curve25519_handshake(uint8_t *output,
curve25519_impl(output, skey->secret_key, pkey->public_key);
}
+int
+curve25519_public_to_base64(char *output,
+ const curve25519_public_key_t *pkey)
+{
+ char buf[128];
+ base64_encode(buf, sizeof(buf),
+ (const char*)pkey->public_key, CURVE25519_PUBKEY_LEN);
+ buf[CURVE25519_BASE64_PADDED_LEN] = '\0';
+ memcpy(output, buf, CURVE25519_BASE64_PADDED_LEN+1);
+ return 0;
+}
+
+int
+curve25519_public_from_base64(curve25519_public_key_t *pkey,
+ const char *input)
+{
+ size_t len = strlen(input);
+ if (len == CURVE25519_BASE64_PADDED_LEN - 1) {
+ /* not padded */
+ return digest256_from_base64((char*)pkey->public_key, input);
+ } else if (len == CURVE25519_BASE64_PADDED_LEN) {
+ char buf[128];
+ if (base64_decode(buf, sizeof(buf), input, len) != CURVE25519_PUBKEY_LEN)
+ return -1;
+ memcpy(pkey->public_key, buf, CURVE25519_PUBKEY_LEN);
+ return 0;
+ } else {
+ return -1;
+ }
+}
diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h
index e768b8c42..9c732b9c4 100644
--- a/src/common/crypto_curve25519.h
+++ b/src/common/crypto_curve25519.h
@@ -51,6 +51,13 @@ int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
char **tag_out,
const char *fname);
+#define CURVE25519_BASE64_PADDED_LEN 44
+
+int curve25519_public_from_base64(curve25519_public_key_t *pkey,
+ const char *input);
+int curve25519_public_to_base64(char *output,
+ const curve25519_public_key_t *pkey);
+
#ifdef CRYPTO_CURVE25519_PRIVATE
int curve25519_impl(uint8_t *output, const uint8_t *secret,
const uint8_t *basepoint);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index c873784c0..dca4176d4 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1288,18 +1288,14 @@ router_parse_entry_from_string(const char *s, const char *end,
tok->key = NULL; /* Prevent free */
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
- uint8_t k[CURVE25519_PUBKEY_LEN+32];
- int r;
+ curve25519_public_key_t k;
tor_assert(tok->n_args >= 1);
- r = base64_decode((char*)k, sizeof(k), tok->args[0], strlen(tok->args[0]));
- if (r != CURVE25519_PUBKEY_LEN) {
- log_warn(LD_DIR, "Bogus onion-key-ntor in routerinfo");
+ if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
+ log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
goto err;
}
router->onion_curve25519_pkey =
- tor_malloc(sizeof(curve25519_public_key_t));
- memcpy(router->onion_curve25519_pkey->public_key,
- k, CURVE25519_PUBKEY_LEN);
+ tor_memdup(&k, sizeof(curve25519_public_key_t));
}
tok = find_by_keyword(tokens, K_SIGNING_KEY);
@@ -4264,19 +4260,14 @@ microdescs_parse_from_string(const char *s, const char *eos,
tok->key = NULL;
if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
- uint8_t k[CURVE25519_PUBKEY_LEN+32];
- int r;
+ curve25519_public_key_t k;
tor_assert(tok->n_args >= 1);
- r = base64_decode((char*)k, sizeof(k),
- tok->args[0], strlen(tok->args[0]));
- if (r != CURVE25519_PUBKEY_LEN) {
- log_warn(LD_DIR, "Bogus onion-key-ntor in microdesc");
+ if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
+ log_warn(LD_DIR, "Bogus ntor-onion-key in microdesc");
goto next;
}
md->onion_curve25519_pkey =
- tor_malloc(sizeof(curve25519_public_key_t));
- memcpy(md->onion_curve25519_pkey->public_key,
- k, CURVE25519_PUBKEY_LEN);
+ tor_memdup(&k, sizeof(curve25519_public_key_t));
}
{
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 67d2b8318..0c846b6db 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1008,6 +1008,42 @@ test_crypto_curve25519_wrappers(void *arg)
}
static void
+test_crypto_curve25519_encode(void *arg)
+{
+ curve25519_secret_key_t seckey;
+ curve25519_public_key_t key1, key2, key3;
+ char buf[64];
+
+ (void)arg;
+
+ curve25519_secret_key_generate(&seckey, 0);
+ curve25519_public_key_generate(&key1, &seckey);
+ tt_int_op(0, ==, curve25519_public_to_base64(buf, &key1));
+ tt_int_op(CURVE25519_BASE64_PADDED_LEN, ==, strlen(buf));
+
+ tt_int_op(0, ==, curve25519_public_from_base64(&key2, buf));
+ test_memeq(key1.public_key, key2.public_key, CURVE25519_PUBKEY_LEN);
+
+ buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0';
+ tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, ==, strlen(buf));
+ tt_int_op(0, ==, curve25519_public_from_base64(&key3, buf));
+ test_memeq(key1.public_key, key3.public_key, CURVE25519_PUBKEY_LEN);
+
+ /* Now try bogus parses. */
+ strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=", sizeof(buf));
+ tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));
+
+ strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", sizeof(buf));
+ tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));
+
+ strlcpy(buf, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", sizeof(buf));
+ tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));
+
+ done:
+ ;
+}
+
+static void
test_crypto_curve25519_persist(void *arg)
{
curve25519_keypair_t keypair, keypair2;
@@ -1100,6 +1136,7 @@ struct testcase_t crypto_tests[] = {
#ifdef CURVE25519_ENABLED
{ "curve25519_impl", test_crypto_curve25519_impl, 0, NULL, NULL },
{ "curve25519_wrappers", test_crypto_curve25519_wrappers, 0, NULL, NULL },
+ { "curve25519_encode", test_crypto_curve25519_encode, 0, NULL, NULL },
{ "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL },
#endif
END_OF_TESTCASES