/* * Test whether readfd is not set by select when counter value is * zero. */ static void readfd_not_set_test(int fd) { int ret; fd_set readfds; struct timeval timeout = { 0, 0 }; FD_ZERO(&readfds); FD_SET(fd, &readfds); ret = clear_counter(fd); if (ret == -1) { tst_resm(TBROK, "error clearing counter"); return; } ret = select(fd + 1, &readfds, NULL, NULL, &timeout); if (ret == -1) { /* EINTR cannot occur, since we don't block. */ tst_resm(TBROK | TERRNO, "select() failed"); return; } if (!FD_ISSET(fd, &readfds)) tst_resm(TPASS, "fd is not set in readfds"); else tst_resm(TFAIL, "fd is set in readfds"); }
/* * set_counter() - sets the count to specified value * @fd: the eventfd * @val: the value to be set * * Clears the counter and sets the counter to @val. * * RETURNS: * 0 on success, -1 on failure */ static int set_counter(int fd, uint64_t val) { int ret; ret = clear_counter(fd); if (ret == -1) return -1; ret = write(fd, &val, sizeof(val)); if (ret == -1) { tst_resm(TINFO | TERRNO, "error setting counter value"); return -1; } return 0; }
/* * Test whether read returns with error EAGAIN when counter is at 0. */ static void read_eagain_test(int fd) { int ret; uint64_t val; ret = clear_counter(fd); if (ret == -1) { tst_resm(TBROK, "error clearing counter"); return; } ret = read(fd, &val, sizeof(val)); if (ret == -1) { if (errno == EAGAIN) tst_resm(TPASS, "read failed with EAGAIN as expected"); else tst_resm(TFAIL | TERRNO, "read failed (wanted EAGAIN)"); } else tst_resm(TFAIL, "read returned with %d", ret); }
/* * Test wheter write returns with error EINVAL, when the written value * is 0xFFFFFFFFFFFFFFFF. */ static void write_einval2_test(int fd) { int ret; uint64_t val; ret = clear_counter(fd); if (ret == -1) { tst_resm(TBROK, "error clearing counter"); return; } val = 0xffffffffffffffffLL; ret = write(fd, &val, sizeof(val)); if (ret == -1) { if (errno == EINVAL) tst_resm(TPASS, "write failed with EINVAL as expected"); else tst_resm(TFAIL | TERRNO, "write failed (wanted EINVAL)"); } else { tst_resm(TFAIL, "write returned with %d", ret); } }
static void reseed(u_int fastslow) { /* Interrupt-context stack is a limited resource; make large * structures static. */ static uint8_t v[TIMEBIN][KEYSIZE]; /* v[i] */ static struct randomdev_hash context; uint8_t hash[KEYSIZE]; /* h' */ uint8_t temp[KEYSIZE]; u_int i; enum esource j; #if 0 printf("Yarrow: %s reseed\n", fastslow == FAST ? "fast" : "slow"); #endif /* The reseed task must not be jumped on */ mtx_lock(&random_reseed_mtx); /* 1. Hash the accumulated entropy into v[0] */ randomdev_hash_init(&context); /* Feed the slow pool hash in if slow */ if (fastslow == SLOW) randomdev_hash_iterate(&context, &random_state.pool[SLOW].hash, sizeof(struct randomdev_hash)); randomdev_hash_iterate(&context, &random_state.pool[FAST].hash, sizeof(struct randomdev_hash)); randomdev_hash_finish(&context, v[0]); /* 2. Compute hash values for all v. _Supposed_ to be computationally * intensive. */ if (random_state.bins > TIMEBIN) random_state.bins = TIMEBIN; for (i = 1; i < random_state.bins; i++) { randomdev_hash_init(&context); /* v[i] #= h(v[i - 1]) */ randomdev_hash_iterate(&context, v[i - 1], KEYSIZE); /* v[i] #= h(v[0]) */ randomdev_hash_iterate(&context, v[0], KEYSIZE); /* v[i] #= h(i) */ randomdev_hash_iterate(&context, &i, sizeof(u_int)); /* Return the hashval */ randomdev_hash_finish(&context, v[i]); } /* 3. Compute a new key; h' is the identity function here; * it is not being ignored! */ randomdev_hash_init(&context); randomdev_hash_iterate(&context, &random_state.key, KEYSIZE); for (i = 1; i < random_state.bins; i++) randomdev_hash_iterate(&context, &v[i], KEYSIZE); randomdev_hash_finish(&context, temp); randomdev_encrypt_init(&random_state.key, temp); /* 4. Recompute the counter */ clear_counter(); randomdev_encrypt(&random_state.key, random_state.counter.byte, temp, BLOCKSIZE); memcpy(random_state.counter.byte, temp, BLOCKSIZE); /* 5. Reset entropy estimate accumulators to zero */ for (i = 0; i <= fastslow; i++) for (j = RANDOM_START; j < ENTROPYSOURCE; j++) random_state.pool[i].source[j].bits = 0; /* 6. Wipe memory of intermediate values */ memset((void *)v, 0, sizeof(v)); memset((void *)temp, 0, sizeof(temp)); memset((void *)hash, 0, sizeof(hash)); /* 7. Dump to seed file */ /* XXX Not done here yet */ /* Unblock the device if it was blocked due to being unseeded */ randomdev_unblock(); /* Release the reseed mutex */ mtx_unlock(&random_reseed_mtx); }
void random_yarrow_init_alg(void) { int i; #ifndef __OSV__ struct sysctl_oid *random_yarrow_o; /* Yarrow parameters. Do not adjust these unless you have * have a very good clue about what they do! */ random_yarrow_o = SYSCTL_ADD_NODE(clist, SYSCTL_STATIC_CHILDREN(_kern_random), OID_AUTO, "yarrow", CTLFLAG_RW, 0, "Yarrow Parameters"); SYSCTL_ADD_PROC(clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "gengateinterval", CTLTYPE_INT|CTLFLAG_RW, &random_state.gengateinterval, 10, random_check_uint_gengateinterval, "I", "Generation gate interval"); SYSCTL_ADD_PROC(clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "bins", CTLTYPE_INT|CTLFLAG_RW, &random_state.bins, 10, random_check_uint_bins, "I", "Execution time tuner"); SYSCTL_ADD_PROC(clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "fastthresh", CTLTYPE_INT|CTLFLAG_RW, &random_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4, random_check_uint_fastthresh, "I", "Fast reseed threshold"); SYSCTL_ADD_PROC(clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "slowthresh", CTLTYPE_INT|CTLFLAG_RW, &random_state.pool[1].thresh, (BLOCKSIZE*8), random_check_uint_slowthresh, "I", "Slow reseed threshold"); SYSCTL_ADD_PROC(clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "slowoverthresh", CTLTYPE_INT|CTLFLAG_RW, &random_state.slowoverthresh, 2, random_check_uint_slowoverthresh, "I", "Slow over-threshold reseed"); #endif random_state.gengateinterval = 10; random_state.bins = 10; random_state.pool[0].thresh = (3*(BLOCKSIZE*8))/4; random_state.pool[1].thresh = (BLOCKSIZE*8); random_state.slowoverthresh = 2; random_state.which = FAST; /* Initialise the fast and slow entropy pools */ for (i = 0; i < 2; i++) randomdev_hash_init(&random_state.pool[i].hash); /* Clear the counter */ clear_counter(); /* Set up a lock for the reseed process */ mtx_init(&random_reseed_mtx, "Yarrow reseed", NULL, MTX_DEF); }