|
@@ -5,6 +5,14 @@
|
|
* \file crypto_curve25519.c
|
|
* \file crypto_curve25519.c
|
|
*
|
|
*
|
|
* \brief Wrapper code for a curve25519 implementation.
|
|
* \brief Wrapper code for a curve25519 implementation.
|
|
|
|
+ *
|
|
|
|
+ * Curve25519 is an Elliptic-Curve Diffie Hellman handshake, designed by
|
|
|
|
+ * Dan Bernstein. For more information, see https://cr.yp.to/ecdh.html
|
|
|
|
+ *
|
|
|
|
+ * Tor uses Curve25519 as the basis of its "ntor" circuit extension
|
|
|
|
+ * handshake, and in related code. The functions in this module are
|
|
|
|
+ * used to find the most suitable available Curve25519 implementation,
|
|
|
|
+ * to provide wrappers around it, and so on.
|
|
*/
|
|
*/
|
|
|
|
|
|
#define CRYPTO_CURVE25519_PRIVATE
|
|
#define CRYPTO_CURVE25519_PRIVATE
|
|
@@ -39,15 +47,23 @@ int curve25519_donna(uint8_t *mypublic,
|
|
|
|
|
|
static void pick_curve25519_basepoint_impl(void);
|
|
static void pick_curve25519_basepoint_impl(void);
|
|
|
|
|
|
|
|
+/** This is set to 1 if we have an optimized Ed25519-based
|
|
|
|
+ * implementation for multiplying a value by the basepoint; to 0 if we
|
|
|
|
+ * don't, and to -1 if we haven't checked. */
|
|
static int curve25519_use_ed = -1;
|
|
static int curve25519_use_ed = -1;
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Helper function: call the most appropriate backend to compute the
|
|
|
|
+ * scalar "secret" times the point "point". Store the result in
|
|
|
|
+ * "output". Return 0 on success, negative on failure.
|
|
|
|
+ **/
|
|
STATIC int
|
|
STATIC int
|
|
curve25519_impl(uint8_t *output, const uint8_t *secret,
|
|
curve25519_impl(uint8_t *output, const uint8_t *secret,
|
|
- const uint8_t *basepoint)
|
|
|
|
|
|
+ const uint8_t *point)
|
|
{
|
|
{
|
|
uint8_t bp[CURVE25519_PUBKEY_LEN];
|
|
uint8_t bp[CURVE25519_PUBKEY_LEN];
|
|
int r;
|
|
int r;
|
|
- memcpy(bp, basepoint, CURVE25519_PUBKEY_LEN);
|
|
|
|
|
|
+ memcpy(bp, point, CURVE25519_PUBKEY_LEN);
|
|
/* Clear the high bit, in case our backend foolishly looks at it. */
|
|
/* Clear the high bit, in case our backend foolishly looks at it. */
|
|
bp[31] &= 0x7f;
|
|
bp[31] &= 0x7f;
|
|
#ifdef USE_CURVE25519_DONNA
|
|
#ifdef USE_CURVE25519_DONNA
|
|
@@ -61,6 +77,11 @@ curve25519_impl(uint8_t *output, const uint8_t *secret,
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Helper function: Multiply the scalar "secret" by the Curve25519
|
|
|
|
+ * basepoint (X=9), and store the result in "output". Return 0 on
|
|
|
|
+ * success, -1 on false.
|
|
|
|
+ */
|
|
STATIC int
|
|
STATIC int
|
|
curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
|
|
curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
|
|
{
|
|
{
|
|
@@ -85,6 +106,10 @@ curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Override the decision of whether to use the Ed25519-based basepoint
|
|
|
|
+ * multiply function. Used for testing.
|
|
|
|
+ */
|
|
void
|
|
void
|
|
curve25519_set_impl_params(int use_ed)
|
|
curve25519_set_impl_params(int use_ed)
|
|
{
|
|
{
|
|
@@ -142,6 +167,10 @@ curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Given a secret key in <b>seckey</b>, create the corresponding public
|
|
|
|
+ * key in <b>key_out</b>.
|
|
|
|
+ */
|
|
void
|
|
void
|
|
curve25519_public_key_generate(curve25519_public_key_t *key_out,
|
|
curve25519_public_key_generate(curve25519_public_key_t *key_out,
|
|
const curve25519_secret_key_t *seckey)
|
|
const curve25519_secret_key_t *seckey)
|
|
@@ -149,6 +178,11 @@ curve25519_public_key_generate(curve25519_public_key_t *key_out,
|
|
curve25519_basepoint_impl(key_out->public_key, seckey->secret_key);
|
|
curve25519_basepoint_impl(key_out->public_key, seckey->secret_key);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Construct a new keypair in *<b>keypair_out</b>. If <b>extra_strong</b>
|
|
|
|
+ * is true, this key is possibly going to get used more than once, so
|
|
|
|
+ * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
|
|
|
|
+ */
|
|
int
|
|
int
|
|
curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
|
|
curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
|
|
int extra_strong)
|
|
int extra_strong)
|
|
@@ -159,7 +193,13 @@ curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* DOCDOC */
|
|
|
|
|
|
+/** Store the keypair <b>keypair</b>, including its secret and public
|
|
|
|
+ * parts, to the file <b>fname</b>. Use the string tag <b>tag</b> to
|
|
|
|
+ * distinguish this from other Curve25519 keypairs. Return 0 on success,
|
|
|
|
+ * -1 on failure.
|
|
|
|
+ *
|
|
|
|
+ * See crypto_write_tagged_contents_to_file() for more information on
|
|
|
|
+ * the metaformat used for these keys.*/
|
|
int
|
|
int
|
|
curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
|
|
curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
|
|
const char *fname,
|
|
const char *fname,
|
|
@@ -182,7 +222,10 @@ curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-/* DOCDOC */
|
|
|
|
|
|
+/** Read a curve25519 keypair from a file named <b>fname</b> created by
|
|
|
|
+ * curve25519_keypair_write_to_file(). Store the keypair in
|
|
|
|
+ * <b>keypair_out</b>, and the associated tag string in <b>tag_out</b>.
|
|
|
|
+ * Return 0 on success, and -1 on failure. */
|
|
int
|
|
int
|
|
curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
|
|
curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
|
|
char **tag_out,
|
|
char **tag_out,
|
|
@@ -197,6 +240,7 @@ curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
|
|
if (len != sizeof(content))
|
|
if (len != sizeof(content))
|
|
goto end;
|
|
goto end;
|
|
|
|
|
|
|
|
+ /* Make sure that the public key matches the secret key */
|
|
memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
|
|
memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
|
|
curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
|
|
curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
|
|
if (tor_memneq(keypair_out->pubkey.public_key,
|
|
if (tor_memneq(keypair_out->pubkey.public_key,
|