|
@@ -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
|