[tor-commits] [tor/master] Unify functions for reading/writing PEM keys, to avoid duplication.
nickm at torproject.org
nickm at torproject.org
Wed Sep 5 00:47:14 UTC 2018
commit 3b5d6ef15bec26c3bda22057ba09e1301613ee71
Author: Nick Mathewson <nickm at torproject.org>
Date: Wed Aug 29 16:43:54 2018 -0400
Unify functions for reading/writing PEM keys, to avoid duplication.
---
src/lib/crypt_ops/crypto_rsa.c | 145 ++++++++++++++++++++---------------------
1 file changed, 71 insertions(+), 74 deletions(-)
diff --git a/src/lib/crypt_ops/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index 31497e650..6a9e2948f 100644
--- a/src/lib/crypt_ops/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -398,29 +398,43 @@ crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
static const char RSA_PUBLIC_TAG[] = "RSA PUBLIC KEY";
static const char RSA_PRIVATE_TAG[] = "RSA PRIVATE KEY";
-/** PEM-encode the public key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
+/* These are overestimates for how many extra bytes we might need to encode
+ * a key in DER */
+#define PRIVATE_ASN_MAX_OVERHEAD_FACTOR 16
+#define PUBLIC_ASN_MAX_OVERHEAD_FACTOR 3
+
+/** Helper: PEM-encode <b>env</b> and write it to a newly allocated string.
+ * If <b>private_key</b>, write the private part of <b>env</b>; otherwise
+ * write only the public portion. On success, set *<b>dest</b> to the new
+ * string, *<b>len</b> to the string's length, and return 0. On failure,
+ * return -1.
*/
-int
-crypto_pk_write_public_key_to_string(crypto_pk_t *env,
- char **dest, size_t *len)
+static int
+crypto_pk_write_to_string_generic(crypto_pk_t *env,
+ char **dest, size_t *len,
+ bool private_key)
{
- size_t buflen = crypto_pk_keysize(env) * 3;
+ const int factor =
+ private_key ? PRIVATE_ASN_MAX_OVERHEAD_FACTOR
+ : PUBLIC_ASN_MAX_OVERHEAD_FACTOR;
+ size_t buflen = crypto_pk_keysize(env) * factor;
+ const char *tag =
+ private_key ? RSA_PRIVATE_TAG : RSA_PUBLIC_TAG;
char *buf = tor_malloc(buflen);
char *result = NULL;
size_t resultlen = 0;
int rv = -1;
- int n = crypto_pk_asn1_encode(env, buf, buflen);
+ int n = private_key
+ ? crypto_pk_asn1_encode_private(env, buf, buflen)
+ : crypto_pk_asn1_encode(env, buf, buflen);
if (n < 0)
goto done;
- resultlen = pem_encoded_size(n, RSA_PUBLIC_TAG);
+ resultlen = pem_encoded_size(n, tag);
result = tor_malloc(resultlen);
if (pem_encode(result, resultlen,
- (const unsigned char *)buf, n, RSA_PUBLIC_TAG) < 0) {
+ (const unsigned char *)buf, n, tag) < 0) {
goto done;
}
@@ -438,6 +452,18 @@ crypto_pk_write_public_key_to_string(crypto_pk_t *env,
return rv;
}
+/** PEM-encode the public key portion of <b>env</b> and write it to a
+ * newly allocated string. On success, set *<b>dest</b> to the new
+ * string, *<b>len</b> to the string's length, and return 0. On
+ * failure, return -1.
+ */
+int
+crypto_pk_write_public_key_to_string(crypto_pk_t *env,
+ char **dest, size_t *len)
+{
+ return crypto_pk_write_to_string_generic(env, dest, len, false);
+}
+
/** PEM-encode the private key portion of <b>env</b> and write it to a
* newly allocated string. On success, set *<b>dest</b> to the new
* string, *<b>len</b> to the string's length, and return 0. On
@@ -447,59 +473,42 @@ int
crypto_pk_write_private_key_to_string(crypto_pk_t *env,
char **dest, size_t *len)
{
- size_t buflen = crypto_pk_keysize(env) * 16;
- char *buf = tor_malloc(buflen);
- char *result = NULL;
- size_t resultlen = 0;
- int rv = -1;
-
- int n = crypto_pk_asn1_encode_private(env, buf, buflen);
- if (n < 0)
- goto done;
-
- resultlen = pem_encoded_size(n, RSA_PRIVATE_TAG);
- result = tor_malloc(resultlen);
- if (pem_encode(result, resultlen,
- (const unsigned char *)buf, n, RSA_PRIVATE_TAG) < 0)
- goto done;
-
- *dest = result;
- *len = resultlen;
- rv = 0;
- done:
- if (rv < 0 && result) {
- memwipe(result, 0, resultlen);
- tor_free(result);
- }
- memwipe(buf, 0, buflen);
- tor_free(buf);
- return rv;
+ return crypto_pk_write_to_string_generic(env, dest, len, true);
}
-/** Read a PEM-encoded public key from the first <b>len</b> characters of
- * <b>src</b>, and store the result in <b>env</b>. Return 0 on success, -1 on
- * failure.
+/**
+ * Helper. Read a PEM-encoded RSA from the first <b>len</b> characters of
+ * <b>src</b>, and store the result in <b>env</b>. If <b>private_key</b>,
+ * expect a private key; otherwise expect a public key. Return 0 on success,
+ * -1 on failure. If len is -1, the string is nul-terminated.
*/
-int
-crypto_pk_read_public_key_from_string(crypto_pk_t *env,
- const char *src, size_t len)
+static int
+crypto_pk_read_from_string_generic(crypto_pk_t *env, const char *src,
+ size_t len, bool private_key)
{
- if (len == (size_t)-1)
+ if (len == (size_t)-1) // "-1" indicates "use the length of the string."
len = strlen(src);
+ const char *tag =
+ private_key ? RSA_PRIVATE_TAG : RSA_PUBLIC_TAG;
size_t buflen = len;
uint8_t *buf = tor_malloc(buflen);
int rv = -1;
- int n = pem_decode(buf, buflen, src, len, RSA_PUBLIC_TAG);
+ int n = pem_decode(buf, buflen, src, len, tag);
if (n < 0)
goto done;
- crypto_pk_t *pk = crypto_pk_asn1_decode((const char*)buf, n);
+ crypto_pk_t *pk = private_key
+ ? crypto_pk_asn1_decode_private((const char*)buf, n)
+ : crypto_pk_asn1_decode((const char*)buf, n);
if (! pk)
goto done;
- crypto_pk_assign_public(env, pk);
+ if (private_key)
+ crypto_pk_assign_private(env, pk);
+ else
+ crypto_pk_assign_public(env, pk);
crypto_pk_free(pk);
rv = 0;
@@ -509,38 +518,26 @@ crypto_pk_read_public_key_from_string(crypto_pk_t *env,
return rv;
}
-/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>s</b>
+/** Read a PEM-encoded public key from the first <b>len</b> characters of
+ * <b>src</b>, and store the result in <b>env</b>. Return 0 on success, -1 on
+ * failure. If len is -1, the string is nul-terminated.
+ */
+int
+crypto_pk_read_public_key_from_string(crypto_pk_t *env,
+ const char *src, size_t len)
+{
+ return crypto_pk_read_from_string_generic(env, src, len, false);
+}
+
+/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>src</b>
* into <b>env</b>. Return 0 on success, -1 on failure. If len is -1,
* the string is nul-terminated.
*/
int
crypto_pk_read_private_key_from_string(crypto_pk_t *env,
- const char *s, ssize_t len)
+ const char *src, ssize_t len)
{
- if (len == -1)
- len = strlen(s);
-
- size_t buflen = len;
- uint8_t *buf = tor_malloc(buflen);
- int rv = -1;
-
- int n = pem_decode(buf, buflen, s, len, RSA_PRIVATE_TAG);
- if (n < 0) {
- goto done;
- }
-
- crypto_pk_t *pk = crypto_pk_asn1_decode_private((const char *)buf, n);
- if (! pk)
- goto done;
-
- crypto_pk_assign_private(env, pk);
- crypto_pk_free(pk);
- rv = 0;
-
- done:
- memwipe(buf, 0, buflen);
- tor_free(buf);
- return rv;
+ return crypto_pk_read_from_string_generic(env, src, len, true);
}
/** Read a PEM-encoded private key from the file named by
More information about the tor-commits
mailing list