aboutsummaryrefslogtreecommitdiff
path: root/minimal-examples/api-tests
diff options
context:
space:
mode:
authorAndy Green <andy@warmcat.com>2018-12-05 13:11:03 +0800
committerAndy Green <andy@warmcat.com>2018-12-27 06:45:31 +0800
commita3dcc95471c34c9a819ee1327ac03a74d1fb4f78 (patch)
treed8e337f52d7a87f5171eb3a03f103c26a530edc3 /minimal-examples/api-tests
parent47e14ba34bc845d81b6387a902c1fa37a0c685bc (diff)
downloadlibwebsockets-a3dcc95471c34c9a819ee1327ac03a74d1fb4f78.tar.gz
genec: generic ECDH crypto layer
!!! WIP This implements the "genec" layer wrapping mbedtls + openssl ECDH support. API tests are added for the parts that are implemented so far. Stuff related to ec at all, like keys, are prefixed lws_genec_. Stuff specific to ECDH are prefixed lws_genecdh_.
Diffstat (limited to 'minimal-examples/api-tests')
-rw-r--r--minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt3
-rw-r--r--minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c16
-rw-r--r--minimal-examples/api-tests/api-test-gencrypto/lws-genec.c132
-rw-r--r--minimal-examples/api-tests/api-test-gencrypto/main.c3
-rw-r--r--minimal-examples/api-tests/api-test-jose/jwe.c21
-rw-r--r--minimal-examples/api-tests/api-test-jose/jws.c82
6 files changed, 206 insertions, 51 deletions
diff --git a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt
index a36a5cda..0679f88a 100644
--- a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt
+++ b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)
include(CheckCSourceCompiles)
set(SAMP lws-api-test-gencrypto)
-set(SRCS main.c lws-genaes.c)
+set(SRCS main.c lws-genaes.c lws-genec.c)
# If we are being built as part of lws, confirm current build config supports
# reqconfig, else skip building ourselves.
@@ -63,6 +63,7 @@ ENDMACRO()
set(requirements 1)
require_lws_config(LWS_WITH_GENAES 1 requirements)
+require_lws_config(LWS_WITH_GENEC 1 requirements)
if (requirements)
diff --git a/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c b/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c
index 63491251..b14e08e5 100644
--- a/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c
+++ b/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c
@@ -38,7 +38,7 @@ static int
test_genaes_cbc(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
/*
@@ -128,7 +128,7 @@ static int
test_genaes_cfb128(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
size_t iv_off = 0;
@@ -215,7 +215,7 @@ static int
test_genaes_cfb8(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
e.buf = (uint8_t *)cfb8_key;
@@ -300,7 +300,7 @@ test_genaes_ctr(void)
{
uint8_t nonce_counter[16], sb[16];
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
size_t nc_off = 0;
@@ -390,7 +390,7 @@ static int
test_genaes_ecb(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
/*
@@ -483,7 +483,7 @@ static int
test_genaes_ofb(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32];
size_t iv_off = 0;
@@ -571,7 +571,7 @@ static int
test_genaes_xts(void)
{
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
uint8_t res[32], res1[32], data_unit[16];
memset(data_unit, 0, sizeof(data_unit));
@@ -663,7 +663,7 @@ test_genaes_gcm(void)
{
uint8_t res[sizeof(gcm_ct)], tag[sizeof(gcm_tag)];
struct lws_genaes_ctx ctx;
- struct lws_jwk_elements e;
+ struct lws_gencrypto_keyelem e;
size_t iv_off = 0;
e.buf = (uint8_t *)gcm_key;
diff --git a/minimal-examples/api-tests/api-test-gencrypto/lws-genec.c b/minimal-examples/api-tests/api-test-gencrypto/lws-genec.c
new file mode 100644
index 00000000..d640650d
--- /dev/null
+++ b/minimal-examples/api-tests/api-test-gencrypto/lws-genec.c
@@ -0,0 +1,132 @@
+/*
+ * lws-api-test-gencrypto - lws-genec
+ *
+ * Copyright (C) 2018 Andy Green <andy@warmcat.com>
+ *
+ * This file is made available under the Creative Commons CC0 1.0
+ * Universal Public Domain Dedication.
+ */
+
+#include <libwebsockets.h>
+
+static const uint8_t
+ *jwk_ec1 = (uint8_t *)
+ "{\"kty\":\"EC\","
+ "\"crv\":\"P-256\","
+ "\"x\":\"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4\","
+ "\"y\":\"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM\","
+ "\"d\":\"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE\","
+ "\"use\":\"enc\","
+ "\"kid\":\"rfc7517-A.2-example private key\"}"
+;
+
+static int
+test_genec1(struct lws_context *context)
+{
+ struct lws_genec_ctx ctx;
+ struct lws_jwk jwk;
+ struct lws_gencrypto_keyelem el[LWS_GENCRYPTO_EC_KEYEL_COUNT];
+ //uint8_t res[32], res1[32];
+ int n;
+
+ memset(el, 0, sizeof(el));
+
+ if (lws_genecdh_create(&ctx, context, NULL))
+ return 1;
+
+ /* let's create a new key */
+
+ if (lws_genecdh_new_keypair(&ctx, LDHS_OURS, "P-256", el)) {
+ lwsl_err("%s: lws_genec_new_keypair failed\n", __func__);
+ return 1;
+ }
+
+ lws_genec_dump(el);
+ lws_genec_destroy_elements(el);
+
+ lws_genec_destroy(&ctx);
+
+ if (lws_jwk_import(&jwk, NULL, NULL, (char *)jwk_ec1,
+ strlen((char *)jwk_ec1)) < 0) {
+ lwsl_notice("Failed to decode JWK test key\n");
+ return 1;
+ }
+
+ lws_jwk_dump(&jwk);
+
+ if (jwk.kty != LWS_GENCRYPTO_KYT_EC) {
+ lws_jwk_destroy(&jwk);
+ lwsl_err("%s: jwk is not an EC key\n", __func__);
+ return 1;
+ }
+
+ if (lws_genecdh_create(&ctx, context, NULL))
+ return 1;
+
+ n = lws_genecdh_set_key(&ctx, jwk.e, LDHS_OURS);
+ if (n) {
+ lws_jwk_destroy(&jwk);
+ lwsl_err("%s: lws_genec_create failed: %d\n", __func__, n);
+ return 1;
+ }
+#if 0
+ if (lws_genec_crypt(&ctx, cbc256, 16, res, (uint8_t *)cbc256_iv,
+ NULL, NULL)) {
+ lwsl_err("%s: lws_genec_crypt failed\n", __func__);
+ goto bail;
+ }
+
+ if (memcmp(cbc256_enc, res, 16)) {
+ lwsl_err("%s: lws_genec_crypt encoding mismatch\n", __func__);
+ lwsl_hexdump_notice(res, 16);
+ goto bail;
+ }
+
+ lws_genec_destroy(&ctx);
+
+ if (lws_genec_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_CBC, &e, NULL)) {
+ lwsl_err("%s: lws_genec_create dec failed\n", __func__);
+ return -1;
+ }
+
+ if (lws_genec_crypt(&ctx, res, 16, res1, (uint8_t *)cbc256_iv,
+ NULL, NULL)) {
+ lwsl_err("%s: lws_genec_crypt dec failed\n", __func__);
+ goto bail;
+ }
+
+ if (memcmp(cbc256, res1, 16)) {
+ lwsl_err("%s: lws_genec_crypt decoding mismatch\n", __func__);
+ lwsl_hexdump_notice(res, 16);
+ goto bail;
+ }
+#endif
+ lws_genec_destroy(&ctx);
+
+ lws_jwk_destroy(&jwk);
+
+ return 0;
+
+//bail:
+// lws_genec_destroy(&ctx);
+
+// return -1;
+}
+
+int
+test_genec(struct lws_context *context)
+{
+ if (test_genec1(context))
+ goto bail;
+
+ /* end */
+
+ lwsl_notice("%s: selftest OK\n", __func__);
+
+ return 0;
+
+bail:
+ lwsl_err("%s: selftest failed ++++++++++++++++++++\n", __func__);
+
+ return 1;
+}
diff --git a/minimal-examples/api-tests/api-test-gencrypto/main.c b/minimal-examples/api-tests/api-test-gencrypto/main.c
index 7bdcdf53..fd808c69 100644
--- a/minimal-examples/api-tests/api-test-gencrypto/main.c
+++ b/minimal-examples/api-tests/api-test-gencrypto/main.c
@@ -11,6 +11,8 @@
int
test_genaes(struct lws_context *context);
+int
+test_genec(struct lws_context *context);
int main(int argc, const char **argv)
{
@@ -36,6 +38,7 @@ int main(int argc, const char **argv)
}
result |= test_genaes(context);
+ result |= test_genec(context);
lwsl_user("Completed: %s\n", result ? "FAIL" : "PASS");
diff --git a/minimal-examples/api-tests/api-test-jose/jwe.c b/minimal-examples/api-tests/api-test-jose/jwe.c
index cb88492c..27b8b9b3 100644
--- a/minimal-examples/api-tests/api-test-jose/jwe.c
+++ b/minimal-examples/api-tests/api-test-jose/jwe.c
@@ -67,8 +67,10 @@ lws_jwe_ex_a2_cek[] = {
"\"qi\":\"eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC"
"tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ"
"B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo\""
-"}",
+"}"
+#if 0
+,
lws_jwe_ex_a2_jwk_enc_key[] = {
80, 104, 72, 58, 11, 130, 236, 139,
132, 189, 255, 205, 61, 86, 151, 176,
@@ -103,7 +105,6 @@ lws_jwe_ex_a2_jwk_enc_key[] = {
248, 29, 232, 90, 29, 147, 110, 169,
146, 114, 165, 204, 71, 136, 41, 252
}
-#if 0
,
*lws_jwe_ex_a2_jwk_enc_key_b64 = (uint8_t *)
"UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm"
@@ -175,9 +176,10 @@ lws_jwe_ex_a2_authtag[] = {
int
test_jwe(struct lws_context *context)
{
+ //const struct lws_jose_jwe_alg *jose_alg;
struct lws_genrsa_ctx rsactx;
struct lws_jwk jwk;
- uint8_t enc_cek[sizeof(lws_jwe_ex_a2_jwk_enc_key) + 2048];
+ uint8_t enc_cek[/* sizeof(lws_jwe_ex_a2_jwk_enc_key) */ 256 + 2048];
char buf[2048], *p = buf, *end = buf + sizeof(buf) - 1;
int n;
@@ -191,7 +193,7 @@ test_jwe(struct lws_context *context)
return -1;
}
- if (jwk.kty != LWS_JWK_KYT_RSA) {
+ if (jwk.kty != LWS_GENCRYPTO_KYT_RSA) {
lwsl_err("%s: unexpected kty %d\n", __func__, jwk.kty);
return -1;
@@ -246,8 +248,8 @@ test_jwe(struct lws_context *context)
/* 1.3: use HMAC SHA-256 with known key on the hdr . payload */
if (lws_genhmac_init(&ctx, LWS_GENHMAC_TYPE_SHA256,
- jwk.el.e[JWK_RSA_KEYEL_E].buf,
- jwk.el.e[JWK_RSA_KEYEL_E].len))
+ jwk.el.e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
+ jwk.el.e[LWS_GENCRYPTO_RSA_KEYEL_E].len))
goto bail;
if (lws_genhmac_update(&ctx, (uint8_t *)buf, p - buf))
goto bail_destroy_hmac;
@@ -296,9 +298,14 @@ test_jwe(struct lws_context *context)
p = strchr(buf + 1, '.');
p1 = strchr(p + 1, '.');
+ if (lws_gencrypto_jwe_alg_to_definition("RSA1_5", &jose_alg)) {
+ lwsl_err("%s: RSA1_5 not supported\n", __func__);
+ goto bail;
+ }
+
n = lws_jws_sign_from_b64(buf, p - buf, p + 1, p1 - (p + 1),
p1 + 1, sizeof(buf) - (p1 - buf) - 1,
- LWS_GENHASH_TYPE_SHA256, &jwk);
+ jose_alg, &jwk, context);
if (n < 0)
goto bail;
diff --git a/minimal-examples/api-tests/api-test-jose/jws.c b/minimal-examples/api-tests/api-test-jose/jws.c
index d82b0ca7..d66978e8 100644
--- a/minimal-examples/api-tests/api-test-jose/jws.c
+++ b/minimal-examples/api-tests/api-test-jose/jws.c
@@ -20,33 +20,6 @@
* The signature stays with the content, it serves a different purpose than eg
* a TLS tunnel to transfer it.
*
- * RFC7518 (JSON Web Algorithms) says for the "alg" names
- *
- * | HS256 | HMAC using SHA-256 | Required |
- * | HS384 | HMAC using SHA-384 | Optional |
- * | HS512 | HMAC using SHA-512 | Optional |
- * | RS256 | RSASSA-PKCS1-v1_5 using | Recommended |
- * | RS384 | RSASSA-PKCS1-v1_5 using | Optional |
- * | | SHA-384 | |
- * | RS512 | RSASSA-PKCS1-v1_5 using | Optional |
- * | | SHA-512 | |
- * | ES256 | ECDSA using P-256 and SHA-256 | Recommended+ |
- * | ES384 | ECDSA using P-384 and SHA-384 | Optional |
- * | ES512 | ECDSA using P-521 and SHA-512 | Optional |
- *
- * Boulder (FOSS ACME provider) supports RS256, ES256, ES384 and ES512
- * currently. The "Recommended+" just means it is recommended but will likely
- * be "very recommended" soon.
- *
- * We support HS256/384/512 for symmetric crypto, but the choice for the
- * asymmetric crypto isn't as easy to make.
- *
- * Normally you'd choose the EC option but these are defined to use the
- * "NIST curves" (RFC7518 3.4) which are believed to be insecure.
- *
- * https://safecurves.cr.yp.to/
- *
- * For that reason we implement RS256/384/512 for asymmetric.
*/
static const char
@@ -101,7 +74,40 @@ static const char
"BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K"
"0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv"
"hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB"
- "p0igcN_IoypGlUPQGe77Rw";
+ "p0igcN_IoypGlUPQGe77Rw"
+
+#if 0
+ ,
+ *rfc7515_ec_a3_jose = "{\"alg\":\"ES256\"}",
+ /* payload is the same as test2 above */
+ *rfc7515_ec_a3_b64_serialization =
+ "eyJhbGciOiJFUzI1NiJ9"
+ "."
+ "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt"
+ "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
+ "."
+ "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSA"
+ "pmWQxfKTUJqPP3-Kg6NU1Q",
+ *rfc7515_ec_a3_jwk =
+ "{"
+ "\"kty\":\"EC\","
+ "\"crv\":\"P-256\","
+ "\"x\":\"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU\","
+ "\"y\":\"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0\","
+ "\"d\":\"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI\""
+ "}",
+ rfc7515_ec_a3_R[] = {
+ 14, 209, 33, 83, 121, 99, 108, 72, 60, 47, 127, 21, 88,
+ 7, 212, 2, 163, 178, 40, 3, 58, 249, 124, 126, 23, 129,
+ 154, 195, 22, 158, 166, 101
+ },
+ rfc7515_ec_a3_S[] = {
+ 197, 10, 7, 211, 140, 60, 112, 229, 216, 241, 45, 175,
+ 8, 74, 84, 128, 166, 101, 144, 197, 242, 147, 80, 154,
+ 143, 63, 127, 138, 131, 163, 84, 213
+ }
+#endif
+;
/*
* These are the inputs and outputs from the worked example in RFC7515
@@ -115,10 +121,11 @@ static const char
int
test_jws(struct lws_context *context)
{
- struct lws_genhmac_ctx ctx;
- struct lws_jwk jwk;
char buf[2048], *p = buf, *end = buf + sizeof(buf) - 1, *enc_ptr, *p1;
+ const struct lws_jose_jwe_alg *jose_alg;
uint8_t digest[LWS_GENHASH_LARGEST];
+ struct lws_genhmac_ctx ctx;
+ struct lws_jwk jwk;
int n;
/* Test 1: SHA256 on RFC7515 worked example */
@@ -129,7 +136,7 @@ test_jws(struct lws_context *context)
lwsl_notice("Failed to decode JWK test key\n");
return -1;
}
- if (jwk.kty != LWS_JWK_KYT_OCT) {
+ if (jwk.kty != LWS_GENCRYPTO_KYT_OCT) {
lwsl_err("%s: unexpected kty %d\n", __func__, jwk.kty);
return -1;
@@ -153,8 +160,8 @@ test_jws(struct lws_context *context)
/* 1.3: use HMAC SHA-256 with known key on the hdr . payload */
if (lws_genhmac_init(&ctx, LWS_GENHMAC_TYPE_SHA256,
- jwk.e[JWK_OCT_KEYEL_K].buf,
- jwk.e[JWK_OCT_KEYEL_K].len))
+ jwk.e[LWS_GENCRYPTO_OCT_KEYEL_K].buf,
+ jwk.e[LWS_GENCRYPTO_OCT_KEYEL_K].len))
goto bail;
if (lws_genhmac_update(&ctx, (uint8_t *)buf, p - buf))
goto bail_destroy_hmac;
@@ -191,7 +198,7 @@ test_jws(struct lws_context *context)
goto bail2;
}
- if (jwk.kty != LWS_JWK_KYT_RSA) {
+ if (jwk.kty != LWS_GENCRYPTO_KYT_RSA) {
lwsl_err("%s: 2.2: kty: %d instead of RSA\n", __func__, jwk.kty);
}
@@ -211,9 +218,14 @@ test_jws(struct lws_context *context)
p = strchr(buf + 1, '.');
p1 = strchr(p + 1, '.');
+ if (lws_gencrypto_jwe_alg_to_definition("RSA1_5", &jose_alg)) {
+ lwsl_err("%s: RSA1_5 not supported\n", __func__);
+ goto bail;
+ }
+
n = lws_jws_sign_from_b64(buf, p - buf, p + 1, p1 - (p + 1),
p1 + 1, sizeof(buf) - (p1 - buf) - 1,
- LWS_GENHASH_TYPE_SHA256, &jwk, context);
+ jose_alg, &jwk, context);
if (n < 0) {
lwsl_err("%s: failed signing test packet\n", __func__);
goto bail;