Avoid fragile aliasing of SHA224/384 update/final
authorViktor Dukhovni <openssl-users@dukhovni.org>
Wed, 14 Feb 2018 03:43:15 +0000 (22:43 -0500)
committerViktor Dukhovni <openssl-users@dukhovni.org>
Wed, 14 Feb 2018 04:29:07 +0000 (23:29 -0500)
This is purported to save a few cycles, but makes the code less
obvious and more brittle, and in fact breaks on platforms where for
ABI continuity reasons there is a SHA2 implementation in libc, and
so EVP needs to call those to avoid conflicts.

A sufficiently good optimizer could simply generate the same entry
points for:

        foo(...) { ... }
    and
        bar(...) { return foo(...); }

but, even without that, the different is negligible, with the
"winner" varying from run to run (openssl speed -evp sha384):

    Old:
    type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes 16384 bytes
    sha384           28864.28k   117362.62k   266469.21k   483258.03k   635144.87k 649123.16k

    New:
    type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes 16384 bytes
    sha384           30055.18k   120725.98k   272057.26k   482847.40k   634585.09k 650308.27k

Reviewed-by: Rich Salz <rsalz@openssl.org>
crypto/evp/m_sha1.c

index 8f30077a4aa32d6189c8c28256de1f428eb17253..ac0ead3b11073e2d6cd9a0b336e0675ad34c22e4 100644 (file)
@@ -115,16 +115,21 @@ static int init224(EVP_MD_CTX *ctx)
     return SHA224_Init(EVP_MD_CTX_md_data(ctx));
 }
 
+static int update224(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+    return SHA224_Update(EVP_MD_CTX_md_data(ctx), data, count);
+}
+
+static int final224(EVP_MD_CTX *ctx, unsigned char *md)
+{
+    return SHA224_Final(md, EVP_MD_CTX_md_data(ctx));
+}
+
 static int init256(EVP_MD_CTX *ctx)
 {
     return SHA256_Init(EVP_MD_CTX_md_data(ctx));
 }
 
-/*
- * Even though there're separate SHA224_[Update|Final], we call
- * SHA256 functions even in SHA224 context. This is what happens
- * there anyway, so we can spare few CPU cycles:-)
- */
 static int update256(EVP_MD_CTX *ctx, const void *data, size_t count)
 {
     return SHA256_Update(EVP_MD_CTX_md_data(ctx), data, count);
@@ -141,8 +146,8 @@ static const EVP_MD sha224_md = {
     SHA224_DIGEST_LENGTH,
     EVP_MD_FLAG_DIGALGID_ABSENT,
     init224,
-    update256,
-    final256,
+    update224,
+    final224,
     NULL,
     NULL,
     SHA256_CBLOCK,
@@ -178,6 +183,16 @@ static int init384(EVP_MD_CTX *ctx)
     return SHA384_Init(EVP_MD_CTX_md_data(ctx));
 }
 
+static int update384(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+    return SHA384_Update(EVP_MD_CTX_md_data(ctx), data, count);
+}
+
+static int final384(EVP_MD_CTX *ctx, unsigned char *md)
+{
+    return SHA384_Final(md, EVP_MD_CTX_md_data(ctx));
+}
+
 static int init512(EVP_MD_CTX *ctx)
 {
     return SHA512_Init(EVP_MD_CTX_md_data(ctx));
@@ -200,8 +215,8 @@ static const EVP_MD sha384_md = {
     SHA384_DIGEST_LENGTH,
     EVP_MD_FLAG_DIGALGID_ABSENT,
     init384,
-    update512,
-    final512,
+    update384,
+    final384,
     NULL,
     NULL,
     SHA512_CBLOCK,