xref: /trunk/ns_server/deps/enacl/c_src/kx.c (revision e35c584a)
1 #include <sodium.h>
2 
3 #include <erl_nif.h>
4 
5 #include "enacl.h"
6 #include "kx.h"
7 
8 /* Key exchange */
9 
enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])10 ERL_NIF_TERM enacl_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc,
11                                             ERL_NIF_TERM const argv[]) {
12   return enif_make_int64(env, crypto_kx_SECRETKEYBYTES);
13 }
14 
enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])15 ERL_NIF_TERM enacl_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc,
16                                             ERL_NIF_TERM const argv[]) {
17   return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES);
18 }
19 
enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])20 ERL_NIF_TERM enacl_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc,
21                                              ERL_NIF_TERM const argv[]) {
22   return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES);
23 }
24 
enacl_crypto_kx_keypair(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])25 ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc,
26                                      ERL_NIF_TERM const argv[]) {
27   ErlNifBinary pk, sk;
28 
29   if (argc != 0) {
30     return enif_make_badarg(env);
31   }
32 
33   if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) {
34     return enacl_internal_error(env);
35   }
36 
37   if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) {
38     enif_release_binary(&pk);
39     return enacl_internal_error(env);
40   }
41 
42   crypto_kx_keypair(pk.data, sk.data);
43 
44   return enif_make_tuple2(env, enif_make_binary(env, &pk),
45                           enif_make_binary(env, &sk));
46 }
47 
48 ERL_NIF_TERM
enacl_crypto_kx_server_session_keys(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])49 enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc,
50                                     ERL_NIF_TERM const argv[]) {
51   ERL_NIF_TERM ret;
52   ErlNifBinary rx, tx, server_pk, server_sk, client_pk;
53 
54   if (argc != 3)
55     goto bad_arg;
56   if (!enif_inspect_binary(env, argv[0], &server_pk))
57     goto bad_arg;
58   if (!enif_inspect_binary(env, argv[1], &server_sk))
59     goto bad_arg;
60   if (!enif_inspect_binary(env, argv[2], &client_pk))
61     goto bad_arg;
62 
63   if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
64     goto bad_arg;
65   if (server_sk.size != crypto_kx_SECRETKEYBYTES)
66     goto bad_arg;
67   if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
68     goto bad_arg;
69 
70   if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
71     ret = enacl_internal_error(env);
72     goto done;
73   }
74 
75   if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
76     ret = enacl_internal_error(env);
77     goto release_rx;
78   }
79 
80   if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data,
81                                          server_sk.data, client_pk.data)) {
82     // suspicious client public key
83     ret = enacl_error_tuple(env, "invalid_client_public_key");
84     goto release_tx_rx;
85   }
86 
87   ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
88                          enif_make_binary(env, &tx));
89   goto done;
90 
91 bad_arg:
92   return enif_make_badarg(env);
93 release_tx_rx:
94   enif_release_binary(&tx);
95 release_rx:
96   enif_release_binary(&rx);
97 done:
98   return ret;
99 }
100 
101 ERL_NIF_TERM
enacl_crypto_kx_client_session_keys(ErlNifEnv * env,int argc,ERL_NIF_TERM const argv[])102 enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc,
103                                     ERL_NIF_TERM const argv[]) {
104   ErlNifBinary rx, tx, client_pk, client_sk, server_pk;
105   ERL_NIF_TERM ret;
106 
107   if (argc != 3)
108     goto bad_arg;
109   if (!enif_inspect_binary(env, argv[0], &client_pk))
110     goto bad_arg;
111   if (!enif_inspect_binary(env, argv[1], &client_sk))
112     goto bad_arg;
113   if (!enif_inspect_binary(env, argv[2], &server_pk))
114     goto bad_arg;
115 
116   if (client_pk.size != crypto_kx_PUBLICKEYBYTES)
117     goto bad_arg;
118   if (client_sk.size != crypto_kx_SECRETKEYBYTES)
119     goto bad_arg;
120   if (server_pk.size != crypto_kx_PUBLICKEYBYTES)
121     goto bad_arg;
122 
123   if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
124     ret = enacl_internal_error(env);
125     goto done;
126   }
127 
128   if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
129     ret = enacl_internal_error(env);
130     goto release_rx;
131   }
132 
133   if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data,
134                                          client_sk.data, server_pk.data)) {
135     // suspicious server public key
136     ret = enacl_error_tuple(env, "invalid_server_public_key");
137     goto release_tx_rx;
138   }
139 
140   ret = enif_make_tuple2(env, enif_make_binary(env, &rx),
141                          enif_make_binary(env, &tx));
142   goto done;
143 bad_arg:
144   return enif_make_badarg(env);
145 release_tx_rx:
146   enif_release_binary(&tx);
147 release_rx:
148   enif_release_binary(&rx);
149 done:
150   return ret;
151 }
152