Add kx_* functions from libsodium 1.0.12

This commit is contained in:
Alexander Malaev 2017-03-19 02:00:52 +03:00
parent a708d0b11e
commit 2da2ba138f
3 changed files with 270 additions and 76 deletions

View File

@ -1028,6 +1028,101 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[
return enif_make_binary(env, &result); return enif_make_binary(env, &result);
} }
/* Key exchange */
static
ERL_NIF_TERM enif_crypto_kx_SECRETKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_kx_SECRETKEYBYTES);
}
static
ERL_NIF_TERM enif_crypto_kx_PUBLICKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_kx_PUBLICKEYBYTES);
}
static
ERL_NIF_TERM enif_crypto_kx_SESSIONKEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_kx_SESSIONKEYBYTES);
}
static
ERL_NIF_TERM enif_crypto_kx_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
ErlNifBinary pk, sk;
if (argc != 0) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(crypto_kx_PUBLICKEYBYTES, &pk)) {
return nacl_error_tuple(env, "alloc_failed");
}
if (!enif_alloc_binary(crypto_kx_SECRETKEYBYTES, &sk)) {
return nacl_error_tuple(env, "alloc_failed");
}
crypto_kx_keypair(pk.data, sk.data);
return enif_make_tuple2(env, enif_make_binary(env, &pk), enif_make_binary(env, &sk));
}
static
ERL_NIF_TERM enif_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
ErlNifBinary rx, tx, server_pk, server_sk, client_pk;
if ((argc != 3) ||
(!enif_inspect_binary(env, argv[0], &server_pk)) ||
(!enif_inspect_binary(env, argv[1], &server_sk)) ||
(!enif_inspect_binary(env, argv[2], &client_pk)) ||
(server_pk.size != crypto_kx_PUBLICKEYBYTES) ||
(server_sk.size != crypto_kx_SECRETKEYBYTES) ||
(client_pk.size != crypto_kx_PUBLICKEYBYTES)) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
return nacl_error_tuple(env, "alloc_failed");
}
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
return nacl_error_tuple(env, "alloc_failed");
}
crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data);
return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx));
}
static
ERL_NIF_TERM enif_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
{
ErlNifBinary rx, tx, client_pk, client_sk, server_pk;
if ((argc != 3) ||
(!enif_inspect_binary(env, argv[0], &client_pk)) ||
(!enif_inspect_binary(env, argv[1], &client_sk)) ||
(!enif_inspect_binary(env, argv[2], &server_pk)) ||
(client_pk.size != crypto_kx_PUBLICKEYBYTES) ||
(client_sk.size != crypto_kx_SECRETKEYBYTES) ||
(server_pk.size != crypto_kx_PUBLICKEYBYTES)) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) {
return nacl_error_tuple(env, "alloc_failed");
}
if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) {
return nacl_error_tuple(env, "alloc_failed");
}
crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data);
return enif_make_tuple2(env, enif_make_binary(env, &rx), enif_make_binary(env, &tx));
}
/* Various other helper functions */ /* Various other helper functions */
static static
void uint64_pack(unsigned char *y, ErlNifUInt64 x) void uint64_pack(unsigned char *y, ErlNifUInt64 x)
@ -1195,6 +1290,13 @@ static ErlNifFunc nif_funcs[] = {
{"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_keypair", 0, enif_crypto_kx_keypair, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_client_session_keys", 3, enif_crypto_kx_client_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_server_session_keys", 3, enif_crypto_kx_server_session_keys, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"crypto_kx_PUBLICKEYBYTES", 0, enif_crypto_kx_PUBLICKEYBYTES},
{"crypto_kx_SECRETKEYBYTES", 0, enif_crypto_kx_SECRETKEYBYTES},
{"crypto_kx_SESSIONKEYBYTES", 0, enif_crypto_kx_SESSIONKEYBYTES},
{"scramble_block_16", 2, enif_scramble_block_16} {"scramble_block_16", 2, enif_scramble_block_16}
}; };

View File

@ -96,6 +96,16 @@
unsafe_memzero/1 unsafe_memzero/1
]). ]).
%% Key exchange functions
-export([
kx_keypair/0,
kx_client_session_keys/3,
kx_server_session_keys/3,
kx_public_key_size/0,
kx_secret_key_size/0,
kx_session_key_size/0
]).
%% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl %% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl
-export([ -export([
randombytes/1 randombytes/1
@ -139,6 +149,9 @@
-define(CRYPTO_STREAM_CHACHA20_NONCEBYTES, 8). -define(CRYPTO_STREAM_CHACHA20_NONCEBYTES, 8).
-define(CRYPTO_STREAM_KEYBYTES, 32). -define(CRYPTO_STREAM_KEYBYTES, 32).
-define(CRYPTO_STREAM_NONCEBYTES, 24). -define(CRYPTO_STREAM_NONCEBYTES, 24).
-define(CRYPTO_KX_PUBLICKEYBYTES, 32).
-define(CRYPTO_KX_SECRETKEYBYTES, 32).
-define(CRYPTO_KX_SESSIONKEYBYTES, 32).
%% @doc Verify makes sure the constants defined in libsodium matches ours %% @doc Verify makes sure the constants defined in libsodium matches ours
verify() -> verify() ->
@ -156,7 +169,10 @@ verify() ->
{crypto_box_ZEROBYTES, ?CRYPTO_BOX_ZEROBYTES}, {crypto_box_ZEROBYTES, ?CRYPTO_BOX_ZEROBYTES},
{crypto_box_BOXZEROBYTES, ?CRYPTO_BOX_BOXZEROBYTES}, {crypto_box_BOXZEROBYTES, ?CRYPTO_BOX_BOXZEROBYTES},
{crypto_secretbox_ZEROBYTES, ?CRYPTO_SECRETBOX_ZEROBYTES}, {crypto_secretbox_ZEROBYTES, ?CRYPTO_SECRETBOX_ZEROBYTES},
{crypto_secretbox_BOXZEROBYTES, ?CRYPTO_SECRETBOX_BOXZEROBYTES} {crypto_secretbox_BOXZEROBYTES, ?CRYPTO_SECRETBOX_BOXZEROBYTES},
{crypto_kx_SESSIONKEYBYTES, ?CRYPTO_KX_SESSIONKEYBYTES},
{crypto_kx_PUBLICKEYBYTES, ?CRYPTO_KX_PUBLICKEYBYTES},
{crypto_kx_SECRETKEYBYTES, ?CRYPTO_KX_SECRETKEYBYTES}
], ],
run_verifiers(Verifiers). run_verifiers(Verifiers).
@ -577,8 +593,6 @@ stream_chacha20_xor(Msg, Nonce, Key) ->
enacl_nif:crypto_stream_chacha20_xor(Msg, Nonce, Key) enacl_nif:crypto_stream_chacha20_xor(Msg, Nonce, Key)
end. end.
%% @doc auth_key_size/0 returns the byte-size of the authentication key
%% @end
%% @doc stream_nonce_size/0 returns the byte size of the nonce for streams %% @doc stream_nonce_size/0 returns the byte size of the nonce for streams
%% @end %% @end
-spec stream_nonce_size() -> ?CRYPTO_STREAM_NONCEBYTES. -spec stream_nonce_size() -> ?CRYPTO_STREAM_NONCEBYTES.
@ -812,6 +826,67 @@ crypto_sign_ed25519_public_size() ->
crypto_sign_ed25519_secret_size() -> crypto_sign_ed25519_secret_size() ->
enacl_nif:crypto_sign_ed25519_SECRETKEYBYTES(). enacl_nif:crypto_sign_ed25519_SECRETKEYBYTES().
%% Key exchange functions
%% ----------------------
%% @doc kx_keypair/0 creates a new Public/Secret keypair.
%%
%% Generates and returns a new key pair for the key exchange. The return value is a
%% map in order to avoid using the public key as a secret key and vice versa.
%% @end
-spec kx_keypair() -> #{ atom() => binary() }.
kx_keypair() ->
{PK, SK} = enacl_nif:crypto_kx_keypair(),
#{ public => PK, secret => SK}.
%% @doc kx_client_session_keys/3 computes and returns shared keys for client session.
%%
%% <p>Compute two shared keys using the server's public key `ServerPk' and the client's secret key `ClientPk'.</p>
%% <p>Returns map with two keys `client_rx' and `client_tx'.
%% `client_rx' will be used by the client to receive data from the server,
%% `client_tx' will by used by the client to send data to the server.</p>
%% @end
-spec kx_client_session_keys(ClientPk, ClientSk, ServerPk) -> #{ atom() => binary() }
when
ClientPk :: binary(),
ClientSk :: binary(),
ServerPk :: binary().
kx_client_session_keys(ClientPk, ClientSk, ServerPk) ->
{Rx, Tx} = enacl_nif:crypto_kx_client_session_keys(ClientPk, ClientSk, ServerPk),
#{ client_rx => Rx, client_tx => Tx}.
%% @doc kx_server_session_keys/3 computes and returns shared keys for server session.
%% <p>Compute two shared keys using the client's public key `ClientPk' and the server's secret key `ServerSk'.</p>
%% <p>Returns map with two keys `server_rx' and `server_tx'.
%% `server_rx' will be used by the server to receive data from the client,
%% `server_tx' will be used by the server to send data to the client.</p>
%% @end
-spec kx_server_session_keys(ServerPk, ServerSk, ClientPk) -> #{ atom() => binary() }
when
ServerPk :: binary(),
ServerSk :: binary(),
ClientPk :: binary().
kx_server_session_keys(ServerPk, ServerSk, ClientPk) ->
{Rx, Tx} = enacl_nif:crypto_kx_server_session_keys(ServerPk, ServerSk, ClientPk),
#{ server_rx => Rx, server_tx => Tx}.
%% @doc kx_session_key_size/0 returns the number of bytes of the generated during key exchange session key.
%% @end
-spec kx_session_key_size() -> pos_integer().
kx_session_key_size() ->
enacl_nif:crypto_kx_SESSIONKEYBYTES().
%% @doc kx_public_key_size/0 returns the number of bytes of the public key used in key exchange.
%% @end
-spec kx_public_key_size() -> pos_integer().
kx_public_key_size() ->
enacl_nif:crypto_kx_PUBLICKEYBYTES().
%% @doc kx_secret_key_size/0 returns the number of bytes of the secret key used in key exchange.
%% @end
-spec kx_secret_key_size() -> pos_integer().
kx_secret_key_size() ->
enacl_nif:crypto_kx_SECRETKEYBYTES().
%% Obtaining random bytes %% Obtaining random bytes
%% @doc randombytes/1 produces a stream of random bytes of the given size %% @doc randombytes/1 produces a stream of random bytes of the given size

View File

@ -104,6 +104,16 @@
crypto_sign_ed25519_SECRETKEYBYTES/0 crypto_sign_ed25519_SECRETKEYBYTES/0
]). ]).
%% Key exchange
-export([
crypto_kx_keypair/0,
crypto_kx_server_session_keys/3,
crypto_kx_client_session_keys/3,
crypto_kx_SESSIONKEYBYTES/0,
crypto_kx_PUBLICKEYBYTES/0,
crypto_kx_SECRETKEYBYTES/0
]).
%% Miscellaneous helper functions %% Miscellaneous helper functions
-export([ -export([
crypto_hash/1, crypto_hash/1,
@ -223,6 +233,13 @@ crypto_verify_16(_X, _Y) -> erlang:nif_error(nif_not_loaded).
crypto_verify_32(_X, _Y) -> erlang:nif_error(nif_not_loaded). crypto_verify_32(_X, _Y) -> erlang:nif_error(nif_not_loaded).
sodium_memzero(Input) when is_binary(Input) -> erlang:nif_error(nif_not_loaded). sodium_memzero(Input) when is_binary(Input) -> erlang:nif_error(nif_not_loaded).
crypto_kx_keypair() -> erlang:nif_error(nif_not_loaded).
crypto_kx_server_session_keys(_ServerPk,_ServerSk,_ClientPk) -> erlang:nif_error(nif_not_loaded).
crypto_kx_client_session_keys(_ClientPk,_ClientSk,_ServerPk) -> erlang:nif_error(nif_not_loaded).
crypto_kx_SESSIONKEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_kx_PUBLICKEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_kx_SECRETKEYBYTES() -> erlang:nif_error(nif_not_loaded).
randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded). randombytes(_RequestedSize) -> erlang:nif_error(nif_not_loaded).
scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded). scramble_block_16(_Block, _Key) -> erlang:nif_error(nif_not_loaded).