Ticket #13869: 0004-libs-bsd-add-getentropy-2.patch

File 0004-libs-bsd-add-getentropy-2.patch, 23.5 KB (added by leorize, 6 years ago)
  • new file headers/compatibility/bsd/sys/sha512.h

    From 717e5eaa66fa6adc179ff804087d3c20c43b888e Mon Sep 17 00:00:00 2001
    From: Leorize <alaviss@users.noreply.github.com>
    Date: Thu, 14 Dec 2017 07:26:19 +0700
    Subject: [PATCH 4/5] libs/bsd: add getentropy(2)
    
    ---
     headers/compatibility/bsd/sys/sha512.h |  53 +++++
     headers/compatibility/bsd/unistd.h     |   1 +
     src/libs/bsd/Jamfile                   |   2 +
     src/libs/bsd/getentropy.c              | 390 +++++++++++++++++++++++++++++++++
     src/libs/bsd/sha512c.c                 | 318 +++++++++++++++++++++++++++
     5 files changed, 764 insertions(+)
     create mode 100644 headers/compatibility/bsd/sys/sha512.h
     create mode 100644 src/libs/bsd/getentropy.c
     create mode 100644 src/libs/bsd/sha512c.c
    
    diff --git a/headers/compatibility/bsd/sys/sha512.h b/headers/compatibility/bsd/sys/sha512.h
    new file mode 100644
    index 00000000..4f368a14
    - +  
     1/*-
     2 * Copyright 2005 Colin Percival
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 * 1. Redistributions of source code must retain the above copyright
     9 *    notice, this list of conditions and the following disclaimer.
     10 * 2. Redistributions in binary form must reproduce the above copyright
     11 *    notice, this list of conditions and the following disclaimer in the
     12 *    documentation and/or other materials provided with the distribution.
     13 *
     14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     24 * SUCH DAMAGE.
     25 *
     26 * $FreeBSD$
     27 */
     28
     29#ifndef _SHA512_H_
     30#define _SHA512_H_
     31
     32#include <sys/types.h>
     33
     34#define SHA512_DIGEST_LENGTH        64
     35
     36typedef struct SHA512Context {
     37    uint64_t state[8];
     38    uint64_t count[2];
     39    unsigned char buf[128];
     40} SHA512_CTX;
     41
     42__BEGIN_DECLS
     43
     44void    SHA512_Init(SHA512_CTX *);
     45void    SHA512_Update(SHA512_CTX *, const void *, size_t);
     46void    SHA512_Final(unsigned char [64], SHA512_CTX *);
     47char   *SHA512_End(SHA512_CTX *, char *);
     48char   *SHA512_File(const char *, char *);
     49char   *SHA512_FileChunk(const char *, char *, off_t, off_t);
     50char   *SHA512_Data(const void *, unsigned int, char *);
     51__END_DECLS
     52
     53#endif /* !_SHA512_H_ */
  • headers/compatibility/bsd/unistd.h

    diff --git a/headers/compatibility/bsd/unistd.h b/headers/compatibility/bsd/unistd.h
    index fbcd17cc..d9021702 100644
    a b char *getpass(const char *prompt);  
    2626char    *getusershell(void);
    2727int     issetugid(void);
    2828void    setusershell(void);
     29int getentropy(void *buf, size_t buflen);
    2930
    3031#ifdef __cplusplus
    3132}
  • src/libs/bsd/Jamfile

    diff --git a/src/libs/bsd/Jamfile b/src/libs/bsd/Jamfile
    index 42f27467..e14b3766 100644
    a b for architectureObject in [ MultiArchSubDirSetup ] {  
    1515            err.c
    1616            explicit_bzero.c
    1717            fgetln.c
     18            getentropy.c
    1819            getpass.c
    1920            issetugid.c
    2021            lutimes.c
    2122            progname.c
    2223            pty.cpp
    2324            readpassphrase.c
     25            sha512c.c
    2426            signal.c
    2527            string.cpp
    2628            stringlist.c
  • new file src/libs/bsd/getentropy.c

    diff --git a/src/libs/bsd/getentropy.c b/src/libs/bsd/getentropy.c
    new file mode 100644
    index 00000000..9bbac076
    - +  
     1/*  $OpenBSD: getentropy_hpux.c,v 1.5 2016/08/07 03:27:21 tb Exp $  */
     2
     3/*
     4 * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
     5 * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
     6 *
     7 * Permission to use, copy, modify, and distribute this software for any
     8 * purpose with or without fee is hereby granted, provided that the above
     9 * copyright notice and this permission notice appear in all copies.
     10 *
     11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18 *
     19 * Emulation of getentropy(2) as documented at:
     20 * http://man.openbsd.org/getentropy.2
     21 */
     22
     23#include <sys/types.h>
     24#include <sys/param.h>
     25#include <sys/ioctl.h>
     26#include <sys/resource.h>
     27#include <sys/statvfs.h>
     28#include <sys/socket.h>
     29#include <sys/mman.h>
     30#include <sys/stat.h>
     31#include <sys/time.h>
     32#include <stdlib.h>
     33#include <stdint.h>
     34#include <stdio.h>
     35#include <termios.h>
     36#include <fcntl.h>
     37#include <signal.h>
     38#include <string.h>
     39#include <errno.h>
     40#include <unistd.h>
     41#include <time.h>
     42#include <sys/sha512.h>
     43
     44#define REPEAT 5
     45#define min(a, b) (((a) < (b)) ? (a) : (b))
     46
     47#define HX(a, b) \
     48    do { \
     49        if ((a)) \
     50            HD(errno); \
     51        else \
     52            HD(b); \
     53    } while (0)
     54
     55#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
     56#define HD(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
     57#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
     58
     59int getentropy(void *buf, size_t len);
     60
     61static int gotdata(char *buf, size_t len);
     62static int getentropy_urandom(void *buf, size_t len, const char *path,
     63    int devfscheck);
     64static int getentropy_fallback(void *buf, size_t len);
     65
     66int
     67getentropy(void *buf, size_t len)
     68{
     69    int ret = -1;
     70
     71    if (len > 256) {
     72        errno = EIO;
     73        return (-1);
     74    }
     75
     76    /*
     77     * Try to get entropy with /dev/urandom
     78     */
     79    ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
     80    if (ret != -1)
     81        return (ret);
     82
     83    /*
     84     * Entropy collection via /dev/urandom has failed.
     85     *
     86     * No other API exists for collecting entropy, and we have
     87     * no failsafe way to get it on Haiku that is not sensitive
     88     * to resource exhaustion.
     89     *
     90     * We have very few options:
     91     *     - Even syslog_r is unsafe to call at this low level, so
     92     *   there is no way to alert the user or program.
     93     *     - Cannot call abort() because some systems have unsafe
     94     *   corefiles.
     95     *     - Could raise(SIGKILL) resulting in silent program termination.
     96     *     - Return EIO, to hint that arc4random's stir function
     97     *       should raise(SIGKILL)
     98     *     - Do the best under the circumstances....
     99     *
     100     * This code path exists to bring light to the issue that Haiku
     101     * does not provide a failsafe API for entropy collection.
     102     *
     103     * We hope this demonstrates that Haiku should consider
     104     * providing a new failsafe API which works in a chroot or
     105     * when file descriptors are exhausted.
     106     */
     107#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
     108#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
     109    raise(SIGKILL);
     110#endif
     111    ret = getentropy_fallback(buf, len);
     112    if (ret != -1)
     113        return (ret);
     114
     115    errno = EIO;
     116    return (ret);
     117}
     118
     119/*
     120 * Basic sanity checking; wish we could do better.
     121 */
     122static int
     123gotdata(char *buf, size_t len)
     124{
     125    char    any_set = 0;
     126    size_t  i;
     127
     128    for (i = 0; i < len; ++i)
     129        any_set |= buf[i];
     130    if (any_set == 0)
     131        return (-1);
     132    return (0);
     133}
     134
     135static int
     136getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
     137{
     138    struct stat st;
     139    size_t i;
     140    int fd, flags;
     141    int save_errno = errno;
     142
     143start:
     144
     145    flags = O_RDONLY;
     146#ifdef O_NOFOLLOW
     147    flags |= O_NOFOLLOW;
     148#endif
     149#ifdef O_CLOEXEC
     150    flags |= O_CLOEXEC;
     151#endif
     152    fd = open(path, flags, 0);
     153    if (fd == -1) {
     154        if (errno == EINTR)
     155            goto start;
     156        goto nodevrandom;
     157    }
     158#ifndef O_CLOEXEC
     159    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
     160#endif
     161
     162    /* Lightly verify that the device node looks sane */
     163    if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
     164        close(fd);
     165        goto nodevrandom;
     166    }
     167    for (i = 0; i < len; ) {
     168        size_t wanted = len - i;
     169        ssize_t ret = read(fd, (char *)buf + i, wanted);
     170
     171        if (ret == -1) {
     172            if (errno == EAGAIN || errno == EINTR)
     173                continue;
     174            close(fd);
     175            goto nodevrandom;
     176        }
     177        i += ret;
     178    }
     179    close(fd);
     180    if (gotdata(buf, len) == 0) {
     181        errno = save_errno;
     182        return (0);     /* satisfied */
     183    }
     184nodevrandom:
     185    errno = EIO;
     186    return (-1);
     187}
     188
     189static const int cl[] = {
     190    CLOCK_REALTIME,
     191#ifdef CLOCK_MONOTONIC
     192    CLOCK_MONOTONIC,
     193#endif
     194#ifdef CLOCK_MONOTONIC_RAW
     195    CLOCK_MONOTONIC_RAW,
     196#endif
     197#ifdef CLOCK_TAI
     198    CLOCK_TAI,
     199#endif
     200#ifdef CLOCK_VIRTUAL
     201    CLOCK_VIRTUAL,
     202#endif
     203#ifdef CLOCK_UPTIME
     204    CLOCK_UPTIME,
     205#endif
     206#ifdef CLOCK_PROCESS_CPUTIME_ID
     207    CLOCK_PROCESS_CPUTIME_ID,
     208#endif
     209#ifdef CLOCK_THREAD_CPUTIME_ID
     210    CLOCK_THREAD_CPUTIME_ID,
     211#endif
     212};
     213
     214static int
     215getentropy_fallback(void *buf, size_t len)
     216{
     217    uint8_t results[SHA512_DIGEST_LENGTH];
     218    int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
     219    static int cnt;
     220    struct timespec ts;
     221    struct timeval tv;
     222    struct rusage ru;
     223    sigset_t sigset;
     224    struct stat st;
     225    SHA512_CTX ctx;
     226    static pid_t lastpid;
     227    pid_t pid;
     228    size_t i, ii, m;
     229    char *p;
     230
     231    pid = getpid();
     232    if (lastpid == pid) {
     233        faster = 1;
     234        repeat = 2;
     235    } else {
     236        faster = 0;
     237        lastpid = pid;
     238        repeat = REPEAT;
     239    }
     240    for (i = 0; i < len; ) {
     241        int j;
     242        SHA512_Init(&ctx);
     243        for (j = 0; j < repeat; j++) {
     244            HX((e = gettimeofday(&tv, NULL)) == -1, tv);
     245            if (e != -1) {
     246                cnt += (int)tv.tv_sec;
     247                cnt += (int)tv.tv_usec;
     248            }
     249
     250            for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
     251                HX(clock_gettime(cl[ii], &ts) == -1, ts);
     252
     253            HX((pid = getpid()) == -1, pid);
     254            HX((pid = getsid(pid)) == -1, pid);
     255            HX((pid = getppid()) == -1, pid);
     256            HX((pid = getpgid(0)) == -1, pid);
     257
     258            if (!faster) {
     259                ts.tv_sec = 0;
     260                ts.tv_nsec = 1;
     261                (void) nanosleep(&ts, NULL);
     262            }
     263
     264            HX(sigpending(&sigset) == -1, sigset);
     265            HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
     266                sigset);
     267
     268            HF(getentropy); /* an addr in this library */
     269            HF(printf);     /* an addr in libc */
     270            p = (char *)&p;
     271            HD(p);      /* an addr on stack */
     272            p = (char *)&errno;
     273            HD(p);      /* the addr of errno */
     274
     275            if (i == 0) {
     276                struct statvfs stvfs;
     277                struct termios tios;
     278                off_t off;
     279
     280                /*
     281                 * Prime-sized mappings encourage fragmentation;
     282                 * thus exposing some address entropy.
     283                 */
     284                struct mm {
     285                    size_t  npg;
     286                    void    *p;
     287                } mm[] =     {
     288                    { 17, MAP_FAILED }, { 3, MAP_FAILED },
     289                    { 11, MAP_FAILED }, { 2, MAP_FAILED },
     290                    { 5, MAP_FAILED }, { 3, MAP_FAILED },
     291                    { 7, MAP_FAILED }, { 1, MAP_FAILED },
     292                    { 57, MAP_FAILED }, { 3, MAP_FAILED },
     293                    { 131, MAP_FAILED }, { 1, MAP_FAILED },
     294                };
     295
     296                for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
     297                    HX(mm[m].p = mmap(NULL,
     298                        mm[m].npg * pgs,
     299                        PROT_READ|PROT_WRITE,
     300                        MAP_PRIVATE|MAP_ANON, -1,
     301                        (off_t)0), mm[m].p);
     302                    if (mm[m].p != MAP_FAILED) {
     303                        size_t mo;
     304
     305                        /* Touch some memory... */
     306                        p = mm[m].p;
     307                        mo = cnt %
     308                            (mm[m].npg * pgs - 1);
     309                        p[mo] = 1;
     310                        cnt += (int)((long)(mm[m].p)
     311                            / pgs);
     312                    }
     313
     314                    /* Check cnts and times... */
     315                    for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
     316                        ii++) {
     317                        HX((e = clock_gettime(cl[ii],
     318                            &ts)) == -1, ts);
     319                        if (e != -1)
     320                            cnt += (int)ts.tv_nsec;
     321                    }
     322
     323                    HX((e = getrusage(RUSAGE_SELF,
     324                        &ru)) == -1, ru);
     325                    if (e != -1) {
     326                        cnt += (int)ru.ru_utime.tv_sec;
     327                        cnt += (int)ru.ru_utime.tv_usec;
     328                    }
     329                }
     330
     331                for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
     332                    if (mm[m].p != MAP_FAILED)
     333                        munmap(mm[m].p, mm[m].npg * pgs);
     334                    mm[m].p = MAP_FAILED;
     335                }
     336
     337                HX(stat(".", &st) == -1, st);
     338                HX(statvfs(".", &stvfs) == -1, stvfs);
     339
     340                HX(stat("/", &st) == -1, st);
     341                HX(statvfs("/", &stvfs) == -1, stvfs);
     342
     343                HX((e = fstat(0, &st)) == -1, st);
     344                if (e == -1) {
     345                    if (S_ISREG(st.st_mode) ||
     346                        S_ISFIFO(st.st_mode) ||
     347                        S_ISSOCK(st.st_mode)) {
     348                        HX(fstatvfs(0, &stvfs) == -1,
     349                            stvfs);
     350                        HX((off = lseek(0, (off_t)0,
     351                            SEEK_CUR)) < 0, off);
     352                    }
     353                    if (S_ISCHR(st.st_mode)) {
     354                        HX(tcgetattr(0, &tios) == -1,
     355                            tios);
     356                    }
     357                }
     358
     359                HX((e = getrusage(RUSAGE_CHILDREN,
     360                    &ru)) == -1, ru);
     361                if (e != -1) {
     362                    cnt += (int)ru.ru_utime.tv_sec;
     363                    cnt += (int)ru.ru_utime.tv_usec;
     364                }
     365            } else {
     366                /* Subsequent hashes absorb previous result */
     367                HD(results);
     368            }
     369
     370            HX((e = gettimeofday(&tv, NULL)) == -1, tv);
     371            if (e != -1) {
     372                cnt += (int)tv.tv_sec;
     373                cnt += (int)tv.tv_usec;
     374            }
     375
     376            HD(cnt);
     377        }
     378        SHA512_Final(results, &ctx);
     379        memcpy((char *)buf + i, results, min(sizeof(results), len - i));
     380        i += min(sizeof(results), len - i);
     381    }
     382    explicit_bzero(&ctx, sizeof ctx);
     383    explicit_bzero(results, sizeof results);
     384    if (gotdata(buf, len) == 0) {
     385        errno = save_errno;
     386        return (0);     /* satisfied */
     387    }
     388    errno = EIO;
     389    return (-1);
     390}
  • new file src/libs/bsd/sha512c.c

    diff --git a/src/libs/bsd/sha512c.c b/src/libs/bsd/sha512c.c
    new file mode 100644
    index 00000000..cb2dbdc5
    - +  
     1/*-
     2 * Copyright 2005 Colin Percival
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 * 1. Redistributions of source code must retain the above copyright
     9 *    notice, this list of conditions and the following disclaimer.
     10 * 2. Redistributions in binary form must reproduce the above copyright
     11 *    notice, this list of conditions and the following disclaimer in the
     12 *    documentation and/or other materials provided with the distribution.
     13 *
     14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     24 * SUCH DAMAGE.
     25 */
     26
     27#include <sys/cdefs.h>
     28#include <endian.h>
     29#include <sys/sha512.h>
     30#include <sys/types.h>
     31
     32#include <string.h>
     33
     34
     35#if BYTE_ORDER == BIG_ENDIAN
     36
     37/* Copy a vector of big-endian uint64_t into a vector of bytes */
     38#define be64enc_vect(dst, src, len) \
     39    memcpy((void *)dst, (const void *)src, (size_t)len)
     40
     41/* Copy a vector of bytes into a vector of big-endian uint64_t */
     42#define be64dec_vect(dst, src, len) \
     43    memcpy((void *)dst, (const void *)src, (size_t)len)
     44
     45#else /* BYTE_ORDER != BIG_ENDIAN */
     46
     47/*
     48 * Encode a length len/4 vector of (uint64_t) into a length len vector of
     49 * (unsigned char) in big-endian form.  Assumes len is a multiple of 8.
     50 */
     51static void
     52be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
     53{
     54    size_t i;
     55
     56    for (i = 0; i < len / 8; i++)
     57        be64enc(dst + i * 8, src[i]);
     58}
     59
     60/*
     61 * Decode a big-endian length len vector of (unsigned char) into a length
     62 * len/4 vector of (uint64_t).  Assumes len is a multiple of 8.
     63 */
     64static void
     65be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
     66{
     67    size_t i;
     68
     69    for (i = 0; i < len / 8; i++)
     70        dst[i] = be64dec(src + i * 8);
     71}
     72
     73#endif /* BYTE_ORDER != BIG_ENDIAN */
     74
     75/* Elementary functions used by SHA512 */
     76#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
     77#define Maj(x, y, z)    ((x & (y | z)) | (y & z))
     78#define SHR(x, n)   (x >> n)
     79#define ROTR(x, n)  ((x >> n) | (x << (64 - n)))
     80#define S0(x)       (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
     81#define S1(x)       (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
     82#define s0(x)       (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
     83#define s1(x)       (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
     84
     85/* SHA512 round function */
     86#define RND(a, b, c, d, e, f, g, h, k)          \
     87    t0 = h + S1(e) + Ch(e, f, g) + k;       \
     88    t1 = S0(a) + Maj(a, b, c);          \
     89    d += t0;                    \
     90    h  = t0 + t1;
     91
     92/* Adjusted round function for rotating state */
     93#define RNDr(S, W, i, k)            \
     94    RND(S[(80 - i) % 8], S[(81 - i) % 8],   \
     95        S[(82 - i) % 8], S[(83 - i) % 8],   \
     96        S[(84 - i) % 8], S[(85 - i) % 8],   \
     97        S[(86 - i) % 8], S[(87 - i) % 8],   \
     98        W[i] + k)
     99
     100/*
     101 * SHA512 block compression function.  The 512-bit state is transformed via
     102 * the 512-bit input block to produce a new state.
     103 */
     104static void
     105SHA512_Transform(uint64_t * state, const unsigned char block[128])
     106{
     107    uint64_t W[80];
     108    uint64_t S[8];
     109    uint64_t t0, t1;
     110    int i;
     111
     112    /* 1. Prepare message schedule W. */
     113    be64dec_vect(W, block, 128);
     114    for (i = 16; i < 80; i++)
     115        W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
     116
     117    /* 2. Initialize working variables. */
     118    memcpy(S, state, 64);
     119
     120    /* 3. Mix. */
     121    RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
     122    RNDr(S, W, 1, 0x7137449123ef65cdULL);
     123    RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
     124    RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
     125    RNDr(S, W, 4, 0x3956c25bf348b538ULL);
     126    RNDr(S, W, 5, 0x59f111f1b605d019ULL);
     127    RNDr(S, W, 6, 0x923f82a4af194f9bULL);
     128    RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
     129    RNDr(S, W, 8, 0xd807aa98a3030242ULL);
     130    RNDr(S, W, 9, 0x12835b0145706fbeULL);
     131    RNDr(S, W, 10, 0x243185be4ee4b28cULL);
     132    RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
     133    RNDr(S, W, 12, 0x72be5d74f27b896fULL);
     134    RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
     135    RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
     136    RNDr(S, W, 15, 0xc19bf174cf692694ULL);
     137    RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
     138    RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
     139    RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
     140    RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
     141    RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
     142    RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
     143    RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
     144    RNDr(S, W, 23, 0x76f988da831153b5ULL);
     145    RNDr(S, W, 24, 0x983e5152ee66dfabULL);
     146    RNDr(S, W, 25, 0xa831c66d2db43210ULL);
     147    RNDr(S, W, 26, 0xb00327c898fb213fULL);
     148    RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
     149    RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
     150    RNDr(S, W, 29, 0xd5a79147930aa725ULL);
     151    RNDr(S, W, 30, 0x06ca6351e003826fULL);
     152    RNDr(S, W, 31, 0x142929670a0e6e70ULL);
     153    RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
     154    RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
     155    RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
     156    RNDr(S, W, 35, 0x53380d139d95b3dfULL);
     157    RNDr(S, W, 36, 0x650a73548baf63deULL);
     158    RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
     159    RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
     160    RNDr(S, W, 39, 0x92722c851482353bULL);
     161    RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
     162    RNDr(S, W, 41, 0xa81a664bbc423001ULL);
     163    RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
     164    RNDr(S, W, 43, 0xc76c51a30654be30ULL);
     165    RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
     166    RNDr(S, W, 45, 0xd69906245565a910ULL);
     167    RNDr(S, W, 46, 0xf40e35855771202aULL);
     168    RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
     169    RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
     170    RNDr(S, W, 49, 0x1e376c085141ab53ULL);
     171    RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
     172    RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
     173    RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
     174    RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
     175    RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
     176    RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
     177    RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
     178    RNDr(S, W, 57, 0x78a5636f43172f60ULL);
     179    RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
     180    RNDr(S, W, 59, 0x8cc702081a6439ecULL);
     181    RNDr(S, W, 60, 0x90befffa23631e28ULL);
     182    RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
     183    RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
     184    RNDr(S, W, 63, 0xc67178f2e372532bULL);
     185    RNDr(S, W, 64, 0xca273eceea26619cULL);
     186    RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
     187    RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
     188    RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
     189    RNDr(S, W, 68, 0x06f067aa72176fbaULL);
     190    RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
     191    RNDr(S, W, 70, 0x113f9804bef90daeULL);
     192    RNDr(S, W, 71, 0x1b710b35131c471bULL);
     193    RNDr(S, W, 72, 0x28db77f523047d84ULL);
     194    RNDr(S, W, 73, 0x32caab7b40c72493ULL);
     195    RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
     196    RNDr(S, W, 75, 0x431d67c49c100d4cULL);
     197    RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
     198    RNDr(S, W, 77, 0x597f299cfc657e2aULL);
     199    RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
     200    RNDr(S, W, 79, 0x6c44198c4a475817ULL);
     201
     202    /* 4. Mix local working variables into global state */
     203    for (i = 0; i < 8; i++)
     204        state[i] += S[i];
     205}
     206
     207static unsigned char PAD[128] = {
     208    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     209    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     210    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     211    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     212    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     213    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     214    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     215    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     216};
     217
     218/* Add padding and terminating bit-count. */
     219static void
     220SHA512_Pad(SHA512_CTX * ctx)
     221{
     222    unsigned char len[16];
     223    uint64_t r, plen;
     224
     225    /*
     226     * Convert length to a vector of bytes -- we do this now rather
     227     * than later because the length will change after we pad.
     228     */
     229    be64enc_vect(len, ctx->count, 16);
     230
     231    /* Add 1--128 bytes so that the resulting length is 112 mod 128 */
     232    r = (ctx->count[1] >> 3) & 0x7f;
     233    plen = (r < 112) ? (112 - r) : (240 - r);
     234    SHA512_Update(ctx, PAD, (size_t)plen);
     235
     236    /* Add the terminating bit-count */
     237    SHA512_Update(ctx, len, 16);
     238}
     239
     240/* SHA-512 initialization.  Begins a SHA-512 operation. */
     241void
     242SHA512_Init(SHA512_CTX * ctx)
     243{
     244
     245    /* Zero bits processed so far */
     246    ctx->count[0] = ctx->count[1] = 0;
     247
     248    /* Magic initialization constants */
     249    ctx->state[0] = 0x6a09e667f3bcc908ULL;
     250    ctx->state[1] = 0xbb67ae8584caa73bULL;
     251    ctx->state[2] = 0x3c6ef372fe94f82bULL;
     252    ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
     253    ctx->state[4] = 0x510e527fade682d1ULL;
     254    ctx->state[5] = 0x9b05688c2b3e6c1fULL;
     255    ctx->state[6] = 0x1f83d9abfb41bd6bULL;
     256    ctx->state[7] = 0x5be0cd19137e2179ULL;
     257}
     258
     259/* Add bytes into the hash */
     260void
     261SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
     262{
     263    uint64_t bitlen[2];
     264    uint64_t r;
     265    const unsigned char *src = in;
     266
     267    /* Number of bytes left in the buffer from previous updates */
     268    r = (ctx->count[1] >> 3) & 0x7f;
     269
     270    /* Convert the length into a number of bits */
     271    bitlen[1] = ((uint64_t)len) << 3;
     272    bitlen[0] = ((uint64_t)len) >> 61;
     273
     274    /* Update number of bits */
     275    if ((ctx->count[1] += bitlen[1]) < bitlen[1])
     276        ctx->count[0]++;
     277    ctx->count[0] += bitlen[0];
     278
     279    /* Handle the case where we don't need to perform any transforms */
     280    if (len < 128 - r) {
     281        memcpy(&ctx->buf[r], src, len);
     282        return;
     283    }
     284
     285    /* Finish the current block */
     286    memcpy(&ctx->buf[r], src, 128 - r);
     287    SHA512_Transform(ctx->state, ctx->buf);
     288    src += 128 - r;
     289    len -= 128 - r;
     290
     291    /* Perform complete blocks */
     292    while (len >= 128) {
     293        SHA512_Transform(ctx->state, src);
     294        src += 128;
     295        len -= 128;
     296    }
     297
     298    /* Copy left over data into buffer */
     299    memcpy(ctx->buf, src, len);
     300}
     301
     302/*
     303 * SHA-512 finalization.  Pads the input data, exports the hash value,
     304 * and clears the context state.
     305 */
     306void
     307SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
     308{
     309
     310    /* Add padding */
     311    SHA512_Pad(ctx);
     312
     313    /* Write the hash */
     314    be64enc_vect(digest, ctx->state, 64);
     315
     316    /* Clear the context state */
     317    memset((void *)ctx, 0, sizeof(*ctx));
     318}