Hi everyone,

enclosed you find a patch to add basic SHA3-/Keccak support to OpenBSD.

Changes have been made to libc, and a suite of sha3 checksum tools
were added (sha3-224, sha3-256, sha3-384, sha-512), extending the 
existing md5(1) checksum tool.

The SHA3 implementation itself was taken from the reference code written
by the Keccak Team (https://keccak.team/) which is available under public
domain (CC0).

We'd be happy to see this in OpenBSD and appreciate any comments.

Best regards,
Daniel, Stefan and Alexander

--
Dr. Daniel Loebenberger
Evaluation & Research

genua GmbH
Domagkstrasse 7, 85551 Kirchheim bei München
Tel. +49 89 991950-0, Fax -999, www.genua.de
Geschäftsführer: Matthias Ochs, Marc Tesch. Amtsgericht München 
HRB 98238.
Die genua GmbH ist ein Unternehmen der Bundesdruckerei-Gruppe.


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    9 Jan 2018 15:17:20 -0000
@@ -2,13 +2,20 @@
 
 PROG=  md5
 SRCS=  crc.c md5.c
-MAN=   cksum.1 md5.1
+
 LINKS= ${BINDIR}/md5 ${BINDIR}/sha1 \
+       ${BINDIR}/md5 ${BINDIR}/sha224 \
        ${BINDIR}/md5 ${BINDIR}/sha256 \
+       ${BINDIR}/md5 ${BINDIR}/sha384 \
        ${BINDIR}/md5 ${BINDIR}/sha512 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-224 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-256 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-384 \
+       ${BINDIR}/md5 ${BINDIR}/sha3-512 \
        ${BINDIR}/md5 ${BINDIR}/cksum
 
-CPPFLAGS+= -I${.CURDIR}
+CPPFLAGS+=-I${.CURDIR}
+
 COPTS+=        -Wall -Wconversion -Wmissing-prototypes
 
 .include <bsd.prog.mk>
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       9 Jan 2018 15:17:20 -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       9 Jan 2018 15:17:20 -0000
@@ -42,6 +42,7 @@
 #include <rmd160.h>
 #include <sha1.h>
 #include <sha2.h>
+#include <sha3.h>
 #include <crc.h>
 
 #define STYLE_MD5      0
@@ -61,6 +62,7 @@ union ANY_CTX {
        SHA1_CTX sha1;
 #endif /* !defined(SHA2_ONLY) */
        SHA2_CTX sha2;
+       SHA3_CTX sha3;
 };
 
 struct hash_function {
@@ -177,6 +179,50 @@ struct hash_function {
                (void (*)(void *, const unsigned char *, size_t))SHA512Update,
                (void (*)(unsigned char *, void *))SHA512Final,
                (char *(*)(void *, char *))SHA512End
+       },
+       {
+               "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
        },
        {
                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    9 Jan 2018 15:17:42 -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      9 Jan 2018 15:17:42 -0000
@@ -0,0 +1,76 @@
+#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;
+
+
+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)));
+
+#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      9 Jan 2018 15:17:42 -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  9 Jan 2018 15:17:42 -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        9 Jan 2018 15:17:42 -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        9 Jan 2018 15:17:42 -0000
@@ -0,0 +1,756 @@
+/*
+ * 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
+ * Alexander von Gernler, Daniel Loebenberger and Stefan-Lukas Gazdag
+ * 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);
+}
+
+void
+SHA3_256Init(SHA3_CTX *context)
+{
+       /* rate = 1088, output width 256 bit */
+       Keccak_HashInitialize(context, 1088, 256);
+}
+
+void
+SHA3_384Init(SHA3_CTX *context)
+{
+       /* rate = 832, output width 384 bit */
+       Keccak_HashInitialize(context, 832, 384);
+}
+
+void
+SHA3_512Init(SHA3_CTX *context)
+{
+       /* rate = 576, output width 512 bit */
+       Keccak_HashInitialize(context, 576, 512);
+}
+
+
+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;
+                       }
+               }
+       }
+}
+
+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;
+               }
+       }
+}
+
+/*
+ * 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      9 Jan 2018 15:17:42 -0000
@@ -0,0 +1,76 @@
+#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;
+
+
+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)));
+
+#endif /* _SHA3_H */

Reply via email to