[tor-commits] [tor/master] Use a single path for all PEM-like objects in get_next_token()

nickm at torproject.org nickm at torproject.org
Tue Dec 18 23:59:14 UTC 2018


commit 0556942284d7dcdf0a5e7a31e94b925378a338a8
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri Dec 14 13:17:17 2018 -0500

    Use a single path for all PEM-like objects in get_next_token()
    
    Previously, we would decode the PEM wrapper for keys twice: once in
    get_next_token, and once later in PEM decode.  Now we just do all of
    the wrapper and base64 stuff in get_next_token, and store the
    base64-decoded part in the token object for keys and non-keys alike.
    
    This change should speed up parsing slightly by letting us skip a
    bunch of stuff in crypto_pk_read_*from_string(), including the tag
    detection parts of pem_decode(), and an extra key allocation and
    deallocation pair.
    
    Retaining the base64-decoded part in the token object will allow us
    to speed up our microdesc parsing, since it is the asn1 portion that
    we actually want to retain.
---
 src/feature/dirparse/parsecommon.c | 24 +++++++++++++-----------
 src/test/test_parsecommon.c        |  8 ++++----
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index 91b775533..2e7cea816 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -266,7 +266,7 @@ get_next_token(memarea_t *area,
    * attack, a bug, or some other nonsense. */
 #define MAX_LINE_LENGTH (128*1024)
 
-  const char *next, *eol, *obstart;
+  const char *next, *eol;
   size_t obname_len;
   int i;
   directory_token_t *tok;
@@ -352,7 +352,6 @@ get_next_token(memarea_t *area,
   if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
     goto check_object;
 
-  obstart = *s; /* Set obstart to start of object spec */
   if (eol - *s <= 16 || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
       strcmp_len(eol-5, "-----", 5) ||           /* nuls or invalid endings */
       (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) {     /* name too long */
@@ -383,15 +382,7 @@ get_next_token(memarea_t *area,
   if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
     RET_ERR("Couldn't parse object: missing footer or object much too big.");
 
-  if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
-    tok->key = crypto_pk_new();
-    if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
-      RET_ERR("Couldn't parse public key.");
-  } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
-    tok->key = crypto_pk_new();
-    if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
-      RET_ERR("Couldn't parse private key.");
-  } else { /* If it's something else, try to base64-decode it */
+  {
     int r;
     size_t maxsize = base64_decode_maxsize(next-*s);
     tok->object_body = ALLOC(maxsize);
@@ -400,6 +391,17 @@ get_next_token(memarea_t *area,
       RET_ERR("Malformed object: bad base64-encoded data");
     tok->object_size = r;
   }
+
+  if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
+    tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size);
+    if (! tok->key)
+      RET_ERR("Couldn't parse public key.");
+  } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
+    tok->key = crypto_pk_asn1_decode_private(tok->object_body,
+                                             tok->object_size);
+    if (! tok->key)
+      RET_ERR("Couldn't parse private key.");
+  }
   *s = eol;
 
  check_object:
diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c
index 6da125dd0..8e74fcdb4 100644
--- a/src/test/test_parsecommon.c
+++ b/src/test/test_parsecommon.c
@@ -300,8 +300,8 @@ test_parsecommon_get_next_token_parse_keys(void *arg)
   tt_int_op(token->tp, OP_EQ, R_IPO_ONION_KEY);
   tt_int_op(token->n_args, OP_EQ, 0);
   tt_str_op(token->object_type, OP_EQ, "RSA PUBLIC KEY");
-  tt_int_op(token->object_size, OP_EQ, 0);
-  tt_assert(!token->object_body);
+  tt_int_op(token->object_size, OP_EQ, 140);
+  tt_assert(token->object_body);
   tt_assert(token->key);
   tt_assert(!token->error);
 
@@ -335,8 +335,8 @@ test_parsecommon_get_next_token_parse_keys(void *arg)
   tt_int_op(token2->tp, OP_EQ, C_CLIENT_KEY);
   tt_int_op(token2->n_args, OP_EQ, 0);
   tt_str_op(token2->object_type, OP_EQ, "RSA PRIVATE KEY");
-  tt_int_op(token2->object_size, OP_EQ, 0);
-  tt_assert(!token2->object_body);
+  tt_int_op(token2->object_size, OP_EQ, 608);
+  tt_assert(token2->object_body);
   tt_assert(token2->key);
   tt_assert(!token->error);
 





More information about the tor-commits mailing list