diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/crypto.c | 82 | ||||
-rw-r--r-- | src/common/crypto.h | 10 | ||||
-rw-r--r-- | src/common/crypto_ed25519.c | 11 | ||||
-rw-r--r-- | src/common/crypto_ed25519.h | 10 | ||||
-rw-r--r-- | src/common/crypto_format.c | 39 |
5 files changed, 151 insertions, 1 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index 218c7bea1e..06631e1604 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -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 diff --git a/src/common/crypto.h b/src/common/crypto.h index d305bc17a0..526619766d 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -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); diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c index 7e8b00abef..6b93751dda 100644 --- a/src/common/crypto_ed25519.c +++ b/src/common/crypto_ed25519.c @@ -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); +} + diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h index 8e06191fc5..79b3db8f9a 100644 --- a/src/common/crypto_ed25519.h +++ b/src/common/crypto_ed25519.h @@ -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 diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c index 00e0e9ea85..503d1de932 100644 --- a/src/common/crypto_format.c +++ b/src/common/crypto_format.c @@ -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; +} + |