Filename: CHANGELIST Author: Jayant Krishnamurthy, Ronald L. Rivest This file contains a list of changes made to the MD6 submission package, in chronological order (most recent changes last). There are at this point three complete "MD6 submission packages": 2008-10-27 original submission package 2009-01-15 first revision, submitted to NIST and posted on MD6 site 2009-04-15 second revision, posted on MD6 site The third submission may be posted on the NIST site as well at some point in the future. The second contains some bugfixes as documented below; those using MD6 should of course use the latest revision of the MD6 code base. ---------------------------------------------------------------------- ---------------------------------------------------------------------- 2009-01-15 ---------------------------------------------------------------------- ---------------------------------------------------------------------- Modified Code Files: -------------------- Optimized_32bit/md6.h Optimized_64bit/md6.h Reference_Implementation/md6.h The same change was made to all three of these files. The size of the hashval buffer on line 217 has been increased from (md6_c/2)*(md6_w/8) to md6_c*(md6_w/8). The change corrects several buffer overflow errors in md6_mode.c. Assuming the code is compiled with a compiler that follows the ANSI C conventions, this change does not affect the output of MD6 for the following reasons: 1. The ANSI C convention states that the members of structures are laid out in the order they are declared (see http://www.lysator.liu.se/c/rat/c5.html#3-5-2-1 ). 2. The next member of the md6_state struct is the hexhashval buffer. Hence any data that overflows the hashval buffer ends up in the hexhashval buffer, which is large enough to contain all of the overflow. 3. The hexhashval buffer is only used AFTER the digest is transferred to the beginning of the hashval buffer by the trim_hashval function. The hashval buffer is large enough to hold 512 bits, so all possible md6 digests fit within it. We therefore believe that this change does not affect our reported results. Documentation Changes: ----------------------- Section 6.1.2: Several minor wording clarifications and typographic corrections were made. Section 6.10.4.3: A minor wording clarification was made. The following text: (We note that if someone wishes to use keyed MD6 for d-bit MAC computations where d <= 160, they may wish to consider keeping r=80, rather than allowing r to decrease to 40 as d approaches 1. That is, in such cases the output length may not be a good determinant of the desired security level, since we are now worried about key protection rather than collision-resistance. Fixing r=80 appears to provide adequate protection against linear cryptanalysis attacks, for example, even for very short output lengths. Further analysis might show that fewer rounds are also safe, but for now a recommended minimum of 80 rounds would be a conservative approach.) was replaced with: (We note that if someone wishes to use keyed MD6 for d-bit MAC computations where d <= 160, we recommend that they keep r=80, rather than allowing r to decrease to 40 as d approaches 1 as is done for unkeyed usage of MD6. That is, in such cases the output length may not be a good determinant of the desired security level, since we are now worried about key protection rather than collision-resistance. Requiring r >= 80 appears to provide adequate protection against linear cryptanalysis attacks, for example, even for very short output lengths. Further analysis might show that fewer rounds are also safe, but for now a recommended minimum of 80 rounds seems a conservative approach. The default number of rounds for MD6 follows this approach.) Section 6.11.2: "Jean-Phillipe Aumasson" was changed to "Jean-Philippe Aumasson." Section 6.13: "Jean-Phillipe Aumasson" was changed to "Jean-Philippe Aumasson." Section 10: "Jean-Phillipe Aumasson" was changed to "Jean-Philippe Aumasson." ---------------------------------------------------------------------- ---------------------------------------------------------------------- 2009-04-15 ---------------------------------------------------------------------- ---------------------------------------------------------------------- Two changes were made: (1) A minor change to routine "optr" in md6sum.c (2) A significant change to routine "md6_final" in md6_mode.c These changes were made in all three directories: Optimized_32bit/ Optimized_64bit/ Reference_Implementation/ Description of the two changes made: (1) In file "md6sum.c", in the routine "optr": The line if (r<0 || r>255) was changed to if (ropt<0 || ropt>255) The if-test tested the wrong variable; "ropt" is the value obtained from the command-line r option, and is the one that should have been tested. This change is extremely minor, and should have little or no perceptible effect on the behavior of program "md6sum", since normally both r and ropt would be in the legal range 0...255 (inclusive) at the time of this test. Only when an illegal (out of range) value of the r option was given would this change make a difference---the illegal value would not be detected and the program would proceed to use the illegal value, with somewhat unpredictable consequences. (2) In the file "md6_mode.c", in the routine "md6_final": The original two lines: if (hashval != NULL) memcpy( hashval, st->hashval, (st->d+7)/8 ); trim_hashval( st ); were out of order, so they were transposed to be in the correct order, which is: trim_hashval( st ); if (hashval != NULL) memcpy( hashval, st->hashval, (st->d+7)/8 ); Thanks to Piotr Krysiuk for finding and reporting this error! We now discuss the consequences of this bug, and its correction. The bug may cause an MD6 caller to sometimes obtain an incorrect final result, depending on the manner in which it obtained its final result from the MD6 routines. The MD6 routines md6_final may return the final MD6 hash value in one (or both) of two ways: (Also see the internal documentation for routine md6_final in md6_mode.c) (1) Through the "hashval" output parameter to md6_final. (2) Through the "st->hashval" and "st->hexhashval" components of the MD6 state object st (an input parameter). The second way always returns the correct output value(s), but the first way is affected by the bug, and returns an incorrect value. The routine "trim_hashval" moves the *last* d bits of st->hashval to become the *first* d bits of st->hashval, and zeros the remaining bits of st->hashval. When the two lines of md6_final are out of order, the value of st->hashval is copied into md6_final parameter hashval *before* it is trimmed. This is a mistake, and effectively means that the output hash value put into parameter hashval has its first d bits as the first d bits of the final (root) chaining value, rather than the last d bits of the final chaining value, as the MD6 specification requires. Thus, the output parameter hashval receives an incorrect value. However, the components st->hashval and st->hexhashvalue receive the correct value. So, whether the caller receives the correct value or not depends on how it chooses to obtain its output: from the hashval output parameter (incorrect), or from st->hashval and st->hexhashval (correct). Note that the md6_final parameter hashval is optional; it may be given as NULL. If it is NULL, then nothing is copied into the (nonexistent) hashval output buffer, and so the output can only be obtained from st->hashval and st->hexhashval, which are correct. What does this mean for higher-level users of the MD6 functions? (1) If the caller calls MD6 using any of the following: * the NIST API to MD6 given in md6_nist.c, * the functions md6_hash or md6_full_hash given in md6_mode.c, or * the functions md6_init, md6_update, md6_final from md6_mode.c, where the call to md6_final has a non-NULL "hashval" output parameter, and the caller obtains the final hash value result from this hashval output buffer then the output value obtained will be *incorrect* (i.e. inconsistent with the MD6 specification). (2) On the other hand, if the caller calls MD6 using * the functions md6_init, md6_update, md6_final from md6_mode.c, and obtains the final output MD6 hash function value from st->hashval and/or st->hexhashval, or * the md6sum program (source code md6sum.c) then the output value obtained will be *correct* (i.e., consistent with the MD6 specification). If the caller specifies a non-NULL output buffer hashval in its call to md6_final, but the caller ignores the value placed there and uses st->hashval and st->hexhashval instead, the caller will obtain the correct output value. Also, if the caller calls the MD6 compression function directly, rather than using the MD6 mode of operation interface, then this caller will not be affected by the bug. It is not clear that the variant output obtained by the buggy code is actually any weaker than the standard MD6 code that follows the specification. It is probably as good. But it is not in agreement with the MD6 specification. The bug-fix fixes this inconsistency. The bug does not affect any of the sample MD6 computations shown in the MD6 specification document (e.g. http://groups.csail.mit.edu/cis/md6/docs/2009-02-21-md6-report.pdf ), as these sample values were computed using md6sum. The bug also does not affect any of the one-block or two-block computations (with full intermediate results shown) in the "Supporting Documentation" directory in our NIST submission, as those computations were also performed via md6sum. The bug *does* affect the KAT/MCT test results, as the NIST genkat program interfaces through the NIST/MD6 interface in md6_nist.c These KAT/MCT results are thus updated in this revised package. ---------------------------------------------------------------------- ----------------------------------------------------------------------