diff options
Diffstat (limited to 'lib/crypto/c_src/ecdh.c')
-rw-r--r-- | lib/crypto/c_src/ecdh.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c new file mode 100644 index 0000000000..9e3f460519 --- /dev/null +++ b/lib/crypto/c_src/ecdh.c @@ -0,0 +1,94 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2010-2018. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +#include "ecdh.h" +#include "ec.h" + +/* + (_OthersPublicKey, _MyPrivateKey) + (_OthersPublicKey, _MyEC_Point) +*/ +ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +/* (OtherPublicKey, Curve, My) */ +{ +#if defined(HAVE_EC) + ERL_NIF_TERM ret; + unsigned char *p; + EC_KEY* key = NULL; + int degree; + size_t field_size; + EC_GROUP *group = NULL; + const BIGNUM *priv_key; + EC_POINT *my_ecpoint = NULL; + EC_KEY *other_ecdh = NULL; + + ASSERT(argc == 3); + + if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) + goto bad_arg; + if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL) + goto bad_arg; + priv_key = EC_KEY_get0_private_key(key); + + if (!term2point(env, argv[0], group, &my_ecpoint)) { + goto err; + } + + if ((other_ecdh = EC_KEY_new()) == NULL) + goto err; + if (!EC_KEY_set_group(other_ecdh, group)) + goto err; + if (!EC_KEY_set_private_key(other_ecdh, priv_key)) + goto err; + + if ((degree = EC_GROUP_get_degree(group)) <= 0) + goto err; + + field_size = (size_t)degree; + if ((p = enif_make_new_binary(env, (field_size+7)/8, &ret)) == NULL) + goto err; + if (ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL) < 1) + goto err; + + goto done; + + bad_arg: + ret = make_badarg_maybe(env); + goto done; + + err: + ret = enif_make_badarg(env); + + done: + if (group) + EC_GROUP_free(group); + if (my_ecpoint) + EC_POINT_free(my_ecpoint); + if (other_ecdh) + EC_KEY_free(other_ecdh); + if (key) + EC_KEY_free(key); + + return ret; + +#else + return atom_notsup; +#endif +} |