From 9ba30dbe41d6594043008d3ab3a72167cbd0569c Mon Sep 17 00:00:00 2001 From: Lucas Gabriel Vuotto Date: Mon, 17 Jun 2024 14:41:20 +0000 Subject: [PATCH] hash/sha512: add SHA-512/224 and SHA-512/256 variants --- README | 5 +- hash_sha384_sha512.c | 170 +++++++++++++++++++++++++++++++++++++++++++ lilcrypto.h | 6 ++ wycheproof/Makefile | 4 +- wycheproof_mac.c | 16 ++++ 5 files changed, 197 insertions(+), 4 deletions(-) diff --git a/README b/README index 38feed5..0ffb871 100644 --- a/README +++ b/README @@ -23,7 +23,8 @@ Hash - [x] SHA-224 - [x] SHA-256 - [x] SHA-384 -- [x] SHA-512 (needed for Ed25519) +- [x] SHA-512 +- [x] SHA-512/224 & SHA-512/256 Authentication -------------- @@ -63,8 +64,6 @@ Utilities Hash ---- -- [ ] SHA-512/224 & SHA-512/256 (most of the work done) - Authentication -------------- diff --git a/hash_sha384_sha512.c b/hash_sha384_sha512.c index 6a0bbeb..de64499 100644 --- a/hash_sha384_sha512.c +++ b/hash_sha384_sha512.c @@ -53,6 +53,24 @@ #define SHA512_H0_6 UINT64_C(0x1f83d9abfb41bd6b) #define SHA512_H0_7 UINT64_C(0x5be0cd19137e2179) +#define SHA512_224_H0_0 UINT64_C(0x8c3d37c819544da2) +#define SHA512_224_H0_1 UINT64_C(0x73e1996689dcd4d6) +#define SHA512_224_H0_2 UINT64_C(0x1dfab7ae32ff9c82) +#define SHA512_224_H0_3 UINT64_C(0x679dd514582f9fcf) +#define SHA512_224_H0_4 UINT64_C(0x0f6d2b697bd44da8) +#define SHA512_224_H0_5 UINT64_C(0x77e36f7304c48942) +#define SHA512_224_H0_6 UINT64_C(0x3f9d85a86a1d36c8) +#define SHA512_224_H0_7 UINT64_C(0x1112e6ad91d692a1) + +#define SHA512_256_H0_0 UINT64_C(0x22312194fc2bf72c) +#define SHA512_256_H0_1 UINT64_C(0x9f555fa3c84c64c2) +#define SHA512_256_H0_2 UINT64_C(0x2393b86b6f53b151) +#define SHA512_256_H0_3 UINT64_C(0x963877195940eabd) +#define SHA512_256_H0_4 UINT64_C(0x96283ee2a88effe3) +#define SHA512_256_H0_5 UINT64_C(0xbe5e1e2553863992) +#define SHA512_256_H0_6 UINT64_C(0x2b0199fc2c85b8aa) +#define SHA512_256_H0_7 UINT64_C(0x0eb72ddc81c52ca2) + static int sha384_init(void *arg) @@ -102,6 +120,54 @@ sha512_init(void *arg) return 1; } +static int +sha512_224_init(void *arg) +{ + struct sha512_state *state = arg; + size_t i; + + state->h0 = SHA512_224_H0_0; + state->h1 = SHA512_224_H0_1; + state->h2 = SHA512_224_H0_2; + state->h3 = SHA512_224_H0_3; + state->h4 = SHA512_224_H0_4; + state->h5 = SHA512_224_H0_5; + state->h6 = SHA512_224_H0_6; + state->h7 = SHA512_224_H0_7; + + state->szhi = state->szlo = 0; + + state->blen = 0; + for (i = 0; i < LC_SHA512_BLOCKLEN; i++) + state->b[i] = 0; + + return 1; +} + +static int +sha512_256_init(void *arg) +{ + struct sha512_state *state = arg; + size_t i; + + state->h0 = SHA512_256_H0_0; + state->h1 = SHA512_256_H0_1; + state->h2 = SHA512_256_H0_2; + state->h3 = SHA512_256_H0_3; + state->h4 = SHA512_256_H0_4; + state->h5 = SHA512_256_H0_5; + state->h6 = SHA512_256_H0_6; + state->h7 = SHA512_256_H0_7; + + state->szhi = state->szlo = 0; + + state->blen = 0; + for (i = 0; i < LC_SHA512_BLOCKLEN; i++) + state->b[i] = 0; + + return 1; +} + static int sha384_sha512_update(void *arg, const uint8_t *in, size_t inlen) { @@ -214,6 +280,46 @@ sha512_final(void *arg, uint8_t *out, size_t *outlen) return 1; } +static int +sha512_224_final(void *arg, uint8_t *out, size_t *outlen) +{ + struct sha512_state *state = arg; + + *outlen = LC_SHA512_224_HASHLEN; + if (out == NULL) + return 1; + + sha384_sha512_final(state); + store64be(out, state->h0); + store64be(out + 8, state->h1); + store64be(out + 16, state->h2); + store32be(out + 24, state->h3 >> 32); + + lc_scrub(state, sizeof(*state)); + + return 1; +} + +static int +sha512_256_final(void *arg, uint8_t *out, size_t *outlen) +{ + struct sha512_state *state = arg; + + *outlen = LC_SHA512_256_HASHLEN; + if (out == NULL) + return 1; + + sha384_sha512_final(state); + store64be(out, state->h0); + store64be(out + 8, state->h1); + store64be(out + 16, state->h2); + store64be(out + 24, state->h3); + + lc_scrub(state, sizeof(*state)); + + return 1; +} + static int sha384_hash(uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen) { @@ -244,6 +350,36 @@ sha512_hash(uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen) sha512_final(&state, out, outlen); } +static int +sha512_224_hash(uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen) +{ + struct sha512_state state; + + if (out == NULL) { + *outlen = LC_SHA512_HASHLEN; + return 1; + } + + return sha512_224_init(&state) && + sha384_sha512_update(&state, in, inlen) && + sha512_224_final(&state, out, outlen); +} + +static int +sha512_256_hash(uint8_t *out, size_t *outlen, const uint8_t *in, size_t inlen) +{ + struct sha512_state state; + + if (out == NULL) { + *outlen = LC_SHA512_HASHLEN; + return 1; + } + + return sha512_256_init(&state) && + sha384_sha512_update(&state, in, inlen) && + sha512_256_final(&state, out, outlen); +} + const struct lc_hash_impl * lc_hash_impl_sha384(void) @@ -278,3 +414,37 @@ lc_hash_impl_sha512(void) return &sha512_impl; } + +const struct lc_hash_impl * +lc_hash_impl_sha512_224(void) +{ + static struct lc_hash_impl sha512_224_impl = { + .init = &sha512_224_init, + .update = &sha384_sha512_update, + .final = &sha512_224_final, + .hash = &sha512_224_hash, + + .argsz = sizeof(struct sha512_state), + .blocklen = LC_SHA512_224_BLOCKLEN, + .hashlen = LC_SHA512_224_HASHLEN, + }; + + return &sha512_224_impl; +} + +const struct lc_hash_impl * +lc_hash_impl_sha512_256(void) +{ + static struct lc_hash_impl sha512_256_impl = { + .init = &sha512_256_init, + .update = &sha384_sha512_update, + .final = &sha512_256_final, + .hash = &sha512_256_hash, + + .argsz = sizeof(struct sha512_state), + .blocklen = LC_SHA512_256_BLOCKLEN, + .hashlen = LC_SHA512_256_HASHLEN, + }; + + return &sha512_256_impl; +} diff --git a/lilcrypto.h b/lilcrypto.h index 91fbfaa..c76cedb 100644 --- a/lilcrypto.h +++ b/lilcrypto.h @@ -35,6 +35,10 @@ #define LC_SHA384_HASHLEN 48 #define LC_SHA512_BLOCKLEN 128 #define LC_SHA512_HASHLEN 64 +#define LC_SHA512_224_BLOCKLEN 128 +#define LC_SHA512_224_HASHLEN 28 +#define LC_SHA512_256_BLOCKLEN 128 +#define LC_SHA512_256_HASHLEN 32 /* Authentitcation. */ #define LC_POLY1305_BLOCKLEN 16 @@ -132,6 +136,8 @@ const struct lc_hash_impl *lc_hash_impl_sha224(void); const struct lc_hash_impl *lc_hash_impl_sha256(void); const struct lc_hash_impl *lc_hash_impl_sha384(void); const struct lc_hash_impl *lc_hash_impl_sha512(void); +const struct lc_hash_impl *lc_hash_impl_sha512_224(void); +const struct lc_hash_impl *lc_hash_impl_sha512_256(void); /* diff --git a/wycheproof/Makefile b/wycheproof/Makefile index 706e95e..5e41cbc 100644 --- a/wycheproof/Makefile +++ b/wycheproof/Makefile @@ -40,7 +40,9 @@ tests-mac: ${WYCHEPROOF_DIR}/testvectors/hmac_sha384_test.json \ ${WYCHEPROOF_DIR}/testvectors_v1/hmac_sha384_test.json \ ${WYCHEPROOF_DIR}/testvectors/hmac_sha512_test.json \ - ${WYCHEPROOF_DIR}/testvectors_v1/hmac_sha512_test.json + ${WYCHEPROOF_DIR}/testvectors_v1/hmac_sha512_test.json \ + ${WYCHEPROOF_DIR}/testvectors_v1/hmac_sha512_224_test.json \ + ${WYCHEPROOF_DIR}/testvectors_v1/hmac_sha512_256_test.json .endfor .include diff --git a/wycheproof_mac.c b/wycheproof_mac.c index ff61840..80a0ecc 100644 --- a/wycheproof_mac.c +++ b/wycheproof_mac.c @@ -51,6 +51,8 @@ static int hmac_sha224_runner(const struct testcase *, int); static int hmac_sha256_runner(const struct testcase *, int); static int hmac_sha384_runner(const struct testcase *, int); static int hmac_sha512_runner(const struct testcase *, int); +static int hmac_sha512_224_runner(const struct testcase *, int); +static int hmac_sha512_256_runner(const struct testcase *, int); static inline uint8_t @@ -103,6 +105,8 @@ static int { "HMACSHA256", &hmac_sha256_runner }, { "HMACSHA384", &hmac_sha384_runner }, { "HMACSHA512", &hmac_sha512_runner }, + { "HMACSHA512/224", &hmac_sha512_224_runner }, + { "HMACSHA512/256", &hmac_sha512_256_runner }, }; struct kwrunner *match; @@ -294,3 +298,15 @@ hmac_sha512_runner(const struct testcase *c, int verbose) { return hmac_sha2_runner(lc_hash_impl_sha512(), c, verbose); } + +static int +hmac_sha512_224_runner(const struct testcase *c, int verbose) +{ + return hmac_sha2_runner(lc_hash_impl_sha512_224(), c, verbose); +} + +static int +hmac_sha512_256_runner(const struct testcase *c, int verbose) +{ + return hmac_sha2_runner(lc_hash_impl_sha512_256(), c, verbose); +}