blake2: avoid writing to output buffer when using default digest length
authorAntoine Salon <asalon@vmware.com>
Mon, 7 Jan 2019 23:09:55 +0000 (15:09 -0800)
committerMatt Caswell <matt@openssl.org>
Wed, 6 Feb 2019 09:24:28 +0000 (09:24 +0000)
Signed-off-by: Antoine Salon <asalon@vmware.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7726)

crypto/blake2/blake2b.c
crypto/blake2/blake2s.c

index b5eb928..73ba0b6 100644 (file)
@@ -304,19 +304,26 @@ int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen)
 int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c)
 {
     uint8_t outbuffer[BLAKE2B_OUTBYTES] = {0};
+    uint8_t *target = outbuffer;
+    int iter = (c->outlen + 7) / 8;
     int i;
 
+    /* Avoid writing to the temporary buffer if possible */
+    if ((c->outlen % sizeof(c->h[0])) == 0)
+        target = md;
+
     blake2b_set_lastblock(c);
     /* Padding */
     memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
     blake2b_compress(c, c->buf, c->buflen);
 
-    /* Output full hash to temp buffer */
-    for (i = 0; i < 8; ++i) {
-        store64(outbuffer + sizeof(c->h[i]) * i, c->h[i]);
-    }
+    /* Output full hash to buffer */
+    for (i = 0; i < iter; ++i)
+        store64(target + sizeof(c->h[i]) * i, c->h[i]);
+
+    if (target != md)
+        memcpy(md, target, c->outlen);
 
-    memcpy(md, outbuffer, c->outlen);
     OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX));
     return 1;
 }
index 94333d1..121f0d1 100644 (file)
@@ -295,19 +295,26 @@ int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen)
 int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c)
 {
     uint8_t outbuffer[BLAKE2S_OUTBYTES] = {0};
+    uint8_t *target = outbuffer;
+    int iter = (c->outlen + 3) / 4;
     int i;
 
+    /* Avoid writing to the temporary buffer if possible */
+    if ((c->outlen % sizeof(c->h[0])) == 0)
+        target = md;
+
     blake2s_set_lastblock(c);
     /* Padding */
     memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
     blake2s_compress(c, c->buf, c->buflen);
 
-    /* Output full hash to temp buffer */
-    for (i = 0; i < 8; ++i) {
-        store32(outbuffer + sizeof(c->h[i]) * i, c->h[i]);
-    }
+    /* Output full hash to buffer */
+    for (i = 0; i < iter; ++i)
+        store32(target + sizeof(c->h[i]) * i, c->h[i]);
+
+    if (target != md)
+        memcpy(md, target, c->outlen);
 
-    memcpy(md, outbuffer, c->outlen);
     OPENSSL_cleanse(c, sizeof(BLAKE2S_CTX));
     return 1;
 }