mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 10:12:15 +01:00
Add basic support for SHA256.
This adds an openssl 0.9.8 dependency. Let's see if anybody cares.
This commit is contained in:
parent
b9e45cc508
commit
f57883a39e
@ -1394,9 +1394,23 @@ crypto_digest(char *digest, const char *m, size_t len)
|
|||||||
return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
|
return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_digest256(char *digest, const char *m, size_t len,
|
||||||
|
digest_algorithm_t algorithm)
|
||||||
|
{
|
||||||
|
tor_assert(m);
|
||||||
|
tor_assert(digest);
|
||||||
|
tor_assert(algorithm == DIGEST_SHA256);
|
||||||
|
return (SHA256((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/** Intermediate information about the digest of a stream of data. */
|
/** Intermediate information about the digest of a stream of data. */
|
||||||
struct crypto_digest_env_t {
|
struct crypto_digest_env_t {
|
||||||
SHA_CTX d;
|
union {
|
||||||
|
SHA_CTX sha1;
|
||||||
|
SHA256_CTX sha2;
|
||||||
|
} d;
|
||||||
|
digest_algorithm_t algorithm : 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Allocate and return a new digest object.
|
/** Allocate and return a new digest object.
|
||||||
@ -1406,7 +1420,19 @@ crypto_new_digest_env(void)
|
|||||||
{
|
{
|
||||||
crypto_digest_env_t *r;
|
crypto_digest_env_t *r;
|
||||||
r = tor_malloc(sizeof(crypto_digest_env_t));
|
r = tor_malloc(sizeof(crypto_digest_env_t));
|
||||||
SHA1_Init(&r->d);
|
SHA1_Init(&r->d.sha1);
|
||||||
|
r->algorithm = DIGEST_SHA1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_digest_env_t *
|
||||||
|
crypto_new_digest256_env(digest_algorithm_t algorithm)
|
||||||
|
{
|
||||||
|
crypto_digest_env_t *r;
|
||||||
|
tor_assert(algorithm == DIGEST_SHA256);
|
||||||
|
r = tor_malloc(sizeof(crypto_digest_env_t));
|
||||||
|
SHA256_Init(&r->d.sha2);
|
||||||
|
r->algorithm = algorithm;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1427,30 +1453,51 @@ crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data,
|
|||||||
{
|
{
|
||||||
tor_assert(digest);
|
tor_assert(digest);
|
||||||
tor_assert(data);
|
tor_assert(data);
|
||||||
/* Using the SHA1_*() calls directly means we don't support doing
|
/* Using the SHA*_*() calls directly means we don't support doing
|
||||||
* SHA1 in hardware. But so far the delay of getting the question
|
* SHA in hardware. But so far the delay of getting the question
|
||||||
* to the hardware, and hearing the answer, is likely higher than
|
* to the hardware, and hearing the answer, is likely higher than
|
||||||
* just doing it ourselves. Hashes are fast.
|
* just doing it ourselves. Hashes are fast.
|
||||||
*/
|
*/
|
||||||
SHA1_Update(&digest->d, (void*)data, len);
|
switch (digest->algorithm) {
|
||||||
|
case DIGEST_SHA1:
|
||||||
|
SHA1_Update(&digest->d.sha1, (void*)data, len);
|
||||||
|
break;
|
||||||
|
case DIGEST_SHA256:
|
||||||
|
SHA256_Update(&digest->d.sha2, (void*)data, len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tor_fragile_assert();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute the hash of the data that has been passed to the digest
|
/** 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>.
|
* object; write the first out_len bytes of the result to <b>out</b>.
|
||||||
* <b>out_len</b> must be \<= DIGEST_LEN.
|
* <b>out_len</b> must be \<= DIGEST256_LEN.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
crypto_digest_get_digest(crypto_digest_env_t *digest,
|
crypto_digest_get_digest(crypto_digest_env_t *digest,
|
||||||
char *out, size_t out_len)
|
char *out, size_t out_len)
|
||||||
{
|
{
|
||||||
unsigned char r[DIGEST_LEN];
|
unsigned char r[DIGEST256_LEN];
|
||||||
SHA_CTX tmpctx;
|
crypto_digest_env_t tmpenv;
|
||||||
tor_assert(digest);
|
tor_assert(digest);
|
||||||
tor_assert(out);
|
tor_assert(out);
|
||||||
|
/* memcpy into a temporary ctx, since SHA*_Final clears the context */
|
||||||
|
memcpy(&tmpenv, digest, sizeof(crypto_digest_env_t));
|
||||||
|
switch (digest->algorithm) {
|
||||||
|
case DIGEST_SHA1:
|
||||||
tor_assert(out_len <= DIGEST_LEN);
|
tor_assert(out_len <= DIGEST_LEN);
|
||||||
/* memcpy into a temporary ctx, since SHA1_Final clears the context */
|
SHA1_Final(r, &digest->d.sha1);
|
||||||
memcpy(&tmpctx, &digest->d, sizeof(SHA_CTX));
|
break;
|
||||||
SHA1_Final(r, &tmpctx);
|
case DIGEST_SHA256:
|
||||||
|
tor_assert(out_len <= DIGEST256_LEN);
|
||||||
|
SHA256_Final(r, &digest->d.sha2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tor_fragile_assert();
|
||||||
|
break;
|
||||||
|
}
|
||||||
memcpy(out, r, out_len);
|
memcpy(out, r, out_len);
|
||||||
memset(r, 0, sizeof(r));
|
memset(r, 0, sizeof(r));
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
/** Length of the output of our message digest. */
|
/** Length of the output of our message digest. */
|
||||||
#define DIGEST_LEN 20
|
#define DIGEST_LEN 20
|
||||||
|
/** Length of the output of our second (improved) message digests. (For now
|
||||||
|
* this is just sha256, but any it can be any other 256-byte digest). */
|
||||||
|
#define DIGEST256_LEN 32
|
||||||
/** Length of our symmetric cipher's keys. */
|
/** Length of our symmetric cipher's keys. */
|
||||||
#define CIPHER_KEY_LEN 16
|
#define CIPHER_KEY_LEN 16
|
||||||
/** Length of our symmetric cipher's IV. */
|
/** Length of our symmetric cipher's IV. */
|
||||||
@ -27,9 +30,12 @@
|
|||||||
/** Length of our DH keys. */
|
/** Length of our DH keys. */
|
||||||
#define DH_BYTES (1024/8)
|
#define DH_BYTES (1024/8)
|
||||||
|
|
||||||
/** Length of a message digest when encoded in base64 with trailing = signs
|
/** Length of a sha1 message digest when encoded in base64 with trailing =
|
||||||
* removed. */
|
* signs removed. */
|
||||||
#define BASE64_DIGEST_LEN 27
|
#define BASE64_DIGEST_LEN 27
|
||||||
|
/** Length of a sha256 message digest when encoded in base64 with trailing =
|
||||||
|
* signs removed. */
|
||||||
|
#define BASE64_DIGEST256_LEN 43
|
||||||
|
|
||||||
/** Constants used to indicate no padding for public-key encryption */
|
/** Constants used to indicate no padding for public-key encryption */
|
||||||
#define PK_NO_PADDING 60000
|
#define PK_NO_PADDING 60000
|
||||||
@ -48,6 +54,13 @@
|
|||||||
#define FINGERPRINT_LEN 49
|
#define FINGERPRINT_LEN 49
|
||||||
/** Length of hex encoding of SHA1 digest, not including final NUL. */
|
/** Length of hex encoding of SHA1 digest, not including final NUL. */
|
||||||
#define HEX_DIGEST_LEN 40
|
#define HEX_DIGEST_LEN 40
|
||||||
|
/** Length of hex encoding of SHA256 digest, not including final NUL. */
|
||||||
|
#define HEX_DIGEST256_LEN 64
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DIGEST_SHA1,
|
||||||
|
DIGEST_SHA256,
|
||||||
|
} digest_algorithm_t;
|
||||||
|
|
||||||
typedef struct crypto_pk_env_t crypto_pk_env_t;
|
typedef struct crypto_pk_env_t crypto_pk_env_t;
|
||||||
typedef struct crypto_cipher_env_t crypto_cipher_env_t;
|
typedef struct crypto_cipher_env_t crypto_cipher_env_t;
|
||||||
@ -145,7 +158,10 @@ int crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *env,
|
|||||||
|
|
||||||
/* SHA-1 */
|
/* SHA-1 */
|
||||||
int crypto_digest(char *digest, const char *m, size_t len);
|
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);
|
||||||
crypto_digest_env_t *crypto_new_digest_env(void);
|
crypto_digest_env_t *crypto_new_digest_env(void);
|
||||||
|
crypto_digest_env_t *crypto_new_digest256_env(digest_algorithm_t algorithm);
|
||||||
void crypto_free_digest_env(crypto_digest_env_t *digest);
|
void crypto_free_digest_env(crypto_digest_env_t *digest);
|
||||||
void crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data,
|
void crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
@ -618,14 +618,19 @@ test_crypto_sha(void)
|
|||||||
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
|
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
|
||||||
int i;
|
int i;
|
||||||
char key[80];
|
char key[80];
|
||||||
char digest[20];
|
char digest[32];
|
||||||
char data[50];
|
char data[50];
|
||||||
char d_out1[DIGEST_LEN], d_out2[DIGEST_LEN];
|
char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN];
|
||||||
|
|
||||||
/* Test SHA-1 with a test vector from the specification. */
|
/* Test SHA-1 with a test vector from the specification. */
|
||||||
i = crypto_digest(data, "abc", 3);
|
i = crypto_digest(data, "abc", 3);
|
||||||
test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||||
|
|
||||||
|
/* Test SHA-256 with a test vector from the specification. */
|
||||||
|
i = crypto_digest256(data, "abc", 3, DIGEST_SHA256);
|
||||||
|
test_memeq_hex(data, "BA7816BF8F01CFEA414140DE5DAE2223B00361A3"
|
||||||
|
"96177A9CB410FF61F20015AD");
|
||||||
|
|
||||||
/* Test HMAC-SHA-1 with test cases from RFC2202. */
|
/* Test HMAC-SHA-1 with test cases from RFC2202. */
|
||||||
|
|
||||||
/* Case 1. */
|
/* Case 1. */
|
||||||
@ -646,7 +651,7 @@ test_crypto_sha(void)
|
|||||||
test_streq(hex_str(digest, 20),
|
test_streq(hex_str(digest, 20),
|
||||||
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA");
|
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA");
|
||||||
|
|
||||||
/* Case . */
|
/* Case 5. */
|
||||||
memset(key, 0xaa, 80);
|
memset(key, 0xaa, 80);
|
||||||
crypto_hmac_sha1(digest, key, 80,
|
crypto_hmac_sha1(digest, key, 80,
|
||||||
"Test Using Larger Than Block-Size Key - Hash Key First",
|
"Test Using Larger Than Block-Size Key - Hash Key First",
|
||||||
@ -672,6 +677,27 @@ test_crypto_sha(void)
|
|||||||
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
|
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
|
||||||
crypto_digest(d_out2, "abcdef", 6);
|
crypto_digest(d_out2, "abcdef", 6);
|
||||||
test_memeq(d_out1, d_out2, DIGEST_LEN);
|
test_memeq(d_out1, d_out2, DIGEST_LEN);
|
||||||
|
crypto_free_digest_env(d1);
|
||||||
|
crypto_free_digest_env(d2);
|
||||||
|
|
||||||
|
/* Incremental digest code with sha256 */
|
||||||
|
d1 = crypto_new_digest256_env(DIGEST_SHA256);
|
||||||
|
test_assert(d1);
|
||||||
|
crypto_digest_add_bytes(d1, "abcdef", 6);
|
||||||
|
d2 = crypto_digest_dup(d1);
|
||||||
|
test_assert(d2);
|
||||||
|
crypto_digest_add_bytes(d2, "ghijkl", 6);
|
||||||
|
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
|
||||||
|
crypto_digest256(d_out2, "abcdefghijkl", 12, DIGEST_SHA256);
|
||||||
|
test_memeq(d_out1, 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_digest256(d_out2, "abcdefmno", 9, DIGEST_SHA256);
|
||||||
|
test_memeq(d_out1, d_out2, DIGEST_LEN);
|
||||||
|
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
|
||||||
|
crypto_digest256(d_out2, "abcdef", 6, DIGEST_SHA256);
|
||||||
|
test_memeq(d_out1, d_out2, DIGEST_LEN);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (d1)
|
if (d1)
|
||||||
|
Loading…
Reference in New Issue
Block a user