[BACK]Return to rnd.h CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / sys

File: [cvs.NetBSD.org] / src / sys / sys / rnd.h (download)

Revision 1.29.2.2, Fri Apr 20 23:35:20 2012 UTC (12 years ago) by riz
Branch: netbsd-6
CVS Tags: netbsd-6-0-RELEASE, netbsd-6-0-RC2, netbsd-6-0-RC1, netbsd-6-0-6-RELEASE, netbsd-6-0-5-RELEASE, netbsd-6-0-4-RELEASE, netbsd-6-0-3-RELEASE, netbsd-6-0-2-RELEASE, netbsd-6-0-1-RELEASE, netbsd-6-0, matt-nb6-plus-nbase, matt-nb6-plus-base, matt-nb6-plus
Changes since 1.29.2.1: +10 -1 lines

Pull up following revision(s) (requested by tls in ticket #190):
	sys/sys/rnd.h: revision 1.31
	sys/sys/rnd.h: revision 1.32
	sys/sys/cprng.h: revision 1.5
	sys/kern/subr_cprng.c: revision 1.8
	share/man/man4/rnd.4: revision 1.19
	sys/kern/kern_rndq.c: revision 1.3
	sys/dev/rndpseudo.c: revision 1.8
	sys/dev/rndpseudo.c: revision 1.9
	sys/kern/kern_rndpool.c: revision 1.2
Address multiple problems with rnd(4)/cprng(9):
1) Add a per-cpu CPRNG to handle short reads from /dev/urandom so that
   programs like perl don't drain the entropy pool dry by repeatedly
   opening, reading 4 bytes, closing.
2) Really fix the locking around reseeds and destroys.
3) Fix the opportunistic-reseed strategy so it actually works, reseeding
   existing RNGs once each (as they are used, so idle RNGs don't get
   reseeded) until the pool is half empty or newly full again.
Fix a bug and a compilation problem.  Bug: spin mutexes don't have owners,
so KASSERT(!mutex_owned()) shouldn't be used to assert that the current
LWP does not have the mutex.  Compilation problem: explicitly include
sys/mutex.h from rnd.h so evbarm builds again.

/*	$NetBSD: rnd.h,v 1.29.2.2 2012/04/20 23:35:20 riz Exp $	*/

/*-
 * Copyright (c) 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Michael Graff <explorer@flame.org>.  This code uses ideas and
 * algorithms from the Linux driver written by Ted Ts'o.
 *
 * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

#ifndef _SYS_RND_H_
#define	_SYS_RND_H_

#ifndef _KERNEL
#include <sys/cdefs.h>
#endif /* !_KERNEL */

#include <sys/types.h>
#include <sys/sha1.h>

#ifdef _KERNEL
#include <sys/mutex.h>
#include <sys/queue.h>
#endif

#ifdef _KERNEL
#include <sys/rngtest.h>
#endif

#define	RND_DEV_RANDOM	0	/* minor devices for random and kinda random */
#define	RND_DEV_URANDOM	1

/*
 * Exposed "size" of entropy pool, for convenience in load/save
 * from userspace.  Do not assume this is the same as the actual in-kernel
 * pool size!
 */
#define RND_SAVEWORDS	128
typedef struct {
	uint32_t entropy;
	uint8_t data[RND_SAVEWORDS * sizeof(uint32_t)];
	uint8_t digest[SHA1_DIGEST_LENGTH];
} rndsave_t;

/* Statistics exposed by RNDGETPOOLSTAT */
typedef struct
{
	uint32_t	poolsize;
	uint32_t 	threshold;
	uint32_t	maxentropy;

	uint32_t	added;
	uint32_t	curentropy;
	uint32_t	removed;
	uint32_t	discarded;
	uint32_t	generated;
} rndpoolstat_t;

/* Sanitized random source view for userspace */
typedef struct {
	char		name[16];	/* device name */
	uint32_t	total;		/* entropy from this source */
	uint32_t	type;		/* type */
	uint32_t	flags;		/* flags */
} rndsource_t;

/*
 * Flags to control the source.  Low byte is type, upper bits are flags.
 */
#define	RND_FLAG_NO_ESTIMATE	0x00000100	/* don't estimate entropy */
#define	RND_FLAG_NO_COLLECT	0x00000200	/* don't collect entropy */

#define	RND_TYPE_UNKNOWN	0	/* unknown source */
#define	RND_TYPE_DISK		1	/* source is physical disk */
#define	RND_TYPE_NET		2	/* source is a network device */
#define	RND_TYPE_TAPE		3	/* source is a tape drive */
#define	RND_TYPE_TTY		4	/* source is a tty device */
#define	RND_TYPE_RNG		5	/* source is a hardware RNG */
#define RND_TYPE_SKEW		6	/* source is skew between clocks */
#define RND_TYPE_ENV		7	/* source is temp or fan sensor */
#define RND_TYPE_VM		8	/* source is VM system events */
#define RND_TYPE_POWER		9	/* source is power events */
#define	RND_TYPE_MAX		9	/* last type id used */

#ifdef _KERNEL
/*
 * Size of entropy pool in 32-bit words.  This _MUST_ be a power of 2.  Don't
 * change this unless you really know what you are doing...
 */
#ifndef RND_POOLWORDS
#define RND_POOLWORDS	128
#endif
#define RND_POOLBITS	(RND_POOLWORDS * 32)

typedef struct krndsource {
	LIST_ENTRY(krndsource) list;	/* the linked list */
        char            name[16];       /* device name */
        uint32_t        last_time;      /* last time recorded */
        uint32_t        last_delta;     /* last delta value */
        uint32_t        last_delta2;    /* last delta2 value */
        uint32_t        total;          /* entropy from this source */
        uint32_t        type;           /* type */
        uint32_t        flags;          /* flags */
        void            *state;         /* state information */
        size_t          test_cnt;       /* how much test data accumulated? */
        rngtest_t	*test;          /* test data for RNG type sources */
} krndsource_t;

enum rsink_st {
	RSTATE_IDLE = 0,
	RSTATE_PENDING,
	RSTATE_HASBITS
};

typedef struct rndsink {
        TAILQ_ENTRY(rndsink) tailq;     /* the queue */
	kmutex_t	mtx;		/* lock to seed or unregister */
	enum rsink_st	state;		/* in-use?  filled? */
        void            (*cb)(void *);  /* callback function when ready */
        void            *arg;           /* callback function argument */
        char            name[16];       /* sink name */
        size_t          len;            /* how many bytes wanted/supplied */
        uint8_t         data[64];       /* random data returned here */
} rndsink_t;

typedef struct {
        uint32_t        cursor;         /* current add point in the pool */
        uint32_t        rotate;         /* how many bits to rotate by */
        rndpoolstat_t   stats;          /* current statistics */
        uint32_t        pool[RND_POOLWORDS]; /* random pool data */
} rndpool_t;

#define RND_ENABLED(rp) \
        (((rp)->flags & RND_FLAG_NO_COLLECT) == 0)

void		rndpool_init(rndpool_t *);
void		rndpool_init_global(void);
uint32_t	rndpool_get_entropy_count(rndpool_t *);
void		rndpool_get_stats(rndpool_t *, void *, int);
void		rndpool_increment_entropy_count(rndpool_t *, uint32_t);
uint32_t	*rndpool_get_pool(rndpool_t *);
uint32_t	rndpool_get_poolsize(void);
void		rndpool_add_data(rndpool_t *, void *, uint32_t, uint32_t);
uint32_t	rndpool_extract_data(rndpool_t *, void *, uint32_t, uint32_t);
void		rnd_init(void);
void		_rnd_add_uint32(krndsource_t *, uint32_t);
void		rnd_add_data(krndsource_t *, const void *const, uint32_t,
		    uint32_t);
void		rnd_attach_source(krndsource_t *, const char *,
		    uint32_t, uint32_t);
void		rnd_detach_source(krndsource_t *);

void		rndsink_attach(rndsink_t *);
void		rndsink_detach(rndsink_t *);

void		rnd_seed(void *, size_t);

static inline void
rnd_add_uint32(krndsource_t *kr, uint32_t val)
{
	if (RND_ENABLED(kr)) {
		_rnd_add_uint32(kr, val);
	}
}

extern int	rnd_full;
extern int	rnd_filled;

#endif /* _KERNEL */

#define	RND_MAXSTATCOUNT	10	/* 10 sources at once max */

/*
 * return "count" random entries, starting at "start"
 */
typedef struct {
	uint32_t	start;
	uint32_t	count;
	rndsource_t	source[RND_MAXSTATCOUNT];
} rndstat_t;

/*
 * return information on a specific source by name
 */
typedef struct {
	char		name[16];
	rndsource_t	source;
} rndstat_name_t;

/*
 * set/clear device flags.  If type is set to 0xff, the name is used
 * instead.  Otherwise, the flags set/cleared apply to all devices of
 * the specified type, and the name is ignored.
 */
typedef struct {
	char		name[16];	/* the name we are adjusting */
	uint32_t	type;		/* the type of device we want */
	uint32_t	flags;		/* flags to set or clear */
	uint32_t	mask;		/* mask for the flags we are setting */
} rndctl_t;

/*
 * Add entropy to the pool.  len is the data length, in bytes.
 * entropy is the number of bits of estimated entropy in the data.
 */
typedef struct {
	uint32_t	len;
	uint32_t	entropy;
	u_char		data[RND_SAVEWORDS * sizeof(uint32_t)];
} rnddata_t;

#define	RNDGETENTCNT	_IOR('R',  101, uint32_t) /* get entropy count */
#define	RNDGETSRCNUM	_IOWR('R', 102, rndstat_t) /* get rnd source info */
#define	RNDGETSRCNAME	_IOWR('R', 103, rndstat_name_t) /* get src by name */
#define	RNDCTL		_IOW('R',  104, rndctl_t)  /* set/clear source flags */
#define	RNDADDDATA	_IOW('R',  105, rnddata_t) /* add data to the pool */
#define	RNDGETPOOLSTAT	_IOR('R',  106, rndpoolstat_t) /* get statistics */

#endif /* !_SYS_RND_H_ */