xref: /trunk/ns_server/deps/enacl/c_src/public.c (revision e35c584a)
1 #include <sodium.h>
2 
3 #include <erl_nif.h>
4 
5 #include "enacl.h"
6 #include "public.h"
7 
8 /* Public-key cryptography */
enacl_crypto_box_NONCEBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])9 ERL_NIF_TERM enacl_crypto_box_NONCEBYTES(ErlNifEnv *env, int argc,
10                                          ERL_NIF_TERM const argv[]) {
11   return enif_make_int64(env, crypto_box_NONCEBYTES);
12 }
13 
enacl_crypto_box_ZEROBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])14 ERL_NIF_TERM enacl_crypto_box_ZEROBYTES(ErlNifEnv *env, int argc,
15                                         ERL_NIF_TERM const argv[]) {
16   return enif_make_int64(env, crypto_box_ZEROBYTES);
17 }
18 
enacl_crypto_box_BOXZEROBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])19 ERL_NIF_TERM enacl_crypto_box_BOXZEROBYTES(ErlNifEnv *env, int argc,
20                                            ERL_NIF_TERM const argv[]) {
21   return enif_make_int64(env, crypto_box_BOXZEROBYTES);
22 }
23 
enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])24 ERL_NIF_TERM enacl_crypto_box_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
25                                              ERL_NIF_TERM const argv[]) {
26   return enif_make_int64(env, crypto_box_PUBLICKEYBYTES);
27 }
28 
enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])29 ERL_NIF_TERM enacl_crypto_box_SECRETKEYBYTES(ErlNifEnv *env, int argc,
30                                              ERL_NIF_TERM const argv[]) {
31   return enif_make_int64(env, crypto_box_SECRETKEYBYTES);
32 }
33 
enacl_crypto_box_BEFORENMBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])34 ERL_NIF_TERM enacl_crypto_box_BEFORENMBYTES(ErlNifEnv *env, int argc,
35                                             ERL_NIF_TERM const argv[]) {
36   return enif_make_int64(env, crypto_box_BEFORENMBYTES);
37 }
38 
enacl_crypto_box_SEALBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])39 ERL_NIF_TERM enacl_crypto_box_SEALBYTES(ErlNifEnv *env, int argc,
40                                         ERL_NIF_TERM const argv[]) {
41   return enif_make_int64(env, crypto_box_SEALBYTES);
42 }
43 
enacl_crypto_box_keypair(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])44 ERL_NIF_TERM enacl_crypto_box_keypair(ErlNifEnv *env, int argc,
45                                       ERL_NIF_TERM const argv[]) {
46   ErlNifBinary pk, sk;
47 
48   if (argc != 0) {
49     return enif_make_badarg(env);
50   }
51 
52   if (!enif_alloc_binary(crypto_box_PUBLICKEYBYTES, &pk)) {
53     return enacl_error_tuple(env, "alloc_failed");
54   }
55 
56   if (!enif_alloc_binary(crypto_box_SECRETKEYBYTES, &sk)) {
57     enif_release_binary(&pk);
58     return enacl_error_tuple(env, "alloc_failed");
59   }
60 
61   crypto_box_keypair(pk.data, sk.data);
62 
63   return enif_make_tuple2(env, enif_make_binary(env, &pk),
64                           enif_make_binary(env, &sk));
65 }
66 
enacl_crypto_box(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])67 ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc,
68                               ERL_NIF_TERM const argv[]) {
69   ErlNifBinary padded_msg, nonce, pk, sk, result;
70   ERL_NIF_TERM ret;
71 
72   if (argc != 4)
73     goto bad_arg;
74   if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_msg))
75     goto bad_arg;
76   if (!enif_inspect_binary(env, argv[1], &nonce))
77     goto bad_arg;
78   if (!enif_inspect_binary(env, argv[2], &pk))
79     goto bad_arg;
80   if (!enif_inspect_binary(env, argv[3], &sk))
81     goto bad_arg;
82 
83   if (nonce.size != crypto_box_NONCEBYTES)
84     goto bad_arg;
85   if (pk.size != crypto_box_PUBLICKEYBYTES)
86     goto bad_arg;
87   if (sk.size != crypto_box_SECRETKEYBYTES)
88     goto bad_arg;
89   if (padded_msg.size < crypto_box_ZEROBYTES)
90     goto bad_arg;
91 
92   if (!enif_alloc_binary(padded_msg.size, &result)) {
93     goto done;
94   }
95 
96   if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data,
97                       pk.data, sk.data)) {
98     goto release;
99   }
100 
101   ret = enif_make_sub_binary(env, enif_make_binary(env, &result),
102                              crypto_box_BOXZEROBYTES,
103                              padded_msg.size - crypto_box_BOXZEROBYTES);
104 
105   goto done;
106 
107 bad_arg:
108   return enif_make_badarg(env);
109 release:
110   enif_release_binary(&result);
111 err:
112   ret = enacl_internal_error(env);
113 done:
114   return ret;
115 }
116 
enacl_crypto_box_open(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])117 ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc,
118                                    ERL_NIF_TERM const argv[]) {
119   ErlNifBinary padded_ciphertext, nonce, pk, sk, result;
120 
121   if ((argc != 4) ||
122       (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) ||
123       (!enif_inspect_binary(env, argv[1], &nonce)) ||
124       (!enif_inspect_binary(env, argv[2], &pk)) ||
125       (!enif_inspect_binary(env, argv[3], &sk))) {
126     return enif_make_badarg(env);
127   }
128 
129   if ((nonce.size != crypto_box_NONCEBYTES) ||
130       (pk.size != crypto_box_PUBLICKEYBYTES) ||
131       (sk.size != crypto_box_SECRETKEYBYTES) ||
132       (padded_ciphertext.size < crypto_box_BOXZEROBYTES)) {
133     return enif_make_badarg(env);
134   }
135 
136   if (!enif_alloc_binary(padded_ciphertext.size, &result)) {
137     return enacl_internal_error(env);
138   }
139 
140   if (0 != crypto_box_open(result.data, padded_ciphertext.data,
141                            padded_ciphertext.size, nonce.data, pk.data,
142                            sk.data)) {
143     enif_release_binary(&result);
144     return enacl_error_tuple(env, "failed_verification");
145   }
146 
147   ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
148   ERL_NIF_TERM ret_bin = enif_make_sub_binary(
149       env, enif_make_binary(env, &result), crypto_box_ZEROBYTES,
150       padded_ciphertext.size - crypto_box_ZEROBYTES);
151 
152   return enif_make_tuple2(env, ret_ok, ret_bin);
153 }
154 
155 /* Precomputed crypto boxes */
156 
enacl_crypto_box_beforenm(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])157 ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc,
158                                        ERL_NIF_TERM const argv[]) {
159   ErlNifBinary k, pk, sk;
160 
161   if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &pk)) ||
162       (!enif_inspect_binary(env, argv[1], &sk)) ||
163       (pk.size != crypto_box_PUBLICKEYBYTES) ||
164       (sk.size != crypto_box_SECRETKEYBYTES)) {
165     return enif_make_badarg(env);
166   }
167 
168   if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) {
169     goto err;
170   }
171 
172   if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) {
173     // error
174     enif_release_binary(&k);
175     goto err;
176   }
177 
178   return enif_make_binary(env, &k);
179 err:
180   return enacl_internal_error(env);
181 }
182 
enacl_crypto_box_afternm(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])183 ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc,
184                                       ERL_NIF_TERM const argv[]) {
185   ErlNifBinary result, m, nonce, k;
186 
187   if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
188       (!enif_inspect_binary(env, argv[1], &nonce)) ||
189       (!enif_inspect_binary(env, argv[2], &k)) ||
190       (m.size < crypto_box_ZEROBYTES) ||
191       (nonce.size != crypto_box_NONCEBYTES) ||
192       (k.size != crypto_box_BEFORENMBYTES)) {
193     return enif_make_badarg(env);
194   }
195 
196   if (!enif_alloc_binary(m.size, &result)) {
197     return enacl_internal_error(env);
198   }
199 
200   crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data);
201 
202   return enif_make_sub_binary(env, enif_make_binary(env, &result),
203                               crypto_box_BOXZEROBYTES,
204                               m.size - crypto_box_BOXZEROBYTES);
205 }
206 
enacl_crypto_box_open_afternm(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])207 ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc,
208                                            ERL_NIF_TERM const argv[]) {
209   ErlNifBinary result, m, nonce, k;
210 
211   if ((argc != 3) || (!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
212       (!enif_inspect_binary(env, argv[1], &nonce)) ||
213       (!enif_inspect_binary(env, argv[2], &k)) ||
214       (m.size < crypto_box_BOXZEROBYTES) ||
215       (nonce.size != crypto_box_NONCEBYTES) ||
216       (k.size != crypto_box_BEFORENMBYTES)) {
217     return enif_make_badarg(env);
218   }
219 
220   if (!enif_alloc_binary(m.size, &result)) {
221     return enacl_internal_error(env);
222   }
223 
224   if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data,
225                                    k.data)) {
226     enif_release_binary(&result);
227     return enacl_error_tuple(env, "failed_verification");
228   }
229 
230   ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
231   ERL_NIF_TERM ret_bin =
232       enif_make_sub_binary(env, enif_make_binary(env, &result),
233                            crypto_box_ZEROBYTES, m.size - crypto_box_ZEROBYTES);
234   return enif_make_tuple2(env, ret_ok, ret_bin);
235 }
236 
237 /* Sealed box functions */
238 
enacl_crypto_box_seal(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])239 ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc,
240                                    ERL_NIF_TERM const argv[]) {
241   ErlNifBinary key, msg, ciphertext;
242 
243   if ((argc != 2) || (!enif_inspect_iolist_as_binary(env, argv[0], &msg)) ||
244       (!enif_inspect_binary(env, argv[1], &key))) {
245     return enif_make_badarg(env);
246   }
247 
248   if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) {
249     return enacl_internal_error(env);
250   }
251 
252   crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data);
253 
254   return enif_make_binary(env, &ciphertext);
255 }
256 
enacl_crypto_box_seal_open(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])257 ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc,
258                                         ERL_NIF_TERM const argv[]) {
259   ErlNifBinary pk, sk, ciphertext, msg;
260 
261   if ((argc != 3) ||
262       (!enif_inspect_iolist_as_binary(env, argv[0], &ciphertext)) ||
263       (!enif_inspect_binary(env, argv[1], &pk)) ||
264       (!enif_inspect_binary(env, argv[2], &sk))) {
265     return enif_make_badarg(env);
266   }
267 
268   if (ciphertext.size < crypto_box_SEALBYTES) {
269     return enif_make_badarg(env);
270   }
271 
272   if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) {
273     return enacl_internal_error(env);
274   }
275 
276   if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data,
277                            sk.data) != 0) {
278     enif_release_binary(&msg);
279     return enacl_error_tuple(env, "failed_verification");
280   }
281 
282   ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
283   ERL_NIF_TERM ret_bin = enif_make_binary(env, &msg);
284 
285   return enif_make_tuple2(env, ret_ok, ret_bin);
286 }
287