mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
genaes: generic AES layer independent of tls library
Although RSA can be used directly for signing / JWS on large chunks of data since it's only operating on the hash, when JWE support arrives, which allows bulk encryption, it's going to be mandatory to support secondary AES ciphers to use on the bulk data. This adds generic support for all AES modes that OpenSSL and mbedTLS have in common, works on both mbedTLS and OpenSSL the same, and adds unit tests for each mode in api-test-gencrypto, to run in CI.
This commit is contained in:
parent
440dacc992
commit
ddb94d4e27
27 changed files with 1783 additions and 29 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -426,6 +426,7 @@ struct lws;
|
|||
#include <libwebsockets/lws-jose.h>
|
||||
#include <libwebsockets/lws-jws.h>
|
||||
#include <libwebsockets/lws-genrsa.h>
|
||||
#include <libwebsockets/lws-genaes.h>
|
||||
#include <libwebsockets/lws-genec.h>
|
||||
|
||||
#endif
|
||||
|
|
161
include/libwebsockets/lws-genaes.h
Normal file
161
include/libwebsockets/lws-genaes.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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 <mbedtls/aes.h>
|
||||
#include <mbedtls/gcm.h>
|
||||
#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);
|
||||
|
||||
///@}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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" */,
|
||||
|
|
242
lib/tls/mbedtls/lws-genaes.c
Normal file
242
lib/tls/mbedtls/lws-genaes.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* libwebsockets - generic AES api hiding the backend
|
||||
*
|
||||
* Copyright (C) 2017 - 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
|
@ -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
|
||||
|
|
313
lib/tls/openssl/lws-genaes.c
Normal file
313
lib/tls/openssl/lws-genaes.c
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* libwebsockets - generic AES api hiding the backend
|
||||
*
|
||||
* Copyright (C) 2017 - 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -50,11 +50,15 @@
|
|||
#undef MBEDTLS_CONFIG_FILE
|
||||
#define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/gcm.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
|
||||
#else /* not esp32 */
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/gcm.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include <mbedtls/x509_csr.h>
|
||||
#include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
|
||||
|
@ -66,6 +70,7 @@
|
|||
#include <openssl/sha.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/aes.h>
|
||||
#ifdef LWS_HAVE_OPENSSL_ECDH_H
|
||||
#include <openssl/ecdh.h>
|
||||
#endif
|
||||
|
|
78
minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt
Normal file
78
minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt
Normal file
|
@ -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 <libwebsockets.h>\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()
|
||||
|
26
minimal-examples/api-tests/api-test-gencrypto/README.md
Normal file
26
minimal-examples/api-tests/api-test-gencrypto/README.md
Normal file
|
@ -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 <loglevel>|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
|
||||
```
|
||||
|
788
minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c
Normal file
788
minimal-examples/api-tests/api-test-gencrypto/lws-genaes.c
Normal file
|
@ -0,0 +1,788 @@
|
|||
/*
|
||||
* lws-api-test-gencrypto - lws-genaes
|
||||
*
|
||||
* 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
|
||||
/*
|
||||
* 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;
|
||||
}
|
45
minimal-examples/api-tests/api-test-gencrypto/main.c
Normal file
45
minimal-examples/api-tests/api-test-gencrypto/main.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* lws-api-test-gencrypto
|
||||
*
|
||||
* 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>
|
||||
|
||||
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;
|
||||
}
|
24
minimal-examples/api-tests/api-test-gencrypto/selftest.sh
Executable file
24
minimal-examples/api-tests/api-test-gencrypto/selftest.sh
Executable file
|
@ -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
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue