commit c57beff4c4df73311fb9be9790097685af84d2c3
parent 8f7e8963934ad99b2d85d5044cc9ece3c15e5169
Author: Florian Dold <florian@dold.me>
Date: Tue, 13 Dec 2022 14:42:14 +0100
kx operations
Diffstat:
| M | quickjs-libc.c | | | 135 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
1 file changed, 119 insertions(+), 16 deletions(-)
diff --git a/quickjs-libc.c b/quickjs-libc.c
@@ -4246,6 +4246,27 @@ exception:
goto done;
}
+uint8_t *expect_fixed_buffer(JSContext *ctx,
+ JSValue val, size_t len,
+ const char *msg)
+{
+ uint8_t *buf;
+ size_t sz;
+
+ buf = JS_GetArrayBuffer(ctx, &sz, val);
+ if (!buf) {
+ return NULL;
+ }
+ if (sz != len) {
+ JS_ThrowTypeError(ctx, "invalid length for %s", msg);
+ return NULL;
+ }
+ return buf;
+}
+
+#define REQUIRE(cond, _label) do { if (!(cond)) { goto _label; } } while (0)
+
+
static JSValue make_js_ta_copy(JSContext *ctx, uint8_t *data, size_t size)
{
JSValue array_buf;
@@ -4276,19 +4297,15 @@ static JSValue js_talercrypto_hash(JSContext *ctx, JSValue this_val,
static JSValue js_talercrypto_eddsa_key_get_public(JSContext *ctx, JSValue this_val,
int argc, JSValueConst *argv)
{
- size_t size;
uint8_t *buf;
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
unsigned char sk[crypto_sign_SECRETKEYBYTES];
- buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
-
+ buf = expect_fixed_buffer(ctx, argv[0], 32, "eddsa private key");
+
if (!buf) {
return JS_EXCEPTION;
}
- if (size != 32) {
- return JS_ThrowTypeError(ctx, "invalid private key size");
- }
crypto_sign_seed_keypair(pk, sk, buf);
// FIXME: clean up stack!
@@ -4296,6 +4313,26 @@ static JSValue js_talercrypto_eddsa_key_get_public(JSContext *ctx, JSValue this_
return make_js_ta_copy(ctx, pk, crypto_sign_PUBLICKEYBYTES);
}
+static JSValue js_talercrypto_ecdhe_key_get_public(JSContext *ctx, JSValue this_val,
+ int argc, JSValueConst *argv)
+{
+ uint8_t *buf;
+ unsigned char pk[crypto_scalarmult_BYTES];
+
+ buf = expect_fixed_buffer(ctx, argv[0], 32, "ecdh private key");
+
+ if (!buf) {
+ return JS_EXCEPTION;
+ }
+
+ if (0 != crypto_scalarmult_base(pk, buf)) {
+ return JS_EXCEPTION;
+ }
+ // FIXME: clean up stack!
+
+ return make_js_ta_copy(ctx, pk, crypto_sign_PUBLICKEYBYTES);
+}
+
/**
* (msg, priv) => sig
*/
@@ -4460,16 +4497,76 @@ exception:
goto done;
}
-//static JSValue js_talercrypto_kx_ecdhe_eddsa(JSContext *ctx, JSValue this_val,
-// int argc, JSValueConst *argv)
-//{
-//}
-//
-//static JSValue js_talercrypto_kx_eddsa_ecdhe(JSContext *ctx, JSValue this_val,
-// int argc, JSValueConst *argv)
-//{
-//}
-//
+/**
+ * (ecdhePriv, eddsaPub) -> keyMaterial
+ */
+static JSValue js_talercrypto_kx_ecdh_eddsa(JSContext *ctx, JSValue this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue ret_val;
+ uint8_t p[crypto_scalarmult_BYTES];
+ uint8_t *ecdh_priv;
+ uint8_t *eddsa_pub;
+ uint8_t curve25510_pk[crypto_scalarmult_BYTES];
+ uint8_t key_material[crypto_hash_BYTES];
+
+ ecdh_priv = expect_fixed_buffer(ctx, argv[0], 32, "ecdhe priv");
+ REQUIRE(ecdh_priv, exception);
+
+ eddsa_pub = expect_fixed_buffer(ctx, argv[1], 32, "eddsa pub");
+ REQUIRE(eddsa_pub, exception);
+
+ if (0 != crypto_sign_ed25519_pk_to_curve25519(curve25510_pk, eddsa_pub)) {
+ goto exception;
+ }
+ if (0 != crypto_scalarmult(p, ecdh_priv, curve25510_pk)) {
+ goto exception;
+ }
+ if (0 != crypto_hash(key_material, p, 32)) {
+ JS_ThrowTypeError(ctx, "hashing failed");
+ goto exception;
+ }
+ ret_val = make_js_ta_copy(ctx, key_material, crypto_hash_BYTES);
+done:
+ return ret_val;
+exception:
+ ret_val = JS_EXCEPTION;
+ goto done;
+}
+
+/**
+ * (eddsaPriv, ecdhePub) -> keyMaterial
+ */
+static JSValue js_talercrypto_kx_eddsa_ecdh(JSContext *ctx, JSValue this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue ret_val;
+ uint8_t *priv;
+ uint8_t *pub;
+ uint8_t hc[crypto_hash_BYTES];
+ uint8_t a[crypto_scalarmult_SCALARBYTES];
+ uint8_t p[crypto_scalarmult_BYTES];
+ uint8_t key_material[crypto_hash_BYTES];
+
+ priv = expect_fixed_buffer(ctx, argv[0], 32, "eddsa priv");
+ REQUIRE(priv, exception);
+ pub = expect_fixed_buffer(ctx, argv[1], 32, "ecdh pub");
+ REQUIRE(pub, exception);
+
+ crypto_hash(hc, priv, 32);
+ memcpy (a, &hc, 32);
+ if (0 != crypto_scalarmult(p, a, pub)) {
+ goto exception;
+ }
+ crypto_hash(key_material, p, crypto_scalarmult_BYTES);
+ ret_val = make_js_ta_copy(ctx, key_material, crypto_hash_BYTES);
+done:
+ return ret_val;
+exception:
+ ret_val = JS_EXCEPTION;
+ goto done;
+}
+
static JSValue js_decode_utf8(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
@@ -4512,12 +4609,18 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv)
JS_NewCFunction(ctx, js_talercrypto_hash, "_hash", 1));
JS_SetPropertyStr(ctx, global_obj, "_eddsaGetPublic",
JS_NewCFunction(ctx, js_talercrypto_eddsa_key_get_public, "_eddsaGetPublic", 1));
+ JS_SetPropertyStr(ctx, global_obj, "_ecdheGetPublic",
+ JS_NewCFunction(ctx, js_talercrypto_ecdhe_key_get_public, "_ecdheGetPublic", 1));
JS_SetPropertyStr(ctx, global_obj, "_eddsaSign",
JS_NewCFunction(ctx, js_talercrypto_eddsa_sign, "_eddsaSign", 2));
JS_SetPropertyStr(ctx, global_obj, "_eddsaVerify",
JS_NewCFunction(ctx, js_talercrypto_eddsa_verify, "_eddsaVerify", 3));
JS_SetPropertyStr(ctx, global_obj, "_kdf",
JS_NewCFunction(ctx, js_talercrypto_kdf, "_kdf", 4));
+ JS_SetPropertyStr(ctx, global_obj, "_keyExchangeEddsaEcdh",
+ JS_NewCFunction(ctx, js_talercrypto_kx_eddsa_ecdh, "_keyExchangeEddsaEcdh", 2));
+ JS_SetPropertyStr(ctx, global_obj, "_keyExchangeEcdhEddsa",
+ JS_NewCFunction(ctx, js_talercrypto_kx_ecdh_eddsa, "_keyExchangeEcdhEddsa", 2));
/* same methods as the mozilla JS shell */
if (argc >= 0) {