1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2010-2020. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #include "rand.h"
22 #include "bn.h"
23
strong_rand_bytes_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])24 ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
25 {/* (Bytes) */
26 unsigned bytes;
27 unsigned char* data;
28 ERL_NIF_TERM ret;
29
30 ASSERT(argc == 1);
31
32 if (!enif_get_uint(env, argv[0], &bytes))
33 goto bad_arg;
34 if (bytes > INT_MAX)
35 goto bad_arg;
36
37 if ((data = enif_make_new_binary(env, bytes, &ret)) == NULL)
38 goto err;
39 if (RAND_bytes(data, (int)bytes) != 1)
40 goto err;
41
42 ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
43 return ret;
44
45 bad_arg:
46 return enif_make_badarg(env);
47
48 err:
49 return atom_false;
50 }
51
strong_rand_range_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])52 ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
53 {/* (Range) */
54 BIGNUM *bn_range = NULL, *bn_rand = NULL;
55 ERL_NIF_TERM ret;
56
57 ASSERT(argc == 1);
58
59 if (!get_bn_from_bin(env, argv[0], &bn_range))
60 goto bad_arg;
61
62 if ((bn_rand = BN_new()) == NULL)
63 goto err;
64 if (!BN_rand_range(bn_rand, bn_range))
65 goto err;
66
67 if ((ret = bin_from_bn(env, bn_rand)) == atom_error)
68 goto err;
69 goto done;
70
71 bad_arg:
72 return enif_make_badarg(env);
73
74 err:
75 ret = atom_false;
76
77 done:
78 if (bn_rand)
79 BN_free(bn_rand);
80 if (bn_range)
81 BN_free(bn_range);
82 return ret;
83 }
84
rand_uniform_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])85 ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
86 {/* (Lo,Hi) */
87 BIGNUM *bn_from = NULL, *bn_to = NULL, *bn_rand = NULL;
88 unsigned char* data;
89 int dlen;
90 ERL_NIF_TERM ret;
91
92 ASSERT(argc == 2);
93
94 if (!get_bn_from_mpint(env, argv[0], &bn_from))
95 goto bad_arg;
96 if (!get_bn_from_mpint(env, argv[1], &bn_rand))
97 goto bad_arg;
98
99 if ((bn_to = BN_new()) == NULL)
100 goto err;
101
102 if (!BN_sub(bn_to, bn_rand, bn_from))
103 goto err;
104 if (!BN_pseudo_rand_range(bn_rand, bn_to))
105 goto err;
106 if (!BN_add(bn_rand, bn_rand, bn_from))
107 goto err;
108
109 if ((dlen = BN_num_bytes(bn_rand)) < 0)
110 goto err;
111 if ((data = enif_make_new_binary(env, (size_t)dlen+4, &ret)) == NULL)
112 goto err;
113
114 put_uint32(data, (unsigned int)dlen);
115 BN_bn2bin(bn_rand, data+4);
116 ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen);
117 goto done;
118
119 bad_arg:
120 err:
121 ret = enif_make_badarg(env);
122
123 done:
124 if (bn_rand)
125 BN_free(bn_rand);
126 if (bn_from)
127 BN_free(bn_from);
128 if (bn_to)
129 BN_free(bn_to);
130 return ret;
131 }
132
rand_seed_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])133 ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
134 {/* (Seed) */
135 ErlNifBinary seed_bin;
136
137 ASSERT(argc == 1);
138
139 if (!enif_inspect_binary(env, argv[0], &seed_bin))
140 goto bad_arg;
141 if (seed_bin.size > INT_MAX)
142 goto bad_arg;
143
144 RAND_seed(seed_bin.data, (int)seed_bin.size);
145 return atom_ok;
146
147 bad_arg:
148 return enif_make_badarg(env);
149 }
150