2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000-2002, 2004, 2007, 2009, 2013, 2016 Internet Systems Consortium, Inc. ("ISC")
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
9a14f870ddc0108402d2daa7a7ff84b6e20f08b4Automatic Updater/* $Id: entropy.c,v 1.10 2009/01/18 23:48:14 tbox Exp $ */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence/*
1016f2638f8a34a802ce41043d5369553ac14246Francis Dupont * This is the system dependent part of the ISC entropy API.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <config.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <windows.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <wincrypt.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <process.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <io.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include <share.h>
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence/*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * There is only one variable in the entropy data structures that is not
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * system independent, but pulling the structure that uses it into this file
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * ultimately means pulling several other independent structures here also to
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * resolve their interdependencies. Thus only the problem variable's type
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * is defined here.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#define FILESOURCE_HANDLE_TYPE HCRYPTPROV
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrewstypedef struct {
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews int dummy;
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews} isc_entropyusocketsource_t;
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence#include "../entropy.c"
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrencestatic unsigned int
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrenceget_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_entropy_t *ent = source->ent;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned char buf[128];
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence HCRYPTPROV hcryptprov = source->sources.file.handle;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ssize_t ndesired;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int added;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source->bad)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return (0);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence added = 0;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence while (desired > 0) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ndesired = ISC_MIN(desired, sizeof(buf));
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews if (!CryptGenRandom(hcryptprov, (DWORD)ndesired, buf)) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence CryptReleaseContext(hcryptprov, 0);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->bad = ISC_TRUE;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence goto out;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews entropypool_adddata(ent, buf,
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews (unsigned int)ndesired,
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews (unsigned int)ndesired * 8);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews added += (unsigned int)ndesired * 8;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews desired -= (isc_uint32_t)ndesired;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence out:
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return (added);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence}
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence/*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Poll each source, trying to get data from it to stuff into the entropy
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * pool.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrencestatic void
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrencefillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int added;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int remaining;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int needed;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int nsource;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_entropysource_t *source;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_entropysource_t *firstsource;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence REQUIRE(VALID_ENTROPY(ent));
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = desired;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * This logic is a little strange, so an explanation is in order.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence *
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * If needed is 0, it means we are being asked to "fill to whatever
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * we think is best." This means that if we have at least a
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * partially full pool (say, > 1/4th of the pool) we probably don't
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * need to add anything.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence *
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Also, we will check to see if the "pseudo" count is too high.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * If it is, try to mix in better data. Too high is currently
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * defined as 1/4th of the pool.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence *
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Next, if we are asked to add a specific bit of entropy, make
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * certain that we will do so. Clamp how much we try to add to
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence *
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Note that if we are in a blocking mode, we will only try to
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * get as much data as we need, not as much as we might want
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * to build up.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (needed == 0) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence REQUIRE(!blocking);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if ((ent->pool.entropy >= RND_POOLBITS / 4)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence && (ent->pool.pseudo <= RND_POOLBITS / 4))
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = THRESHOLD_BITS * 4;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence } else {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = ISC_MAX(needed, THRESHOLD_BITS);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = ISC_MIN(needed, RND_POOLBITS);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * In any case, clamp how much we need to how much we can add.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * But wait! If we're not yet initialized, we need at least
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * THRESHOLD_BITS
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * of randomness.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (ent->initialized < THRESHOLD_BITS)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Poll each file source to see if we can read anything useful from
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * it. XXXMLG When where are multiple sources, we should keep a
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * record of which one we last used so we can start from it (or the
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * next one) to avoid letting some sources build up entropy while
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * others are always drained.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence added = 0;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence remaining = needed;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (ent->nextsource == NULL) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ent->nextsource = ISC_LIST_HEAD(ent->sources);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (ent->nextsource == NULL)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = ent->nextsource;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Remember the first source so we can break if we have looped back to
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * the beginning and still have nothing
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence firstsource = source;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence again_file:
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson for (nsource = 0; nsource < ent->nsources; nsource++) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int got;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (remaining == 0)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence break;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence got = 0;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source->type == ENTROPY_SOURCETYPE_FILE)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence got = get_from_filesource(source, remaining);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence added += got;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence remaining -= ISC_MIN(remaining, got);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = ISC_LIST_NEXT(source, link);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source == NULL)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = ISC_LIST_HEAD(ent->sources);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ent->nextsource = source;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Go again only if there's been progress and we've not
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * gone back to the beginning
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (!(ent->nextsource == firstsource && added == 0)) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (blocking && remaining != 0) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence goto again_file;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Here, if there are bits remaining to be had and we can block,
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * check to see if we have a callback source. If so, call them.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = ISC_LIST_HEAD(ent->sources);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence while ((remaining != 0) && (source != NULL)) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence unsigned int got;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence got = 0;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence got = get_from_callback(source, remaining, blocking);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence added += got;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence remaining -= ISC_MIN(remaining, got);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (added >= needed)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence break;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = ISC_LIST_NEXT(source, link);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Mark as initialized if we've added enough data.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (ent->initialized < THRESHOLD_BITS)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ent->initialized += added;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence}
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence/*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Requires "ent" be locked.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrencestatic void
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrencedestroyfilesource(isc_entropyfilesource_t *source) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence CryptReleaseContext(source->handle, 0);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence}
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrewsstatic void
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrewsdestroyusocketsource(isc_entropyusocketsource_t *source) {
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews UNUSED(source);
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews}
945cb085b859dbfc6a883813dda03c83e06995d3Mark Andrews
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrenceisc_result_t
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrenceisc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_result_t ret;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_entropysource_t *source;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence HCRYPTPROV hcryptprov;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence BOOL err;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence REQUIRE(VALID_ENTROPY(ent));
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence REQUIRE(fname != NULL);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence LOCK(&ent->lock);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = NULL;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * The first time we just try to acquire the context
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL,
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence CRYPT_VERIFYCONTEXT);
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer if (!err){
bbb3705e4cbdacf7cf6da7e448d79d97fdab2411Mark Andrews (void)GetLastError();
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer ret = ISC_R_IOERROR;
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer goto errout;
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source == NULL) {
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ret = ISC_R_NOMEMORY;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence goto closecontext;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence }
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * From here down, no failures can occur.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->magic = SOURCE_MAGIC;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->type = ENTROPY_SOURCETYPE_FILE;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->ent = ent;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->total = 0;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->bad = ISC_FALSE;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence memset(source->name, 0, sizeof(source->name));
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ISC_LINK_INIT(source, link);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence source->sources.file.handle = hcryptprov;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence /*
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence * Hook it into the entropy system.
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence */
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ISC_LIST_APPEND(ent->sources, source, link);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence ent->nsources++;
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence UNLOCK(&ent->lock);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return (ISC_R_SUCCESS);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence closecontext:
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence CryptReleaseContext(hcryptprov, 0);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence errout:
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence if (source != NULL)
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence UNLOCK(&ent->lock);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence return (ret);
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence}
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence
2d67c2474475acf52c8251dc48bfb7565ee5f2ffDavid Lawrence