diff --git a/.travis.yml b/.travis.yml index c2186067f..ed642a5cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ env: global: - secure: "KhAdQ9ja+LBObWNQTYO7Df5J4DyOih6S+eerDMu8UPSO+CoWV2pWoQzbOfocjyOscGOwC+2PrrHDNZyGfqkCLDXg1BxynXPCFerHC1yc2IajvKpGXmAAygNIvp4KACDfGv/dkXrViqIzr/CdcNaU4vIMHSVb5xkeLi0W1dPnQOI=" matrix: - - LWS_METHOD=lwsws CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/" + - LWS_METHOD=lwsws CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -DLWS_WITH_JWS=1 -DLWS_WITH_GENRSA=1 -DLWS_WITH_GENHASH=1 -DLWS_WITH_GENAES=1" - LWS_METHOD=lwsws2 CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/" - LWS_METHOD=default CMAKE_ARGS="-DLWS_WITH_MINIMAL_EXAMPLES=1" - LWS_METHOD=mbedtls CMAKE_ARGS="-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG" diff --git a/CMakeLists.txt b/CMakeLists.txt index 7de8765df..2c932866b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ option(LWS_WITH_JWS "JSON Web Signature (RFC7515) API" OFF) option(LWS_WITH_JWE "JSON Web Encryption (RFC7516) API" OFF) option(LWS_WITH_GENHASH "Enable support for Generic Hash (SHA1 + SHA2 with api independent of TLS backend)" OFF) option(LWS_WITH_GENRSA "Enable support for Generic RSA (RSA with api independent of TLS backend)" OFF) +option(LWS_WITH_GENAES "Enable support for Generic AES (AES with api independent of TLS backend)" OFF) option(LWS_WITH_GENEC "Enable support for Generic EC (EC with api independent of TLS backend)" OFF) option(LWS_WITH_SELFTESTS "Selftests run at context creation" OFF) option(LWS_WITH_GCOV "Build with gcc gcov coverage instrumentation" OFF) @@ -1031,6 +1032,11 @@ if (LWS_WITH_SSL) lib/tls/mbedtls/lws-genrsa.c ) endif() + if (LWS_WITH_GENAES) + list(APPEND SOURCES + lib/tls/mbedtls/lws-genaes.c + ) + endif() if (LWS_WITH_GENEC) list(APPEND SOURCES lib/tls/mbedtls/lws-genec.c @@ -1050,6 +1056,11 @@ if (LWS_WITH_SSL) lib/tls/openssl/lws-genrsa.c ) endif() + if (LWS_WITH_GENAES) + list(APPEND SOURCES + lib/tls/openssl/lws-genaes.c + ) + endif() if (LWS_WITH_GENEC) list(APPEND SOURCES lib/tls/openssl/lws-genec.c diff --git a/README.md b/README.md index 2ae78a8d7..d1c64b76c 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,12 @@ News ## New features on master + - **lws-genaes Generic AES crypto** - thin api layer works identically with both mbedtls and openssl + backends. Supports CBC, CFB128, CFB8, CTR, ECB, OFB, XTS and GCM variants. Unit tests in CI. + [genaes api](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genaes.h), + [api test](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-gencrypto), + CMake config: `-DLWS_WITH_GENAES=1` + - **http fallback support** - you can specify a role and protocol to apply if non-http or non-tls packets arrive at an http(s) listen port. For example, you can specify that the new `raw proxy` role + protocol should be used, to proxy your sshd port over :443 or :80. Without affecting diff --git a/READMEs/README.crypto-apis.md b/READMEs/README.crypto-apis.md index 193c801f6..e82a6980a 100644 --- a/READMEs/README.crypto-apis.md +++ b/READMEs/README.crypto-apis.md @@ -23,9 +23,27 @@ All the necessary includes are part of `libwebsockets.h`. |---|---|---|---| |genhash|`LWS_WITH_GENHASH`|[./include/libwebsockets/lws-genhash.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genhash.h)|Provides SHA1 + SHA2 hashes and hmac| |genrsa|`LWS_WITH_GENRSA`|[./include/libwebsockets/lws-genrsa.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genrsa.h)|Provides RSA encryption, decryption, signing, verification, key generation and creation| +|genaes|`LWS_WITH_GENAES`|[./include/libwebsockets/lws-genaes.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-genaes.h)|Provides AES in all common variants for encryption and decryption| Unit tests for these apis, which serve as usage examples, can be found in [./minimal-examples/api-tests/api-test-gencrypto](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-gencrypto) +### Keys in the generic layer + +The necessary types and defines are brought in by `libwebsockets.h`. + +Keys are represented only by an array of `struct lws_jwk_elements`... the +length of the array is defined by the cipher... it's one of + +|key elements count|definition| +|---|---| +|`LWS_COUNT_OCT_KEY_ELEMENTS`|1| +|`LWS_COUNT_RSA_KEY_ELEMENTS`|8| +|`LWS_COUNT_EC_KEY_ELEMENTS`|4| +|`LWS_COUNT_AES_KEY_ELEMENTS`|1| + +`struct lws_jwk_elements` is a simple pointer / length combination used to +store arbitrary octets that make up the key element's binary representation. + ## Using the JOSE layer All the necessary includes are part of `libwebsockets.h`. @@ -38,3 +56,19 @@ All the necessary includes are part of `libwebsockets.h`. Unit tests for these apis, which serve as usage examples, can be found in [./minimal-examples/api-tests/api-test-jose](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/api-tests/api-test-jose) +### Keys in the JOSE layer + +Keys in the JOSE layer use a `struct lws_jwk`, this contains two arrays of +`struct lws_jwk_elements` sized for the worst case (currently RSA). One +array contains the key elements as described for the generic case, and the +other contains various key metadata taken from JWK JSON. + +|metadata index|function| +|---|---| +|`JWK_META_KTY`|Key type, eg, "EC"| +|`JWK_META_KID`|Arbitrary ID string| +|`JWK_META_USE`|What the public key may be used to validate, "enc" or "sig"| +|`JWK_META_KEY_OPS`|Which operations the key is authorized for, eg, "encrypt"| +|`JWK_META_X5C`|Optional X.509 cert version of the key| +|`JWK_META_ALG`|Optional overall crypto algorithm the key is intended for use with| + diff --git a/READMEs/README-plugin-sshd-base.md b/READMEs/README.plugin-sshd-base.md similarity index 100% rename from READMEs/README-plugin-sshd-base.md rename to READMEs/README.plugin-sshd-base.md diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index ee2f4f800..a0ae900dd 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -70,6 +70,9 @@ #cmakedefine LWS_WITH_CGI #cmakedefine LWS_WITH_ESP32 #cmakedefine LWS_WITH_FTS +#cmakedefine LWS_WITH_GENRSA +#cmakedefine LWS_WITH_GENHASH +#cmakedefine LWS_WITH_GENAES #cmakedefine LWS_WITH_HTTP2 #cmakedefine LWS_WITH_HTTP_BROTLI #cmakedefine LWS_WITH_HTTP_PROXY diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 831904f3a..0052bcbd9 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -426,6 +426,7 @@ struct lws; #include #include #include +#include #include #endif diff --git a/include/libwebsockets/lws-genaes.h b/include/libwebsockets/lws-genaes.h new file mode 100644 index 000000000..5ea734eb7 --- /dev/null +++ b/include/libwebsockets/lws-genaes.h @@ -0,0 +1,161 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2018 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * included from libwebsockets.h + */ + +/*! \defgroup generic AES + * ## Generic AES related functions + * + * Lws provides generic AES functions that abstract the ones + * provided by whatever tls library you are linking against. + * + * It lets you use the same code if you build against mbedtls or OpenSSL + * for example. + */ +///@{ + +#if defined(LWS_WITH_MBEDTLS) +#include +#include +#endif + +enum enum_aes_modes { + LWS_GAESM_CBC, + LWS_GAESM_CFB128, + LWS_GAESM_CFB8, + LWS_GAESM_CTR, + LWS_GAESM_ECB, + LWS_GAESM_OFB, + LWS_GAESM_XTS, /* care... requires double-length key */ + LWS_GAESM_GCM, +}; + +enum enum_aes_operation { + LWS_GAESO_ENC, + LWS_GAESO_DEC +}; + +/* include/libwebsockets/lws-jwk.h must be included before this */ + +#define LWS_AES_BLOCKSIZE 128 + +struct lws_genaes_ctx { +#if defined(LWS_WITH_MBEDTLS) + union { + mbedtls_aes_context ctx; +#if defined(MBEDTLS_CIPHER_MODE_XTS) + mbedtls_aes_xts_context ctx_xts; +#endif + mbedtls_gcm_context ctx_gcm; + } u; +#else + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + ENGINE *engine; + char init; +#endif + unsigned char tag[16]; + struct lws_jwk_elements *k; + enum enum_aes_operation op; + enum enum_aes_modes mode; + int taglen; + char underway; +}; + +/** lws_genaes_create() - Create RSA public decrypt context + * + * \param ctx: your struct lws_genaes_ctx + * \param op: LWS_GAESO_ENC or LWS_GAESO_DEC + * \param mode: one of LWS_GAESM_ + * \param el: struct prepared with key element data + * \param padding: 0 = no padding, 1 = padding + * \param engine: if openssl engine used, pass the pointer here + * + * Creates an RSA context with a public key associated with it, formed from + * the key elements in \p el. + * + * Returns 0 for OK or nonzero for error. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, + enum enum_aes_modes mode, struct lws_jwk_elements *el, + int padding, void *engine); + +/** lws_genaes_destroy() - Destroy genaes AES context + * + * \param ctx: your struct lws_genaes_ctx + * \param tag: NULL, or, GCM-only: buffer to receive tag + * \param tlen: 0, or, GCM-only: length of tag buffer + * + * Destroys any allocations related to \p ctx. + * + * For GCM only, up to tlen bytes of tag buffer will be set on exit. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen); + +/** lws_genaes_crypt() - Encrypt or decrypt + * + * \param ctx: your struct lws_genaes_ctx + * \param op: LWS_GAESO_ENC or LWS_GAESO_DEC + * \param iv_or_nonce_ctr_or_data_unit_16: NULL, iv, nonce_ctr16, or data_unit16 + * \param stream_block_16: pointer to 16-byte stream block for CTR mode only + * \param nc_or_iv_off: NULL or pointer to nc, or iv_off + * \param in: input plaintext or ciphertext + * \param len: length of input (which is always length of output) + * \param out: output plaintext or ciphertext + * + * Encrypts or decrypts using the AES mode set when the ctx was created. + * The last three arguments have different meanings depending on the mode: + * + * CBC CFB128 CFB8 CTR ECB OFB XTS + * iv_or_nonce_ctr_or_data_unit_16 : iv iv iv nonce NULL iv dataunt + * stream_block_16 : NULL NULL NULL stream NULL NULL NULL + * nc_or_iv_off : NULL iv_off NULL nc_off NULL iv_off NULL + * + * For GCM: + * + * iv_or_nonce_ctr_or_data_unit_16 : iv + * stream_block_16 : pointer to tag + * nc_or_iv_off : set pointed-to size_t to iv length + * in : first call: additional data, subsequently + * : input data + * len : first call: add data length, subsequently + * : input / output length + * + * The length of the optional arg is always 16 if used, regardless of the mode. + * + * Returns 0 for OK or nonzero for error. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, + uint8_t *out, + uint8_t *iv_or_nonce_ctr_or_data_unit_16, + uint8_t *stream_block_16, + size_t *nc_or_iv_off, int taglen); + +///@} diff --git a/include/libwebsockets/lws-jwk.h b/include/libwebsockets/lws-jwk.h index d4c846844..5dd0e777b 100644 --- a/include/libwebsockets/lws-jwk.h +++ b/include/libwebsockets/lws-jwk.h @@ -71,12 +71,18 @@ enum enum_jwk_rsa_tok { enum enum_jwk_ec_tok { JWK_EC_KEYEL_CRV, JWK_EC_KEYEL_X, - JWK_EC_KEYEL_D, /* note... same offset as RSA D */ + JWK_EC_KEYEL_D = JWK_RSA_KEYEL_D, /* note... same offset as RSA D */ JWK_EC_KEYEL_Y, LWS_COUNT_EC_KEY_ELEMENTS }; +enum enum_jwk_aes_tok { + JWK_EC_KEYEL_K = JWK_OCT_KEYEL_K, + + LWS_COUNT_AES_KEY_ELEMENTS +}; + enum enum_jwk_meta_tok { JWK_META_KTY, JWK_META_KID, diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index d84415c28..6bb446193 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -715,6 +715,9 @@ LWS_VISIBLE LWS_EXTERN SSL* lws_get_ssl(struct lws *wsi); #endif +LWS_VISIBLE LWS_EXTERN void +lws_explicit_bzero(void *p, size_t len); + /** \defgroup smtp SMTP related functions * ##SMTP related functions * \ingroup lwsapi diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 35218a385..91dc77a43 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -1437,6 +1437,15 @@ lws_get_network_wsi(struct lws *wsi) return wsi; } +LWS_VISIBLE void +lws_explicit_bzero(void *p, size_t len) +{ + volatile uint8_t *vp = p; + + while (len--) + *vp++ = 0; +} + LWS_VISIBLE int LWS_WARN_UNUSED_RESULT lws_raw_transaction_completed(struct lws *wsi) diff --git a/lib/jose/jwk/jwk.c b/lib/jose/jwk/jwk.c index a216697f7..ee051366c 100644 --- a/lib/jose/jwk/jwk.c +++ b/lib/jose/jwk/jwk.c @@ -43,7 +43,7 @@ static const char * const jwk_tok[] = { "keys[]", /* dummy */ "e", "n", "d", "p", "q", "dp", "dq", "qi", /* RSA */ "kty", /* generic */ - "k", /* symmetric oct key data */ + "k", /* symmetric key data */ "crv", "x", "y", /* EC (also "D") */ "kid", /* generic */ "use" /* mutually exclusive with "key_ops" */, diff --git a/lib/tls/mbedtls/lws-genaes.c b/lib/tls/mbedtls/lws-genaes.c new file mode 100644 index 000000000..392e685b4 --- /dev/null +++ b/lib/tls/mbedtls/lws-genaes.c @@ -0,0 +1,242 @@ +/* + * libwebsockets - generic AES api hiding the backend + * + * Copyright (C) 2017 - 2018 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * lws_genaes provides an abstraction api for AES in lws that works the + * same whether you are using openssl or mbedtls hash functions underneath. + */ +#include "core/private.h" +#include "../../jose/private.h" + +static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT }; + +LWS_VISIBLE int +lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, + enum enum_aes_modes mode, struct lws_jwk_elements *el, + int padding, void *engine) +{ + int n; + + ctx->mode = mode; + ctx->k = el; + ctx->op = operation_map[op]; + ctx->underway = 0; + + switch (ctx->mode) { + case LWS_GAESM_XTS: + mbedtls_aes_xts_init(&ctx->u.ctx_xts); + break; + case LWS_GAESM_GCM: + mbedtls_gcm_init(&ctx->u.ctx_gcm); + n = mbedtls_gcm_setkey(&ctx->u.ctx_gcm, MBEDTLS_CIPHER_ID_AES, + ctx->k->buf, ctx->k->len * 8); + if (n) { + lwsl_notice("%s: mbedtls_gcm_setkey: -0x%x\n", + __func__, -n); + return n; + } + return n; + default: + mbedtls_aes_init(&ctx->u.ctx); + break; + } + + switch (op) { + case LWS_GAESO_ENC: + if (ctx->mode == LWS_GAESM_XTS) +#if defined(MBEDTLS_CIPHER_MODE_XTS) + n = mbedtls_aes_xts_setkey_enc(&ctx->u.ctx_xts, + ctx->k->buf, + ctx->k->len * 8); +#else + return -1; +#endif + else + n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf, + ctx->k->len * 8); + break; + case LWS_GAESO_DEC: + switch (ctx->mode) { + case LWS_GAESM_XTS: +#if defined(MBEDTLS_CIPHER_MODE_XTS) + n = mbedtls_aes_xts_setkey_dec(&ctx->u.ctx_xts, + ctx->k->buf, + ctx->k->len * 8); + break; +#else + return -1; +#endif + + case LWS_GAESM_CFB128: + case LWS_GAESM_CFB8: + case LWS_GAESM_CTR: + case LWS_GAESM_OFB: + n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf, + ctx->k->len * 8); + break; + default: + n = mbedtls_aes_setkey_dec(&ctx->u.ctx, ctx->k->buf, + ctx->k->len * 8); + break; + } + break; + } + + if (n) + lwsl_notice("%s: setting key: -0x%x\n", __func__, -n); + + return n; +} + +LWS_VISIBLE int +lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen) +{ + int n; + + if (ctx->mode == LWS_GAESM_GCM) { + if (tag) { + n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, tag, tlen); + if (n) + lwsl_notice("%s: mbedtls_gcm_finish: -0x%x\n", + __func__, -n); + else + if (memcmp(ctx->tag, tag, ctx->taglen)) { + lwsl_err("%s: lws_genaes_crypt tag " + "mismatch (bad first)\n", + __func__); + lwsl_hexdump_notice(tag, tlen); + lwsl_hexdump_notice(ctx->tag, ctx->taglen); + n = -1; + } + } + mbedtls_gcm_free(&ctx->u.ctx_gcm); + return n; + } + if (ctx->mode == LWS_GAESM_XTS) +#if defined(MBEDTLS_CIPHER_MODE_XTS) + mbedtls_aes_xts_free(&ctx->u.ctx_xts); +#else + return -1; +#endif + else + mbedtls_aes_free(&ctx->u.ctx); + + return 0; +} + +LWS_VISIBLE int +lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, + uint8_t *out, uint8_t *iv_or_nonce_ctr_or_data_unit_16, + uint8_t *stream_block_16, size_t *nc_or_iv_off, int taglen) +{ + uint8_t iv[16], sb[16]; + int n; + + switch (ctx->mode) { + case LWS_GAESM_CBC: + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + n = mbedtls_aes_crypt_cbc(&ctx->u.ctx, ctx->op, len, iv, + in, out); + break; + + case LWS_GAESM_CFB128: + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + n = mbedtls_aes_crypt_cfb128(&ctx->u.ctx, ctx->op, len, + nc_or_iv_off, iv, in, out); + break; + + case LWS_GAESM_CFB8: + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + n = mbedtls_aes_crypt_cfb8(&ctx->u.ctx, ctx->op, len, iv, + in, out); + break; + + case LWS_GAESM_CTR: + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + memcpy(sb, stream_block_16, 16); + n = mbedtls_aes_crypt_ctr(&ctx->u.ctx, len, nc_or_iv_off, + iv, sb, in, out); + memcpy(iv_or_nonce_ctr_or_data_unit_16, iv, 16); + memcpy(stream_block_16, sb, 16); + break; + + case LWS_GAESM_ECB: + n = mbedtls_aes_crypt_ecb(&ctx->u.ctx, ctx->op, in, out); + break; + + case LWS_GAESM_OFB: + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + n = mbedtls_aes_crypt_ofb(&ctx->u.ctx, len, nc_or_iv_off, iv, + in, out); + break; + + case LWS_GAESM_XTS: +#if defined(MBEDTLS_CIPHER_MODE_XTS) + memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); + n = mbedtls_aes_crypt_xts(&ctx->u.ctx_xts, ctx->op, len, iv, + in, out); + break; +#else + return -1; +#endif + case LWS_GAESM_GCM: + if (!ctx->underway) { + ctx->underway = 1; + + memcpy(ctx->tag, stream_block_16, taglen); + ctx->taglen = taglen; + + /* + * iv: iv_or_nonce_ctr_or_data_unit_16 + * iv_len: *nc_or_iv_off + * stream_block_16: pointer to tag + * additional data: in + * additional data len: len + */ + + n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, ctx->op, + iv_or_nonce_ctr_or_data_unit_16, + *nc_or_iv_off, in, len); + if (n) { + lwsl_notice("%s: mbedtls_gcm_starts: -0x%x\n", + __func__, -n); + + return -1; + } + break; + } + + n = mbedtls_gcm_update(&ctx->u.ctx_gcm, len, in, out); + if (n) { + lwsl_notice("%s: mbedtls_gcm_update: -0x%x\n", + __func__, -n); + + return -1; + } + break; + } + + if (n) { + lwsl_notice("%s: enc: -0x%x, len %d\n", __func__, -n, (int)len); + + return -1; + } + + return 0; +} diff --git a/lib/tls/mbedtls/lws-genrsa.c b/lib/tls/mbedtls/lws-genrsa.c index 937ed6927..ebf36798d 100644 --- a/lib/tls/mbedtls/lws-genrsa.c +++ b/lib/tls/mbedtls/lws-genrsa.c @@ -18,16 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * - * lws_genhash provides a hash / hmac abstraction api in lws that works the + * lws_genrsa provides an RSA abstraction api in lws that works the * same whether you are using openssl or mbedtls hash functions underneath. */ #include "core/private.h" -#include "../../jose/private.h" LWS_VISIBLE void lws_jwk_destroy_genrsa_elements(struct lws_jwk_elements *el) { - lws_jwk_destroy_elements(el, LWS_COUNT_RSA_KEY_ELEMENTS); + int n; + + for (n = 0; n < LWS_COUNT_RSA_KEY_ELEMENTS; n++) + if (el[n].buf) + lws_free_set_NULL(el[n].buf); } LWS_VISIBLE int diff --git a/lib/tls/openssl/lws-genaes.c b/lib/tls/openssl/lws-genaes.c new file mode 100644 index 000000000..47c87b051 --- /dev/null +++ b/lib/tls/openssl/lws-genaes.c @@ -0,0 +1,313 @@ +/* + * libwebsockets - generic AES api hiding the backend + * + * Copyright (C) 2017 - 2018 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * lws_genaes provides an AES abstraction api in lws that works the + * same whether you are using openssl or mbedtls hash functions underneath. + */ +#include "core/private.h" +#include "../../jose/private.h" + +/* + * Care: many openssl apis return 1 for success. These are translated to the + * lws convention of 0 for success. + */ + +LWS_VISIBLE int +lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, + enum enum_aes_modes mode, struct lws_jwk_elements *el, + int padding, void *engine) +{ + int n; + + ctx->ctx = EVP_CIPHER_CTX_new(); + if (!ctx->ctx) + return -1; + + ctx->mode = mode; + ctx->k = el; + ctx->engine = engine; + ctx->init = 0; + ctx->op = op; + + switch (ctx->k->len) { + case 128 / 8: + switch (mode) { + case LWS_GAESM_CBC: + ctx->cipher = EVP_aes_128_cbc(); + break; + case LWS_GAESM_CFB128: + ctx->cipher = EVP_aes_128_cfb128(); + break; + case LWS_GAESM_CFB8: + ctx->cipher = EVP_aes_128_cfb8(); + break; + case LWS_GAESM_CTR: + ctx->cipher = EVP_aes_128_ctr(); + break; + case LWS_GAESM_ECB: + ctx->cipher = EVP_aes_128_ecb(); + break; + case LWS_GAESM_OFB: + ctx->cipher = EVP_aes_128_ofb(); + break; + case LWS_GAESM_XTS: + lwsl_err("%s: AES XTS requires double-length key\n", + __func__); + break; + case LWS_GAESM_GCM: + ctx->cipher = EVP_aes_128_gcm(); + break; + default: + return -1; + } + break; + + case 192 / 8: + switch (mode) { + case LWS_GAESM_CBC: + ctx->cipher = EVP_aes_192_cbc(); + break; + case LWS_GAESM_CFB128: + ctx->cipher = EVP_aes_192_cfb128(); + break; + case LWS_GAESM_CFB8: + ctx->cipher = EVP_aes_192_cfb8(); + break; + case LWS_GAESM_CTR: + ctx->cipher = EVP_aes_192_ctr(); + break; + case LWS_GAESM_ECB: + ctx->cipher = EVP_aes_192_ecb(); + break; + case LWS_GAESM_OFB: + ctx->cipher = EVP_aes_192_ofb(); + break; + case LWS_GAESM_XTS: + lwsl_err("%s: AES XTS 192 invalid\n", __func__); + return -1; + case LWS_GAESM_GCM: + ctx->cipher = EVP_aes_192_gcm(); + break; + default: + return -1; + } + break; + + case 256 / 8: + switch (mode) { + case LWS_GAESM_CBC: + ctx->cipher = EVP_aes_256_cbc(); + break; + case LWS_GAESM_CFB128: + ctx->cipher = EVP_aes_256_cfb128(); + break; + case LWS_GAESM_CFB8: + ctx->cipher = EVP_aes_256_cfb8(); + break; + case LWS_GAESM_CTR: + ctx->cipher = EVP_aes_256_ctr(); + break; + case LWS_GAESM_ECB: + ctx->cipher = EVP_aes_256_ecb(); + break; + case LWS_GAESM_OFB: + ctx->cipher = EVP_aes_256_ofb(); + break; + case LWS_GAESM_XTS: + ctx->cipher = EVP_aes_128_xts(); + break; + case LWS_GAESM_GCM: + ctx->cipher = EVP_aes_256_gcm(); + break; + default: + return -1; + } + break; + + case 512 / 8: + switch (mode) { + case LWS_GAESM_XTS: + ctx->cipher = EVP_aes_256_xts(); + break; + default: + return -1; + } + break; + + default: + lwsl_err("%s: unsupported AES size %d bits\n", __func__, + ctx->k->len * 8); + return -1; + } + + switch (ctx->op) { + case LWS_GAESO_ENC: + n = EVP_EncryptInit_ex(ctx->ctx, ctx->cipher, ctx->engine, + NULL, NULL); + EVP_CIPHER_CTX_set_padding(ctx->ctx, padding); + break; + case LWS_GAESO_DEC: + n = EVP_DecryptInit_ex(ctx->ctx, ctx->cipher, ctx->engine, + NULL, NULL); + EVP_CIPHER_CTX_set_padding(ctx->ctx, padding); + break; + } + if (!n) { + lwsl_err("%s: cipher init failed (cipher %p)\n", __func__, + ctx->cipher); + + return -1; + } + + return 0; +} + +LWS_VISIBLE int +lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen) +{ + int outl = 0, n = 0; + uint8_t buf[256]; + + if (!ctx->ctx) + return 0; + + if (ctx->init) { + switch (ctx->op) { + case LWS_GAESO_ENC: + + if (EVP_EncryptFinal_ex(ctx->ctx, buf, &outl) != 1) { + lwsl_err("%s: enc final failed\n", __func__); + n = -1; + } + if (ctx->mode == LWS_GAESM_GCM) { + memset(tag, 0, tlen); + if (EVP_CIPHER_CTX_ctrl(ctx->ctx, + EVP_CTRL_GCM_GET_TAG, + ctx->taglen, tag) != 1) { + lwsl_err("get tag ctrl failed\n"); + lws_tls_err_describe(); + n = 1; + } else + if (memcmp(tag, ctx->tag, ctx->taglen)) { + lwsl_err("%s: tag mismatch " + "(bad first)\n", __func__); + lws_tls_err_describe(); + lwsl_hexdump_notice(tag, tlen); + lwsl_hexdump_notice(ctx->tag, ctx->taglen); + n = -1; + } + } + break; + case LWS_GAESO_DEC: + if (EVP_DecryptFinal_ex(ctx->ctx, buf, &outl) != 1) { + lwsl_err("%s: dec final failed\n", __func__); + lws_tls_err_describe(); + n = -1; + } + break; + } + if (outl) + lwsl_debug("%s: final len %d\n", __func__, outl); + } + + ctx->k = NULL; + EVP_CIPHER_CTX_free(ctx->ctx); + ctx->ctx = NULL; + + return n; +} + +LWS_VISIBLE int +lws_genaes_crypt(struct lws_genaes_ctx *ctx, + const uint8_t *in, size_t len, uint8_t *out, + uint8_t *iv_or_nonce_ctr_or_data_unit_16, + uint8_t *stream_block_16, size_t *nc_or_iv_off, int taglen) +{ + int n, outl, olen; + + if (!ctx->init) { + + EVP_CIPHER_CTX_set_key_length(ctx->ctx, ctx->k->len); + + if (ctx->mode == LWS_GAESM_GCM) { + EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, + *nc_or_iv_off, NULL); + memcpy(ctx->tag, stream_block_16, taglen); + ctx->taglen = taglen; + } + + switch (ctx->op) { + case LWS_GAESO_ENC: + n = EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, + ctx->k->buf, + iv_or_nonce_ctr_or_data_unit_16); + break; + case LWS_GAESO_DEC: + if (ctx->mode == LWS_GAESM_GCM) + EVP_CIPHER_CTX_ctrl(ctx->ctx, + EVP_CTRL_CCM_SET_TAG, + ctx->taglen, ctx->tag); + n = EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, + ctx->k->buf, + iv_or_nonce_ctr_or_data_unit_16); + break; + } + + if (!n) { + lwsl_err("%s: init failed (cipher %p)\n", + __func__, ctx->cipher); + + return -1; + } + ctx->init = 1; + if (ctx->mode == LWS_GAESM_GCM) { + /* AAD */ + if (len) + if (EVP_EncryptUpdate(ctx->ctx, NULL, &olen, + in, len) != 1) { + lwsl_err("%s: set aad failed\n", + __func__); + + return -1; + } + + return 0; + } + } + + switch (ctx->op) { + case LWS_GAESO_ENC: + n = EVP_EncryptUpdate(ctx->ctx, out, &outl, in, len); + break; + case LWS_GAESO_DEC: + n = EVP_DecryptUpdate(ctx->ctx, out, &outl, in, len); + break; + } + + // lwsl_notice("discarding outl %d\n", (int)outl); + + if (!n) { + lwsl_notice("%s: update failed\n", __func__); + + return -1; + } + + return 0; +} diff --git a/lib/tls/openssl/lws-genrsa.c b/lib/tls/openssl/lws-genrsa.c index 8bb52bf0b..ce9c94776 100644 --- a/lib/tls/openssl/lws-genrsa.c +++ b/lib/tls/openssl/lws-genrsa.c @@ -18,16 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * - * lws_genhash provides a hash / hmac abstraction api in lws that works the + * lws_genrsa provides an RSA abstraction api in lws that works the * same whether you are using openssl or mbedtls hash functions underneath. */ #include "core/private.h" -#include "../../jose/private.h" LWS_VISIBLE void lws_jwk_destroy_genrsa_elements(struct lws_jwk_elements *el) { - lws_jwk_destroy_elements(el, LWS_COUNT_RSA_KEY_ELEMENTS); + int n; + + for (n = 0; n < LWS_COUNT_RSA_KEY_ELEMENTS; n++) + if (el[n].buf) + lws_free_set_NULL(el[n].buf); } LWS_VISIBLE int diff --git a/lib/tls/private.h b/lib/tls/private.h index ad01bfd4f..b9536be09 100644 --- a/lib/tls/private.h +++ b/lib/tls/private.h @@ -50,11 +50,15 @@ #undef MBEDTLS_CONFIG_FILE #define MBEDTLS_CONFIG_FILE #include + #include + #include #include #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */ #else /* not esp32 */ #if defined(LWS_WITH_MBEDTLS) #include + #include + #include #include #include #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */ @@ -66,6 +70,7 @@ #include #include #include + #include #ifdef LWS_HAVE_OPENSSL_ECDH_H #include #endif diff --git a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt new file mode 100644 index 000000000..a36a5cda8 --- /dev/null +++ b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) + +set(SAMP lws-api-test-gencrypto) +set(SRCS main.c lws-genaes.c) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + endif() +ENDMACRO() + +set(requirements 1) +require_lws_config(LWS_WITH_GENAES 1 requirements) + +if (requirements) + + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() +endif() + diff --git a/minimal-examples/api-tests/api-test-gencrypto/README.md b/minimal-examples/api-tests/api-test-gencrypto/README.md new file mode 100644 index 000000000..ab8ff0bea --- /dev/null +++ b/minimal-examples/api-tests/api-test-gencrypto/README.md @@ -0,0 +1,26 @@ +# lws api test gencrypto + +Demonstrates how to use and performs selftests for Generic Crypto, +which works the same whether the tls backend is OpenSSL or mbedTLS + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` + $ ./lws-api-test-gencrypto +[2018/12/05 08:30:27:1342] USER: LWS gencrypto apis tests +[2018/12/05 08:30:27:1343] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 off +[2018/12/05 08:30:27:1343] NOTICE: created client ssl context for default +[2018/12/05 08:30:27:1344] NOTICE: test_genaes: selftest OK +[2018/12/05 08:30:27:1344] USER: Completed: PASS +``` + diff --git a/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c b/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c new file mode 100644 index 000000000..634912518 --- /dev/null +++ b/minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c @@ -0,0 +1,788 @@ +/* + * lws-api-test-gencrypto - lws-genaes + * + * Copyright (C) 2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include + +static const uint8_t + /* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes256 \ + * -K "0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210" \ + * -iv "0123456789abcdeffedcba9876543210" + * -in plaintext.txt -out out.enc + * + */ + *cbc256 = (uint8_t *)"test plaintext\0\0", + cbc256_enc[] = { + 0x2b, 0x5d, 0xb2, 0xa8, 0x5a, 0x5a, 0xf4, 0x2e, + 0xf7, 0xf9, 0xc5, 0x3c, 0x73, 0xef, 0x40, 0x88, + }, cbc256_iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }, cbc256_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + } +; + +static int +test_genaes_cbc(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + + /* + * As part of a jwk, these are allocated. But here we just use one as + * a wrapper on a static binary key. + */ + e.buf = (uint8_t *)cbc256_key; + e.len = sizeof(cbc256_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_CBC, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, cbc256, 16, res, (uint8_t *)cbc256_iv, + NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy enc failed\n", __func__); + return -1; + } + + if (memcmp(cbc256_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_CBC, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, (uint8_t *)cbc256_iv, + NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy dec failed\n", __func__); + lwsl_hexdump_notice(res1, 16); + return -1; + } + + if (memcmp(cbc256, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t +/* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes-128-cfb \ + * -K "0123456789abcdeffedcba9876543210" \ + * -iv "0123456789abcdeffedcba9876543210" + * -in plaintext.txt -out out.enc + * + */ +*cfb128 = (uint8_t *)"test plaintext\0\0", +cfb128_enc[] = { + 0xd2, 0x11, 0x86, 0xd7, 0xa9, 0x55, 0x59, 0x04, + 0x4f, 0x63, 0x7c, 0xb9, 0xc6, 0xa1, 0xc9, 0x71 +}, cfb128_iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}, cfb128_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static int +test_genaes_cfb128(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + size_t iv_off = 0; + + e.buf = (uint8_t *)cfb128_key; + e.len = sizeof(cfb128_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_CFB128, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, cfb128, 16, res, (uint8_t *)cfb128_iv, + NULL, &iv_off, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(cfb128_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + iv_off = 0; + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_CFB128, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, (uint8_t *)cfb128_iv, + NULL, &iv_off, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(cfb128, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res1, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t +/* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes-128-cfb8 \ + * -K "0123456789abcdeffedcba9876543210" \ + * -iv "0123456789abcdeffedcba9876543210" + * -in plaintext.txt -out out.enc + * + */ +*cfb8 = (uint8_t *)"test plaintext\0\0", +cfb8_enc[] = { + 0xd2, 0x91, 0x06, 0x2d, 0x1b, 0x1e, 0x9b, 0x39, + 0xa6, 0x65, 0x8e, 0xbe, 0x68, 0x32, 0x3d, 0xab +}, cfb8_iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}, cfb8_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static int +test_genaes_cfb8(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + + e.buf = (uint8_t *)cfb8_key; + e.len = sizeof(cfb8_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_CFB8, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, cfb8, 16, res, (uint8_t *)cfb8_iv, + NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(cfb8_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_CFB8, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, (uint8_t *)cfb8_iv, + NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(cfb8, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res1, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t +/* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes-128-ctr \ + * -K "0123456789abcdeffedcba9876543210" \ + * -iv "0123456789abcdeffedcba9876543210" + * -in plaintext.txt -out out.enc + * + */ +*ctr = (uint8_t *)"test plaintext\0\0", +ctr_enc[] = { + 0xd2, 0x11, 0x86, 0xd7, 0xa9, 0x55, 0x59, 0x04, + 0x4f, 0x63, 0x7c, 0xb9, 0xc6, 0xa1, 0xc9, 0x71 +}, ctr_iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}, ctr_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static int +test_genaes_ctr(void) +{ + uint8_t nonce_counter[16], sb[16]; + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + size_t nc_off = 0; + + e.buf = (uint8_t *)ctr_key; + e.len = sizeof(ctr_key); + + memset(sb, 0, sizeof(nonce_counter)); + memcpy(nonce_counter, ctr_iv, sizeof(ctr_iv)); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_CTR, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, ctr, 16, res, nonce_counter, sb, &nc_off, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ctr_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + nc_off = 0; + memset(sb , 0, sizeof(nonce_counter)); + memcpy(nonce_counter, ctr_iv, sizeof(ctr_iv)); + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_CTR, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, nonce_counter, sb, &nc_off, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ctr, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res1, 16); + return -1; + } + + lws_explicit_bzero(sb, sizeof(sb)); + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t +/* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes-128-ecb \ + * -K "0123456789abcdeffedcba9876543210" \ + * -in plaintext.txt -out out.enc + * + */ +*ecb = (uint8_t *)"test plaintext\0\0", +ecb_enc[] = { + 0xf3, 0xe5, 0x6c, 0x80, 0x3a, 0xf1, 0xc4, 0xa0, + 0x7e, 0xdf, 0x86, 0x0f, 0x6d, 0xca, 0x5d, 0x36, + 0x17, 0x22, 0x37, 0x42, 0x47, 0x41, 0x67, 0x7d, + 0x99, 0x25, 0x02, 0x6b, 0x6b, 0x8f, 0x9c, 0x7f +}, ecb_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static int +test_genaes_ecb(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + + /* + * As part of a jwk, these are allocated. But here we just use one as + * a wrapper on a static binary key. + */ + e.buf = (uint8_t *)ecb_key; + e.len = sizeof(ecb_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_ECB, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, ecb, 16, res, NULL, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ecb_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_ECB, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, NULL, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ecb, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t + /* + * produced with (plaintext.txt contains "test plaintext\0\0") + * + * openssl enc -aes-128-ofb \ + * -K "0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210" \ + * -iv "0123456789abcdeffedcba9876543210" + * -in plaintext.txt -out out.enc + * + */ + *ofb = (uint8_t *)"test plaintext\0\0", + ofb_enc[] = { + /* !!! ugh... openssl app produces this... */ + // 0xd2, 0x11, 0x86, 0xd7, 0xa9, 0x55, 0x59, 0x04, + // 0x4f, 0x63, 0x7c, 0xb9, 0xc6, 0xa1, 0xc9, 0x71, + /* but both OpenSSL and mbedTLS produce this */ + 0x11, 0x33, 0x6D, 0xFC, 0x88, 0x4C, 0x28, 0xBA, + 0xD0, 0xF2, 0x6C, 0xBC, 0xDE, 0x4A, 0x56, 0x20 + }, ofb_iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }, ofb_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + } +; + +static int +test_genaes_ofb(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32]; + size_t iv_off = 0; + + e.buf = (uint8_t *)ofb_key; + e.len = sizeof(ofb_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_OFB, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, ofb, 16, res, (uint8_t *)ofb_iv, NULL, + &iv_off, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ofb_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + iv_off = 0; + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_OFB, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, (uint8_t *)ofb_iv, NULL, + &iv_off, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(ofb, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t + /* + * Fedora openssl tool doesn't support xts... this data produced + * by testing on mbedtls + OpenSSL and getting the same result + * + * NOTICE that xts requires a double-length key... + */ + *xts = (uint8_t *)"test plaintext\0\0", + xts_enc[] = { + 0xA9, 0x26, 0xFD, 0x68, 0x1E, 0x6A, 0x80, 0xCA, + 0x18, 0xD5, 0xEB, 0x08, 0x23, 0xF1, 0x90, 0x15 + }, xts_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + } +; + +static int +test_genaes_xts(void) +{ + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + uint8_t res[32], res1[32], data_unit[16]; + + memset(data_unit, 0, sizeof(data_unit)); + + e.buf = (uint8_t *)xts_key; + e.len = sizeof(xts_key); + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_XTS, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + if (lws_genaes_crypt(&ctx, xts, 16, res, data_unit, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(xts_enc, res, 16)) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_XTS, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create dec failed\n", __func__); + return -1; + } + + if (lws_genaes_crypt(&ctx, res, 16, res1, data_unit, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt dec failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, NULL, 0)) { + lwsl_err("%s: lws_genaes_destroy failed\n", __func__); + return -1; + } + + if (memcmp(xts, res1, 16)) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res, 16); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +static const uint8_t + /* + * https://csrc.nist.gov/CSRC/media/Projects/ + * Cryptographic-Algorithm-Validation-Program/ + * documents/mac/gcmtestvectors.zip + */ + + gcm_ct[] = { + 0xf7, 0x26, 0x44, 0x13, 0xa8, 0x4c, 0x0e, 0x7c, + 0xd5, 0x36, 0x86, 0x7e, 0xb9, 0xf2, 0x17, 0x36 + }, gcm_iv[] = { + 0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, + 0xee, 0xd0, 0x66, 0x84 + }, gcm_key[] = { + 0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, + 0x1c, 0x04, 0x65, 0x66, 0x5f, 0x8a, 0xe6, 0xd1, + 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69, + 0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f + }, gcm_pt[] = { + 0xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e, + 0xeb, 0x31, 0xb2, 0xea, 0xcc, 0x2b, 0xf2, 0xa5 + }, gcm_aad[] = { + 0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, + 0xdb, 0x37, 0x0c, 0x43, 0x7f, 0xec, 0x78, 0xde + }, gcm_tag[] = { + 0x67, 0xba, 0x05, 0x10, 0x26, 0x2a, 0xe4, 0x87, + 0xd7, 0x37, 0xee, 0x62, 0x98, 0xf7, 0x7e, 0x0c + }; + +static int +test_genaes_gcm(void) +{ + uint8_t res[sizeof(gcm_ct)], tag[sizeof(gcm_tag)]; + struct lws_genaes_ctx ctx; + struct lws_jwk_elements e; + size_t iv_off = 0; + + e.buf = (uint8_t *)gcm_key; + e.len = sizeof(gcm_key); + + /* Encrypt */ + + if (lws_genaes_create(&ctx, LWS_GAESO_ENC, LWS_GAESM_GCM, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + /* first we set the iv and aad */ + + iv_off = sizeof(gcm_iv); + if (lws_genaes_crypt(&ctx, gcm_aad, sizeof(gcm_aad), NULL, + (uint8_t *)gcm_iv, (uint8_t *)gcm_tag, + &iv_off, sizeof(gcm_tag))) { + lwsl_err("%s: lws_genaes_crypt 1 failed\n", __func__); + goto bail; + } + + if (lws_genaes_crypt(&ctx, gcm_pt, sizeof(gcm_pt), res, + NULL, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt 2 failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, tag, sizeof(tag))) { + lwsl_err("%s: lws_genaes_destroy enc failed\n", __func__); + return -1; + } + + if (memcmp(gcm_ct, res, sizeof(gcm_ct))) { + lwsl_err("%s: lws_genaes_crypt encoding mismatch\n", __func__); + lwsl_hexdump_notice(res, sizeof(gcm_ct)); + return -1; + } + + + /* Decrypt */ + + if (lws_genaes_create(&ctx, LWS_GAESO_DEC, LWS_GAESM_GCM, &e, 0, NULL)) { + lwsl_err("%s: lws_genaes_create failed\n", __func__); + return 1; + } + + iv_off = sizeof(gcm_iv); /* initial call sets iv + aad + tag */ + if (lws_genaes_crypt(&ctx, gcm_aad, sizeof(gcm_aad), NULL, + (uint8_t *)gcm_iv, (uint8_t *)gcm_tag, + &iv_off, sizeof(gcm_tag))) { + lwsl_err("%s: lws_genaes_crypt 1 failed\n", __func__); + goto bail; + } + + if (lws_genaes_crypt(&ctx, gcm_ct, sizeof(gcm_ct), res, + NULL, NULL, NULL, 0)) { + lwsl_err("%s: lws_genaes_crypt 2 failed\n", __func__); + goto bail; + } + + if (lws_genaes_destroy(&ctx, tag, sizeof(tag))) { + lwsl_err("%s: lws_genaes_destroy dec failed\n", __func__); + return -1; + } + + if (memcmp(gcm_pt, res, sizeof(gcm_pt))) { + lwsl_err("%s: lws_genaes_crypt decoding mismatch\n", __func__); + lwsl_hexdump_notice(res, sizeof(gcm_ct)); + return -1; + } + + return 0; + +bail: + lws_genaes_destroy(&ctx, NULL, 0); + + return -1; +} + +int +test_genaes(struct lws_context *context) +{ + + if (test_genaes_cbc()) + goto bail; + + if (test_genaes_cfb128()) + goto bail; + + if (test_genaes_cfb8()) + goto bail; + + if (test_genaes_ctr()) + goto bail; + + if (test_genaes_ecb()) + goto bail; + + if (test_genaes_ofb()) + goto bail; + +#if defined(MBEDTLS_CONFIG_H) && !defined(MBEDTLS_CIPHER_MODE_XTS) +#else + if (test_genaes_xts()) + goto bail; +#endif + + if (test_genaes_gcm()) + 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 new file mode 100644 index 000000000..7bdcdf532 --- /dev/null +++ b/minimal-examples/api-tests/api-test-gencrypto/main.c @@ -0,0 +1,45 @@ +/* + * lws-api-test-gencrypto + * + * Copyright (C) 2018 Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#include + +int +test_genaes(struct lws_context *context); + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + const char *p; + int result = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS gencrypto apis tests\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + result |= test_genaes(context); + + lwsl_user("Completed: %s\n", result ? "FAIL" : "PASS"); + + lws_context_destroy(context); + + return result; +} diff --git a/minimal-examples/api-tests/api-test-gencrypto/selftest.sh b/minimal-examples/api-tests/api-test-gencrypto/selftest.sh new file mode 100755 index 000000000..16d1e2e8e --- /dev/null +++ b/minimal-examples/api-tests/api-test-gencrypto/selftest.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# $1: path to minimal example binaries... +# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 +# that will be ./bin from your build dir +# +# $2: path for logs and results. The results will go +# in a subdir named after the directory this script +# is in +# +# $3: offset for test index count +# +# $4: total test count +# +# $5: path to ./minimal-examples dir in lws +# +# Test return code 0: OK, 254: timed out, other: error indication + +. $5/selftests-library.sh + +COUNT_TESTS=1 + +dotest $1 $2 apiselftest +exit $FAILS diff --git a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt index 49207b7b2..3f6f768e9 100644 --- a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt @@ -61,7 +61,12 @@ MACRO(require_lws_config reqconfig _val result) endif() ENDMACRO() +set(requirements 1) +require_lws_config(LWS_WITH_JWK 1 requirements) +require_lws_config(LWS_WITH_JWS 1 requirements) +require_lws_config(LWS_WITH_JWE 1 requirements) +if (requirements) add_executable(${SAMP} ${SRCS}) @@ -71,3 +76,4 @@ ENDMACRO() else() target_link_libraries(${SAMP} websockets) endif() +endif() diff --git a/plugins/ssh-base/crypto/chacha.c b/plugins/ssh-base/crypto/chacha.c index 5c9bb696c..694de2565 100644 --- a/plugins/ssh-base/crypto/chacha.c +++ b/plugins/ssh-base/crypto/chacha.c @@ -345,9 +345,9 @@ chachapoly_crypt(struct lws_ssh_keys *keys, u_int seqnr, u_char *dest, } r = 0; out: - explicit_bzero(expected_tag, sizeof(expected_tag)); - explicit_bzero(seqbuf, sizeof(seqbuf)); - explicit_bzero(poly_key, sizeof(poly_key)); + lws_explicit_bzero(expected_tag, sizeof(expected_tag)); + lws_explicit_bzero(seqbuf, sizeof(seqbuf)); + lws_explicit_bzero(poly_key, sizeof(poly_key)); return r; } diff --git a/plugins/ssh-base/include/lws-ssh.h b/plugins/ssh-base/include/lws-ssh.h index 4ffb17eae..10de9ff15 100644 --- a/plugins/ssh-base/include/lws-ssh.h +++ b/plugins/ssh-base/include/lws-ssh.h @@ -559,9 +559,6 @@ lws_g32(uint8_t **p); extern uint32_t lws_p32(uint8_t *p, uint32_t v); -extern void -explicit_bzero(void *p, size_t len); - extern int lws_timingsafe_bcmp(const void *a, const void *b, uint32_t len); diff --git a/plugins/ssh-base/kex-25519.c b/plugins/ssh-base/kex-25519.c index f4ee5acb0..2fd3aa4ce 100644 --- a/plugins/ssh-base/kex-25519.c +++ b/plugins/ssh-base/kex-25519.c @@ -534,7 +534,7 @@ kex_ecdh(struct per_session_data__sshd *pss, uint8_t *reply, uint32_t *plen) kbi, kbi_len, temp, 'B' + (c * 2), pss->session_id); } - explicit_bzero(temp, sizeof(temp)); + lws_explicit_bzero(temp, sizeof(temp)); return 0; diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index baa79e80e..7706b2960 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -86,16 +86,6 @@ lws_buf(uint8_t **p, void *s, uint32_t len) return 0; } - -void -explicit_bzero(void *p, size_t len) -{ - volatile uint8_t *vp = p; - - while (len--) - *vp++ = 0; -} - int lws_timingsafe_bcmp(const void *a, const void *b, uint32_t len) { @@ -402,7 +392,7 @@ lws_kex_destroy(struct per_session_data__sshd *pss) pss->kex->I_S = NULL; } - explicit_bzero(pss->kex, sizeof(*pss->kex)); + lws_explicit_bzero(pss->kex, sizeof(*pss->kex)); free(pss->kex); pss->kex = NULL; } @@ -436,11 +426,11 @@ lws_ua_destroy(struct per_session_data__sshd *pss) if (pss->ua->pubkey) ssh_free(pss->ua->pubkey); if (pss->ua->sig) { - explicit_bzero(pss->ua->sig, pss->ua->sig_len); + lws_explicit_bzero(pss->ua->sig, pss->ua->sig_len); ssh_free(pss->ua->sig); } - explicit_bzero(pss->ua, sizeof(*pss->ua)); + lws_explicit_bzero(pss->ua, sizeof(*pss->ua)); free(pss->ua); pss->ua = NULL; }