Add SHA-512-256.

(Not wired up into all the signature verifiers because we don't need or
recommend that.)

Change-Id: Ia212a1f0e1c389a31d303e00a6fafb0ec3db7c71
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40704
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/digest_extra/digest_test.cc b/crypto/digest_extra/digest_test.cc
index 5cfe1c8..ba0884a 100644
--- a/crypto/digest_extra/digest_test.cc
+++ b/crypto/digest_extra/digest_test.cc
@@ -53,6 +53,7 @@
 static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 };
 static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 };
 static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 };
+static const MD sha512_256 = { "SHA512-256", &EVP_sha512_256, &SHA512_256 };
 static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
 
 struct DigestTestVector {
@@ -69,79 +70,81 @@
 static const DigestTestVector kTestVectors[] = {
     // MD4 tests, from RFC 1320. (crypto/md4 does not provide a
     // one-shot MD4 function.)
-    { md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
-    { md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
-    { md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
-    { md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" },
-    { md4, "abcdefghijklmnopqrstuvwxyz", 1,
-      "d79e1c308aa5bbcdeea8ed63df412da9" },
-    { md4,
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
-      "043f8582f241db351ce627e153e7f0e4" },
-    { md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
+    {md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0"},
+    {md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24"},
+    {md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d"},
+    {md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b"},
+    {md4, "abcdefghijklmnopqrstuvwxyz", 1, "d79e1c308aa5bbcdeea8ed63df412da9"},
+    {md4, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
+     "043f8582f241db351ce627e153e7f0e4"},
+    {md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536"},
 
     // MD5 tests, from RFC 1321.
-    { md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
-    { md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
-    { md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
-    { md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
-    { md5, "abcdefghijklmnopqrstuvwxyz", 1,
-      "c3fcd3d76192e4007dfb496cca67e13b" },
-    { md5,
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
-      "d174ab98d277d9f5a5611c2c9f419d9f" },
-    { md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
+    {md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e"},
+    {md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661"},
+    {md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72"},
+    {md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0"},
+    {md5, "abcdefghijklmnopqrstuvwxyz", 1, "c3fcd3d76192e4007dfb496cca67e13b"},
+    {md5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
+     "d174ab98d277d9f5a5611c2c9f419d9f"},
+    {md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"},
 
     // SHA-1 tests, from RFC 3174.
-    { sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
-    { sha1,
-      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
-      "84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
-    { sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
-    { sha1,
-      "0123456701234567012345670123456701234567012345670123456701234567", 10,
-      "dea356a2cddd90c7a7ecedc5ebb563934f460452" },
+    {sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d"},
+    {sha1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+     "84983e441c3bd26ebaae4aa1f95129e5e54670f1"},
+    {sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"},
+    {sha1, "0123456701234567012345670123456701234567012345670123456701234567",
+     10, "dea356a2cddd90c7a7ecedc5ebb563934f460452"},
 
     // SHA-224 tests, from RFC 3874.
-    { sha224, "abc", 1,
-      "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
-    { sha224,
-      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
-      "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
-    { sha224,
-      "a", 1000000,
-      "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
+    {sha224, "abc", 1,
+     "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"},
+    {sha224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+     "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"},
+    {sha224, "a", 1000000,
+     "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"},
 
     // SHA-256 tests, from NIST.
-    { sha256, "abc", 1,
-      "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
-    { sha256,
-      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
-      "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
+    {sha256, "abc", 1,
+     "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"},
+    {sha256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+     "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"},
 
     // SHA-384 tests, from NIST.
-    { sha384, "abc", 1,
-      "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
-      "8086072ba1e7cc2358baeca134c825a7" },
-    { sha384,
-      "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
-      "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
-      "fcc7c71a557e2db966c3e9fa91746039" },
+    {sha384, "abc", 1,
+     "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
+     "8086072ba1e7cc2358baeca134c825a7"},
+    {sha384,
+     "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+     1,
+     "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+     "fcc7c71a557e2db966c3e9fa91746039"},
 
     // SHA-512 tests, from NIST.
-    { sha512, "abc", 1,
-      "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
-      "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
-    { sha512,
-      "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
-      "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
-      "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
+    {sha512, "abc", 1,
+     "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+     "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"},
+    {sha512,
+     "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+     1,
+     "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+     "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"},
+
+    // SHA-512-256 tests, from
+    // https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha512_256.pdf
+    {sha512_256, "abc", 1,
+     "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"},
+    {sha512_256,
+     "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopj"
+     "klmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+     1, "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"},
 
     // MD5-SHA1 tests.
-    { md5_sha1, "abc", 1,
-      "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
+    {md5_sha1, "abc", 1,
+     "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d"},
 };
 
 static void CompareDigest(const DigestTestVector *test,
diff --git a/crypto/fipsmodule/digest/digests.c b/crypto/fipsmodule/digest/digests.c
index f2fa349..16daeba 100644
--- a/crypto/fipsmodule/digest/digests.c
+++ b/crypto/fipsmodule/digest/digests.c
@@ -243,6 +243,22 @@
 }
 
 
+static void sha512_256_init(EVP_MD_CTX *ctx) {
+  CHECK(SHA512_256_Init(ctx->md_data));
+}
+
+DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {
+  out->type = NID_sha512_256;
+  out->md_size = SHA512_256_DIGEST_LENGTH;
+  out->flags = 0;
+  out->init = sha512_256_init;
+  out->update = sha512_update;
+  out->final = sha512_final;
+  out->block_size = 128;
+  out->ctx_size = sizeof(SHA512_CTX);
+}
+
+
 typedef struct {
   MD5_CTX md5;
   SHA_CTX sha1;
diff --git a/crypto/fipsmodule/sha/sha512.c b/crypto/fipsmodule/sha/sha512.c
index 848f3b6..fd02574 100644
--- a/crypto/fipsmodule/sha/sha512.c
+++ b/crypto/fipsmodule/sha/sha512.c
@@ -105,6 +105,23 @@
   return 1;
 }
 
+int SHA512_256_Init(SHA512_CTX *sha) {
+  sha->h[0] = UINT64_C(0x22312194fc2bf72c);
+  sha->h[1] = UINT64_C(0x9f555fa3c84c64c2);
+  sha->h[2] = UINT64_C(0x2393b86b6f53b151);
+  sha->h[3] = UINT64_C(0x963877195940eabd);
+  sha->h[4] = UINT64_C(0x96283ee2a88effe3);
+  sha->h[5] = UINT64_C(0xbe5e1e2553863992);
+  sha->h[6] = UINT64_C(0x2b0199fc2c85b8aa);
+  sha->h[7] = UINT64_C(0x0eb72ddc81c52ca2);
+
+  sha->Nl = 0;
+  sha->Nh = 0;
+  sha->num = 0;
+  sha->md_len = SHA512_256_DIGEST_LENGTH;
+  return 1;
+}
+
 uint8_t *SHA384(const uint8_t *data, size_t len,
                 uint8_t out[SHA384_DIGEST_LENGTH]) {
   SHA512_CTX ctx;
@@ -125,6 +142,16 @@
   return out;
 }
 
+uint8_t *SHA512_256(const uint8_t *data, size_t len,
+                    uint8_t out[SHA512_256_DIGEST_LENGTH]) {
+  SHA512_CTX ctx;
+  SHA512_256_Init(&ctx);
+  SHA512_Update(&ctx, data, len);
+  SHA512_Final(out, &ctx);
+  OPENSSL_cleanse(&ctx, sizeof(ctx));
+  return out;
+}
+
 #if !defined(SHA512_ASM)
 static void sha512_block_data_order(uint64_t *state, const uint8_t *in,
                                     size_t num_blocks);
@@ -141,6 +168,17 @@
   return SHA512_Update(sha, data, len);
 }
 
+int SHA512_256_Update(SHA512_CTX *sha, const void *data, size_t len) {
+  return SHA512_Update(sha, data, len);
+}
+
+int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH],
+                                    SHA512_CTX *sha) {
+  // |SHA512_256_Init| sets |sha->md_len| to |SHA512_256_DIGEST_LENGTH|, so this
+  // has a |smaller output.
+  return SHA512_Final(out, sha);
+}
+
 void SHA512_Transform(SHA512_CTX *c, const uint8_t block[SHA512_CBLOCK]) {
   sha512_block_data_order(c->h, block, 1);
 }
@@ -231,41 +269,12 @@
     return 0;
   }
 
-  switch (sha->md_len) {
-    // Let compiler decide if it's appropriate to unroll...
-    case SHA384_DIGEST_LENGTH:
-      for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) {
-        uint64_t t = sha->h[n];
-
-        *(out++) = (uint8_t)(t >> 56);
-        *(out++) = (uint8_t)(t >> 48);
-        *(out++) = (uint8_t)(t >> 40);
-        *(out++) = (uint8_t)(t >> 32);
-        *(out++) = (uint8_t)(t >> 24);
-        *(out++) = (uint8_t)(t >> 16);
-        *(out++) = (uint8_t)(t >> 8);
-        *(out++) = (uint8_t)(t);
-      }
-      break;
-    case SHA512_DIGEST_LENGTH:
-      for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) {
-        uint64_t t = sha->h[n];
-
-        *(out++) = (uint8_t)(t >> 56);
-        *(out++) = (uint8_t)(t >> 48);
-        *(out++) = (uint8_t)(t >> 40);
-        *(out++) = (uint8_t)(t >> 32);
-        *(out++) = (uint8_t)(t >> 24);
-        *(out++) = (uint8_t)(t >> 16);
-        *(out++) = (uint8_t)(t >> 8);
-        *(out++) = (uint8_t)(t);
-      }
-      break;
-    // ... as well as make sure md_len is not abused.
-    default:
-      // TODO(davidben): This bad |md_len| case is one of the few places a
-      // low-level hash 'final' function can fail. This should never happen.
-      return 0;
+  assert(sha->md_len % 8 == 0);
+  const size_t out_words = sha->md_len / 8;
+  for (size_t i = 0; i < out_words; i++) {
+    const uint64_t t = CRYPTO_bswap8(sha->h[i]);
+    memcpy(out, &t, sizeof(t));
+    out += sizeof(t);
   }
 
   return 1;
diff --git a/crypto/obj/obj_dat.h b/crypto/obj/obj_dat.h
index 888ea67..778d8e3 100644
--- a/crypto/obj/obj_dat.h
+++ b/crypto/obj/obj_dat.h
@@ -57,7 +57,7 @@
 /* This file is generated by crypto/obj/objects.go. */
 
 
-#define NUM_NID 962
+#define NUM_NID 963
 
 static const uint8_t kObjectData[] = {
     /* NID_rsadsi */
@@ -7127,6 +7127,16 @@
     0x2b,
     0x65,
     0x6f,
+    /* NID_sha512_256 */
+    0x60,
+    0x86,
+    0x48,
+    0x01,
+    0x65,
+    0x03,
+    0x04,
+    0x02,
+    0x06,
 };
 
 static const ASN1_OBJECT kObjects[NUM_NID] = {
@@ -8770,6 +8780,7 @@
     {"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0},
     {"ED448", "ED448", NID_ED448, 3, &kObjectData[6181], 0},
     {"X448", "X448", NID_X448, 3, &kObjectData[6184], 0},
+    {"SHA512-256", "sha512-256", NID_sha512_256, 9, &kObjectData[6187], 0},
 };
 
 static const uint16_t kNIDsInShortNameOrder[] = {
@@ -8959,6 +8970,7 @@
     672 /* SHA256 */,
     673 /* SHA384 */,
     674 /* SHA512 */,
+    962 /* SHA512-256 */,
     188 /* SMIME */,
     167 /* SMIME-CAPS */,
     100 /* SN */,
@@ -10632,6 +10644,7 @@
     673 /* sha384 */,
     669 /* sha384WithRSAEncryption */,
     674 /* sha512 */,
+    962 /* sha512-256 */,
     670 /* sha512WithRSAEncryption */,
     42 /* shaWithRSAEncryption */,
     52 /* signingTime */,
@@ -11391,6 +11404,7 @@
     673 /* 2.16.840.1.101.3.4.2.2 (OBJ_sha384) */,
     674 /* 2.16.840.1.101.3.4.2.3 (OBJ_sha512) */,
     675 /* 2.16.840.1.101.3.4.2.4 (OBJ_sha224) */,
+    962 /* 2.16.840.1.101.3.4.2.6 (OBJ_sha512_256) */,
     802 /* 2.16.840.1.101.3.4.3.1 (OBJ_dsa_with_SHA224) */,
     803 /* 2.16.840.1.101.3.4.3.2 (OBJ_dsa_with_SHA256) */,
     71 /* 2.16.840.1.113730.1.1 (OBJ_netscape_cert_type) */,
diff --git a/crypto/obj/obj_mac.num b/crypto/obj/obj_mac.num
index f73ebf9..f110ee9 100644
--- a/crypto/obj/obj_mac.num
+++ b/crypto/obj/obj_mac.num
@@ -950,3 +950,4 @@
 CECPQ2		959
 ED448		960
 X448		961
+sha512_256		962
diff --git a/crypto/obj/objects.txt b/crypto/obj/objects.txt
index 798da1e..b88342d 100644
--- a/crypto/obj/objects.txt
+++ b/crypto/obj/objects.txt
@@ -905,6 +905,7 @@
 nist_hashalgs 2		: SHA384		: sha384
 nist_hashalgs 3		: SHA512		: sha512
 nist_hashalgs 4		: SHA224		: sha224
+nist_hashalgs 6		: SHA512-256		: sha512-256
 
 # OIDs for dsa-with-sha224 and dsa-with-sha256
 !Alias dsa_with_sha2 nistAlgorithms 3
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index c3ceb7f..7b0ed06 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -83,6 +83,7 @@
 OPENSSL_EXPORT const EVP_MD *EVP_sha256(void);
 OPENSSL_EXPORT const EVP_MD *EVP_sha384(void);
 OPENSSL_EXPORT const EVP_MD *EVP_sha512(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha512_256(void);
 
 // EVP_md5_sha1 is a TLS-specific |EVP_MD| which computes the concatenation of
 // MD5 and SHA-1, as used in TLS 1.1 and below.
diff --git a/include/openssl/nid.h b/include/openssl/nid.h
index a15f4e3..bf7f3da 100644
--- a/include/openssl/nid.h
+++ b/include/openssl/nid.h
@@ -4246,6 +4246,11 @@
 #define NID_X448 961
 #define OBJ_X448 1L, 3L, 101L, 111L
 
+#define SN_sha512_256 "SHA512-256"
+#define LN_sha512_256 "sha512-256"
+#define NID_sha512_256 962
+#define OBJ_sha512_256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 6L
+
 
 #if defined(__cplusplus)
 } /* extern C */
diff --git a/include/openssl/sha.h b/include/openssl/sha.h
index b163e6a..b113798 100644
--- a/include/openssl/sha.h
+++ b/include/openssl/sha.h
@@ -261,6 +261,32 @@
 };
 
 
+// SHA-512-256
+//
+// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6
+
+#define SHA512_256_DIGEST_LENGTH 32
+
+// SHA512_256_Init initialises |sha| and returns 1.
+OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha);
+
+// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1.
+OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data,
+                                     size_t len);
+
+// SHA512_256_Final adds the final padding to |sha| and writes the resulting
+// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of
+// space. It returns one on success and zero on programmer error.
+OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH],
+                                    SHA512_CTX *sha);
+
+// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns
+// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in
+// |out|.
+OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len,
+                                   uint8_t out[SHA512_256_DIGEST_LENGTH]);
+
+
 #if defined(__cplusplus)
 }  // extern C
 #endif
diff --git a/tool/digest.cc b/tool/digest.cc
index 7b6c88b..742fa7f 100644
--- a/tool/digest.cc
+++ b/tool/digest.cc
@@ -474,3 +474,7 @@
 bool SHA512Sum(const std::vector<std::string> &args) {
   return DigestSum(EVP_sha512(), args);
 }
+
+bool SHA512256Sum(const std::vector<std::string> &args) {
+  return DigestSum(EVP_sha512_256(), args);
+}
diff --git a/tool/internal.h b/tool/internal.h
index b626270..4cace9d 100644
--- a/tool/internal.h
+++ b/tool/internal.h
@@ -87,6 +87,7 @@
 bool SHA256Sum(const std::vector<std::string> &args);
 bool SHA384Sum(const std::vector<std::string> &args);
 bool SHA512Sum(const std::vector<std::string> &args);
+bool SHA512256Sum(const std::vector<std::string> &args);
 bool Server(const std::vector<std::string> &args);
 bool Sign(const std::vector<std::string> &args);
 bool Speed(const std::vector<std::string> &args);
diff --git a/tool/tool.cc b/tool/tool.cc
index 670d4e7..d278535 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -58,6 +58,7 @@
   { "sha256sum", SHA256Sum },
   { "sha384sum", SHA384Sum },
   { "sha512sum", SHA512Sum },
+  { "sha512256sum", SHA512256Sum },
   { "sign", Sign },
   { "speed", Speed },
   { "", nullptr },