--- /dev/null
+mydir=lib/crypto/krb/prng
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+SUBDIRS= @PRNG_ALG@
+LOCALINCLUDES = -I$(srcdir) -I$(srcdir)/../../@CRYPTO_IMPL@/enc_provider \
+ -I$(srcdir)/../../@CRYPTO_IMPL@/hash_provider \
+ -I$(srcdir)/@PRNG_ALG@ \
+ -I$(srcdir)/../../@CRYPTO_IMPL@/ \
+ -I$(srcdir)/../../@CRYPTO_IMPL@/aes \
+ -I$(srcdir)/../../@CRYPTO_IMPL@/sha1 -I$(srcdir)/../../@CRYPTO_IMPL@/sha2
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+DEFS=
+
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS=\
+ prng.o
+
+OBJS=\
+ $(OUTPRE)prng.$(OBJEXT)
+
+SRCS=\
+ $(srcdir)/prng.c
+
+STOBJLISTS= OBJS.ST @PRNG_ALG@/OBJS.ST
+
+SUBDIROBJLISTS= @PRNG_ALG@/OBJS.ST
+
+
+all-unix:: all-libobjs
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@lib_frag@
+@libobj_frag@
+
--- /dev/null
+#
+# Generated makefile dependencies follow.
+#
+prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../builtin/enc_provider/enc_provider.h \
+ $(srcdir)/../../builtin/sha1/shs.h $(srcdir)/../../builtin/yhash.h \
+ $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ prng.c
--- /dev/null
+mydir=lib/crypto/krb/prng/fortuna
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../.. \
+ -I$(srcdir)/../../../@CRYPTO_IMPL@ \
+ -I$(srcdir)/../../../@CRYPTO_IMPL@/sha2 \
+ -I$(srcdir)/../../../@CRYPTO_IMPL@/aes \
+ -I$(srcdir)/../../../@CRYPTO_IMPL@/enc_provider
+DEFS=
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS= \
+ prng_fortuna.o entropy.o
+OBJS= \
+ $(OUTPRE)prng_fortuna.$(OBJEXT) \
+ $(OUTPRE)entropy.$(OBJEXT)
+
+SRCS=\
+ $(srcdir)/entropy.c \
+ $(srcdir)/prng_fortuna.c
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+t_fortuna: t_fortuna.$(OBJEXT) $(SUPPORT_DEPLIB)
+ $(CC_LINK) -o t_fortuna t_fortuna.$(OBJEXT) -lcom_err $(SUPPORT_LIB) $(CRYPTO_DEPLIB)
+
+t_fortuna_make_oct: t_fortuna_make_oct.$(OBJEXT) $(SUPPORT_DEPLIB)
+ $(CC_LINK) -o t_fortuna_make_oct t_fortuna_make_oct.$(OBJEXT) -lcom_err $(SUPPORT_LIB) $(CRYPTO_DEPLIB)
+
+check-unix:: t_fortuna t_fortuna_make_oct
+# ifdef TEST_FORTUNA
+ifeq ("@PRNG_FORTUNA_TEST@","yes")
+ $(RUN_SETUP) $(VALGRIND) ./t_fortuna_make_oct > t_fortuna_make_oct.result && \
+ diff t_fortuna_make_oct.result t_fortuna_make_oct.expected
+else
+ $(RUN_SETUP) $(VALGRIND) ./t_fortuna
+ $(RUN_SETUP) $(VALGRIND) ./t_fortuna_make_oct > t_fortuna_make_oct.result
+endif
+
+clean::
+ $(RM) t_fortuna$(EXEEXT) t_fortuna.$(OBJEXT) t_fortuna_make_oct.result t_fortuna_make_oct$(EXEEXT) t_fortuna_make_oct.$(OBJEXT)
+
+
+clean-unix:: clean-libobjs
+
+@lib_frag@
+@libobj_frag@
+
--- /dev/null
+#
+# Generated makefile dependencies follow.
+#
+prng_fortuna.so prng_fortuna.po $(OUTPRE)prng_fortuna.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../../builtin/aes/aes.h \
+ $(srcdir)/../prng.h \
+ $(srcdir)/../../../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ prng_fortuna.c fortuna.h
+entropy.so entropy.po $(OUTPRE)entropy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) \
+ $(top_srcdir)/include/k5-buf.h \
+ $(srcdir)/../prng.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ entropy.c
+t_fortuna.so t_fortuna.po $(OUTPRE)t_fortuna.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../../builtin/aes/aes.h \
+ $(srcdir)/../prng.h \
+ $(srcdir)/../../../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ t_fortuna.c fortuna.h
+
--- /dev/null
+/* various methods to collect entropy */
+#include "prng.h"
+
+#include "fortuna.h"
+#include "k5-int.h"
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+krb5_error_code
+k5_entropy_from_device(krb5_context context, const char *device, unsigned char* buf, int buflen)
+{
+ struct stat sb;
+ int fd;
+ unsigned char *bp;
+ size_t left;
+ fd = open(device, O_RDONLY);
+ if (fd == -1)
+ return 0;
+ set_cloexec_fd(fd);
+ if (fstat(fd, &sb) == -1 || S_ISREG(sb.st_mode)) {
+ close(fd);
+ return 0;
+ }
+
+ for (bp = buf, left = sizeof(buf); left > 0;) {
+ ssize_t count;
+ count = read(fd, bp, (unsigned) left);
+ if (count <= 0) {
+ close(fd);
+ return 0;
+ }
+ left -= count;
+ bp += count;
+ }
+ close(fd);
+ return 0;
+}
+
+krb5_error_code
+k5_entropy_dev_random(krb5_context context, unsigned char* buf, int buflen)
+{
+ memset(buf, 0, buflen);
+ return k5_entropy_from_device(context,"/dev/random", buf, buflen);
+}
+
+krb5_error_code
+k5_entropy_dev_urandom(krb5_context context, unsigned char* buf, int buflen)
+{
+ memset(buf, 0, buflen);
+ return k5_entropy_from_device(context,"/dev/urandom", buf, buflen);
+}
+
+krb5_error_code
+k5_entropy_pid(krb5_context context, unsigned char* buf, int buflen)
+{
+ pid_t pid = getpid();
+ int pidlen = min(buflen,(int)sizeof(&pid));
+ memset(buf, 0, buflen);
+ memcpy(buf, &pid, pidlen);
+ return 0;
+}
+
+krb5_error_code
+k5_entropy_uid(krb5_context context, unsigned char* buf, int buflen)
+{
+ pid_t uid = getuid();
+ int uidlen=min(buflen,(int)sizeof(&uid));
+ memset(buf, 0, buflen);
+ memcpy(buf, &uid, uidlen);
+ return 0;
+}
+
+#ifdef TEST_FORTUNA
+int
+test_entr(krb5_context context, unsigned char* buf, int buflen)
+{
+ char buf1[26] = "Seed To Test Fortuna PRNG";
+ memset(buf, 0, buflen);
+ memcpy(buf, buf1, min(buflen, 26));
+ return 0;
+}
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prng/fortuna.h
+ *
+ * Copyright 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef FORTUNA_H
+#define FORTUNA_H
+
+#include "k5-int.h"
+#include "prng.h"
+#ifndef OPENSSL
+#include "aes.h"
+#endif
+#include "enc_provider.h"
+#include "sha2.h"
+#include "enc_provider.h"
+
+extern const struct krb5_prng_provider krb5int_prng_fortuna;
+
+/* various entropy collect functions */
+krb5_error_code
+k5_entropy_from_device(krb5_context context, const char *device, unsigned char* buf, int buflen);
+krb5_error_code
+k5_entropy_dev_random(krb5_context context, unsigned char* buf, int buflen);
+krb5_error_code
+k5_entropy_dev_urandom(krb5_context context, unsigned char* buf, int buflen);
+krb5_error_code
+k5_entropy_pid(krb5_context context, unsigned char* buf, int buflen);
+krb5_error_code
+k5_entropy_uid(krb5_context context, unsigned char* buf, int buflen);
+
+#ifdef TEST_FORTUNA
+int test_entr(krb5_context context, unsigned char* buf, int buflen);
+#endif
+
+#define FORTUNA_OK 1 /* All is well */
+#define FORTUNA_FAIL 0 /* generic failure */
+#define FORTUNA_LOCKING -12
+
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* prng_fortuna.c */
+/*
+ * fortuna.c
+ * Fortuna-like PRNG.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.8 2006/10/04 00:29:46 momjian Exp $
+ */
+/*
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "fortuna.h"
+#include "k5-int.h"
+
+
+#include "k5-thread.h"
+k5_mutex_t fortuna_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/*
+ * Why Fortuna-like: There does not seem to be any definitive reference
+ * on Fortuna in the net. Instead this implementation is based on
+ * following references:
+ *
+ * http://en.wikipedia.org/wiki/Fortuna_(PRNG)
+ * - Wikipedia article
+ * http://jlcooke.ca/random/
+ * - Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
+ */
+
+/*
+ * There is some confusion about whether and how to carry forward
+ * the state of the pools. Seems like original Fortuna does not
+ * do it, resetting hash after each request. I guess expecting
+ * feeding to happen more often that requesting. This is absolutely
+ * unsuitable for pgcrypto, as nothing asynchronous happens here.
+ *
+ * J.L. Cooke fixed this by feeding previous hash to new re-initialized
+ * hash context.
+ *
+ * Fortuna predecessor Yarrow requires ability to query intermediate
+ * 'final result' from hash, without affecting it.
+ *
+ * This implementation uses the Yarrow method - asking intermediate
+ * results, but continuing with old state.
+ */
+
+/*
+ * Algorithm parameters
+ */
+
+#define NUM_POOLS 32
+
+/* in microseconds */
+#define RESEED_INTERVAL 100000 /* 0.1 sec */
+
+/* for one big request, reseed after this many bytes */
+#define RESEED_BYTES (1024*1024)
+
+/*
+ * Skip reseed if pool 0 has less than this many
+ * bytes added since last reseed.
+ */
+#define POOL0_FILL (256/8)
+
+/* Entropy gathering */
+int (*entropy_collector[])(krb5_context context, unsigned char buf[], int buflen) =
+{
+#ifndef TEST_FORTUNA
+ /* k5_entropy_dev_random, */
+ k5_entropy_dev_urandom,
+ k5_entropy_pid,
+ k5_entropy_uid
+#else
+ test_entr
+#endif
+};
+
+/*
+ * Algorithm constants
+ */
+
+#define AES_BLOCK_SIZE 16
+#define AES_MAXNR 14
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+/* Both cipher key size and hash result size */
+#define BLOCK 32
+
+/* cipher block size */
+#define CIPH_BLOCK 16
+
+/* for internal wrappers */
+
+#define MD_CTX SHA256_CTX
+#define CIPH_CTX aes_ctx
+
+/* Genarator - block cipher in CTR mode */
+struct fortuna_state
+{
+ unsigned char counter[CIPH_BLOCK];
+ unsigned char result[CIPH_BLOCK];
+ unsigned char key[BLOCK];
+ MD_CTX pool[NUM_POOLS];
+ CIPH_CTX ciph;
+ unsigned reseed_count;
+ struct timeval last_reseed_time;
+ unsigned pool0_bytes;
+ unsigned rnd_pos;
+ int tricks_done;
+ pid_t pid;
+};
+typedef struct fortuna_state FState;
+
+
+/*
+ * Use our own wrappers here.
+ * - Need to get intermediate result from digest, without affecting it.
+ * - Need re-set key on a cipher context.
+ * - Algorithms are guaranteed to exist.
+ * - No memory allocations.
+ */
+
+static void
+ciph_init(CIPH_CTX * ctx /*out*/, const unsigned char *key, int klen)
+{
+ krb5int_aes_enc_key(key, klen, ctx);
+}
+
+static void
+ciph_encrypt(CIPH_CTX *ctx, const unsigned char *in, unsigned char *out)
+{
+ aes_enc_blk(in, out, ctx);
+}
+
+static void
+md_init(MD_CTX * ctx)
+{
+ sha2Init(ctx);
+}
+
+static void
+md_update(MD_CTX * ctx, const unsigned char *data, int len)
+{
+ sha2Update(ctx, data, len);
+}
+
+static void
+md_result(MD_CTX * ctx, unsigned char *dst)
+{
+ MD_CTX tmp_ctx;
+
+ memcpy(&tmp_ctx, ctx, sizeof(*ctx));
+ sha2Final(dst, &tmp_ctx);
+ memset(&tmp_ctx, 0, sizeof(tmp_ctx));
+}
+
+/*
+ * initialize state
+ */
+static krb5_error_code
+init_state(FState * st)
+{
+ int i;
+ krb5_error_code ret = 0;
+
+ ret = k5_mutex_finish_init(&fortuna_lock);
+ if (ret)
+ return ret;
+
+ memset(st, 0, sizeof(*st));
+ for (i = 0; i < NUM_POOLS; i++)
+ md_init(&st->pool[i]);
+ st->pid = getpid();
+
+ return 0;
+}
+
+/*
+ * Endianess does not matter.
+ * It just needs to change without repeating.
+ */
+static void
+inc_counter(FState * st)
+{
+ uint32_t *val = (uint32_t *) st->counter;
+
+ if (++val[0])
+ return;
+ if (++val[1])
+ return;
+ if (++val[2])
+ return;
+ ++val[3];
+}
+
+/*
+ * This is called 'cipher in counter mode'.
+ */
+static void
+encrypt_counter(FState * st, unsigned char *dst)
+{
+ ciph_encrypt(&st->ciph, st->counter, dst);
+ inc_counter(st);
+}
+
+
+/*
+ * The time between reseed must be at least RESEED_INTERVAL microseconds.
+ */
+static int
+enough_time_passed(FState * st)
+{
+ int ok = FORTUNA_FAIL;
+ struct timeval tv;
+ struct timeval *last = &st->last_reseed_time;
+
+ gettimeofday(&tv, NULL);
+
+ /* check how much time has passed */
+ if (tv.tv_sec > last->tv_sec + 1)
+ ok = FORTUNA_OK;
+ else if (tv.tv_sec == last->tv_sec + 1) {
+ if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ ok = FORTUNA_OK;
+ } else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ ok = FORTUNA_OK;
+
+ /* reseed will happen, update last_reseed_time */
+ if (ok)
+ memcpy(last, &tv, sizeof(tv));
+
+ memset(&tv, 0, sizeof(tv));
+
+ return ok;
+}
+
+/*
+ * generate new key from all the pools
+ */
+static void
+reseed(FState * st)
+{
+ unsigned k;
+ unsigned n;
+ MD_CTX key_md;
+ unsigned char buf[BLOCK];
+
+ /* set pool as empty */
+ st->pool0_bytes = 0;
+
+ /*
+ * Both #0 and #1 reseed would use only pool 0. Just skip #0 then.
+ */
+ n = ++st->reseed_count;
+
+ /*
+ * The goal: use k-th pool only 1/(2^k) of the time.
+ */
+ md_init(&key_md);
+ for (k = 0; k < NUM_POOLS; k++) {
+ md_result(&st->pool[k], buf);
+ md_update(&key_md, buf, BLOCK);
+
+ if (n & 1 || !n)
+ break;
+ n >>= 1;
+ }
+ /* add old key into mix too */
+ md_update(&key_md, st->key, BLOCK);
+
+#ifndef TEST_FORTUNA
+ /* add pid to make output diverse after fork() */
+ md_update(&key_md, (const unsigned char *)&st->pid, sizeof(st->pid));
+#endif
+
+ /* now we have new key */
+ md_result(&key_md, st->key);
+ /* use new key */
+ ciph_init(&st->ciph, st->key, BLOCK);
+
+ memset(&key_md, 0, sizeof(key_md));
+ memset(buf, 0, BLOCK);
+}
+
+/*
+ * Pick a random pool. This uses key bytes as random source.
+ */
+static unsigned
+get_rand_pool(FState * st)
+{
+ unsigned rnd;
+
+ /*
+ * This slightly prefers lower pools - thats OK.
+ */
+ rnd = st->key[st->rnd_pos] % NUM_POOLS;
+
+ st->rnd_pos++;
+ if (st->rnd_pos >= BLOCK)
+ st->rnd_pos = 0;
+
+ return rnd;
+}
+
+/*
+ * update pools
+ */
+static void
+add_entropy(FState * st, const unsigned char data[], unsigned len)
+{
+ unsigned pos;
+ unsigned char hash[BLOCK];
+ MD_CTX md;
+
+ /* hash given data */
+ md_init(&md);
+ md_update(&md, data, len);
+ md_result(&md, hash);
+
+ /*
+ * Make sure the pool 0 is initialized, then update randomly.
+ */
+ if (st->reseed_count == 0)
+ pos = 0;
+ else
+ pos = get_rand_pool(st);
+ md_update(&st->pool[pos], hash, BLOCK);
+
+ if (pos == 0)
+ st->pool0_bytes += len;
+
+ memset(hash, 0, BLOCK);
+ memset(&md, 0, sizeof(md));
+}
+
+/*
+ * Just take 2 next blocks as new key
+ */
+static void
+rekey(FState * st)
+{
+ encrypt_counter(st, st->key);
+ encrypt_counter(st, st->key + CIPH_BLOCK);
+ ciph_init(&st->ciph, st->key, BLOCK);
+}
+
+/*
+ * Hide public constants. (counter, pools > 0)
+ *
+ * This can also be viewed as spreading the startup
+ * entropy over all of the components.
+ */
+static void
+startup_tricks(FState * st)
+{
+ int i;
+ unsigned char buf[BLOCK];
+
+ /* Use next block as counter. */
+ encrypt_counter(st, st->counter);
+
+ /* Now shuffle pools, excluding #0 */
+ for (i = 1; i < NUM_POOLS; i++) {
+ encrypt_counter(st, buf);
+ encrypt_counter(st, buf + CIPH_BLOCK);
+ md_update(&st->pool[i], buf, BLOCK);
+ }
+ memset(buf, 0, BLOCK);
+
+ /* Hide the key. */
+ rekey(st);
+
+ /* This can be done only once. */
+ st->tricks_done = 1;
+}
+
+static void
+extract_data(FState * st, unsigned count, unsigned char *dst)
+{
+ unsigned n;
+ unsigned block_nr = 0;
+ pid_t pid = getpid();
+
+ /* Should we reseed? */
+ if (st->pool0_bytes >= POOL0_FILL || st->reseed_count == 0)
+ if (enough_time_passed(st))
+ reseed(st);
+
+ /* Do some randomization on first call */
+ if (!st->tricks_done)
+ startup_tricks(st);
+
+ /* If we forked, force a reseed again */
+ if (pid != st->pid) {
+ st->pid = pid;
+ reseed(st);
+ }
+ while (count > 0) {
+ /* produce bytes */
+ encrypt_counter(st, st->result);
+
+ /* copy result */
+ if (count > CIPH_BLOCK)
+ n = CIPH_BLOCK;
+ else
+ n = count;
+ memcpy(dst, st->result, n);
+ dst += n;
+ count -= n;
+
+ /* must not give out too many bytes with one key */
+ block_nr++;
+ if (block_nr > (RESEED_BYTES / CIPH_BLOCK)) {
+ rekey(st);
+ block_nr = 0;
+ }
+ }
+ /* Set new key for next request. */
+ rekey(st);
+}
+
+/*
+ * public interface
+ */
+
+static FState main_state;
+static int init_done;
+static int have_entropy;
+static int resend_bytes;
+
+#define FORTUNA_RESEED_BYTE 10000
+
+/*
+ * Try our best to do an inital seed
+ */
+#define INIT_BYTES 128
+
+static int
+fortuna_reseed(void)
+{
+ int entropy_p = 0;
+ krb5_context ctx;
+ unsigned char buf[ENTROPY_BUFSIZE];
+ int num = sizeof(entropy_collector)/sizeof(entropy_collector[0]);
+
+ if (!init_done)
+ abort();
+
+ while(num > 0){
+ entropy_collector[num-1](ctx, buf, ENTROPY_BUFSIZE);
+ add_entropy(&main_state, buf, sizeof(buf));
+ num--;
+ }
+ memset (buf,0,ENTROPY_BUFSIZE);
+ entropy_p = 1;
+
+ return entropy_p;
+}
+
+static int
+fortuna_init(void)
+{
+ krb5_error_code ret = 0;
+
+ if (!init_done) {
+ ret = init_state(&main_state);
+ if (ret == 0)
+ init_done = 1;
+ }
+ if (!have_entropy)
+ have_entropy = fortuna_reseed();
+ return (init_done && have_entropy);
+}
+
+static krb5_error_code
+fortuna_seed(const unsigned char *indata, int size)
+{
+ krb5_error_code ret = 0;
+
+ fortuna_init();
+
+ ret = k5_mutex_lock(&fortuna_lock);
+ if (ret)
+ return FORTUNA_LOCKING;
+
+ add_entropy(&main_state, indata, size);
+ if (size >= INIT_BYTES)
+ have_entropy = 1;
+
+ k5_mutex_unlock(&fortuna_lock);
+
+ return FORTUNA_OK;
+}
+
+static int
+fortuna_bytes(unsigned char *outdata, int size)
+{
+ krb5_error_code ret = 0;
+
+ if (!fortuna_init()){
+ return FORTUNA_FAIL;
+ }
+
+ ret = k5_mutex_lock(&fortuna_lock);
+ if (ret)
+ return FORTUNA_LOCKING;
+
+ resend_bytes += size;
+ if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) {
+ resend_bytes = 0;
+ fortuna_reseed();
+ }
+ extract_data(&main_state, size, outdata);
+
+ k5_mutex_unlock(&fortuna_lock);
+
+ return FORTUNA_OK;
+}
+
+static void
+fortuna_cleanup(void)
+{
+ krb5_error_code ret = 0;
+
+ ret = k5_mutex_lock(&fortuna_lock);
+
+ init_done = 0;
+ have_entropy = 0;
+ memset(&main_state, 0, sizeof(main_state));
+
+ if (!ret)
+ k5_mutex_unlock(&fortuna_lock);
+
+ k5_mutex_destroy(&fortuna_lock);
+
+}
+
+static krb5_error_code
+fortuna_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *indata)
+{
+ krb5_error_code ret = 0;
+ ret = fortuna_seed((const unsigned char *)indata->data, indata->length);
+ if (ret != FORTUNA_OK)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+static krb5_error_code
+fortuna_make_octets(krb5_context context, krb5_data *outdata)
+{
+ krb5_error_code ret = 0;
+ ret = fortuna_bytes((unsigned char *)outdata->data, outdata->length);
+ if (ret != FORTUNA_OK)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+const struct krb5_prng_provider krb5int_prng_fortuna = {
+ "fortuna",
+ fortuna_make_octets,
+ fortuna_add_entropy,
+ fortuna_init,
+ fortuna_cleanup
+};
+
--- /dev/null
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "prng.h"
+#include "fortuna.h"
+#include <k5-int.h>
+
+
+#define LEN_TEST_BUF 1024 * 1024
+static int len = LEN_TEST_BUF;
+
+int
+main(int argc, char **argv)
+{
+ char buffer[LEN_TEST_BUF];
+ krb5_data data = {0, LEN_TEST_BUF, (char*)buffer};
+ int bit, i;
+ double res;
+ int bits[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ if (len < 100000)
+ return 0;
+
+ for (i = 0; i < LEN_TEST_BUF; i++)
+ buffer[i] = 0;
+
+ /* head vs tail */
+ krb5_c_random_make_octets(NULL, &data);
+ for (i = 0; i < len; i++) {
+ unsigned char c = ((unsigned char *)buffer)[i];
+ for (bit = 0; bit < 8 && c; bit++) {
+ if (c & 1)
+ bits[bit]++;
+ c = c >> 1;
+ }
+ }
+
+ for (bit = 0; bit < 8; bit++) {
+
+ res = ((double)abs(len - bits[bit] * 2)) / (double)len;
+ if (res > 0.005){
+ printf("head %d vs tail %d > 0.5%%%% %lf == %d vs %d\n",
+ bit, bit, res, len, bits[bit]);
+ return 1;
+ }
+
+ printf("head vs tails bit %d is %lf\n", bit, res);
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "prng.h"
+#include "fortuna.h"
+#include <k5-int.h>
+
+#define LEN_TEST_BUF 1024
+static int len = LEN_TEST_BUF;
+
+static void hex_print( FILE* f, const char* var, void* data, size_t size );
+
+int
+main(int argc, char **argv)
+{
+ char buffer[LEN_TEST_BUF];
+ krb5_data data = {0, LEN_TEST_BUF, (char*)buffer};
+ int i;
+
+ for (i = 0; i < LEN_TEST_BUF; i++)
+ buffer[i] = 0;
+
+ krb5_c_random_make_octets(NULL, &data);
+
+ hex_print( stdout, "random1", data.data, data.length );
+
+ /* To target FORTUNA_RESEED_BYTE */
+ i = 0;
+ while (i++ < 11){
+ krb5_c_random_make_octets(NULL, &data);
+ }
+
+ hex_print( stdout, "random2", data.data, data.length );
+
+ return 0;
+}
+static void
+hex_print( FILE* f, const char* var, void* data, size_t size )
+{
+ const char* conv = "0123456789abcdef";
+ size_t i;
+ char* p = (char*) data;
+ char c, d;
+
+ fprintf( f, var );
+ fprintf( f, " = " );
+ for ( i = 0; i < size; i++ )
+ {
+ c = conv[ (p[ i ] >> 4) & 0xf ];
+ d = conv[ p[ i ] & 0xf ];
+ fprintf( f, "%c%c", c, d );
+ }
+ fprintf( f, "\n" );
+}
+
--- /dev/null
+random1 = c27d031fce09ad26525e107021c1038062c9e05672065bce1139a9ae583d9cd70319e9a68d1f4da2cf24099af05ab1a910c781035864ab7e45337199cfa7ece05111d3604215feac555e847148dcf47fa8361746ce162201edbb83f4f753ad9933f9c618f86e15ff28eecdddbcaacd2ff212c236141b2edc5e5b91f2a95f89af5070eed9652f2857963801cff9f21d6a08f8c1480270009ebde555a00dcc60b0688cba89950aeeac8a0806922ea1baae494e1bc1be7920fa6c9b980a80f374a5ea53f3e10ffeef047bea388949fc0b66252d25c8775dd01a03a27528a4c801993129e581e3c4d77ecca9efaf27047d7eec025f6f0601d469a93f5be5cbac10b773a392a3d0a167ec76637014974fe6808e88b9b8fbd51dfbad7192d1edad971b11404f96849cc88dab07b21ff14d5d528d60c3bb7ad4b1ddc3e6b082df9d89b020d276db81676ffcf6521b2bab33c404b27f15f5547ee4a37654680fb331afb256a6cd83146a5baf70a6a5a455c7ead49493f7aa85d4afde951f33f44a99c49ea1e3f568b70735c46dce20460150d2c96aa0849cd5b7062253fdb11ba4a7e046fe24ccd3c87bbebe3351c10a8b6fb4b1e2dd46803782982970cf9805fa2a8540d9f910ea4e360a342a320cce34101472fdc258ba339038e464da6bc20b79df5fc6ae27762a7315d3b342d99eca5d23c5ce2f1ba800bdb68882a6b520e31037e8c1e1ea3444334ed6ec3913994344b714009b9cc816d57d5a74e1cbfe3f038f0def48f43ef81983a872068f60e808ed75997d23e4896faba5542738bd403b3d5fc33f64d606d376e936f89a60cf0ad417ba0f9cd4bb70287437e9f7d63572432d859473dadd9b8c51a8813e3e734968288afdb22a5779c1f6ccc681cf2332f634096f4d40088bdee97270a7d7c04d7b367001b7c154da3f69734fd91590710e54af97f4e03b80c800ccef3282b519aaa4a76f9cb06d6746211be6ca8ac910b3b0bb799ae185dbc92c8ac2d91f0c6e5bc7095e41ebd2b3217648ba62616a3820f282154ab2787f26c47c47bb099810b65e862ed44b9d47ac87d693d2f87295834274310f337b15a4d7b33d91ffefa7b3dfec270327db4b46a5e0e1cdc072e5d0a2e8392a2bede194ee715070785f1d1cb6a5bcd2f13b4aa644541b9e6336bbb87d88bead71858dfc4c211589865faf08c8cc9ba47728dc8d2ebc3fb6d9c434b8ad7f99fbc14124fb5ffaa24fb0c7650bb19e5e17379fb58579d3b41a007e3783f68cf523a9b1fbbbab2e40c9aa8049f4e2a609c4adc528b904792121e139bbf340980adc38ac32f9538790cad55351b46faae28a0c8d5a995d55e254694102901556c9ce648da6803c6480d5ad0e567ace44d88f5d45cc02e55f81b011d2c2188cd6e89aa6a7cffed6a14a8dbb592e4f386b5a7204d6a0d56cb0844c8df76f7697
+random2 = 9d87e8e1b4b74803357d0cc36ca668584c2bba571cb38f66fba3a2d03f897fcf392fd2f88184d330ca03e85b7c4531269849864ee6bc61d81501b7a5796377a73aa6c594b9b37f0e7c130acfac926a329d742ca0bf9edbc39d5bb64dffbbd81467be1fab250eaedbeff79bb2a697584a0b14626833d06f92dbdddd6bc12d6caba725d1eae4a899b4fd75b9bbd9ed05cca9f96c7cc41ae236f3c904f0d9ee4c83111e8dc2bf520a30bcfb2afb8943f61cfd4ef9364dab069276b282f831e1abad31048926ca3cccaa7406998620c941b1ded73d623c0659462e13bf68c0ceafbd5a23afb402b2477297e431182d964cd57cc494b26886af5037964467df5b2f0f981a5aaac9a1718b5b00c174adb0d4de383eb46ffb0ecffc4a432822b9af3d21e7b5b10b7e221978ffb47d058f33456518bc647f78d5e3f5e2850957a12f83b9a0c5a8736b509336eced539c9c0faeb37285f90bb12e3499ef9aaae8c5de67ac2e5b374dffe4e1c5c3f14c4cd8905c7a7db03ac69dbdcf627c2bd4f98dda671dd0da9b70495e476fdba17894665ee2c3f8bb9e5d015b0ee727ddf85115d5833fd13633afd2dd4d5bfa751c9a4b7e937c77939cb72f057714ad94a112d28b578ce265306b415339280748fd20977967f5b04ff92d93e994fe3fd4b887bb8fb7c8cd16af9877532e49df4ee3b7132fed5920d5fc5aeda6784f4371af614d1502f036c1519c53bec2a79303050562b1b929cf705254607486c550fbb40fb7445262929bb4ef8ed658c9e4a825ca0d3e796e5e681a5ce19c2c8880a44c78f205add4c8092a790f7a8d2fbae663d32ac0640317a9735e43369ed680247789330a372910a7ce356f8eafd8776972315bb83794589f22f21770cb1b7c17f25861da3fd142398a85ba357865da0684e916eade4d078deb78ccd5442c27d4e4973eb582d2d55fd5877c64f234a61dcc11a828afa5a52ddea02ad8001c09a60fc7a14bd7118486722db6bf3a54dded4691a7937c3cb546395fc99e49954216f203aaee05985a25ea284022c72dd0a156f030c6a2604b9332ab5324c35f77674836321bcd263f8c2176558d83e23cc00d0fa4d438e9536ab7e574067baeeaeda20b2af5f8ee0821e5ff7949a50c286da61b19d8c32cca7ce1459989731cedd2852a297a6b65637413747b47286a62cf4eabfb5308acbf2d593769f0e8d148945556f1fcfdc7cadd8a6e0c0e174ddb301610d201c7b78b079c2270ac5737fe4771d9bab5257dcf5cca173af2f374c6f68e4658189f1aff3bb81c99e56dc69d14249b07d36c2f73adcb5fa1b71b629a0957b571bf6af13c12983056b6263c9c484b0778c3c1eb1261399644e942eb54479461af9397d7413822a4f267304b1dafc32744ef543a3f3442e05d70c727ac1afb846454aa50d2d979349c508f46981c297672ee78a1
--- /dev/null
+mydir=lib/crypto/krb/prng/nss
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../.. \
+ -I$(srcdir)/../../../@CRYPTO_IMPL@
+DEFS=
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS= prng_nss.o
+OBJS= \
+ $(OUTPRE)prng_nss.$(OBJEXT)
+
+SRCS=\
+ $(srcdir)/prng_nss.c
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean::
+ $(RM) t_nss$(EXEEXT) t_nss.$(OBJEXT) t_nss_make_oct.result t_nss_make_oct$(EXEEXT) t_nss_make_oct.$(OBJEXT)
+
+
+clean-unix:: clean-libobjs
+
+@lib_frag@
+@libobj_frag@
+
--- /dev/null
+#
+# Generated makefile dependencies follow.
+#
+prng_nss.so prng_nss.po $(OUTPRE)prng_nss.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../../builtin/aes/aes.h \
+ $(srcdir)/../prng.h \
+ $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ prng_nss.c prng_nss.h
+
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * prng_nss.c
+ *
+ * Copyright (C) 2008, 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "prng.h"
+#include <assert.h>
+#include "k5-thread.h"
+
+#ifdef CRYPTO_IMPL_NSS
+
+/*
+ * Using Yarrow with NSS is a bit problematic because the MD5 contexts it holds
+ * open for the entropy pools would be invalidated by a fork(), causing us to
+ * lose the entropy contained therein.
+ *
+ * Therefore, use the NSS PRNG if NSS is the crypto implementation.
+ */
+
+#include "../nss/nss_gen.h"
+#include <pk11pub.h>
+
+static int
+nss_init(void)
+{
+ return 0;
+}
+
+static krb5_error_code
+nss_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *data)
+{
+ krb5_error_code ret;
+
+ ret = k5_nss_init();
+ if (ret)
+ return ret;
+ if (PK11_RandomUpdate(data->data, data->length) != SECSuccess)
+ return k5_nss_map_last_error();
+ return 0;
+}
+
+static krb5_error_code
+nss_make_octets(krb5_context context, krb5_data *data)
+{
+ krb5_error_code ret;
+
+ ret = k5_nss_init();
+ if (ret)
+ return ret;
+ if (PK11_GenerateRandom((unsigned char *)data->data,
+ data->length) != SECSuccess)
+ return k5_nss_map_last_error();
+ return 0;
+}
+
+static void
+nss_cleanup (void)
+{
+}
+
+const struct krb5_prng_provider krb5int_prng_nss = {
+ "nss",
+ nss_make_octets,
+ nss_add_entropy,
+ nss_init,
+ nss_cleanup
+};
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prng/fortuna.h
+ *
+ * Copyright 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef FORTUNA_H
+#define FORTUNA_H
+
+#include "k5-int.h"
+#include "prng.h"
+
+extern const struct krb5_prng_provider krb5int_prng_nss;
+
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prng/prng.h
+ *
+ * Copyright 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#ifndef PRNG_H
+#define PRNG_H
+
+#include "k5-int.h"
+
+#if defined(FORTUNA)
+#define ENTROPY_BUFSIZE 32 /* SHA256 digest length */
+#elif defined(CRYPTO_IMPL_NSS)
+/*
+ * NSS gathers its own OS entropy, so it doesn't really matter how much we read
+ * in krb5_c_random_os_entropy. Use the same value as Yarrow (without using a
+ * Yarrow constant), so that we don't read too much from /dev/random.
+ */
+#define ENTROPY_BUFSIZE 20
+#else
+#define ENTROPY_BUFSIZE YARROW_SLOW_THRESH/8 /* SHA1 digest length*/
+#endif
+
+/* prng.h */
+struct krb5_prng_provider {
+ char prng_name[8];
+ krb5_error_code (*make_octets)(krb5_context, krb5_data *);
+ krb5_error_code (*add_entropy)(krb5_context, unsigned int randsource, const krb5_data*);
+ int (*init)(void);
+ void (*cleanup)(void);
+};
+
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * prng_yarrow.c
+ *
+ * Copyright (C) 2001, 2002, 2004, 2007, 2008, 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "prng.h"
+#include "enc_provider.h"
+#include <assert.h>
+#include "k5-thread.h"
+
+#include "yarrow.h"
+static Yarrow_CTX y_ctx;
+#define yarrow_lock krb5int_yarrow_lock
+k5_mutex_t yarrow_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/* Helper function to estimate entropy based on sample length
+ * and where it comes from.
+ */
+
+static size_t
+entropy_estimate(unsigned int randsource, size_t length)
+{
+ switch (randsource) {
+ case KRB5_C_RANDSOURCE_OLDAPI:
+ return 4 * length;
+ case KRB5_C_RANDSOURCE_OSRAND:
+ return 8 * length;
+ case KRB5_C_RANDSOURCE_TRUSTEDPARTY:
+ return 4 * length;
+ case KRB5_C_RANDSOURCE_TIMING:
+ return 2;
+ case KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL:
+ return 0;
+ default:
+ abort();
+ }
+ return 0;
+}
+
+static int
+yarrow_init(void)
+{
+ unsigned i, source_id;
+ int yerr;
+
+ yerr = k5_mutex_finish_init(&yarrow_lock);
+ if (yerr)
+ return yerr;
+
+ yerr = krb5int_yarrow_init (&y_ctx, NULL);
+ if (yerr != YARROW_OK && yerr != YARROW_NOT_SEEDED)
+ return KRB5_CRYPTO_INTERNAL;
+
+ for (i=0; i < KRB5_C_RANDSOURCE_MAX; i++ ) {
+ if (krb5int_yarrow_new_source(&y_ctx, &source_id) != YARROW_OK)
+ return KRB5_CRYPTO_INTERNAL;
+ assert (source_id == i);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+yarrow_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *data)
+{
+ int yerr;
+ /* Make sure the mutex got initialized. */
+ yerr = krb5int_crypto_init();
+ if (yerr)
+ return yerr;
+ /* Now, finally, feed in the data. */
+ yerr = krb5int_yarrow_input(&y_ctx, randsource,
+ data->data, data->length,
+ entropy_estimate(randsource, data->length));
+ if (yerr != YARROW_OK)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+/*
+static krb5_error_code
+yarrow_seed(krb5_context context, krb5_data *data)
+{
+ return yarrow_add_entropy(context, KRB5_C_RANDSOURCE_OLDAPI, data);
+}
+*/
+static krb5_error_code
+yarrow_make_octets(krb5_context context, krb5_data *data)
+{
+ int yerr;
+ yerr = krb5int_yarrow_output(&y_ctx, data->data, data->length);
+ if (yerr == YARROW_NOT_SEEDED) {
+ yerr = krb5int_yarrow_reseed(&y_ctx, YARROW_SLOW_POOL);
+ if (yerr == YARROW_OK)
+ yerr = krb5int_yarrow_output(&y_ctx, data->data, data->length);
+ }
+ if (yerr != YARROW_OK)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+static void
+yarrow_cleanup (void)
+{
+ krb5int_yarrow_final (&y_ctx);
+ k5_mutex_destroy(&yarrow_lock);
+}
+
+const struct krb5_prng_provider krb5int_prng_yarrow = {
+ "yarrow",
+ yarrow_make_octets,
+ yarrow_add_entropy,
+ yarrow_init,
+ yarrow_cleanup
+};
--- /dev/null
+mydir=lib/crypto/nss/sha2
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+DEFS=
+LOCALINCLUDES = -I$(srcdir)/.. @CRYPTO_IMPL_CFLAGS@
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR=sha1
+##DOS##OBJFILE=..\$(OUTPRE)sha2.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS= sha2.o
+
+OBJS= $(OUTPRE)sha2.$(OBJEXT)
+
+SRCS= $(srcdir)/sha2.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean::
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
--- /dev/null
+#
+# Generated makefile dependencies follow.
+#
+shs.so shs.po $(OUTPRE)shs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
+ $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h $(srcdir)/shs.c \
+ $(srcdir)/shs.h
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+#include "k5-int.h"
+#include "sha2.h"
+
+void sha2Init(SHA2_INFO *shsInfo)
+{
+ return;
+}
+
+void sha2Update(SHA2_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count)
+{
+ return;
+}
+
+void sha2Final(SHA2_INFO *shsInfo)
+{
+ return;
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#ifndef _SHA2_DEFINED
+
+#include "k5-int.h"
+
+#define _SHA2_DEFINED
+
+typedef krb5_octet SHS_BYTE;
+#define SHA2_DIGESTSIZE 32
+
+/* The structure for storing SHA2 info */
+
+typedef struct {
+ void *nss_ctxt;
+ unsigned char digestBuf[SHA2_DIGESTSIZE]; /* output */
+ unsigned int digestLen; /* output */
+} SHA2_INFO;
+
+void sha2Init(SHA2_INFO *shsInfo);
+void sha2Update(SHA2_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count);
+void sha2Final(SHA2_INFO *shsInfo);
+
+#endif /* _SHA2_DEFINED */