Skip to content

Commit 6cde8e7

Browse files
SHA512 support (#223)
1 parent cdd052b commit 6cde8e7

File tree

9 files changed

+509
-45
lines changed

9 files changed

+509
-45
lines changed

include/aws/cal/hash.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
AWS_PUSH_SANE_WARNING_LEVEL
1313

14+
#define AWS_SHA512_LEN 64
1415
#define AWS_SHA256_LEN 32
1516
#define AWS_SHA1_LEN 20
1617
#define AWS_MD5_LEN 16
@@ -36,6 +37,11 @@ struct aws_hash {
3637
typedef struct aws_hash *(aws_hash_new_fn)(struct aws_allocator *allocator);
3738

3839
AWS_EXTERN_C_BEGIN
40+
/**
41+
* Allocates and initializes a sha256 hash instance.
42+
*/
43+
AWS_CAL_API struct aws_hash *aws_sha512_new(struct aws_allocator *allocator);
44+
3945
/**
4046
* Allocates and initializes a sha256 hash instance.
4147
*/
@@ -78,6 +84,20 @@ AWS_CAL_API int aws_md5_compute(
7884
struct aws_byte_buf *output,
7985
size_t truncate_to);
8086

87+
/**
88+
* Computes the sha512 hash over input and writes the digest output to 'output'.
89+
* Use this if you don't need to stream the data you're hashing and you can load
90+
* the entire input to hash into memory. If you specify truncate_to to something
91+
* other than 0, the output will be truncated to that number of bytes. For
92+
* example, if you want a SHA512 digest as the first 16 bytes, set truncate_to
93+
* to 16. If you want the full digest size, just set this to 0.
94+
*/
95+
AWS_CAL_API int aws_sha512_compute(
96+
struct aws_allocator *allocator,
97+
const struct aws_byte_cursor *input,
98+
struct aws_byte_buf *output,
99+
size_t truncate_to);
100+
81101
/**
82102
* Computes the sha256 hash over input and writes the digest output to 'output'.
83103
* Use this if you don't need to stream the data you're hashing and you can load
@@ -115,6 +135,15 @@ AWS_CAL_API int aws_sha1_compute(
115135
*/
116136
AWS_CAL_API void aws_set_md5_new_fn(aws_hash_new_fn *fn);
117137

138+
/**
139+
* Set the implementation of sha512 to use. If you compiled without
140+
* BYO_CRYPTO, you do not need to call this. However, if use this, we will
141+
* honor it, regardless of compile options. This may be useful for testing
142+
* purposes. If you did set BYO_CRYPTO, and you do not call this function
143+
* you will segfault.
144+
*/
145+
AWS_CAL_API void aws_set_sha512_new_fn(aws_hash_new_fn *fn);
146+
118147
/**
119148
* Set the implementation of sha256 to use. If you compiled without
120149
* BYO_CRYPTO, you do not need to call this. However, if use this, we will

source/darwin/commoncrypto_sha1.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ struct cc_sha1_hash {
2727
struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator) {
2828
struct cc_sha1_hash *sha1_hash = aws_mem_acquire(allocator, sizeof(struct cc_sha1_hash));
2929

30-
if (!sha1_hash) {
31-
return NULL;
32-
}
33-
3430
sha1_hash->hash.allocator = allocator;
3531
sha1_hash->hash.vtable = &s_vtable;
3632
sha1_hash->hash.impl = sha1_hash;

source/darwin/commoncrypto_sha256.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ struct cc_sha256_hash {
2626
struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) {
2727
struct cc_sha256_hash *sha256_hash = aws_mem_acquire(allocator, sizeof(struct cc_sha256_hash));
2828

29-
if (!sha256_hash) {
30-
return NULL;
31-
}
32-
3329
sha256_hash->hash.allocator = allocator;
3430
sha256_hash->hash.vtable = &s_vtable;
3531
sha256_hash->hash.impl = sha256_hash;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#include <aws/cal/hash.h>
6+
7+
#include <CommonCrypto/CommonDigest.h>
8+
9+
static void s_destroy(struct aws_hash *hash);
10+
static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash);
11+
static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output);
12+
13+
static struct aws_hash_vtable s_vtable = {
14+
.destroy = s_destroy,
15+
.update = s_update,
16+
.finalize = s_finalize,
17+
.alg_name = "SHA512",
18+
.provider = "CommonCrypto",
19+
};
20+
21+
struct cc_sha512_hash {
22+
struct aws_hash hash;
23+
CC_SHA512_CTX cc_hash;
24+
};
25+
26+
struct aws_hash *aws_sha512_default_new(struct aws_allocator *allocator) {
27+
struct cc_sha512_hash *sha512_hash = aws_mem_acquire(allocator, sizeof(struct cc_sha512_hash));
28+
29+
sha512_hash->hash.allocator = allocator;
30+
sha512_hash->hash.vtable = &s_vtable;
31+
sha512_hash->hash.impl = sha512_hash;
32+
sha512_hash->hash.digest_size = AWS_SHA512_LEN;
33+
sha512_hash->hash.good = true;
34+
35+
CC_SHA512_Init(&sha512_hash->cc_hash);
36+
return &sha512_hash->hash;
37+
}
38+
39+
static void s_destroy(struct aws_hash *hash) {
40+
struct cc_sha512_hash *ctx = hash->impl;
41+
aws_mem_release(hash->allocator, ctx);
42+
}
43+
44+
static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) {
45+
if (!hash->good) {
46+
return aws_raise_error(AWS_ERROR_INVALID_STATE);
47+
}
48+
49+
struct cc_sha512_hash *ctx = hash->impl;
50+
51+
CC_SHA512_Update(&ctx->cc_hash, to_hash->ptr, (CC_LONG)to_hash->len);
52+
return AWS_OP_SUCCESS;
53+
}
54+
55+
static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) {
56+
if (!hash->good) {
57+
return aws_raise_error(AWS_ERROR_INVALID_STATE);
58+
}
59+
60+
struct cc_sha512_hash *ctx = hash->impl;
61+
62+
size_t buffer_len = output->capacity - output->len;
63+
64+
if (buffer_len < hash->digest_size) {
65+
return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
66+
}
67+
68+
CC_SHA512_Final(output->buffer + output->len, &ctx->cc_hash);
69+
hash->good = false;
70+
output->len += hash->digest_size;
71+
return AWS_OP_SUCCESS;
72+
}

source/hash.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
#include <aws/cal/hash.h>
66

77
#ifndef BYO_CRYPTO
8+
extern struct aws_hash *aws_sha512_default_new(struct aws_allocator *allocator);
89
extern struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator);
910
extern struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator);
1011
extern struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator);
1112

13+
static aws_hash_new_fn *s_sha512_new_fn = aws_sha512_default_new;
1214
static aws_hash_new_fn *s_sha256_new_fn = aws_sha256_default_new;
1315
static aws_hash_new_fn *s_sha1_new_fn = aws_sha1_default_new;
1416
static aws_hash_new_fn *s_md5_new_fn = aws_md5_default_new;
@@ -18,6 +20,7 @@ static struct aws_hash *aws_hash_new_abort(struct aws_allocator *allocator) {
1820
abort();
1921
}
2022

23+
static aws_hash_new_fn *s_sha512_new_fn = aws_hash_new_abort;
2124
static aws_hash_new_fn *s_sha256_new_fn = aws_hash_new_abort;
2225
static aws_hash_new_fn *s_sha1_new_fn = aws_hash_new_abort;
2326
static aws_hash_new_fn *s_md5_new_fn = aws_hash_new_abort;
@@ -27,6 +30,10 @@ struct aws_hash *aws_sha1_new(struct aws_allocator *allocator) {
2730
return s_sha1_new_fn(allocator);
2831
}
2932

33+
struct aws_hash *aws_sha512_new(struct aws_allocator *allocator) {
34+
return s_sha512_new_fn(allocator);
35+
}
36+
3037
struct aws_hash *aws_sha256_new(struct aws_allocator *allocator) {
3138
return s_sha256_new_fn(allocator);
3239
}
@@ -39,6 +46,10 @@ void aws_set_md5_new_fn(aws_hash_new_fn *fn) {
3946
s_md5_new_fn = fn;
4047
}
4148

49+
void aws_set_sha512_new_fn(aws_hash_new_fn *fn) {
50+
s_sha512_new_fn = fn;
51+
}
52+
4253
void aws_set_sha256_new_fn(aws_hash_new_fn *fn) {
4354
s_sha256_new_fn = fn;
4455
}
@@ -112,6 +123,14 @@ int aws_md5_compute(
112123
return compute_hash(aws_md5_new(allocator), input, output, truncate_to);
113124
}
114125

126+
int aws_sha512_compute(
127+
struct aws_allocator *allocator,
128+
const struct aws_byte_cursor *input,
129+
struct aws_byte_buf *output,
130+
size_t truncate_to) {
131+
return compute_hash(aws_sha512_new(allocator), input, output, truncate_to);
132+
}
133+
115134
int aws_sha256_compute(
116135
struct aws_allocator *allocator,
117136
const struct aws_byte_cursor *input,

source/unix/opensslcrypto_hash.c

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ static struct aws_hash_vtable s_md5_vtable = {
2020
.provider = "OpenSSL Compatible libcrypto",
2121
};
2222

23+
static struct aws_hash_vtable s_sha512_vtable = {
24+
.destroy = s_destroy,
25+
.update = s_update,
26+
.finalize = s_finalize,
27+
.alg_name = "SHA512",
28+
.provider = "OpenSSL Compatible libcrypto",
29+
};
30+
2331
static struct aws_hash_vtable s_sha256_vtable = {
2432
.destroy = s_destroy,
2533
.update = s_update,
@@ -52,22 +60,14 @@ static void s_destroy(struct aws_hash *hash) {
5260
struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) {
5361
struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash));
5462

55-
if (!hash) {
56-
return NULL;
57-
}
58-
5963
hash->allocator = allocator;
6064
hash->vtable = &s_md5_vtable;
6165
hash->digest_size = AWS_MD5_LEN;
6266
EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn();
6367
hash->impl = ctx;
6468
hash->good = true;
6569

66-
if (!hash->impl) {
67-
s_destroy(hash);
68-
aws_raise_error(AWS_ERROR_OOM);
69-
return NULL;
70-
}
70+
AWS_FATAL_ASSERT(hash->impl);
7171

7272
if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_md5(), NULL)) {
7373
s_destroy(hash);
@@ -78,25 +78,38 @@ struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) {
7878
return hash;
7979
}
8080

81-
struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) {
81+
struct aws_hash *aws_sha512_default_new(struct aws_allocator *allocator) {
8282
struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash));
8383

84-
if (!hash) {
84+
hash->allocator = allocator;
85+
hash->vtable = &s_sha512_vtable;
86+
hash->digest_size = AWS_SHA512_LEN;
87+
EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn();
88+
hash->impl = ctx;
89+
hash->good = true;
90+
91+
AWS_FATAL_ASSERT(hash->impl);
92+
93+
if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha512(), NULL)) {
94+
s_destroy(hash);
95+
aws_raise_error(AWS_ERROR_UNKNOWN);
8596
return NULL;
8697
}
8798

99+
return hash;
100+
}
101+
102+
struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) {
103+
struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash));
104+
88105
hash->allocator = allocator;
89106
hash->vtable = &s_sha256_vtable;
90107
hash->digest_size = AWS_SHA256_LEN;
91108
EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn();
92109
hash->impl = ctx;
93110
hash->good = true;
94111

95-
if (!hash->impl) {
96-
s_destroy(hash);
97-
aws_raise_error(AWS_ERROR_OOM);
98-
return NULL;
99-
}
112+
AWS_FATAL_ASSERT(hash->impl);
100113

101114
if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha256(), NULL)) {
102115
s_destroy(hash);
@@ -110,22 +123,14 @@ struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) {
110123
struct aws_hash *aws_sha1_default_new(struct aws_allocator *allocator) {
111124
struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash));
112125

113-
if (!hash) {
114-
return NULL;
115-
}
116-
117126
hash->allocator = allocator;
118127
hash->vtable = &s_sha1_vtable;
119128
hash->digest_size = AWS_SHA1_LEN;
120129
EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn();
121130
hash->impl = ctx;
122131
hash->good = true;
123132

124-
if (!hash->impl) {
125-
s_destroy(hash);
126-
aws_raise_error(AWS_ERROR_OOM);
127-
return NULL;
128-
}
133+
AWS_FATAL_ASSERT(hash->impl);
129134

130135
if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha1(), NULL)) {
131136
s_destroy(hash);

0 commit comments

Comments
 (0)