Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 39F4B200B88 for ; Thu, 8 Sep 2016 04:08:14 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 38A79160AD4; Thu, 8 Sep 2016 02:08:14 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 1554F160ACF for ; Thu, 8 Sep 2016 04:08:12 +0200 (CEST) Received: (qmail 53922 invoked by uid 500); 8 Sep 2016 02:08:12 -0000 Mailing-List: contact commits-help@hawq.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hawq.incubator.apache.org Delivered-To: mailing list commits@hawq.incubator.apache.org Received: (qmail 53910 invoked by uid 99); 8 Sep 2016 02:08:12 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Sep 2016 02:08:12 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id B9897C0EF7 for ; Thu, 8 Sep 2016 02:08:11 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.396 X-Spam-Level: X-Spam-Status: No, score=-4.396 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, KAM_LOTSOFHASH=0.25, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.426] autolearn=disabled Received: from mx2-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id OKKb4udAn6k2 for ; Thu, 8 Sep 2016 02:08:01 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx2-lw-eu.apache.org (ASF Mail Server at mx2-lw-eu.apache.org) with SMTP id 8A3246122C for ; Thu, 8 Sep 2016 02:07:38 +0000 (UTC) Received: (qmail 50725 invoked by uid 99); 8 Sep 2016 02:07:36 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Sep 2016 02:07:36 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 69C46E053F; Thu, 8 Sep 2016 02:07:36 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mli@apache.org To: commits@hawq.incubator.apache.org Date: Thu, 08 Sep 2016 02:08:34 -0000 Message-Id: <35a77498970e462baa116c1875a74dd1@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [61/70] incubator-hawq git commit: HAWQ-1007. Add the pgcrypto code into hawq archived-at: Thu, 08 Sep 2016 02:08:14 -0000 http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/expected/sha2.out ---------------------------------------------------------------------- diff --git a/contrib/pgcrypto/expected/sha2.out b/contrib/pgcrypto/expected/sha2.out new file mode 100644 index 0000000..2df5a0d --- /dev/null +++ b/contrib/pgcrypto/expected/sha2.out @@ -0,0 +1,139 @@ +-- +-- SHA2 family +-- +-- SHA224 +SELECT encode(digest('', 'sha224'), 'hex'); + encode +---------------------------------------------------------- + d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f +(1 row) + +SELECT encode(digest('a', 'sha224'), 'hex'); + encode +---------------------------------------------------------- + abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5 +(1 row) + +SELECT encode(digest('abc', 'sha224'), 'hex'); + encode +---------------------------------------------------------- + 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 +(1 row) + +SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha224'), 'hex'); + encode +---------------------------------------------------------- + 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525 +(1 row) + +SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha224'), 'hex'); + encode +---------------------------------------------------------- + b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e +(1 row) + +-- SHA256 +SELECT encode(digest('', 'sha256'), 'hex'); + encode +------------------------------------------------------------------ + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +(1 row) + +SELECT encode(digest('a', 'sha256'), 'hex'); + encode +------------------------------------------------------------------ + ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb +(1 row) + +SELECT encode(digest('abc', 'sha256'), 'hex'); + encode +------------------------------------------------------------------ + ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad +(1 row) + +SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha256'), 'hex'); + encode +------------------------------------------------------------------ + 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1 +(1 row) + +SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha256'), 'hex'); + encode +------------------------------------------------------------------ + f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e +(1 row) + +-- SHA384 +SELECT encode(digest('', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b +(1 row) + +SELECT encode(digest('a', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31 +(1 row) + +SELECT encode(digest('abc', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 +(1 row) + +SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b +(1 row) + +SELECT encode(digest('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039 +(1 row) + +SELECT encode(digest('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz', 'sha384'), 'hex'); + encode +-------------------------------------------------------------------------------------------------- + 3d208973ab3508dbbd7e2c2862ba290ad3010e4978c198dc4d8fd014e582823a89e16f9b2a7bbc1ac938e2d199e8bea4 +(1 row) + +-- SHA512 +SELECT encode(digest('', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e +(1 row) + +SELECT encode(digest('a', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75 +(1 row) + +SELECT encode(digest('abc', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f +(1 row) + +SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445 +(1 row) + +SELECT encode(digest('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909 +(1 row) + +SELECT encode(digest('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz', 'sha512'), 'hex'); + encode +---------------------------------------------------------------------------------------------------------------------------------- + 930d0cefcb30ff1133b6898121f1cf3d27578afcafe8677c5257cf069911f75d8f5831b56ebfda67b278e66dff8b84fe2b2870f742a580d8edb41987232850c9 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/fortuna.c ---------------------------------------------------------------------- diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c new file mode 100644 index 0000000..1228fb4 --- /dev/null +++ b/contrib/pgcrypto/fortuna.c @@ -0,0 +1,462 @@ +/* + * 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. + * + * contrib/pgcrypto/fortuna.c + */ + +#include "postgres.h" + +#include +#include + +#include "rijndael.h" +#include "sha2.h" +#include "fortuna.h" + + +/* + * 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 + */ + +/* + * How many pools. + * + * Original Fortuna uses 32 pools, that means 32'th pool is + * used not earlier than in 13th year. This is a waste in + * pgcrypto, as we have very low-frequancy seeding. Here + * is preferable to have all entropy usable in reasonable time. + * + * With 23 pools, 23th pool is used after 9 days which seems + * more sane. + * + * In our case the minimal cycle time would be bit longer + * than the system-randomness feeding frequency. + */ +#define NUM_POOLS 23 + +/* 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) + +/* + * Algorithm constants + */ + +/* 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 rijndael_ctx + +struct fortuna_state +{ + uint8 counter[CIPH_BLOCK]; + uint8 result[CIPH_BLOCK]; + uint8 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; +}; +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, const uint8 *key, int klen) +{ + rijndael_set_key(ctx, (const uint32 *) key, klen, 1); +} + +static void +ciph_encrypt(CIPH_CTX * ctx, const uint8 *in, uint8 *out) +{ + rijndael_encrypt(ctx, (const uint32 *) in, (uint32 *) out); +} + +static void +md_init(MD_CTX * ctx) +{ + SHA256_Init(ctx); +} + +static void +md_update(MD_CTX * ctx, const uint8 *data, int len) +{ + SHA256_Update(ctx, data, len); +} + +static void +md_result(MD_CTX * ctx, uint8 *dst) +{ + SHA256_CTX tmp; + + memcpy(&tmp, ctx, sizeof(*ctx)); + SHA256_Final(dst, &tmp); + memset(&tmp, 0, sizeof(tmp)); +} + +/* + * initialize state + */ +static void +init_state(FState *st) +{ + int i; + + memset(st, 0, sizeof(*st)); + for (i = 0; i < NUM_POOLS; i++) + md_init(&st->pool[i]); +} + +/* + * Endianess does not matter. + * It just needs to change without repeating. + */ +static void +inc_counter(FState *st) +{ + uint32 *val = (uint32 *) 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, uint8 *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; + struct timeval tv; + struct timeval *last = &st->last_reseed_time; + + gettimeofday(&tv, NULL); + + /* check how much time has passed */ + ok = 0; + if (tv.tv_sec > last->tv_sec + 1) + ok = 1; + else if (tv.tv_sec == last->tv_sec + 1) + { + if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) + ok = 1; + } + else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) + ok = 1; + + /* 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; + uint8 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); + + /* 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 uint8 *data, unsigned len) +{ + unsigned pos; + uint8 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; + uint8 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, uint8 *dst) +{ + unsigned n; + unsigned block_nr = 0; + + /* 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); + + 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 = 0; + +void +fortuna_add_entropy(const uint8 *data, unsigned len) +{ + if (!init_done) + { + init_state(&main_state); + init_done = 1; + } + if (!data || !len) + return; + add_entropy(&main_state, data, len); +} + +void +fortuna_get_bytes(unsigned len, uint8 *dst) +{ + if (!init_done) + { + init_state(&main_state); + init_done = 1; + } + if (!dst || !len) + return; + extract_data(&main_state, len, dst); +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/fortuna.h ---------------------------------------------------------------------- diff --git a/contrib/pgcrypto/fortuna.h b/contrib/pgcrypto/fortuna.h new file mode 100644 index 0000000..2e49f8a --- /dev/null +++ b/contrib/pgcrypto/fortuna.h @@ -0,0 +1,38 @@ +/* + * fortuna.c + * Fortuna 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. + * + * contrib/pgcrypto/fortuna.h + */ + +#ifndef __FORTUNA_H +#define __FORTUNA_H + +void fortuna_get_bytes(unsigned len, uint8 *dst); +void fortuna_add_entropy(const uint8 *data, unsigned len); + +#endif