Commit fe5d2477 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Implement ed25519-signed descriptors

Now that we have ed25519 keys, we can sign descriptors with them
and check those signatures as documented in proposal 220.
parent 818e6f93
Loading
Loading
Loading
Loading
+81 −1
Original line number Diff line number Diff line
@@ -1724,7 +1724,24 @@ crypto_digest_assign(crypto_digest_t *into,
 * <b>out_len</b> must be \<= DIGEST256_LEN. */
void
crypto_digest_smartlist(char *digest_out, size_t len_out,
                        const smartlist_t *lst, const char *append,
                        const smartlist_t *lst,
                        const char *append,
                        digest_algorithm_t alg)
{
  crypto_digest_smartlist_prefix(digest_out, len_out, NULL, lst, append, alg);
}

/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
 * at <b>digest_out</b> to the hash of the concatenation of: the
 * optional string <b>prepend</b>, those strings,
 * and the optional string <b>append</b>, computed with the algorithm
 * <b>alg</b>.
 * <b>out_len</b> must be \<= DIGEST256_LEN. */
void
crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
                        const char *prepend,
                        const smartlist_t *lst,
                        const char *append,
                        digest_algorithm_t alg)
{
  crypto_digest_t *d;
@@ -1732,6 +1749,8 @@ crypto_digest_smartlist(char *digest_out, size_t len_out,
    d = crypto_digest_new();
  else
    d = crypto_digest256_new(alg);
  if (prepend)
    crypto_digest_add_bytes(d, prepend, strlen(prepend));
  SMARTLIST_FOREACH(lst, const char *, cp,
                    crypto_digest_add_bytes(d, cp, strlen(cp)));
  if (append)
@@ -2692,6 +2711,8 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen)
    return -1;
  if (destlen > SIZE_T_CEILING)
    return -1;
  if (destlen)
    *dest = 0; /* Ensure we always initialize the buffer */

  EVP_EncodeInit(&ctx);
  EVP_EncodeUpdate(&ctx, (unsigned char*)dest, &len,
@@ -2701,6 +2722,65 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen)
  return ret;
}

/** As base64_encode, but do not add any internal spaces or external padding
 * to the output stream. */
int
base64_encode_nopad(char *dest, size_t destlen,
                    const uint8_t *src, size_t srclen)
{
  int n = base64_encode(dest, destlen, (const char*) src, srclen);
  if (n <= 0)
    return n;
  tor_assert((size_t)n < destlen && dest[n] == 0);
  char *in, *out;
  in = out = dest;
  while (*in) {
    if (*in == '=' || *in == '\n') {
      ++in;
    } else {
      *out++ = *in++;
    }
  }
  *out = 0;

  tor_assert(out - dest <= INT_MAX);

  return (int)(out - dest);
}

/** As base64_decode, but do not require any padding on the input */
int
base64_decode_nopad(uint8_t *dest, size_t destlen,
                    const char *src, size_t srclen)
{
  if (srclen > SIZE_T_CEILING - 4)
    return -1;
  char *buf = tor_malloc(srclen + 4);
  memcpy(buf, src, srclen+1);
  size_t buflen;
  switch (srclen % 4)
    {
    case 0:
    default:
      buflen = srclen;
      break;
    case 1:
      tor_free(buf);
      return -1;
    case 2:
      memcpy(buf+srclen, "==", 3);
      buflen = srclen + 2;
      break;
    case 3:
      memcpy(buf+srclen, "=", 2);
      buflen = srclen + 1;
      break;
  }
  int n = base64_decode((char*)dest, destlen, buf, buflen);
  tor_free(buf);
  return n;
}

/** @{ */
/** Special values used for the base64_decode_table */
#define X 255
+10 −0
Original line number Diff line number Diff line
@@ -207,6 +207,11 @@ int crypto_digest256(char *digest, const char *m, size_t len,
                     digest_algorithm_t algorithm);
int crypto_digest_all(digests_t *ds_out, const char *m, size_t len);
struct smartlist_t;
void crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
                                    const char *prepend,
                                    const struct smartlist_t *lst,
                                    const char *append,
                                    digest_algorithm_t alg);
void crypto_digest_smartlist(char *digest_out, size_t len_out,
                             const struct smartlist_t *lst, const char *append,
                             digest_algorithm_t alg);
@@ -270,6 +275,11 @@ void smartlist_shuffle(struct smartlist_t *sl);

int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen);
int base64_encode_nopad(char *dest, size_t destlen,
                        const uint8_t *src, size_t srclen);
int base64_decode_nopad(uint8_t *dest, size_t destlen,
                        const char *src, size_t srclen);

/** Characters that can appear (case-insensitively) in a base32 encoding. */
#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
+11 −0
Original line number Diff line number Diff line
@@ -351,6 +351,7 @@ ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
  return 0;
}

/** Release all storage held for <b>kp</b>. */
void
ed25519_keypair_free(ed25519_keypair_t *kp)
{
@@ -361,3 +362,13 @@ ed25519_keypair_free(ed25519_keypair_t *kp)
  tor_free(kp);
}

/** Return true iff <b>key1</b> and <b>key2</b> are the same public key. */
int
ed25519_pubkey_eq(const ed25519_public_key_t *key1,
                  const ed25519_public_key_t *key2)
{
  tor_assert(key1);
  tor_assert(key2);
  return tor_memeq(key1->pubkey, key2->pubkey, ED25519_PUBKEY_LEN);
}
+10 −0
Original line number Diff line number Diff line
@@ -95,6 +95,13 @@ int ed25519_public_from_base64(ed25519_public_key_t *pkey,
int ed25519_public_to_base64(char *output,
                             const ed25519_public_key_t *pkey);

#define ED25519_SIG_BASE64_LEN 86

int ed25519_signature_from_base64(ed25519_signature_t *sig,
                                  const char *input);
int ed25519_signature_to_base64(char *output,
                                const ed25519_signature_t *sig);

/* XXXX read encrypted, write encrypted. */

int ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
@@ -112,5 +119,8 @@ int ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,

void ed25519_keypair_free(ed25519_keypair_t *kp);

int ed25519_pubkey_eq(const ed25519_public_key_t *key1,
                      const ed25519_public_key_t *key2);

#endif
+39 −0
Original line number Diff line number Diff line
@@ -65,3 +65,42 @@ ed25519_public_to_base64(char *output,
  return digest256_to_base64(output, (const char *)pkey->pubkey);
}

/** Encode the signature <b>sig</b> into the buffer at <b>output</b>,
 * which must have space for ED25519_SIG_BASE64_LEN bytes of encoded signature,
 * plus one byte for a terminating NUL.  Return 0 on success, -1 on failure.
 */
int
ed25519_signature_to_base64(char *output,
                            const ed25519_signature_t *sig)
{
  char buf[256];
  int n = base64_encode_nopad(buf, sizeof(buf), sig->sig, ED25519_SIG_LEN);
  tor_assert(n == ED25519_SIG_BASE64_LEN);
  memcpy(output, buf, ED25519_SIG_BASE64_LEN+1);
  return 0;
}

/** Try to decode the string <b>input</b> into an ed25519 signature. On
 * success, store the value in <b>sig</b> and return 0. Otherwise return
 * -1. */
int
ed25519_signature_from_base64(ed25519_signature_t *sig,
                              const char *input)
{

  if (strlen(input) != ED25519_SIG_BASE64_LEN)
    return -1;
  char buf[ED25519_SIG_BASE64_LEN+3];
  memcpy(buf, input, ED25519_SIG_BASE64_LEN);
  buf[ED25519_SIG_BASE64_LEN+0] = '=';
  buf[ED25519_SIG_BASE64_LEN+1] = '=';
  buf[ED25519_SIG_BASE64_LEN+2] = 0;
  char decoded[128];
  int n = base64_decode(decoded, sizeof(decoded), buf, strlen(buf));
  if (n < 0 || n != ED25519_SIG_LEN)
    return -1;
  memcpy(sig->sig, decoded, ED25519_SIG_LEN);

  return 0;
}
Loading