diff --git a/c_src/kx.c b/c_src/kx.c index 283328b..e4d9a6d 100644 --- a/c_src/kx.c +++ b/c_src/kx.c @@ -48,63 +48,104 @@ ERL_NIF_TERM enacl_crypto_kx_keypair(ErlNifEnv *env, int argc, ERL_NIF_TERM enacl_crypto_kx_server_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { + ERL_NIF_TERM ret; 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 (argc != 3) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &server_pk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &server_sk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &client_pk)) + goto bad_arg; + + if (server_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; + if (server_sk.size != crypto_kx_SECRETKEYBYTES) + goto bad_arg; + if (client_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto release_rx; } if (0 != crypto_kx_server_session_keys(rx.data, tx.data, server_pk.data, server_sk.data, client_pk.data)) { // suspicious client public key - return nacl_error_tuple(env, "invalid_client_public_key"); + ret = nacl_error_tuple(env, "invalid_client_public_key"); + goto release_tx; } - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); + ret = enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); + goto done; + +bad_arg: + return enif_make_badarg(env); +release_tx: + enif_release_binary(&tx); +release_rx: + enif_release_binary(&rx); +done: + return ret; } ERL_NIF_TERM enacl_crypto_kx_client_session_keys(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary rx, tx, client_pk, client_sk, server_pk; + ERL_NIF_TERM ret; - 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 (argc != 3) + goto bad_arg; + if (!enif_inspect_binary(env, argv[0], &client_pk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[1], &client_sk)) + goto bad_arg; + if (!enif_inspect_binary(env, argv[2], &server_pk)) + goto bad_arg; + + if (client_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; + if (client_sk.size != crypto_kx_SECRETKEYBYTES) + goto bad_arg; + if (server_pk.size != crypto_kx_PUBLICKEYBYTES) + goto bad_arg; if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &rx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto done; } if (!enif_alloc_binary(crypto_kx_SESSIONKEYBYTES, &tx)) { - return nacl_error_tuple(env, "alloc_failed"); + ret = nacl_error_tuple(env, "alloc_failed"); + goto release_rx; } if (0 != crypto_kx_client_session_keys(rx.data, tx.data, client_pk.data, client_sk.data, server_pk.data)) { // suspicious server public key - return nacl_error_tuple(env, "invalid_server_public_key"); + ret = nacl_error_tuple(env, "invalid_server_public_key"); + goto release_tx; } - return enif_make_tuple2(env, enif_make_binary(env, &rx), - enif_make_binary(env, &tx)); + ret = enif_make_tuple2(env, enif_make_binary(env, &rx), + enif_make_binary(env, &tx)); + goto done; +bad_arg: + return enif_make_badarg(env); +release_tx: + enif_release_binary(&tx); +release_rx: + enif_release_binary(&rx); +done: + return ret; } \ No newline at end of file diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index 0cb6f97..8ff5b5c 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -43,7 +43,8 @@ groups() -> aead_xchacha20poly1305, aead_chacha20poly1305, pwhash, - sign]}, + sign, + kx]}, [Neg, Pos]. @@ -139,3 +140,12 @@ sign_chunked(S, M, N) -> S2 = enacl:sign_update(S, M), sign_chunked(S2, M, N-1). +kx(_Config) -> + #{ public := CPK, secret := CSK} = enacl:kx_keypair(), + #{ public := SPK, secret := SSK} = enacl:kx_keypair(), + #{ client_tx := CTX, client_rx := CRX} = enacl:kx_client_session_keys(CPK, CSK, SPK), + #{ server_tx := STX, server_rx := SRX} = enacl:kx_server_session_keys(SPK, SSK, CPK), + %% Verify we got a shared keypair + CTX = SRX, + STX = CRX, + ok.