static inline void _rs_init(u_char *buf, size_t n) { if (n < KEYSZ + IVSZ) return; if (rs == NULL) { #ifndef GETDNS_ON_WINDOWS if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) abort(); #ifdef MAP_INHERIT_ZERO if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1) abort(); #endif #else /* WINDOWS */ rs = malloc(sizeof(*rs)); if(!rs) abort(); #endif } if (rsx == NULL) { #ifndef GETDNS_ON_WINDOWS if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) abort(); #else /* WINDOWS */ rsx = malloc(sizeof(*rsx)); if(!rsx) abort(); #endif } chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); }
int64_t s2n_public_random(int64_t max) { uint64_t r; gt_check(max, 0); while(1) { struct s2n_blob blob = { .data = (void *) &r, sizeof(r) }; GUARD(s2n_get_public_random_data(&blob)); /* Imagine an int was one byte and UINT_MAX was 256. If the * caller asked for s2n_random(129, ...) we'd end up in * trouble. Each number in the range 0...127 would be twice * as likely as 128. That's because r == 0 % 129 -> 0, and * r == 129 % 129 -> 0, but only r == 128 returns 128, * r == 257 is out of range. * * To de-bias the dice, we discard values of r that are higher * that the highest multiple of 'max' an int can support. If * max is a uint, then in the worst case we discard 50% - 1 r's. * But since 'max' is an int and INT_MAX is <= UINT_MAX / 2, * in the worst case we discard 25% - 1 r's. */ if (r < (UINT64_MAX - (UINT64_MAX % max))) { return r % max; } } return -1; } #ifndef OPENSSL_IS_BORINGSSL int s2n_openssl_compat_rand(unsigned char *buf, int num) { struct s2n_blob out = {.data = buf, .size = num}; if(s2n_get_private_random_data(&out) < 0) { return 0; } return 1; } int s2n_openssl_compat_status(void) { return 1; } int s2n_openssl_compat_init(ENGINE *unused) { return 1; } RAND_METHOD s2n_openssl_rand_method = { .seed = NULL, .bytes = s2n_openssl_compat_rand, .cleanup = NULL, .add = NULL, .pseudorand = s2n_openssl_compat_rand, .status = s2n_openssl_compat_status }; #endif int s2n_init(void) { GUARD(s2n_mem_init()); OPEN: entropy_fd = open(ENTROPY_SOURCE, O_RDONLY); if (entropy_fd == -1) { if (errno == EINTR) { goto OPEN; } S2N_ERROR(S2N_ERR_OPEN_RANDOM); } #if defined(MAP_INHERIT_ZERO) if ((zero_if_forked_ptr = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { S2N_ERROR(S2N_ERR_OPEN_RANDOM); } if (minherit(zero_if_forked_ptr, sizeof(int), MAP_INHERIT_ZERO) == -1) { S2N_ERROR(S2N_ERR_OPEN_RANDOM); } #else if (pthread_atfork(NULL, NULL, s2n_on_fork) != 0) { S2N_ERROR(S2N_ERR_OPEN_RANDOM); } #endif GUARD(s2n_check_fork()); #ifndef OPENSSL_IS_BORINGSSL /* Create an engine */ ENGINE *e = ENGINE_new(); if (e == NULL || ENGINE_set_id(e, "s2n") != 1 || ENGINE_set_name(e, "s2n entropy generator") != 1 || ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) != 1 || ENGINE_set_init_function(e, s2n_openssl_compat_init) != 1 || ENGINE_set_RAND(e, &s2n_openssl_rand_method) != 1 || ENGINE_add(e) != 1 || ENGINE_free(e) != 1) { S2N_ERROR(S2N_ERR_OPEN_RANDOM); } /* Use that engine for rand() */ e = ENGINE_by_id("s2n"); if (e == NULL || ENGINE_init(e) != 1 || ENGINE_set_default(e, ENGINE_METHOD_RAND) != 1) { S2N_ERROR(S2N_ERR_OPEN_RANDOM); } #endif return 0; }
int main(int argc, char *argv[]) { u_char filebuffer[FILESIZE]; char temppath[PATH_MAX]; struct sockaddr_in sin; int ch, error, i; char *pagebuffer; ssize_t len; pid_t pid; while ((ch = getopt(argc, argv, "t")) != -1) { switch (ch) { case 't': threaded = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1 && argc != 2) usage(); len = roundup(sizeof(struct state), getpagesize()); pagebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); if (pagebuffer == MAP_FAILED) err(-1, "mmap"); if (minherit(pagebuffer, len, INHERIT_SHARE) < 0) err(-1, "minherit"); statep = (struct state *)pagebuffer; if (uname(&statep->utsname) < 0) err(-1, "utsname"); statep->listen_sock = socket(PF_INET, SOCK_STREAM, 0); if (statep->listen_sock < 0) err(-1, "socket(PF_INET, SOCK_STREAM)"); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = htons(atoi(argv[0])); /* * If a path is specified, use it. Otherwise, create temporary files * with some data for each thread. */ statep->path = argv[1]; if (statep->path != NULL) { statep->data_file = open(statep->path, O_RDONLY); if (statep->data_file < 0) err(-1, "open: %s", statep->path); for (i = 0; i < THREADS; i++) statep->hts[i].hts_fd = statep->data_file; } else { memset(filebuffer, 'A', FILESIZE - 1); filebuffer[FILESIZE - 1] = '\n'; for (i = 0; i < THREADS; i++) { snprintf(temppath, PATH_MAX, "/tmp/httpd.XXXXXXXXXXX"); statep->hts[i].hts_fd = mkstemp(temppath); if (statep->hts[i].hts_fd < 0) err(-1, "mkstemp"); (void)unlink(temppath); len = write(statep->hts[i].hts_fd, filebuffer, FILESIZE); if (len < 0) err(-1, "write"); if (len < FILESIZE) errx(-1, "write: short"); } } if (bind(statep->listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "bind"); if (listen(statep->listen_sock, -1) < 0) err(-1, "listen"); for (i = 0; i < THREADS; i++) { if (threaded) { if (pthread_create(&statep->hts[i].hts_thread, NULL, httpd_worker, &statep->hts[i]) != 0) err(-1, "pthread_create"); } else { pid = fork(); if (pid < 0) { error = errno; killall(); errno = error; err(-1, "fork"); } if (pid == 0) httpd_worker(&statep->hts[i]); statep->hts[i].hts_pid = pid; } } for (i = 0; i < THREADS; i++) { if (threaded) { if (pthread_join(statep->hts[i].hts_thread, NULL) != 0) err(-1, "pthread_join"); } else { pid = waitpid(statep->hts[i].hts_pid, NULL, 0); if (pid == statep->hts[i].hts_pid) statep->hts[i].hts_pid = 0; } } if (!threaded) killall(); return (0); }
int main(int argc, char *argv[]) { int ch, error, i; char *pagebuffer; uintmax_t total; size_t len; pid_t pid; numthreads = DEFAULTTHREADS; numseconds = DEFAULTSECONDS; while ((ch = getopt(argc, argv, "n:s:t")) != -1) { switch (ch) { case 'n': numthreads = atoi(optarg); break; case 's': numseconds = atoi(optarg); break; case 't': threaded = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 3) usage(); if (numthreads > MAXTHREADS) errx(-1, "%d exceeds max threads %d", numthreads, MAXTHREADS); len = roundup(sizeof(struct state), getpagesize()); pagebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); if (pagebuffer == MAP_FAILED) err(-1, "mmap"); if (minherit(pagebuffer, len, INHERIT_SHARE) < 0) err(-1, "minherit"); statep = (struct state *)pagebuffer; bzero(&statep->sin, sizeof(statep->sin)); statep->sin.sin_len = sizeof(statep->sin); statep->sin.sin_family = AF_INET; statep->sin.sin_addr.s_addr = inet_addr(argv[0]); statep->sin.sin_port = htons(atoi(argv[1])); statep->path = argv[2]; /* * Do one test retrieve so we can report the error from it, if any. */ if (http_fetch(&statep->sin, statep->path, 0) < 0) exit(-1); if (threaded) { if (pthread_barrier_init(&statep->start_barrier, NULL, numthreads) != 0) err(-1, "pthread_barrier_init"); } for (i = 0; i < numthreads; i++) { statep->hwd[i].hwd_count = 0; if (threaded) { if (pthread_create(&statep->hwd[i].hwd_thread, NULL, http_worker, &statep->hwd[i]) != 0) err(-1, "pthread_create"); } else { curthread = i; pid = fork(); if (pid < 0) { error = errno; killall(); errno = error; err(-1, "fork"); } if (pid == 0) { http_worker(&statep->hwd[i]); printf("Doh\n"); exit(0); } statep->hwd[i].hwd_pid = pid; } } if (!threaded) { signal(SIGHUP, main_sighup); sleep(2); signal_barrier_wakeup(); } sleep(numseconds); statep->run_done = 1; if (!threaded) sleep(2); for (i = 0; i < numthreads; i++) { if (threaded) { if (pthread_join(statep->hwd[i].hwd_thread, NULL) != 0) err(-1, "pthread_join"); } else { pid = waitpid(statep->hwd[i].hwd_pid, NULL, 0); if (pid == statep->hwd[i].hwd_pid) statep->hwd[i].hwd_pid = 0; } } if (!threaded) killall(); total = 0; for (i = 0; i < numthreads; i++) total += statep->hwd[i].hwd_count; printf("%ju transfers/second\n", total / numseconds); total = 0; for (i = 0; i < numthreads; i++) total += statep->hwd[i].hwd_errorcount; printf("%ju errors/second\n", total / numseconds); return (0); }