]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
hs-v3: Don't allow registration of an all-zeroes client auth key.
authorGeorge Kadianakis <desnacked@riseup.net>
Mon, 30 Mar 2020 13:09:52 +0000 (16:09 +0300)
committerNick Mathewson <nickm@torproject.org>
Mon, 13 Apr 2020 18:13:33 +0000 (14:13 -0400)
The client auth protocol allows attacker-controlled x25519 private keys being
passed around, which allows an attacker to potentially trigger the all-zeroes
assert for client_auth_sk in hs_descriptor.c:decrypt_descriptor_cookie().

We fixed that by making sure that an all-zeroes client auth key will not be
used.

There are no guidelines for validating x25519 private keys, and the assert was
there as a sanity check for code flow issues (we don't want to enter that
function with an unitialized key if client auth is being used). To avoid such
crashes in the future, we also changed the assert to a BUG-and-err.

changes/bug33545 [new file with mode: 0644]
src/feature/control/control_hs.c
src/feature/hs/hs_client.h
src/test/test_hs_control.c

diff --git a/changes/bug33545 b/changes/bug33545
new file mode 100644 (file)
index 0000000..c051b01
--- /dev/null
@@ -0,0 +1,4 @@
+  o Minor bugfixes (hidden services):
+    - Block a client-side assert by disallowing the registration of an x25519
+      client auth key that's all zeroes. Fixes bug 33545; bugfix on
+      0.4.3.1-alpha. Patch based on patch from "cypherpunks".
\ No newline at end of file
index d3cd363f63514644984eb9dc38f5dc5d0163debe..f5b331de9ac9ed5e8fb4b28df2f785bf88ed6866 100644 (file)
@@ -50,11 +50,18 @@ parse_private_key_from_control_port(const char *client_privkey_str,
 
   if (base64_decode((char*)privkey->secret_key, sizeof(privkey->secret_key),
                     key_blob,
-                   strlen(key_blob)) != sizeof(privkey->secret_key)) {
+                    strlen(key_blob)) != sizeof(privkey->secret_key)) {
     control_printf_endreply(conn, 512, "Failed to decode x25519 private key");
     goto err;
   }
 
+  if (fast_mem_is_zero((const char*)privkey->secret_key,
+                       sizeof(privkey->secret_key))) {
+    control_printf_endreply(conn, 553,
+                            "Invalid private key \"%s\"", key_blob);
+    goto err;
+  }
+
   retval = 0;
 
  err:
index 3660bfa96ccdd4933a80444ae7bc21588578f88a..d0a3a7015f5c29b2ae7b5e3fb450ece53f6aadda 100644 (file)
@@ -45,7 +45,7 @@ typedef enum {
   REGISTER_SUCCESS_AND_DECRYPTED,
   /* We failed to register these credentials, because of a bad HS address. */
   REGISTER_FAIL_BAD_ADDRESS,
-  /* We failed to register these credentials, because of a bad HS address. */
+  /* We failed to store these credentials in a persistent file on disk. */
   REGISTER_FAIL_PERMANENT_STORAGE,
 } hs_client_register_auth_status_t;
 
index 9277711d2aa870ae258e5634c255086293c54f38..8ba9f1173c71bda7f681c8c8843bf04f6fd9741c 100644 (file)
@@ -467,6 +467,20 @@ test_hs_control_bad_onion_client_auth_add(void *arg)
   cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
   tt_str_op(cp1, OP_EQ, "512 Failed to decode x25519 private key\r\n");
 
+  tor_free(cp1);
+  tor_free(args);
+
+  /* Register with an all zero client key */
+  args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+                    "x25519:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=");
+  retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+  tt_int_op(retval, OP_EQ, 0);
+
+  /* Check contents */
+  cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+  tt_str_op(cp1, OP_EQ, "553 Invalid private key \"AAAAAAAAAAAAAAAAAAAA"
+                        "AAAAAAAAAAAAAAAAAAAAAAA=\"\r\n");
+
   client_auths = get_hs_client_auths_map();
   tt_assert(!client_auths);