Hi,

we thank you for all your comments!

The following contains our answers specific to your technical remarks
on the patch itself. Another email on the cryptographic discussion
will follow.

1.) We agree that six new commands are not a good idea. The minimal
variant would be to include sha3-256. If there is a sha512 command, one
could think of adding -- for the sake of consistency -- sha3-512 as
well.

2.) The issue with the SHA2_ONLY macro is fixed now, we also
crosschecked that in distrib/special/md5 no additional code is included
by our patch.

3.) Concerning the question on whether one should also include the
implementation in LibreSSL, we did not think of such an application in
the first place (and also think that we cannot answer it competently).
This is also the reason for the wording "basic" in our submission.

Attached you find the updated patch.

Best regards,
Daniel, Stefan and Alexander

Index: bin/md5/Makefile
===================================================================
RCS file: /cvs/src/bin/md5/Makefile,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 Makefile
--- bin/md5/Makefile    30 Mar 2016 06:38:40 -0000      1.15
+++ bin/md5/Makefile    11 Jan 2018 09:04:04 -0000
@@ -6,6 +6,8 @@ MAN=    cksum.1 md5.1
 LINKS= ${BINDIR}/md5 ${BINDIR}/sha1 \
        ${BINDIR}/md5 ${BINDIR}/sha256 \
        ${BINDIR}/md5 ${BINDIR}/sha512 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-256 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-512 \
        ${BINDIR}/md5 ${BINDIR}/cksum
 
 CPPFLAGS+= -I${.CURDIR}
Index: bin/md5/md5.1
===================================================================
RCS file: /cvs/src/bin/md5/md5.1,v
retrieving revision 1.47
diff -u -p -u -p -r1.47 md5.1
--- bin/md5/md5.1       23 Feb 2017 20:46:08 -0000      1.47
+++ bin/md5/md5.1       11 Jan 2018 09:04:04 -0000
@@ -18,14 +18,18 @@
 .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
 .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
 .\"
-.Dd $Mdocdate: February 23 2017 $
+.Dd $Mdocdate: January 9 2018 $
 .Dt MD5 1
 .Os
 .Sh NAME
 .Nm md5 ,
 .Nm sha1 ,
 .Nm sha256 ,
-.Nm sha512
+.Nm sha512 ,
+.Nm sha3-224 ,
+.Nm sha3-256 ,
+.Nm sha3-384 ,
+.Nm sha3-512
 .Nd calculate a message digest (checksum) for a file
 .Sh SYNOPSIS
 .Nm md5
@@ -52,6 +56,30 @@
 .Op Fl h Ar hashfile
 .Op Fl s Ar string
 .Op Ar
+.Nm sha3-224
+.Op Fl bcpqrtx
+.Op Fl C Ar checklist
+.Op Fl h Ar hashfile
+.Op Fl s Ar string
+.Op Ar
+.Nm sha3-256
+.Op Fl bcpqrtx
+.Op Fl C Ar checklist
+.Op Fl h Ar hashfile
+.Op Fl s Ar string
+.Op Ar
+.Nm sha3-384
+.Op Fl bcpqrtx
+.Op Fl C Ar checklist
+.Op Fl h Ar hashfile
+.Op Fl s Ar string
+.Op Ar
+.Nm sha3-512
+.Op Fl bcpqrtx
+.Op Fl C Ar checklist
+.Op Fl h Ar hashfile
+.Op Fl s Ar string
+.Op Ar
 .Sh DESCRIPTION
 These utilities take as input a message of arbitrary length and produce
 as output a message digest (checksum) of the input.
@@ -136,7 +164,13 @@ and \*(Gt0 if an error occurs.
 .%R RFC 3174
 .%T US Secure Hash Algorithm 1 (SHA1)
 .Re
+.Pp
 .Rs
 .%T Secure Hash Standard
 .%O FIPS PUB 180-2
+.Re
+.Pp
+.Rs
+.%T SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions
+.%O FIPS PUB 202
 .Re
Index: bin/md5/md5.c
===================================================================
RCS file: /cvs/src/bin/md5/md5.c,v
retrieving revision 1.92
diff -u -p -u -p -r1.92 md5.c
--- bin/md5/md5.c       11 Sep 2017 16:35:38 -0000      1.92
+++ bin/md5/md5.c       11 Jan 2018 09:04:04 -0000
@@ -42,6 +42,7 @@
 #include <rmd160.h>
 #include <sha1.h>
 #include <sha2.h>
+#include <sha3.h>
 #include <crc.h>
 
 #define STYLE_MD5      0
@@ -59,6 +60,7 @@ union ANY_CTX {
        MD5_CTX md5;
        RMD160_CTX rmd160;
        SHA1_CTX sha1;
+       SHA3_CTX sha3;
 #endif /* !defined(SHA2_ONLY) */
        SHA2_CTX sha2;
 };
@@ -178,6 +180,52 @@ struct hash_function {
                (void (*)(unsigned char *, void *))SHA512Final,
                (char *(*)(void *, char *))SHA512End
        },
+#if !defined(SHA2_ONLY)
+       {
+               "SHA3-224",
+               SHA3_224_DIGEST_LENGTH,
+               STYLE_MD5,
+               0,
+               NULL,
+               (void (*)(void *))SHA3_224Init,
+               (void (*)(void *, const unsigned char *, size_t))SHA3_Update,
+               (void (*)(unsigned char *, void *))SHA3_Final,
+               (char *(*)(void *, char *))SHA3_224End
+       },
+       {
+               "SHA3-256",
+               SHA3_256_DIGEST_LENGTH,
+               STYLE_MD5,
+               0,
+               NULL,
+               (void (*)(void *))SHA3_256Init,
+               (void (*)(void *, const unsigned char *, size_t))SHA3_Update,
+               (void (*)(unsigned char *, void *))SHA3_Final,
+               (char *(*)(void *, char *))SHA3_256End
+       },
+       {
+               "SHA3-384",
+               SHA3_384_DIGEST_LENGTH,
+               STYLE_MD5,
+               0,
+               NULL,
+               (void (*)(void *))SHA3_384Init,
+               (void (*)(void *, const unsigned char *, size_t))SHA3_Update,
+               (void (*)(unsigned char *, void *))SHA3_Final,
+               (char *(*)(void *, char *))SHA3_384End
+       },
+       {
+               "SHA3-512",
+               SHA3_512_DIGEST_LENGTH,
+               STYLE_MD5,
+               0,
+               NULL,
+               (void (*)(void *))SHA3_512Init,
+               (void (*)(void *, const unsigned char *, size_t))SHA3_Update,
+               (void (*)(unsigned char *, void *))SHA3_Final,
+               (char *(*)(void *, char *))SHA3_512End
+       },
+#endif /* !defined(SHA2_ONLY) */
        {
                NULL,
        }
Index: include/Makefile
===================================================================
RCS file: /cvs/src/include/Makefile,v
retrieving revision 1.222
diff -u -p -u -p -r1.222 Makefile
--- include/Makefile    17 Oct 2017 09:34:52 -0000      1.222
+++ include/Makefile    11 Jan 2018 09:04:18 -0000
@@ -23,7 +23,7 @@ FILES=        a.out.h ar.h asr.h assert.h \
        ndbm.h netdb.h netgroup.h nlist.h nl_types.h \
        paths.h poll.h pthread.h pthread_np.h pwd.h \
        ranlib.h readpassphrase.h regex.h resolv.h rmd160.h \
-       sched.h search.h setjmp.h semaphore.h sha1.h sha2.h \
+       sched.h search.h setjmp.h semaphore.h sha1.h sha2.h sha3.h \
        signal.h siphash.h sndio.h spawn.h stdbool.h stddef.h \
        stdio.h stdlib.h string.h strings.h sysexits.h \
        tar.h tgmath.h tib.h time.h ttyent.h \
Index: include/sha3.h
===================================================================
RCS file: include/sha3.h
diff -N include/sha3.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/sha3.h      11 Jan 2018 09:04:18 -0000
@@ -0,0 +1,78 @@
+#ifndef _SHA3_H
+#define _SHA3_H
+
+#define SHA3_224_DIGEST_LENGTH         28
+#define SHA3_224_DIGEST_STRING_LENGTH  (SHA3_224_DIGEST_LENGTH * 2 + 1)
+
+#define SHA3_256_DIGEST_LENGTH         32
+#define SHA3_256_DIGEST_STRING_LENGTH  (SHA3_256_DIGEST_LENGTH * 2 + 1)
+
+#define SHA3_384_DIGEST_LENGTH         48
+#define SHA3_384_DIGEST_STRING_LENGTH  (SHA3_384_DIGEST_LENGTH * 2 + 1)
+
+#define SHA3_512_DIGEST_LENGTH         64
+#define SHA3_512_DIGEST_STRING_LENGTH  (SHA3_512_DIGEST_LENGTH * 2 + 1)
+
+#define SHA3_STATE_SIZE                (1600 / 8)
+
+
+typedef struct _SHA3_CTX {
+       unsigned char state[SHA3_STATE_SIZE];
+       unsigned int rate;
+       unsigned int byteIOIndex;
+       unsigned int fixedOutputLength;
+} SHA3_CTX;
+
+
+__BEGIN_DECLS
+void SHA3_224Init(SHA3_CTX *);
+char *SHA3_224End(SHA3_CTX *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH)));
+char *SHA3_224File(const char *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH)));
+char *SHA3_224FileChunk(const char *, char *, off_t, off_t)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH)));
+char *SHA3_224Data(const u_int8_t *, size_t, char *)
+       __attribute__((__bounded__(__string__,1,2)))
+       
__attribute__((__bounded__(__minbytes__,3,SHA3_224_DIGEST_STRING_LENGTH)));
+
+void SHA3_256Init(SHA3_CTX *);
+char *SHA3_256End(SHA3_CTX *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH)));
+char *SHA3_256File(const char *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH)));
+char *SHA3_256FileChunk(const char *, char *, off_t, off_t)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH)));
+char *SHA3_256Data(const u_int8_t *, size_t, char *)
+       __attribute__((__bounded__(__string__,1,2)))
+       
__attribute__((__bounded__(__minbytes__,3,SHA3_256_DIGEST_STRING_LENGTH)));
+
+void SHA3_384Init(SHA3_CTX *);
+char *SHA3_384End(SHA3_CTX *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH)));
+char *SHA3_384File(const char *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH)));
+char *SHA3_384FileChunk(const char *, char *, off_t, off_t)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH)));
+char *SHA3_384Data(const u_int8_t *, size_t, char *)
+       __attribute__((__bounded__(__string__,1,2)))
+       
__attribute__((__bounded__(__minbytes__,3,SHA3_384_DIGEST_STRING_LENGTH)));
+
+void SHA3_512Init(SHA3_CTX *);
+char *SHA3_512End(SHA3_CTX *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH)));
+char *SHA3_512File(const char *, char *)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH)));
+char *SHA3_512FileChunk(const char *, char *, off_t, off_t)
+       
__attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH)));
+char *SHA3_512Data(const u_int8_t *, size_t, char *)
+       __attribute__((__bounded__(__string__,1,2)))
+       
__attribute__((__bounded__(__minbytes__,3,SHA3_512_DIGEST_STRING_LENGTH)));
+
+void SHA3_Update(SHA3_CTX *, const u_int8_t *, size_t)
+       __attribute__((__bounded__(__string__,2,3)));
+void SHA3_Final(u_int8_t [SHA3_224_DIGEST_LENGTH], SHA3_CTX *)
+       __attribute__((__bounded__(__minbytes__,1,SHA3_224_DIGEST_LENGTH)));
+__END_DECLS
+
+#endif /* _SHA3_H */
Index: lib/libc/shlib_version
===================================================================
RCS file: /cvs/src/lib/libc/shlib_version,v
retrieving revision 1.197
diff -u -p -u -p -r1.197 shlib_version
--- lib/libc/shlib_version      26 Dec 2017 15:11:17 -0000      1.197
+++ lib/libc/shlib_version      11 Jan 2018 09:04:18 -0000
@@ -1,4 +1,4 @@
 major=92
-minor=2
+minor=3
 # note: If changes were made to include/thread_private.h or if system
 # calls were added/changed then librthread/shlib_version also be updated.
Index: lib/libc/hash/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libc/hash/Makefile.inc,v
retrieving revision 1.24
diff -u -p -u -p -r1.24 Makefile.inc
--- lib/libc/hash/Makefile.inc  3 Sep 2016 16:25:03 -0000       1.24
+++ lib/libc/hash/Makefile.inc  11 Jan 2018 09:04:18 -0000
@@ -3,9 +3,9 @@
 # hash functions
 .PATH: ${LIBCSRCDIR}/hash
 
-HELPER=        md5hl.c rmd160hl.c sha1hl.c sha224hl.c sha256hl.c sha384hl.c 
sha512hl.c sha512_256hl.c
-SRCS+= md5.c rmd160.c sha1.c sha2.c ${HELPER} siphash.c
-MAN+=  md5.3 rmd160.3 sha1.3 sha2.3 SipHash24.3
+HELPER=        md5hl.c rmd160hl.c sha1hl.c sha224hl.c sha256hl.c sha384hl.c 
sha512hl.c sha512_256hl.c sha3-224hl.c sha3-256hl.c sha3-384hl.c sha3-512hl.c   
+SRCS+= md5.c rmd160.c sha1.c sha2.c sha3.c ${HELPER} siphash.c
+MAN+=  md5.3 rmd160.3 sha1.3 sha2.3 sha3.3 SipHash24.3
 
 CLEANFILES+= ${HELPER}
 
@@ -43,4 +43,32 @@ sha512_256hl.c:      helper.c
            -e 's/HASH/SHA512_256/g' \
            -e 's/SHA512_256_CTX/SHA2_CTX/g' $> > $@
 
-beforedepend: md5hl.c rmd160hl.c sha1hl.c sha256hl.c sha384hl.c sha512hl.c 
sha512_256hl.c
+sha3-224hl.c:   helper.c
+       sed -e 's/hashinc/sha3.h/g' \
+            -e 's/HASH/SHA3_224/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Update/SHA3_Update/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Final/SHA3_Final/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]_CTX/SHA3_CTX/g' $> > $@
+
+sha3-256hl.c:   helper.c
+       sed -e 's/hashinc/sha3.h/g' \
+            -e 's/HASH/SHA3_256/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Update/SHA3_Update/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Final/SHA3_Final/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]_CTX/SHA3_CTX/g' $> > $@
+
+sha3-384hl.c:   helper.c
+       sed -e 's/hashinc/sha3.h/g' \
+            -e 's/HASH/SHA3_384/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Update/SHA3_Update/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Final/SHA3_Final/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]_CTX/SHA3_CTX/g' $> > $@
+
+sha3-512hl.c:   helper.c
+       sed -e 's/hashinc/sha3.h/g' \
+            -e 's/HASH/SHA3_512/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Update/SHA3_Update/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]Final/SHA3_Final/g' \
+            -e 's/SHA3_[0-9][0-9][0-9]_CTX/SHA3_CTX/g' $> > $@
+
+beforedepend: md5hl.c rmd160hl.c sha1hl.c sha256hl.c sha384hl.c sha512hl.c 
sha512_256hl.c sha3-224hl.c sha3-256hl.c sha3-384hl.c sha3-512hl.c  
Index: lib/libc/hash/sha3.3
===================================================================
RCS file: lib/libc/hash/sha3.3
diff -N lib/libc/hash/sha3.3
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/hash/sha3.3        11 Jan 2018 09:04:18 -0000
@@ -0,0 +1,292 @@
+.\"    $OpenBSD: sha2.3,v 1.26 2016/09/04 09:28:12 tedu Exp $
+.\"
+.\" Copyright (c) 2003, 2004 Todd C. Miller <todd.mil...@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.\" See http://www.nist.gov/sha/ for the detailed standard
+.\"
+.Dd $Mdocdate: January 9 2018 $
+.Dt SHA3INIT 3
+.Os
+.Sh NAME
+.Nm SHA3_224Init ,
+.Nm SHA3_224Update ,
+.Nm SHA3_224Final ,
+.Nm SHA3_224End ,
+.Nm SHA3_224File ,
+.Nm SHA3_224FileChunk ,
+.Nm SHA3_224Data ,
+.Nm SHA3_256Init ,
+.Nm SHA3_256Update ,
+.Nm SHA3_256Final ,
+.Nm SHA3_256End ,
+.Nm SHA3_256File ,
+.Nm SHA3_256FileChunk ,
+.Nm SHA3_256Data ,
+.Nm SHA3_384Init ,
+.Nm SHA3_384Update ,
+.Nm SHA3_384Final ,
+.Nm SHA3_384End ,
+.Nm SHA3_384File ,
+.Nm SHA3_384FileChunk ,
+.Nm SHA3_384Data ,
+.Nm SHA3_512Init ,
+.Nm SHA3_512Update ,
+.Nm SHA3_512Final ,
+.Nm SHA3_512End ,
+.Nm SHA3_512File ,
+.Nm SHA3_512FileChunk ,
+.Nm SHA3_512Data ,
+.Nm SHA3_512_256Init ,
+.Nm SHA3_512_256Update ,
+.Nm SHA3_512_256Final ,
+.Nm SHA3_512_256End ,
+.Nm SHA3_512_256File ,
+.Nm SHA3_512_256FileChunk ,
+.Nm SHA3_512_256Data
+.Nd calculate the NIST Secure Hash Standard (version 3)
+.Sh SYNOPSIS
+.In sys/types.h
+.In sha3.h
+.Ft void
+.Fn SHA3_224Init "SHA3_CTX *context"
+.Ft void
+.Fn SHA3_224Update "SHA3_CTX *context" "const u_int8_t *data" "size_t len"
+.Ft void
+.Fn SHA3_224Final "u_int8_t digest[SHA3_224_DIGEST_LENGTH]" "SHA3_CTX *context"
+.Ft "char *"
+.Fn SHA3_224End "SHA3_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA3_224File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA3_224FileChunk "const char *filename" "char *buf" "off_t offset" "off_t 
length"
+.Ft "char *"
+.Fn SHA3_224Data "const u_int8_t *data" "size_t len" "char *buf"
+.Ft void
+.Fn SHA3_256Init "SHA3_CTX *context"
+.Ft void
+.Fn SHA3_256Update "SHA3_CTX *context" "const u_int8_t *data" "size_t len"
+.Ft void
+.Fn SHA3_256Final "u_int8_t digest[SHA3_256_DIGEST_LENGTH]" "SHA3_CTX *context"
+.Ft "char *"
+.Fn SHA3_256End "SHA3_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA3_256File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA3_256FileChunk "const char *filename" "char *buf" "off_t offset" "off_t 
length"
+.Ft "char *"
+.Fn SHA3_256Data "const u_int8_t *data" "size_t len" "char *buf"
+.Ft void
+.Fn SHA3_384Init "SHA3_CTX *context"
+.Ft void
+.Fn SHA3_384Update "SHA3_CTX *context" "const u_int8_t *data" "size_t len"
+.Ft void
+.Fn SHA3_384Final "u_int8_t digest[SHA3_384_DIGEST_LENGTH]" "SHA3_CTX *context"
+.Ft "char *"
+.Fn SHA3_384End "SHA3_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA3_384File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA3_384FileChunk "const char *filename" "char *buf" "off_t offset" "off_t 
length"
+.Ft "char *"
+.Fn SHA3_384Data "const u_int8_t *data" "size_t len" "char *buf"
+.Ft void
+.Fn SHA3_512Init "SHA3_CTX *context"
+.Ft void
+.Fn SHA3_512Update "SHA3_CTX *context" "const u_int8_t *data" "size_t len"
+.Ft void
+.Fn SHA3_512Final "u_int8_t digest[SHA3_512_DIGEST_LENGTH]" "SHA3_CTX *context"
+.Ft "char *"
+.Fn SHA3_512End "SHA3_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA3_512File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA3_512FileChunk "const char *filename" "char *buf" "off_t offset" "off_t 
length"
+.Ft "char *"
+.Fn SHA3_512Data "const u_int8_t *data" "size_t len" "char *buf"
+.Ft void
+.Fn SHA3_512_256Init "SHA3_CTX *context"
+.Ft void
+.Fn SHA3_512_256Update "SHA3_CTX *context" "const u_int8_t *data" "size_t len"
+.Ft void
+.Fn SHA3_512_256Final "u_int8_t digest[SHA3_512_256_DIGEST_LENGTH]" "SHA3_CTX 
*context"
+.Ft "char *"
+.Fn SHA3_512_256End "SHA3_CTX *context" "char *buf"
+.Ft "char *"
+.Fn SHA3_512_256File "const char *filename" "char *buf"
+.Ft "char *"
+.Fn SHA3_512_256FileChunk "const char *filename" "char *buf" "off_t offset" 
"off_t length"
+.Ft "char *"
+.Fn SHA3_512_256Data "const u_int8_t *data" "size_t len" "char *buf"
+.Sh DESCRIPTION
+The SHA-3 functions implement the NIST Secure Hash Standard,
+FIPS PUB 202.
+The SHA-3 functions are used to generate a condensed representation of a
+message called a message digest, suitable for use as a digital signature.
+There are four families of functions, with names corresponding to
+the number of bits in the resulting message digest.
+The functions can process a message of arbitrary length as input.
+.Pp
+The SHA-3 functions are considered to be more secure than the
+.Xr sha1 3
+functions with which they share a similar interface. They are an
+alternative to the
+.Xr sha2 3
+functions.
+The 224, 256, 384, and 512-bit versions of SHA-3 share the same interface.
+For brevity, only the 256-bit variants are described below.
+.Pp
+The
+.Fn SHA3_256Init
+function initializes a SHA3_CTX
+.Fa context
+for use with
+.Fn SHA3_256Update
+and
+.Fn SHA3_256Final .
+The
+.Fn SHA3_256Update
+function adds
+.Fa data
+of length
+.Fa len
+to the SHA3_CTX specified by
+.Fa context .
+.Fn SHA3_256Final
+is called when all data has been added via
+.Fn SHA3_256Update
+and stores a message digest in the
+.Fa digest
+parameter.
+.Pp
+The
+.Fn SHA3_256End
+function is a front end for
+.Fn SHA3_256Final
+which converts the digest into an
+.Tn ASCII
+representation of the digest in hexadecimal.
+.Pp
+The
+.Fn SHA3_256File
+function calculates the digest for a file and returns the result via
+.Fn SHA3_256End .
+If
+.Fn SHA3_256File
+is unable to open the file, a
+.Dv NULL
+pointer is returned.
+.Pp
+.Fn SHA3_256FileChunk
+behaves like
+.Fn SHA3_256File
+but calculates the digest only for that portion of the file starting at
+.Fa offset
+and continuing for
+.Fa length
+bytes or until end of file is reached, whichever comes first.
+A zero
+.Fa length
+can be specified to read until end of file.
+A negative
+.Fa length
+or
+.Fa offset
+will be ignored.
+.Pp
+The
+.Fn SHA3_256Data
+function
+calculates the digest of an arbitrary string and returns the result via
+.Fn SHA3_256End .
+.Pp
+For each of the
+.Fn SHA3_256End ,
+.Fn SHA3_256File ,
+.Fn SHA3_256FileChunk ,
+and
+.Fn SHA3_256Data
+functions the
+.Fa buf
+parameter should either be a string large enough to hold the resulting digest
+(e.g.\&
+.Dv SHA3_224_DIGEST_STRING_LENGTH ,
+.Dv SHA3_256_DIGEST_STRING_LENGTH ,
+.Dv SHA3_384_DIGEST_STRING_LENGTH ,
+.Dv SHA3_512_DIGEST_STRING_LENGTH ,
+or
+.Dv SHA3_512_256_DIGEST_STRING_LENGTH ,
+depending on the function being used)
+or a
+.Dv NULL
+pointer.
+In the latter case, space will be dynamically allocated via
+.Xr malloc 3
+and should be freed using
+.Xr free 3
+when it is no longer needed.
+.Sh EXAMPLES
+The following code fragment will calculate the SHA3-256 digest for the string
+.Qq abc ,
+which is
+.Dq 0x3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532 .
+.Bd -literal -offset indent
+SHA3_CTX ctx;
+u_int8_t results[SHA3_256_DIGEST_LENGTH];
+char *buf;
+int n;
+
+buf = "abc";
+n = strlen(buf);
+SHA3_256Init(&ctx);
+SHA3_256Update(&ctx, (u_int8_t *)buf, n);
+SHA3_256Final(results, &ctx);
+
+/* Print the digest as one long hex value */
+printf("0x");
+for (n = 0; n \*(Lt SHA3_256_DIGEST_LENGTH; n++)
+       printf("%02x", results[n]);
+putchar('\en');
+.Ed
+.Pp
+Alternately, the helper functions could be used in the following way:
+.Bd -literal -offset indent
+u_int8_t output[SHA3_256_DIGEST_STRING_LENGTH];
+char *buf = "abc";
+
+printf("0x%s\en", SHA3_256Data(buf, strlen(buf), output));
+.Ed
+.Sh SEE ALSO
+.Xr cksum 1 ,
+.Xr md5 3 ,
+.Xr rmd160 3 ,
+.Xr sha1 3 ,
+.Xr sha2 3
+.Rs
+.%T SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions
+.%O FIPS PUB 202
+.Re
+.Pp
+The
+.Fn SHA3_256End ,
+.Fn SHA3_256File ,
+.Fn SHA3_256FileChunk ,
+and
+.Fn SHA3_256Data
+helper functions are derived from code written by
+.An Poul-Henning Kamp .
Index: lib/libc/hash/sha3.c
===================================================================
RCS file: lib/libc/hash/sha3.c
diff -N lib/libc/hash/sha3.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/hash/sha3.c        11 Jan 2018 09:04:18 -0000
@@ -0,0 +1,761 @@
+/*
+ * Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
+ * Joan Daemen, Michaƫl Peeters, Gilles Van Assche and Ronny Van Keer, hereby
+ * denoted as "the implementer".
+ * 
+ * For more information, feedback or questions, please refer to our websites:
+ * http://keccak.noekeon.org/
+ * http://keyak.noekeon.org/
+ * http://ketje.noekeon.org/
+ * 
+ * Adaptation to OpenBSD in 2017/18 by
+ * Stefan-Lukas Gazdag, Alexander von Gernler and Daniel Loebenberger
+ * https://www.genua.de/
+ * also denoted as "the implementer"
+ * 
+ * To the extent possible under law, the implementer has waived all copyright
+ * and related or neighboring rights to the source code in this file.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <string.h>
+#include <strings.h>
+#include <sha3.h>
+
+typedef unsigned long long tKeccakLane;
+
+#define SHA3_NRROUNDS 24
+#define SHA3_NRLANES 25
+#define SHA3_DELIMITER 0x06
+
+#define index(x, y) (((x)%5)+5*((y)%5))
+
+const tKeccakLane KeccakRoundConstants[SHA3_NRROUNDS] =
+{
+       0x0000000000000001,
+       0x0000000000008082,
+       0x800000000000808a,
+       0x8000000080008000,
+       0x000000000000808b,
+       0x0000000080000001,
+       0x8000000080008081,
+       0x8000000000008009,
+       0x000000000000008a,
+       0x0000000000000088,
+       0x0000000080008009,
+       0x000000008000000a,
+       0x000000008000808b,
+       0x800000000000008b,
+       0x8000000000008089,
+       0x8000000000008003,
+       0x8000000000008002,
+       0x8000000000000080,
+       0x000000000000800a,
+       0x800000008000000a,
+       0x8000000080008081,
+       0x8000000000008080,
+       0x0000000080000001,
+       0x8000000080008008,
+};
+
+const unsigned int KeccakRhoOffsets[SHA3_NRLANES] =
+{
+       0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43,
+       25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
+};
+
+/*
+ * unused, but these constance denote the one implementation out of the
+ * Keccak Code Package that was taken here
+ */
+#define KeccakP1600_implementation      "64-bit reference implementation"
+#define KeccakP1600_stateSizeInBytes    200
+#define KeccakP1600_stateAlignment      8
+
+/* prototypes for local functions */
+static void KeccakP1600_AddByte(void *state, unsigned char data,
+    unsigned int offset);
+static void KeccakP1600_AddBytes(void *state, const unsigned char *data,
+    unsigned int offset, unsigned int length);
+static void KeccakP1600_Permute_24rounds(void *state);
+static void KeccakP1600_ExtractBytes(const void *state, unsigned char *data,
+    unsigned int offset, unsigned int length);
+static void Keccak_HashInitialize(SHA3_CTX *, unsigned int, unsigned int);
+
+
+/*
+ * interface functions external use
+ * (rate + capacity) = 1600,
+ * thus the rate specifies the capacity
+ */
+void
+SHA3_224Init(SHA3_CTX *context)
+{
+       /* rate = 1152, output width 224 bit */
+       Keccak_HashInitialize(context, 1152, 224);
+}
+DEF_WEAK(SHA3_224Init);
+
+void
+SHA3_256Init(SHA3_CTX *context)
+{
+       /* rate = 1088, output width 256 bit */
+       Keccak_HashInitialize(context, 1088, 256);
+}
+DEF_WEAK(SHA3_256Init);
+
+void
+SHA3_384Init(SHA3_CTX *context)
+{
+       /* rate = 832, output width 384 bit */
+       Keccak_HashInitialize(context, 832, 384);
+}
+DEF_WEAK(SHA3_384Init);
+
+void
+SHA3_512Init(SHA3_CTX *context)
+{
+       /* rate = 576, output width 512 bit */
+       Keccak_HashInitialize(context, 576, 512);
+}
+DEF_WEAK(SHA3_512Init);
+
+
+void
+SHA3_Update(SHA3_CTX *context, const u_int8_t *data, size_t len)
+{
+       size_t i, j;
+       unsigned int partialBlock;
+       const unsigned char *curData;
+       unsigned int rateInBytes;
+       rateInBytes = context->rate/8;
+
+       i = 0;
+       curData = data;
+       while(i < len) {
+               if ((context->byteIOIndex == 0) && (len >= (i + rateInBytes))) {
+#ifdef SnP_FastLoop_Absorb
+                       /* processing full blocks first */
+                       if ((rateInBytes % (KeccakP1600_width/200)) == 0) {
+                               /* fast lane: whole lane rate */
+                               j = KeccakP1600_FastLoop_Absorb(context->state,
+                                   rateInBytes/(KeccakP1600_width/200), 
curData, len - i);
+                               i += j;
+                               curData += j;
+                       }
+                       else {
+#endif
+                               for(j=len-i; j>=rateInBytes; j-=rateInBytes) {
+#ifdef KeccakReference
+                                       displayBytes(1, "Block to be absorbed", 
curData, rateInBytes);
+#endif
+                                       KeccakP1600_AddBytes(context->state, 
curData, 0, rateInBytes);
+                                       
KeccakP1600_Permute_24rounds(context->state);
+                                       curData+=rateInBytes;
+                               }
+                               i = len - j;
+#ifdef SnP_FastLoop_Absorb
+                       }
+#endif
+               }
+               else {
+                       /* normal lane: using the message queue */
+                       partialBlock = (unsigned int)(len - i);
+                       if (partialBlock+context->byteIOIndex > rateInBytes)
+                               partialBlock = rateInBytes-context->byteIOIndex;
+#ifdef KeccakReference
+                       displayBytes(1, "Block to be absorbed (part)", curData, 
partialBlock);
+#endif
+                       i += partialBlock;
+
+                       KeccakP1600_AddBytes(context->state, curData, 
context->byteIOIndex, partialBlock);
+                       curData += partialBlock;
+                       context->byteIOIndex += partialBlock;
+                       if (context->byteIOIndex == rateInBytes) {
+                               KeccakP1600_Permute_24rounds(context->state);
+                               context->byteIOIndex = 0;
+                       }
+               }
+       }
+}
+DEF_WEAK(SHA3_Update);
+
+void
+SHA3_Final(u_int8_t* digest, SHA3_CTX *context)
+{
+       size_t i, j;
+       unsigned int partialBlock;
+       unsigned char *curData;
+       unsigned int rateInBytes;
+       size_t dataByteLen;
+
+       rateInBytes = context->rate/8;
+       dataByteLen = context->fixedOutputLength/8;
+
+       /* Last few bits, whose delimiter coincides with first bit of padding */
+       KeccakP1600_AddByte(context->state, SHA3_DELIMITER, 
context->byteIOIndex);
+
+       /*
+        * If the first bit of padding is at position rate-1, we need a whole
+        * new block for the second bit of padding
+        */
+       /* Second bit of padding */
+       KeccakP1600_AddByte(context->state, 0x80, rateInBytes-1);
+
+       KeccakP1600_Permute_24rounds(context->state);
+       context->byteIOIndex = 0;
+
+       /* SQUEEZE */
+       i = 0;
+       curData = digest;
+       while(i < dataByteLen) {
+               if ((context->byteIOIndex == rateInBytes) && (dataByteLen >= (i 
+ rateInBytes))) {
+                       for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
+                               KeccakP1600_Permute_24rounds(context->state);
+                               KeccakP1600_ExtractBytes(context->state, 
curData, 0, rateInBytes);
+                               curData+=rateInBytes;
+                       }
+                       i = dataByteLen - j;
+               }
+               else {
+                       /* normal lane: using the message queue */
+                       if (context->byteIOIndex == rateInBytes) {
+                               KeccakP1600_Permute_24rounds(context->state);
+                               context->byteIOIndex = 0;
+                       }
+                       partialBlock = (unsigned int)(dataByteLen - i);
+                       if (partialBlock+context->byteIOIndex > rateInBytes)
+                               partialBlock = rateInBytes-context->byteIOIndex;
+                       i += partialBlock;
+
+                       KeccakP1600_ExtractBytes(context->state, curData, 
context->byteIOIndex, partialBlock);
+                       curData += partialBlock;
+                       context->byteIOIndex += partialBlock;
+               }
+       }
+}
+DEF_WEAK(SHA3_Final);
+
+/*
+ * internal functions
+ */
+static void
+Keccak_HashInitialize(SHA3_CTX *context, unsigned int rate,
+    unsigned int hashbitlen)
+{
+       bzero(context->state, SHA3_STATE_SIZE);
+       context->rate = rate;
+       context->byteIOIndex = 0;
+       context->fixedOutputLength = hashbitlen;
+}
+
+static void
+KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)
+{
+       assert(offset < 200);
+       ((unsigned char *)state)[offset] ^= byte;
+}
+
+static void
+KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int 
offset, unsigned int length)
+{
+       unsigned int i;
+
+       assert(offset < 200);
+       assert(offset+length <= 200);
+       for(i=0; i<length; i++)
+               ((unsigned char *)state)[offset+i] ^= data[i];
+}
+
+#if BYTE_ORDER == BIG_ENDIAN
+static void fromBytesToWords(tKeccakLane *stateAsWords, const unsigned char 
*state);
+static void fromWordsToBytes(unsigned char *state, const tKeccakLane 
*stateAsWords);
+#endif
+static void KeccakP1600OnWords(tKeccakLane *state);
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void KeccakP1600QuadRound(tKeccakLane *state, unsigned int indexRound);
+#else
+static void KeccakP1600RoundSlow(tKeccakLane *state, unsigned int indexRound);
+static void theta(tKeccakLane *A);
+static void rho(tKeccakLane *A);
+static void pi(tKeccakLane *A);
+static void chi(tKeccakLane *A);
+static void iota(tKeccakLane *A, unsigned int indexRound);
+#endif
+
+static void
+KeccakP1600_Permute_24rounds(void *state)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+       KeccakP1600OnWords((tKeccakLane*)state);
+#else
+       tKeccakLane stateAsWords[1600/64];
+
+       fromBytesToWords(stateAsWords, (const unsigned char *)state);
+       KeccakP1600OnWords(stateAsWords);
+       fromWordsToBytes((unsigned char *)state, stateAsWords);
+#endif
+}
+
+#if BYTE_ORDER == BIG_ENDIAN
+static void 
+fromBytesToWords(tKeccakLane *stateAsWords, const unsigned char *state)
+{
+       unsigned int i, j;
+
+       for(i=0; i<SHA3_NRLANES; i++) {
+               stateAsWords[i] = 0;
+               for(j=0; j<(64/8); j++)
+                       stateAsWords[i] |= (tKeccakLane)(state[i*(64/8)+j]) << 
(8*j);
+       }
+}
+
+static void 
+fromWordsToBytes(unsigned char *state, const tKeccakLane *stateAsWords)
+{
+       unsigned int i, j;
+
+       for(i=0; i<SHA3_NRLANES; i++)
+               for(j=0; j<(64/8); j++)
+                       state[i*(64/8)+j] = (unsigned char)((stateAsWords[i] >> 
(8*j)) & 0xFF);
+}
+#endif
+
+static void
+KeccakP1600OnWords(tKeccakLane *state)
+{
+       unsigned int i;
+
+
+#if BYTE_ORDER == BIG_ENDIAN
+       /*
+        * Use the unoptimized reference implementation when
+        * on big endian machines
+        */
+       for(i=0; i<SHA3_NRROUNDS; i++)
+               KeccakP1600RoundSlow(state, i);
+#else
+       /* 
+        * Use the inplace version from the Keccak optimized reference
+        * code of KeccakP1600 on little endian machines
+        * Note that this routine does four rounds in one call.
+        * */
+       for(i=0; i<SHA3_NRROUNDS; i+=4)
+               KeccakP1600QuadRound(state, i);
+#endif
+}
+
+#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ 
(((tKeccakLane)a) >> (64-offset))) : a)
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void
+KeccakP1600QuadRound(tKeccakLane *state, unsigned int indexRound)
+{        
+        /*
+        * Inplace implementation by Ronny Van Keer and the designers
+        * of Keccak from the optimized Keccak reference code
+        */
+       
+       tKeccakLane Ba, Be, Bi, Bo, Bu;
+        tKeccakLane Ca, Ce, Ci, Co, Cu;
+        tKeccakLane Da, De, Di, Do, Du;
+
+#define Aba state[ 0]
+#define Abe state[ 1]
+#define Abi state[ 2]
+#define Abo state[ 3]
+#define Abu state[ 4]
+#define Aga state[ 5]
+#define Age state[ 6]
+#define Agi state[ 7]
+#define Ago state[ 8]
+#define Agu state[ 9]
+#define Aka state[10]
+#define Ake state[11]
+#define Aki state[12]
+#define Ako state[13]
+#define Aku state[14]
+#define Ama state[15]
+#define Ame state[16]
+#define Ami state[17]
+#define Amo state[18]
+#define Amu state[19]
+#define Asa state[20]
+#define Ase state[21]
+#define Asi state[22]
+#define Aso state[23]
+#define Asu state[24]
+
+        Ca = Aba^Aga^Aka^Ama^Asa;
+        Ce = Abe^Age^Ake^Ame^Ase;
+        Ci = Abi^Agi^Aki^Ami^Asi;
+        Co = Abo^Ago^Ako^Amo^Aso;
+        Cu = Abu^Agu^Aku^Amu^Asu;
+        Da = Cu^ROL64(Ce, 1);
+        De = Ca^ROL64(Ci, 1);
+        Di = Ce^ROL64(Co, 1);
+        Do = Ci^ROL64(Cu, 1);
+        Du = Co^ROL64(Ca, 1);
+
+        Ba = (Aba^Da);
+        Be = ROL64((Age^De), 44);
+        Bi = ROL64((Aki^Di), 43);
+        Bo = ROL64((Amo^Do), 21);
+        Bu = ROL64((Asu^Du), 14);
+        Aba =   Ba ^((~Be)&  Bi );
+        Aba ^= KeccakRoundConstants[indexRound];
+        Age =   Be ^((~Bi)&  Bo );
+        Aki =   Bi ^((~Bo)&  Bu );
+        Amo =   Bo ^((~Bu)&  Ba );
+        Asu =   Bu ^((~Ba)&  Be );
+
+        Bi = ROL64((Aka^Da), 3);
+        Bo = ROL64((Ame^De), 45);
+        Bu = ROL64((Asi^Di), 61);
+        Ba = ROL64((Abo^Do), 28);
+        Be = ROL64((Agu^Du), 20);
+        Aka =   Ba ^((~Be)&  Bi );
+        Ame =   Be ^((~Bi)&  Bo );
+        Asi =   Bi ^((~Bo)&  Bu );
+        Abo =   Bo ^((~Bu)&  Ba );
+        Agu =   Bu ^((~Ba)&  Be );
+
+        Bu = ROL64((Asa^Da), 18);
+        Ba = ROL64((Abe^De), 1);
+        Be = ROL64((Agi^Di), 6);
+        Bi = ROL64((Ako^Do), 25);
+        Bo = ROL64((Amu^Du), 8);
+        Asa =   Ba ^((~Be)&  Bi );
+        Abe =   Be ^((~Bi)&  Bo );
+        Agi =   Bi ^((~Bo)&  Bu );
+        Ako =   Bo ^((~Bu)&  Ba );
+        Amu =   Bu ^((~Ba)&  Be );
+
+        Be = ROL64((Aga^Da), 36);
+        Bi = ROL64((Ake^De), 10);
+        Bo = ROL64((Ami^Di), 15);
+        Bu = ROL64((Aso^Do), 56);
+        Ba = ROL64((Abu^Du), 27);
+        Aga =   Ba ^((~Be)&  Bi );
+        Ake =   Be ^((~Bi)&  Bo );
+        Ami =   Bi ^((~Bo)&  Bu );
+        Aso =   Bo ^((~Bu)&  Ba );
+        Abu =   Bu ^((~Ba)&  Be );
+
+        Bo = ROL64((Ama^Da), 41);
+        Bu = ROL64((Ase^De), 2);
+        Ba = ROL64((Abi^Di), 62);
+        Be = ROL64((Ago^Do), 55);
+        Bi = ROL64((Aku^Du), 39);
+        Ama =   Ba ^((~Be)&  Bi );
+        Ase =   Be ^((~Bi)&  Bo );
+        Abi =   Bi ^((~Bo)&  Bu );
+        Ago =   Bo ^((~Bu)&  Ba );
+        Aku =   Bu ^((~Ba)&  Be );
+
+        Ca = Aba^Aka^Asa^Aga^Ama;
+        Ce = Age^Ame^Abe^Ake^Ase;
+        Ci = Aki^Asi^Agi^Ami^Abi;
+        Co = Amo^Abo^Ako^Aso^Ago;
+        Cu = Asu^Agu^Amu^Abu^Aku;
+        Da = Cu^ROL64(Ce, 1);
+        De = Ca^ROL64(Ci, 1);
+        Di = Ce^ROL64(Co, 1);
+        Do = Ci^ROL64(Cu, 1);
+        Du = Co^ROL64(Ca, 1);
+
+        Ba = (Aba^Da);
+        Be = ROL64((Ame^De), 44);
+        Bi = ROL64((Agi^Di), 43);
+        Bo = ROL64((Aso^Do), 21);
+        Bu = ROL64((Aku^Du), 14);
+        Aba =   Ba ^((~Be)&  Bi );
+        Aba ^= KeccakRoundConstants[indexRound+1];
+        Ame =   Be ^((~Bi)&  Bo );
+        Agi =   Bi ^((~Bo)&  Bu );
+        Aso =   Bo ^((~Bu)&  Ba );
+        Aku =   Bu ^((~Ba)&  Be );
+
+        Bi = ROL64((Asa^Da), 3);
+        Bo = ROL64((Ake^De), 45);
+        Bu = ROL64((Abi^Di), 61);
+        Ba = ROL64((Amo^Do), 28);
+        Be = ROL64((Agu^Du), 20);
+        Asa =   Ba ^((~Be)&  Bi );
+        Ake =   Be ^((~Bi)&  Bo );
+        Abi =   Bi ^((~Bo)&  Bu );
+        Amo =   Bo ^((~Bu)&  Ba );
+        Agu =   Bu ^((~Ba)&  Be );
+
+        Bu = ROL64((Ama^Da), 18);
+        Ba = ROL64((Age^De), 1);
+        Be = ROL64((Asi^Di), 6);
+        Bi = ROL64((Ako^Do), 25);
+        Bo = ROL64((Abu^Du), 8);
+        Ama =   Ba ^((~Be)&  Bi );
+        Age =   Be ^((~Bi)&  Bo );
+        Asi =   Bi ^((~Bo)&  Bu );
+        Ako =   Bo ^((~Bu)&  Ba );
+        Abu =   Bu ^((~Ba)&  Be );
+
+        Be = ROL64((Aka^Da), 36);
+        Bi = ROL64((Abe^De), 10);
+        Bo = ROL64((Ami^Di), 15);
+        Bu = ROL64((Ago^Do), 56);
+        Ba = ROL64((Asu^Du), 27);
+        Aka =   Ba ^((~Be)&  Bi );
+        Abe =   Be ^((~Bi)&  Bo );
+        Ami =   Bi ^((~Bo)&  Bu );
+        Ago =   Bo ^((~Bu)&  Ba );
+        Asu =   Bu ^((~Ba)&  Be );
+
+        Bo = ROL64((Aga^Da), 41);
+        Bu = ROL64((Ase^De), 2);
+        Ba = ROL64((Aki^Di), 62);
+        Be = ROL64((Abo^Do), 55);
+        Bi = ROL64((Amu^Du), 39);
+        Aga =   Ba ^((~Be)&  Bi );
+        Ase =   Be ^((~Bi)&  Bo );
+        Aki =   Bi ^((~Bo)&  Bu );
+        Abo =   Bo ^((~Bu)&  Ba );
+        Amu =   Bu ^((~Ba)&  Be );
+
+        Ca = Aba^Asa^Ama^Aka^Aga;
+        Ce = Ame^Ake^Age^Abe^Ase;
+        Ci = Agi^Abi^Asi^Ami^Aki;
+        Co = Aso^Amo^Ako^Ago^Abo;
+        Cu = Aku^Agu^Abu^Asu^Amu;
+        Da = Cu^ROL64(Ce, 1);
+        De = Ca^ROL64(Ci, 1);
+        Di = Ce^ROL64(Co, 1);
+        Do = Ci^ROL64(Cu, 1);
+        Du = Co^ROL64(Ca, 1);
+
+        Ba = (Aba^Da);
+        Be = ROL64((Ake^De), 44);
+        Bi = ROL64((Asi^Di), 43);
+        Bo = ROL64((Ago^Do), 21);
+        Bu = ROL64((Amu^Du), 14);
+        Aba =   Ba ^((~Be)&  Bi );
+        Aba ^= KeccakRoundConstants[indexRound+2];
+        Ake =   Be ^((~Bi)&  Bo );
+        Asi =   Bi ^((~Bo)&  Bu );
+        Ago =   Bo ^((~Bu)&  Ba );
+        Amu =   Bu ^((~Ba)&  Be );
+
+        Bi = ROL64((Ama^Da), 3);
+        Bo = ROL64((Abe^De), 45);
+        Bu = ROL64((Aki^Di), 61);
+        Ba = ROL64((Aso^Do), 28);
+        Be = ROL64((Agu^Du), 20);
+        Ama =   Ba ^((~Be)&  Bi );
+        Abe =   Be ^((~Bi)&  Bo );
+        Aki =   Bi ^((~Bo)&  Bu );
+        Aso =   Bo ^((~Bu)&  Ba );
+        Agu =   Bu ^((~Ba)&  Be );
+
+        Bu = ROL64((Aga^Da), 18);
+        Ba = ROL64((Ame^De), 1);
+        Be = ROL64((Abi^Di), 6);
+        Bi = ROL64((Ako^Do), 25);
+        Bo = ROL64((Asu^Du), 8);
+        Aga =   Ba ^((~Be)&  Bi );
+        Ame =   Be ^((~Bi)&  Bo );
+        Abi =   Bi ^((~Bo)&  Bu );
+        Ako =   Bo ^((~Bu)&  Ba );
+        Asu =   Bu ^((~Ba)&  Be );
+
+        Be = ROL64((Asa^Da), 36);
+        Bi = ROL64((Age^De), 10);
+        Bo = ROL64((Ami^Di), 15);
+        Bu = ROL64((Abo^Do), 56);
+        Ba = ROL64((Aku^Du), 27);
+        Asa =   Ba ^((~Be)&  Bi );
+        Age =   Be ^((~Bi)&  Bo );
+        Ami =   Bi ^((~Bo)&  Bu );
+        Abo =   Bo ^((~Bu)&  Ba );
+        Aku =   Bu ^((~Ba)&  Be );
+
+        Bo = ROL64((Aka^Da), 41);
+        Bu = ROL64((Ase^De), 2);
+        Ba = ROL64((Agi^Di), 62);
+        Be = ROL64((Amo^Do), 55);
+        Bi = ROL64((Abu^Du), 39);
+        Aka =   Ba ^((~Be)&  Bi );
+        Ase =   Be ^((~Bi)&  Bo );
+        Agi =   Bi ^((~Bo)&  Bu );
+        Amo =   Bo ^((~Bu)&  Ba );
+        Abu =   Bu ^((~Ba)&  Be );
+
+        Ca = Aba^Ama^Aga^Asa^Aka;
+        Ce = Ake^Abe^Ame^Age^Ase;
+        Ci = Asi^Aki^Abi^Ami^Agi;
+        Co = Ago^Aso^Ako^Abo^Amo;
+        Cu = Amu^Agu^Asu^Aku^Abu;
+        Da = Cu^ROL64(Ce, 1);
+        De = Ca^ROL64(Ci, 1);
+        Di = Ce^ROL64(Co, 1);
+        Do = Ci^ROL64(Cu, 1);
+        Du = Co^ROL64(Ca, 1);
+
+        Ba = (Aba^Da);
+        Be = ROL64((Abe^De), 44);
+        Bi = ROL64((Abi^Di), 43);
+        Bo = ROL64((Abo^Do), 21);
+        Bu = ROL64((Abu^Du), 14);
+        Aba =   Ba ^((~Be)&  Bi );
+        Aba ^= KeccakRoundConstants[indexRound+3];
+        Abe =   Be ^((~Bi)&  Bo );
+        Abi =   Bi ^((~Bo)&  Bu );
+        Abo =   Bo ^((~Bu)&  Ba );
+        Abu =   Bu ^((~Ba)&  Be );
+
+        Bi = ROL64((Aga^Da), 3);
+        Bo = ROL64((Age^De), 45);
+        Bu = ROL64((Agi^Di), 61);
+        Ba = ROL64((Ago^Do), 28);
+        Be = ROL64((Agu^Du), 20);
+        Aga =   Ba ^((~Be)&  Bi );
+        Age =   Be ^((~Bi)&  Bo );
+        Agi =   Bi ^((~Bo)&  Bu );
+        Ago =   Bo ^((~Bu)&  Ba );
+        Agu =   Bu ^((~Ba)&  Be );
+
+        Bu = ROL64((Aka^Da), 18);
+        Ba = ROL64((Ake^De), 1);
+        Be = ROL64((Aki^Di), 6);
+        Bi = ROL64((Ako^Do), 25);
+        Bo = ROL64((Aku^Du), 8);
+        Aka =   Ba ^((~Be)&  Bi );
+        Ake =   Be ^((~Bi)&  Bo );
+        Aki =   Bi ^((~Bo)&  Bu );
+        Ako =   Bo ^((~Bu)&  Ba );
+        Aku =   Bu ^((~Ba)&  Be );
+
+        Be = ROL64((Ama^Da), 36);
+        Bi = ROL64((Ame^De), 10);
+        Bo = ROL64((Ami^Di), 15);
+        Bu = ROL64((Amo^Do), 56);
+        Ba = ROL64((Amu^Du), 27);
+        Ama =   Ba ^((~Be)&  Bi );
+        Ame =   Be ^((~Bi)&  Bo );
+        Ami =   Bi ^((~Bo)&  Bu );
+        Amo =   Bo ^((~Bu)&  Ba );
+        Amu =   Bu ^((~Ba)&  Be );
+
+        Bo = ROL64((Asa^Da), 41);
+        Bu = ROL64((Ase^De), 2);
+        Ba = ROL64((Asi^Di), 62);
+        Be = ROL64((Aso^Do), 55);
+        Bi = ROL64((Asu^Du), 39);
+        Asa =   Ba ^((~Be)&  Bi );
+        Ase =   Be ^((~Bi)&  Bo );
+        Asi =   Bi ^((~Bo)&  Bu );
+        Aso =   Bo ^((~Bu)&  Ba );
+        Asu =   Bu ^((~Ba)&  Be );
+
+#undef Aba
+#undef Abe
+#undef Abi
+#undef Abo
+#undef Abu
+#undef Aga
+#undef Age
+#undef Agi
+#undef Ago
+#undef Agu
+#undef Aka
+#undef Ake
+#undef Aki
+#undef Ako
+#undef Aku
+#undef Ama
+#undef Ame
+#undef Ami
+#undef Amo
+#undef Amu
+#undef Asa
+#undef Ase
+#undef Asi
+#undef Aso
+#undef Asu
+}
+
+#else /* BYTE_ORDER != BIG_ENDIAN */
+void
+KeccakP1600RoundSlow(tKeccakLane *state, unsigned int indexRound)
+{        
+       theta(state);
+       rho(state);
+       pi(state);
+       chi(state);
+       iota(state, indexRound);
+}
+
+#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ 
(((tKeccakLane)a) >> (64-offset))) : a)
+
+static void theta(tKeccakLane *A)
+{
+       unsigned int x, y;
+       tKeccakLane C[5], D[5];
+
+       for(x=0; x<5; x++) {
+               C[x] = 0;
+               for(y=0; y<5; y++)
+                       C[x] ^= A[index(x, y)];
+       }
+       for(x=0; x<5; x++)
+               D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
+       for(x=0; x<5; x++)
+               for(y=0; y<5; y++)
+                       A[index(x, y)] ^= D[x];
+}
+
+static void rho(tKeccakLane *A)
+{
+       unsigned int x, y;
+
+       for(x=0; x<5; x++) for(y=0; y<5; y++)
+               A[index(x, y)] = ROL64(A[index(x, y)], 
KeccakRhoOffsets[index(x, y)]);
+}
+
+static void pi(tKeccakLane *A)
+{
+       unsigned int x, y;
+       tKeccakLane tempA[25];
+
+       for(x=0; x<5; x++) for(y=0; y<5; y++)
+               tempA[index(x, y)] = A[index(x, y)];
+       for(x=0; x<5; x++) for(y=0; y<5; y++)
+               A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
+}
+
+static void chi(tKeccakLane *A)
+{
+       unsigned int x, y;
+       tKeccakLane C[5];
+
+       for(y=0; y<5; y++) {
+               for(x=0; x<5; x++)
+                       C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & 
A[index(x+2, y)]);
+               for(x=0; x<5; x++)
+                       A[index(x, y)] = C[x];
+       }
+}
+
+static void iota(tKeccakLane *A, unsigned int indexRound)
+{
+       A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
+}
+#endif /* BYTE_ORDER != BIG_ENDIAN */
+
+static void
+KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int 
offset, unsigned int length)
+{
+       assert(offset < 200);
+       assert(offset+length <= 200);
+       memcpy(data, (unsigned char*)state+offset, length);
+}
+
Index: lib/libc/hidden/sha3.h
===================================================================
RCS file: lib/libc/hidden/sha3.h
diff -N lib/libc/hidden/sha3.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/hidden/sha3.h      11 Jan 2018 09:04:18 -0000
@@ -0,0 +1,29 @@
+#ifndef _LIBC_SHA3_H
+#define _LIBC_SHA3_H
+
+#include_next <sha3.h>
+
+PROTO_NORMAL(SHA3_Update);
+PROTO_NORMAL(SHA3_Final);
+PROTO_NORMAL(SHA3_224Data);
+PROTO_NORMAL(SHA3_224End);
+PROTO_NORMAL(SHA3_224File);
+PROTO_NORMAL(SHA3_224FileChunk);
+PROTO_NORMAL(SHA3_224Init);
+PROTO_NORMAL(SHA3_256Data);
+PROTO_NORMAL(SHA3_256End);
+PROTO_NORMAL(SHA3_256File);
+PROTO_NORMAL(SHA3_256FileChunk);
+PROTO_NORMAL(SHA3_256Init);
+PROTO_NORMAL(SHA3_384Data);
+PROTO_NORMAL(SHA3_384End);
+PROTO_NORMAL(SHA3_384File);
+PROTO_NORMAL(SHA3_384FileChunk);
+PROTO_NORMAL(SHA3_384Init);
+PROTO_NORMAL(SHA3_512Data);
+PROTO_NORMAL(SHA3_512End);
+PROTO_NORMAL(SHA3_512File);
+PROTO_NORMAL(SHA3_512FileChunk);
+PROTO_NORMAL(SHA3_512Init);
+
+#endif /* _LIBC_SHA3_H */

Reply via email to