mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
add SHA512 support to crypto
This commit is contained in:
parent
6cdd024c94
commit
ff54cc8481
@ -1609,6 +1609,19 @@ crypto_digest256(char *digest, const char *m, size_t len,
|
||||
return (SHA256((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
|
||||
}
|
||||
|
||||
/** Compute a 512-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
|
||||
* using the algorithm <b>algorithm</b>. Write the DIGEST_LEN512-byte result
|
||||
* into <b>digest</b>. Return 0 on success, -1 on failure. */
|
||||
int
|
||||
crypto_digest512(char *digest, const char *m, size_t len,
|
||||
digest_algorithm_t algorithm)
|
||||
{
|
||||
tor_assert(m);
|
||||
tor_assert(digest);
|
||||
tor_assert(algorithm == DIGEST_SHA512);
|
||||
return (SHA512((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
|
||||
}
|
||||
|
||||
/** Set the digests_t in <b>ds_out</b> to contain every digest on the
|
||||
* <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on
|
||||
* success, -1 on failure. */
|
||||
@ -1621,8 +1634,18 @@ crypto_digest_all(digests_t *ds_out, const char *m, size_t len)
|
||||
if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0)
|
||||
return -1;
|
||||
for (i = DIGEST_SHA256; i < N_DIGEST_ALGORITHMS; ++i) {
|
||||
if (crypto_digest256(ds_out->d[i], m, len, i) < 0)
|
||||
return -1;
|
||||
switch (i) {
|
||||
case DIGEST_SHA256:
|
||||
if (crypto_digest256(ds_out->d[i], m, len, i) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case DIGEST_SHA512:
|
||||
if (crypto_digest512(ds_out->d[i], m, len, i) < 0)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1636,6 +1659,8 @@ crypto_digest_algorithm_get_name(digest_algorithm_t alg)
|
||||
return "sha1";
|
||||
case DIGEST_SHA256:
|
||||
return "sha256";
|
||||
case DIGEST_SHA512:
|
||||
return "sha512";
|
||||
default:
|
||||
tor_fragile_assert();
|
||||
return "??unknown_digest??";
|
||||
@ -1651,6 +1676,8 @@ crypto_digest_algorithm_parse_name(const char *name)
|
||||
return DIGEST_SHA1;
|
||||
else if (!strcmp(name, "sha256"))
|
||||
return DIGEST_SHA256;
|
||||
else if (!strcmp(name, "sha512"))
|
||||
return DIGEST_SHA512;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
@ -1660,6 +1687,7 @@ struct crypto_digest_t {
|
||||
union {
|
||||
SHA_CTX sha1; /**< state for SHA1 */
|
||||
SHA256_CTX sha2; /**< state for SHA256 */
|
||||
SHA512_CTX sha512; /**< state for SHA512 */
|
||||
} d; /**< State for the digest we're using. Only one member of the
|
||||
* union is usable, depending on the value of <b>algorithm</b>. */
|
||||
digest_algorithm_bitfield_t algorithm : 8; /**< Which algorithm is in use? */
|
||||
@ -1690,6 +1718,19 @@ crypto_digest256_new(digest_algorithm_t algorithm)
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Allocate and return a new digest object to compute 512-bit digests
|
||||
* using <b>algorithm</b>. */
|
||||
crypto_digest_t *
|
||||
crypto_digest512_new(digest_algorithm_t algorithm)
|
||||
{
|
||||
crypto_digest_t *r;
|
||||
tor_assert(algorithm == DIGEST_SHA512);
|
||||
r = tor_malloc(sizeof(crypto_digest_t));
|
||||
SHA512_Init(&r->d.sha512);
|
||||
r->algorithm = algorithm;
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Deallocate a digest object.
|
||||
*/
|
||||
void
|
||||
@ -1721,6 +1762,9 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
|
||||
case DIGEST_SHA256:
|
||||
SHA256_Update(&digest->d.sha2, (void*)data, len);
|
||||
break;
|
||||
case DIGEST_SHA512:
|
||||
SHA512_Update(&digest->d.sha512, (void*)data, len);
|
||||
break;
|
||||
default:
|
||||
tor_fragile_assert();
|
||||
break;
|
||||
@ -1729,13 +1773,13 @@ crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
|
||||
|
||||
/** Compute the hash of the data that has been passed to the digest
|
||||
* object; write the first out_len bytes of the result to <b>out</b>.
|
||||
* <b>out_len</b> must be \<= DIGEST256_LEN.
|
||||
* <b>out_len</b> must be \<= DIGEST512_LEN.
|
||||
*/
|
||||
void
|
||||
crypto_digest_get_digest(crypto_digest_t *digest,
|
||||
char *out, size_t out_len)
|
||||
{
|
||||
unsigned char r[DIGEST256_LEN];
|
||||
unsigned char r[DIGEST512_LEN];
|
||||
crypto_digest_t tmpenv;
|
||||
tor_assert(digest);
|
||||
tor_assert(out);
|
||||
@ -1750,6 +1794,10 @@ crypto_digest_get_digest(crypto_digest_t *digest,
|
||||
tor_assert(out_len <= DIGEST256_LEN);
|
||||
SHA256_Final(r, &tmpenv.d.sha2);
|
||||
break;
|
||||
case DIGEST_SHA512:
|
||||
tor_assert(out_len <= DIGEST512_LEN);
|
||||
SHA512_Final(r, &tmpenv.d.sha512);
|
||||
break;
|
||||
default:
|
||||
log_warn(LD_BUG, "Called with unknown algorithm %d", digest->algorithm);
|
||||
/* If fragile_assert is not enabled, then we should at least not
|
||||
@ -1791,7 +1839,7 @@ crypto_digest_assign(crypto_digest_t *into,
|
||||
* at <b>digest_out</b> to the hash of the concatenation of those strings,
|
||||
* plus the optional string <b>append</b>, computed with the algorithm
|
||||
* <b>alg</b>.
|
||||
* <b>out_len</b> must be \<= DIGEST256_LEN. */
|
||||
* <b>out_len</b> must be \<= DIGEST512_LEN. */
|
||||
void
|
||||
crypto_digest_smartlist(char *digest_out, size_t len_out,
|
||||
const smartlist_t *lst,
|
||||
@ -1806,7 +1854,7 @@ crypto_digest_smartlist(char *digest_out, size_t len_out,
|
||||
* 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. */
|
||||
* <b>out_len</b> must be \<= DIGEST512_LEN. */
|
||||
void
|
||||
crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
|
||||
const char *prepend,
|
||||
@ -1815,10 +1863,13 @@ crypto_digest_smartlist_prefix(char *digest_out, size_t len_out,
|
||||
digest_algorithm_t alg)
|
||||
{
|
||||
crypto_digest_t *d;
|
||||
if (alg == DIGEST_SHA1)
|
||||
if (alg == DIGEST_SHA1) {
|
||||
d = crypto_digest_new();
|
||||
else
|
||||
} else if (alg == DIGEST_SHA512) {
|
||||
d = crypto_digest512_new(alg);
|
||||
} else {
|
||||
d = crypto_digest256_new(alg);
|
||||
}
|
||||
if (prepend)
|
||||
crypto_digest_add_bytes(d, prepend, strlen(prepend));
|
||||
SMARTLIST_FOREACH(lst, const char *, cp,
|
||||
|
@ -54,6 +54,8 @@
|
||||
/** Length of the output of our second (improved) message digests. (For now
|
||||
* this is just sha256, but it could be any other 256-bit digest.) */
|
||||
#define DIGEST256_LEN 32
|
||||
/** Length of the output of our 64-bit optimized message digests (SHA512). */
|
||||
#define DIGEST512_LEN 64
|
||||
/** Length of our symmetric cipher's keys. */
|
||||
#define CIPHER_KEY_LEN 16
|
||||
/** Length of our symmetric cipher's IV. */
|
||||
@ -69,6 +71,9 @@
|
||||
/** Length of a sha256 message digest when encoded in base64 with trailing =
|
||||
* signs removed. */
|
||||
#define BASE64_DIGEST256_LEN 43
|
||||
/** Length of a sha512 message digest when encoded in base64 with trailing =
|
||||
* signs removed. */
|
||||
#define BASE64_DIGEST512_LEN 86
|
||||
|
||||
/** Constant used to indicate OAEP padding for public-key encryption */
|
||||
#define PK_PKCS1_OAEP_PADDING 60002
|
||||
@ -83,24 +88,27 @@
|
||||
#define HEX_DIGEST_LEN 40
|
||||
/** Length of hex encoding of SHA256 digest, not including final NUL. */
|
||||
#define HEX_DIGEST256_LEN 64
|
||||
/** Length of hex encoding of SHA512 digest, not including final NUL. */
|
||||
#define HEX_DIGEST512_LEN 128
|
||||
|
||||
typedef enum {
|
||||
DIGEST_SHA1 = 0,
|
||||
DIGEST_SHA256 = 1,
|
||||
DIGEST_SHA512 = 2,
|
||||
} digest_algorithm_t;
|
||||
#define N_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
|
||||
#define N_DIGEST_ALGORITHMS (DIGEST_SHA512+1)
|
||||
#define digest_algorithm_bitfield_t ENUM_BF(digest_algorithm_t)
|
||||
|
||||
/** A set of all the digests we know how to compute, taken on a single
|
||||
* string. Any digests that are shorter than 256 bits are right-padded
|
||||
* string. Any digests that are shorter than 512 bits are right-padded
|
||||
* with 0 bits.
|
||||
*
|
||||
* Note that this representation wastes 12 bytes for the SHA1 case, so
|
||||
* Note that this representation wastes 44 bytes for the SHA1 case, so
|
||||
* don't use it for anything where we need to allocate a whole bunch at
|
||||
* once.
|
||||
**/
|
||||
typedef struct {
|
||||
char d[N_DIGEST_ALGORITHMS][DIGEST256_LEN];
|
||||
char d[N_DIGEST_ALGORITHMS][DIGEST512_LEN];
|
||||
} digests_t;
|
||||
|
||||
typedef struct crypto_pk_t crypto_pk_t;
|
||||
@ -207,6 +215,8 @@ int crypto_cipher_decrypt_with_iv(const char *key,
|
||||
int crypto_digest(char *digest, const char *m, size_t len);
|
||||
int crypto_digest256(char *digest, const char *m, size_t len,
|
||||
digest_algorithm_t algorithm);
|
||||
int crypto_digest512(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,
|
||||
@ -221,6 +231,7 @@ const char *crypto_digest_algorithm_get_name(digest_algorithm_t alg);
|
||||
int crypto_digest_algorithm_parse_name(const char *name);
|
||||
crypto_digest_t *crypto_digest_new(void);
|
||||
crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
|
||||
crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
|
||||
void crypto_digest_free(crypto_digest_t *digest);
|
||||
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
|
||||
size_t len);
|
||||
|
@ -302,6 +302,13 @@ test_crypto_sha(void *arg)
|
||||
"96177A9CB410FF61F20015AD");
|
||||
tt_int_op(i, OP_EQ, 0);
|
||||
|
||||
/* Test SHA-512 with a test vector from the specification. */
|
||||
i = crypto_digest512(data, "abc", 3, DIGEST_SHA512);
|
||||
test_memeq_hex(data, "ddaf35a193617abacc417349ae20413112e6fa4e89a97"
|
||||
"ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3"
|
||||
"feebbd454d4423643ce80e2a9ac94fa54ca49f");
|
||||
tt_int_op(i, OP_EQ, 0);
|
||||
|
||||
/* Test HMAC-SHA256 with test cases from wikipedia and RFC 4231 */
|
||||
|
||||
/* Case empty (wikipedia) */
|
||||
@ -410,6 +417,27 @@ test_crypto_sha(void *arg)
|
||||
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
|
||||
crypto_digest256(d_out2, "abcdef", 6, DIGEST_SHA256);
|
||||
tt_mem_op(d_out1,OP_EQ, d_out2, DIGEST_LEN);
|
||||
crypto_digest_free(d1);
|
||||
crypto_digest_free(d2);
|
||||
|
||||
/* Incremental digest code with sha512 */
|
||||
d1 = crypto_digest512_new(DIGEST_SHA512);
|
||||
tt_assert(d1);
|
||||
crypto_digest_add_bytes(d1, "abcdef", 6);
|
||||
d2 = crypto_digest_dup(d1);
|
||||
tt_assert(d2);
|
||||
crypto_digest_add_bytes(d2, "ghijkl", 6);
|
||||
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
|
||||
crypto_digest512(d_out2, "abcdefghijkl", 12, DIGEST_SHA512);
|
||||
tt_mem_op(d_out1,OP_EQ, d_out2, DIGEST_LEN);
|
||||
crypto_digest_assign(d2, d1);
|
||||
crypto_digest_add_bytes(d2, "mno", 3);
|
||||
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
|
||||
crypto_digest512(d_out2, "abcdefmno", 9, DIGEST_SHA512);
|
||||
tt_mem_op(d_out1,OP_EQ, d_out2, DIGEST_LEN);
|
||||
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
|
||||
crypto_digest512(d_out2, "abcdef", 6, DIGEST_SHA512);
|
||||
tt_mem_op(d_out1,OP_EQ, d_out2, DIGEST_LEN);
|
||||
|
||||
done:
|
||||
if (d1)
|
||||
|
Loading…
Reference in New Issue
Block a user