int s2n_rsa_keys_match(struct s2n_rsa_public_key *pub, struct s2n_rsa_private_key *priv) { uint8_t plain_inpad[36], plain_outpad[36], encpad[8192]; struct s2n_blob plain_in, plain_out, enc; plain_in.data = plain_inpad; plain_in.size = sizeof(plain_inpad); GUARD(s2n_get_private_random_data(&plain_in)); enc.data = encpad; enc.size = s2n_rsa_public_encrypted_size(pub); lte_check(enc.size, sizeof(encpad)); GUARD(s2n_rsa_encrypt(pub, &plain_in, &enc)); plain_out.data = plain_outpad; plain_out.size = sizeof(plain_outpad); GUARD(s2n_rsa_decrypt(priv, &enc, &plain_out)); if (memcmp(plain_in.data, plain_out.data, plain_in.size)) { S2N_ERROR(S2N_ERR_KEY_MISMATCH); } return 0; }
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 get_random_bytes(OUT unsigned char *buffer, unsigned int num_bytes) { struct s2n_blob out = {.data = buffer,.size = num_bytes }; return s2n_get_private_random_data(&out); }