]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update ZONEMD to match RFC 8976
authorMark Andrews <marka@isc.org>
Wed, 28 Apr 2021 02:05:02 +0000 (12:05 +1000)
committerMark Andrews <marka@isc.org>
Fri, 30 Apr 2021 01:31:05 +0000 (11:31 +1000)
* The location of the digest type field has changed to where the
  reserved field was.
* The reserved field is now called scheme and is where the digest
  type field was.
* Digest type 2 has been defined (SHA256).

(cherry picked from commit 8510ccaa547f9f8c75a3f2572f1ac1871f9e0787)

CHANGES
bin/tests/system/genzone.sh
bin/tests/system/xfer/dig1.good
bin/tests/system/xfer/dig2.good
doc/arm/notes-9.11.32.xml
lib/dns/rdata/generic/zonemd_63.c
lib/dns/rdata/generic/zonemd_63.h
lib/dns/tests/rdata_test.c

diff --git a/CHANGES b/CHANGES
index 7abce1fa5ee792190750550d3836a033c046ebd3..318cb93c6f639d13b6def38850a7743cf24b2e19 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+5631.  [bug]           Update ZONEMD to match RFC 8976. [GL #2658]
+
 5629.  [func]          Reduce the supported maximum number of iterations
                        that can be configured in an NSEC3 zone to 150.
                        [GL #2642]
index cd5676f03b0f8d29e80985c03bda21c049c432d6..765a4be73b0fdc58d87f89f73cc5d2d68fd178ee 100644 (file)
@@ -369,11 +369,17 @@ csync01                   CSYNC   0 0 A NS AAAA
 csync02                        CSYNC   0 0
 
 ;type  63
-zonemd01               ZONEMD  2019020700 1 0 (
+zonemd01               ZONEMD  2019020700 1 1 (
                                 C220B8A6ED5728A971902F7E3D4FD93A
                                 DEEA88B0453C2E8E8C863D465AB06CF3
                                 4EB95B266398C98B59124FA239CB7EEB
                                )
+zonemd02               ZONEMD  2019020700 1 2 (
+                               08CFA1115C7B948C4163A901270395EA
+                               226A930CD2CBCF2FA9A5E6EB85F37C8A
+                                4E114D884E66F176EAB121CB02DB7D65
+                                2E0CC4827E7A3204F166B47E5613FD27
+                               )
 
 ; type 64 -- 98 (unassigned)
 
index e813b718893952a94efa53d901082cef568a8053..0f8fad0f3127e4e541cd80ebb1f8f6e1a96a3864 100644 (file)
@@ -166,7 +166,8 @@ wks01.example.              3600    IN      WKS     10.0.0.1 6 0 1 2 21 23
 wks02.example.         3600    IN      WKS     10.0.0.1 17 0 1 2 53
 wks03.example.         3600    IN      WKS     10.0.0.2 6 65535
 x2501.example.         3600    IN      X25     "123456789"
-zonemd01.example.      3600    IN      ZONEMD  2019020700 1 0 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd01.example.      3600    IN      ZONEMD  2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example.      3600    IN      ZONEMD  2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
 8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
 kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
 mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
index f6c22d418de6d502a1efb40a7906eaf50e5c011d..fed8926817eda1b003da4607a32715924dd1a5da 100644 (file)
@@ -166,7 +166,8 @@ wks01.example.              3600    IN      WKS     10.0.0.1 6 0 1 2 21 23
 wks02.example.         3600    IN      WKS     10.0.0.1 17 0 1 2 53
 wks03.example.         3600    IN      WKS     10.0.0.2 6 65535
 x2501.example.         3600    IN      X25     "123456789"
-zonemd01.example.      3600    IN      ZONEMD  2019020700 1 0 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd01.example.      3600    IN      ZONEMD  2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB
+zonemd02.example.      3600    IN      ZONEMD  2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27
 8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
 kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E
 mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG
index 5490e8d894487c3e22e8dd6b20b6207202fd97a1..92bbc8ec1d432efba26807d10d4e18cb2810b617 100644 (file)
@@ -66,7 +66,7 @@
     <itemizedlist>
       <listitem>
         <para>
-          None.
+          Update ZONEMD to match RFC 8976. [GL #2658]
         </para>
       </listitem>
     </itemizedlist>
index 7026fde13c7fc79b24ceb50fe4f7217fe3ebe1f0..2f89ad30e7adde0f8b6fcc904ea8fe7828e0cfdf 100644 (file)
@@ -9,7 +9,7 @@
  * information regarding copyright ownership.
  */
 
-/* draft-wessels-zone-digest-05 */
+/* RFC 8976 */
 
 #ifndef RDATA_GENERIC_ZONEMD_63_C
 #define RDATA_GENERIC_ZONEMD_63_C
@@ -20,6 +20,8 @@ static inline isc_result_t
 fromtext_zonemd(ARGS_FROMTEXT) {
        isc_token_t token;
        int digest_type, length;
+       isc_buffer_t save;
+       isc_result_t result;
 
        UNUSED(type);
        UNUSED(rdclass);
@@ -28,26 +30,26 @@ fromtext_zonemd(ARGS_FROMTEXT) {
        UNUSED(callbacks);
 
        /*
-        * Serial.
+        * Zone Serial.
         */
        RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
                                      false));
        RETERR(uint32_tobuffer(token.value.as_ulong, target));
 
        /*
-        * Digest type.
+        * Digest Scheme.
         */
        RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
                                      false));
-       digest_type = token.value.as_ulong;
-       RETERR(uint8_tobuffer(digest_type, target));
+       RETERR(uint8_tobuffer(token.value.as_ulong, target));
 
        /*
-        * Reserved.
+        * Digest Type.
         */
        RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
                                      false));
-       RETERR(uint8_tobuffer(token.value.as_ulong, target));
+       digest_type = token.value.as_ulong;
+       RETERR(uint8_tobuffer(digest_type, target));
 
        /*
         * Digest.
@@ -56,12 +58,21 @@ fromtext_zonemd(ARGS_FROMTEXT) {
        case DNS_ZONEMD_DIGEST_SHA384:
                length = ISC_SHA384_DIGESTLENGTH;
                break;
+       case DNS_ZONEMD_DIGEST_SHA512:
+               length = ISC_SHA512_DIGESTLENGTH;
+               break;
        default:
                length = -2;
                break;
        }
 
-       return (isc_hex_tobuffer(lexer, target, length));
+       save = *target;
+       result = isc_hex_tobuffer(lexer, target, length);
+       /* Minimum length of digest is 12 octets. */
+       if (isc_buffer_usedlength(target) - isc_buffer_usedlength(&save) < 12) {
+               return (ISC_R_UNEXPECTEDEND);
+       }
+       return (result);
 }
 
 static inline isc_result_t
@@ -77,7 +88,7 @@ totext_zonemd(ARGS_TOTEXT) {
        dns_rdata_toregion(rdata, &sr);
 
        /*
-        * Serial.
+        * Zone Serial.
         */
        num = uint32_fromregion(&sr);
        isc_region_consume(&sr, 4);
@@ -87,7 +98,7 @@ totext_zonemd(ARGS_TOTEXT) {
        RETERR(str_totext(" ", target));
 
        /*
-        * Digest type.
+        * Digest scheme.
         */
        num = uint8_fromregion(&sr);
        isc_region_consume(&sr, 1);
@@ -95,8 +106,9 @@ totext_zonemd(ARGS_TOTEXT) {
        RETERR(str_totext(buf, target));
 
        RETERR(str_totext(" ", target));
+
        /*
-        * Reserved.
+        * Digest type.
         */
        num = uint8_fromregion(&sr);
        isc_region_consume(&sr, 1);
@@ -127,6 +139,7 @@ totext_zonemd(ARGS_TOTEXT) {
 static inline isc_result_t
 fromwire_zonemd(ARGS_FROMWIRE) {
        isc_region_t sr;
+       size_t digestlen = 0;
 
        UNUSED(type);
        UNUSED(rdclass);
@@ -136,16 +149,28 @@ fromwire_zonemd(ARGS_FROMWIRE) {
        isc_buffer_activeregion(source, &sr);
 
        /*
-        * If we do not recognize the digest type, only ensure that the digest
-        * is present at all.
+        * If we do not recognize the digest type, ensure that the digest
+        * meets minimum length (12).
         *
         * If we do recognize the digest type, ensure that the digest is of the
         * correct length.
         */
-       if (sr.length < 7 ||
-           (sr.base[4] == DNS_ZONEMD_DIGEST_SHA384 &&
-            sr.length < 6 + ISC_SHA384_DIGESTLENGTH))
-       {
+       if (sr.length < 18) {
+               return (ISC_R_UNEXPECTEDEND);
+       }
+
+       switch (sr.base[5]) {
+       case DNS_ZONEMD_DIGEST_SHA384:
+               digestlen = ISC_SHA384_DIGESTLENGTH;
+               break;
+       case DNS_ZONEMD_DIGEST_SHA512:
+               digestlen = ISC_SHA512_DIGESTLENGTH;
+               break;
+       default:
+               break;
+       }
+
+       if (digestlen != 0 && sr.length < 6 + digestlen) {
                return (ISC_R_UNEXPECTEDEND);
        }
 
@@ -155,8 +180,8 @@ fromwire_zonemd(ARGS_FROMWIRE) {
         *
         * If there is extra data, dns_rdata_fromwire() will detect that.
         */
-       if (sr.base[4] == DNS_ZONEMD_DIGEST_SHA384) {
-               sr.length = 6 + ISC_SHA384_DIGESTLENGTH;
+       if (digestlen != 0) {
+               sr.length = 6 + digestlen;
        }
 
        isc_buffer_forward(source, sr.length);
@@ -209,11 +234,14 @@ fromstruct_zonemd(ARGS_FROMSTRUCT) {
        case DNS_ZONEMD_DIGEST_SHA384:
                REQUIRE(zonemd->length == ISC_SHA384_DIGESTLENGTH);
                break;
+       case DNS_ZONEMD_DIGEST_SHA512:
+               REQUIRE(zonemd->length == ISC_SHA512_DIGESTLENGTH);
+               break;
        }
 
        RETERR(uint32_tobuffer(zonemd->serial, target));
+       RETERR(uint8_tobuffer(zonemd->scheme, target));
        RETERR(uint8_tobuffer(zonemd->digest_type, target));
-       RETERR(uint8_tobuffer(zonemd->reserved, target));
 
        return (mem_tobuffer(target, zonemd->digest, zonemd->length));
 }
@@ -237,9 +265,9 @@ tostruct_zonemd(ARGS_TOSTRUCT) {
 
        zonemd->serial = uint32_fromregion(&region);
        isc_region_consume(&region, 4);
-       zonemd->digest_type = uint8_fromregion(&region);
+       zonemd->scheme = uint8_fromregion(&region);
        isc_region_consume(&region, 1);
-       zonemd->reserved = uint8_fromregion(&region);
+       zonemd->digest_type = uint8_fromregion(&region);
        isc_region_consume(&region, 1);
        zonemd->length = region.length;
 
index ff4e2923b75b25d2c29a83a4a9d8536ae73083a8..592d89f46ab9ee813ac88982dd97405ea583eefd 100644 (file)
 #ifndef GENERIC_ZONEMD_63_H
 #define GENERIC_ZONEMD_63_H 1
 
-/* Digest type(s). Currently only SHA-384 is defined. */
+/* Known digest type(s). */
 #define DNS_ZONEMD_DIGEST_SHA384 (1)
+#define DNS_ZONEMD_DIGEST_SHA512 (2)
 
 /*
- *  \brief per draft-wessels-zone-digest-05
+ *  \brief per RFC 8976
  */
 typedef struct dns_rdata_zonemd {
-       dns_rdatacommon_t       common;
-       isc_mem_t               *mctx;
-       uint32_t                serial;
-       uint8_t                 digest_type;
-       uint8_t                 reserved;
-       unsigned char           *digest;
-       uint16_t                length;
+       dns_rdatacommon_t common;
+       isc_mem_t *mctx;
+       uint32_t serial;
+       uint8_t scheme;
+       uint8_t digest_type;
+       unsigned char *digest;
+       uint16_t length;
 } dns_rdata_zonemd_t;
 
 #endif /* GENERIC_ZONEMD_63_H */
index 770623addda089dcb86d5fb1d95a0cdc56d6a7f2..fe01e48fa399733a30a97dedf17b401ddd0521a1 100644 (file)
@@ -626,6 +626,10 @@ check_wire_ok(const wire_ok_t *wire_ok, bool empty_ok, dns_rdataclass_t rdclass,
         * Check all entries in the supplied array.
         */
        for (i = 0; wire_ok[i].len != 0; i++) {
+               if (debug) {
+                       fprintf(stderr, "calling check_wire_ok_single on %zu\n",
+                               i);
+               }
                check_wire_ok_single(&wire_ok[i], rdclass, type, structsize);
        }
 
@@ -2501,7 +2505,7 @@ wks(void **state) {
 /*
  * ZONEMD tests.
  *
- * Excerpted from draft-wessels-dns-zone-digest:
+ * Excerpted from RFC 8976:
  *
  * The ZONEMD RDATA wire format is encoded as follows:
  *
@@ -2510,55 +2514,129 @@ wks(void **state) {
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *    |                             Serial                            |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *    |  Digest Type  |   Reserved    |                               |
+ *    |    Scheme     |Hash Algorithm |                               |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
  *    |                             Digest                            |
  *    /                                                               /
  *    /                                                               /
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * 2.1.1.  The Serial Field
+ * 2.2.1.  The Serial Field
+ *
+ *    The Serial field is a 32-bit unsigned integer in network byte order.
+ *    It is the serial number from the zone's SOA record ([RFC1035],
+ *    Section 3.3.13) for which the zone digest was generated.
+ *
+ *    It is included here to clearly bind the ZONEMD RR to a particular
+ *    version of the zone's content.  Without the serial number, a stand-
+ *    alone ZONEMD digest has no obvious association to any particular
+ *    instance of a zone.
+ *
+ * 2.2.2.  The Scheme Field
+ *
+ *    The Scheme field is an 8-bit unsigned integer that identifies the
+ *    methods by which data is collated and presented as input to the
+ *    hashing function.
+ *
+ *    Herein, SIMPLE, with Scheme value 1, is the only standardized Scheme
+ *    defined for ZONEMD records and it MUST be supported by
+ *    implementations.  The "ZONEMD Schemes" registry is further described
+ *    in Section 5.
+ *
+ *    Scheme values 240-254 are allocated for Private Use.
  *
- *    The Serial field is a 32-bit unsigned integer in network order.  It
- *    is equal to the serial number from the zone's SOA record
+ * 2.2.3.  The Hash Algorithm Field
  *
- * 2.1.2.  The Digest Type Field
+ *    The Hash Algorithm field is an 8-bit unsigned integer that identifies
+ *    the cryptographic hash algorithm used to construct the digest.
  *
- *    The Digest Type field is an 8-bit unsigned integer that identifies
- *    the algorithm used to construct the digest.
+ *    Herein, SHA384 ([RFC6234]), with Hash Algorithm value 1, is the only
+ *    standardized Hash Algorithm defined for ZONEMD records that MUST be
+ *    supported by implementations.  When SHA384 is used, the size of the
+ *    Digest field is 48 octets.  The result of the SHA384 digest algorithm
+ *    MUST NOT be truncated, and the entire 48-octet digest is published in
+ *    the ZONEMD record.
  *
- *    At the time of this writing, SHA384, with value 1, is the only Digest
- *    Type defined for ZONEMD records.
+ *    SHA512 ([RFC6234]), with Hash Algorithm value 2, is also defined for
+ *    ZONEMD records and SHOULD be supported by implementations.  When
+ *    SHA512 is used, the size of the Digest field is 64 octets.  The
+ *    result of the SHA512 digest algorithm MUST NOT be truncated, and the
+ *    entire 64-octet digest is published in the ZONEMD record.
  *
- * 2.1.3.  The Reserved Field
+ *    Hash Algorithm values 240-254 are allocated for Private Use.
  *
- *    The Reserved field is an 8-bit unsigned integer, which is always set
- *    to zero.
+ *    The "ZONEMD Hash Algorithms" registry is further described in
+ *    Section 5.
  *
- * 2.1.4.  The Digest Field
+ * 2.2.4.  The Digest Field
  *
  *    The Digest field is a variable-length sequence of octets containing
- *    the message digest.
+ *    the output of the hash algorithm.  The length of the Digest field is
+ *    determined by deducting the fixed size of the Serial, Scheme, and
+ *    Hash Algorithm fields from the RDATA size in the ZONEMD RR header.
+ *
+ *    The Digest field MUST NOT be shorter than 12 octets.  Digests for the
+ *    SHA384 and SHA512 hash algorithms specified herein are never
+ *    truncated.  Digests for future hash algorithms MAY be truncated but
+ *    MUST NOT be truncated to a length that results in less than 96 bits
+ *    (12 octets) of equivalent strength.
+ *
+ *    Section 3 describes how to calculate the digest for a zone.
+ *    Section 4 describes how to use the digest to verify the contents of a
+ *    zone.
+ *
  */
 
 static void
 zonemd(void **state) {
        text_ok_t text_ok[] = {
                TEXT_INVALID(""),
+               /* No digest scheme or digest type*/
                TEXT_INVALID("0"),
+               /* No digest type */
                TEXT_INVALID("0 0"),
+               /* No digest */
                TEXT_INVALID("0 0 0"),
+               /* No digest */
                TEXT_INVALID("99999999 0 0"),
+               /* No digest */
                TEXT_INVALID("2019020700 0 0"),
-               TEXT_INVALID("2019020700 1 0 DEADBEEF"),
-               TEXT_VALID("2019020700 2 0 DEADBEEF"),
-               TEXT_VALID("2019020700 255 0 DEADBEEF"),
-               TEXT_INVALID("2019020700 256 0 DEADBEEF"),
-               TEXT_VALID("2019020700 2 255 DEADBEEF"),
-               TEXT_INVALID("2019020700 2 256 DEADBEEF"),
-               TEXT_VALID("2019020700 1 0 7162D2BB75C047A53DE98767C9192BEB"
-                                         "14DB01E7E2267135DAF0230A 19BA4A31"
-                                         "6AF6BF64AA5C7BAE24B2992850300509"),
+               /* Digest too short */
+               TEXT_INVALID("2019020700 1 1 DEADBEEF"),
+               /* Digest too short */
+               TEXT_INVALID("2019020700 1 2 DEADBEEF"),
+               /* Digest too short */
+               TEXT_INVALID("2019020700 1 3 DEADBEEFDEADBEEFDEADBE"),
+               /* Digest type unknown */
+               TEXT_VALID("2019020700 1 3 DEADBEEFDEADBEEFDEADBEEF"),
+               /* Digest type max */
+               TEXT_VALID("2019020700 1 255 DEADBEEFDEADBEEFDEADBEEF"),
+               /* Digest type too big */
+               TEXT_INVALID("2019020700 0 256 DEADBEEFDEADBEEFDEADBEEF"),
+               /* Scheme max */
+               TEXT_VALID("2019020700 255 3 DEADBEEFDEADBEEFDEADBEEF"),
+               /* Scheme too big */
+               TEXT_INVALID("2019020700 256 3 DEADBEEFDEADBEEFDEADBEEF"),
+               /* SHA384 */
+               TEXT_VALID("2019020700 1 1 "
+                          "7162D2BB75C047A53DE98767C9192BEB"
+                          "14DB01E7E2267135DAF0230A 19BA4A31"
+                          "6AF6BF64AA5C7BAE24B2992850300509"),
+               /* SHA512 */
+               TEXT_VALID("2019020700 1 2 "
+                          "08CFA1115C7B948C4163A901270395EA"
+                          "226A930CD2CBCF2FA9A5E6EB 85F37C8A"
+                          "4E114D884E66F176EAB121CB02DB7D65"
+                          "2E0CC4827E7A3204 F166B47E5613FD27"),
+               /* SHA384 too short and with private scheme */
+               TEXT_INVALID("2021042801 0 1 "
+                            "7162D2BB75C047A53DE98767C9192BEB"
+                            "6AF6BF64AA5C7BAE24B2992850300509"),
+               /* SHA512 too short and with private scheme */
+               TEXT_INVALID("2021042802 5 2 "
+                            "A897B40072ECAE9E4CA3F1F227DE8F5E"
+                            "480CDEBB16DFC64C1C349A7B5F6C71AB"
+                            "E8A88B76EF0BA1604EC25752E946BF98"),
                TEXT_SENTINEL()
        };
        wire_ok_t wire_ok[] = {
@@ -2587,51 +2665,89 @@ zonemd(void **state) {
                 */
                WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
                /*
-                * Minimal, one-octet hash for an undefined digest type.
+                * Short 11-octet digest.
                 */
-               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                            0x00),
+               /*
+                * Minimal, 12-octet hash for an undefined digest type.
+                */
+               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                          0x00),
                /*
                 * SHA-384 is defined, so we insist there be a digest of
                 * the expected length.
                 */
-               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00),
+               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00),
                /*
                 * 48-octet digest, valid for SHA-384.
                 */
-               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce),
+               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa,
+                          0xce),
                /*
                 * 56-octet digest, too long for SHA-384.
                 */
-               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce),
+               /*
+                * 56-octet digest, too short for SHA-512
+                */
+               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad),
+               /*
+                * 64-octet digest, just right for SHA-512
+                */
+               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef),
+               /*
+                * 72-octet digest, too long for SHA-512
+                */
+               WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                            0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad,
+                            0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+                            0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
                             0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce),
                /*
                 * 56-octet digest, valid for an undefined digest type.
                 */
-               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
-                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+               WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
+                          0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe,
+                          0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce,
                           0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce),
                /*
                 * Sentinel.