From: Aki Tuomi Date: Wed, 2 Dec 2020 12:53:39 +0000 (+0200) Subject: lib: hash-method - Add sha384 support X-Git-Tag: 2.3.14.rc1~234 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79bc83dad7a1fc3d270ccdbbc5b37b7fa62265c1;p=thirdparty%2Fdovecot%2Fcore.git lib: hash-method - Add sha384 support --- diff --git a/src/lib/hash-method.c b/src/lib/hash-method.c index ccf0f8b2c5..d7a6bed0ea 100644 --- a/src/lib/hash-method.c +++ b/src/lib/hash-method.c @@ -89,6 +89,7 @@ const struct hash_method *hash_methods[] = { &hash_method_md5, &hash_method_sha1, &hash_method_sha256, + &hash_method_sha384, &hash_method_sha512, &hash_method_sha3_256, &hash_method_sha3_512, diff --git a/src/lib/sha-common.h b/src/lib/sha-common.h index 47c58feac1..abc63ae57f 100644 --- a/src/lib/sha-common.h +++ b/src/lib/sha-common.h @@ -3,6 +3,9 @@ #define SHA256_RESULTLEN (256 / 8) #define SHA256_BLOCK_SIZE (512 / 8) +#define SHA384_RESULTLEN (384 / 8) +#define SHA384_BLOCK_SIZE (1024 / 8) + #define SHA512_RESULTLEN (512 / 8) #define SHA512_BLOCK_SIZE (1024 / 8) diff --git a/src/lib/sha2.c b/src/lib/sha2.c index ca46132751..93dddfbb39 100644 --- a/src/lib/sha2.c +++ b/src/lib/sha2.c @@ -45,6 +45,11 @@ #define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) +#define SHA384_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define SHA384_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define SHA384_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7)) +#define SHA384_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6)) + #define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) #define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) #define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7)) @@ -96,6 +101,12 @@ + SHA256_F3(w[i - 15]) + w[i - 16]; \ } +#define SHA384_SCR(i) \ +{ \ + w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \ + + SHA512_F3(w[i - 15]) + w[i - 16]; \ +} + #define SHA512_SCR(i) \ { \ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \ @@ -106,6 +117,12 @@ static const uint32_t sha256_h0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; +static const uint64_t sha384_h0[8] = + {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}; + static const uint64_t sha512_h0[8] = {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, @@ -300,6 +317,134 @@ void sha256_get_digest(const void *data, size_t size, sha256_result(&ctx, digest); } +/* SHA-384 functions */ + +static void ATTR_UNSIGNED_WRAPS +sha384_transf(struct sha384_ctx *ctx, const unsigned char *data, + size_t block_nb) +{ + uint64_t w[80]; + uint64_t wv[8]; + uint64_t t1, t2; + const unsigned char *sub_block; + int i, j; + + for (i = 0; i < (int) block_nb; i++) { + sub_block = data + (i << 7); + + for (j = 0; j < 16; j++) { + PACK64(&sub_block[j << 3], &w[j]); + } + + for (j = 16; j < 80; j++) { + SHA384_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 80; j++) { + /* sha384_k is same as sha512_k */ + t1 = wv[7] + SHA384_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha512_k[j] + w[j]; + t2 = SHA384_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } + } +} + +void sha384_init(struct sha384_ctx *ctx) +{ + int i; + + for (i = 0; i < 8; i++) { + ctx->h[i] = sha384_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha384_loop(struct sha384_ctx *ctx, const void *data, + size_t len) +{ + const unsigned char *shifted_message; + size_t block_nb; + size_t new_len, rem_len, tmp_len; + + tmp_len = SHA384_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], data, rem_len); + + if (ctx->len + len < SHA384_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA384_BLOCK_SIZE; + + shifted_message = CONST_PTR_OFFSET(data, rem_len); + + sha384_transf(ctx, ctx->block, 1); + sha384_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA384_BLOCK_SIZE; + memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha384_result(struct sha384_ctx *ctx, + unsigned char digest[STATIC_ARRAY SHA384_RESULTLEN]) +{ + unsigned int block_nb; + unsigned int pm_len; + size_t len_b; + int i; + + block_nb = 1 + ((SHA384_BLOCK_SIZE - 17) + < (ctx->len % SHA384_BLOCK_SIZE)); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha384_transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 6; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +} + +void sha384_get_digest(const void *data, size_t size, + unsigned char digest[STATIC_ARRAY SHA384_RESULTLEN]) +{ + struct sha384_ctx ctx; + + sha384_init(&ctx); + sha384_loop(&ctx, data, size); + sha384_result(&ctx, digest); +} + + /* SHA-512 functions */ static void ATTR_UNSIGNED_WRAPS @@ -451,6 +596,31 @@ const struct hash_method hash_method_sha256 = { .result = hash_method_result_sha256, }; +static void hash_method_init_sha384(void *context) +{ + sha384_init(context); +} +static void hash_method_loop_sha384(void *context, const void *data, size_t size) +{ + sha384_loop(context, data, size); +} + +static void hash_method_result_sha384(void *context, unsigned char *result_r) +{ + sha384_result(context, result_r); +} + +const struct hash_method hash_method_sha384 = { + .name = "sha384", + .block_size = SHA384_BLOCK_SIZE, + .context_size = sizeof(struct sha384_ctx), + .digest_size = SHA384_RESULTLEN, + + .init = hash_method_init_sha384, + .loop = hash_method_loop_sha384, + .result = hash_method_result_sha384, +}; + static void hash_method_init_sha512(void *context) { sha512_init(context); diff --git a/src/lib/sha2.h b/src/lib/sha2.h index 5d9d2f0b04..8c893eb3ad 100644 --- a/src/lib/sha2.h +++ b/src/lib/sha2.h @@ -44,6 +44,13 @@ struct sha256_ctx { uint32_t h[8]; }; +struct sha384_ctx { + size_t tot_len; + size_t len; + unsigned char block[2 * SHA384_BLOCK_SIZE]; + uint64_t h[8]; +}; + struct sha512_ctx { size_t tot_len; size_t len; @@ -59,6 +66,14 @@ void sha256_result(struct sha256_ctx *ctx, void sha256_get_digest(const void *data, size_t size, unsigned char digest[STATIC_ARRAY SHA256_RESULTLEN]); +void sha384_init(struct sha384_ctx *ctx); +void sha384_loop(struct sha384_ctx *ctx, const void *data, size_t len); +void sha384_result(struct sha384_ctx *ctx, + unsigned char digest[STATIC_ARRAY SHA384_RESULTLEN]); + +void sha384_get_digest(const void *data, size_t size, + unsigned char digest[STATIC_ARRAY SHA384_RESULTLEN]); + void sha512_init(struct sha512_ctx *ctx); void sha512_loop(struct sha512_ctx *ctx, const void *data, size_t len); void sha512_result(struct sha512_ctx *ctx, @@ -68,6 +83,7 @@ void sha512_get_digest(const void *data, size_t size, unsigned char digest[STATIC_ARRAY SHA512_RESULTLEN]); extern const struct hash_method hash_method_sha256; +extern const struct hash_method hash_method_sha384; extern const struct hash_method hash_method_sha512; #endif /* !SHA2_H */