Tarantool development patches archive
 help / color / mirror / Atom feed
From: Konstantin Osipov <kostja@tarantool.org>
To: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Cc: tarantool-patches@freelists.org
Subject: [tarantool-patches] Re: [PATCH v2 3/3] crypto: implement crypto codec API and AES 128 encryption
Date: Mon, 29 Apr 2019 15:24:47 +0300	[thread overview]
Message-ID: <20190429122447.GB25624@atlas> (raw)
In-Reply-To: <8491f1b7c3bc2c0297153c2e033b62f1a13461ac.1556535949.git.v.shpilevoy@tarantool.org>

* Vladislav Shpilevoy <v.shpilevoy@tarantool.org> [19/04/29 14:09]:

LGTM, please ask Georgy for a second opinion.

> OpenSSL API is quite complex and hard to follow, additionally it
> is very unstable. Encoding/decoding via OpenSSL methods usually
> consists of multiple calls of a lot of functions. This patch
> wraps OpenSSL API with one more easy to use and conforming
> Tarantool code style in scope of crypto library.
> 
> The API provides struct crypto_codec which encapsulates all the
> encryption logic and exposes quite simple API like this:
> 
>     crypto_codec_encode/decode(in, in_size, out, out_size)
> 
> A caller can create a needed codec via crypto_codec_new, which
> now supports only AES 128 algorithm. The reason behind such a
> choice is simple - it is needed in SWIM now.
> 
> The API is flexible in terms of extending and adding new
> algorithms in future.
> 
> Needed for #3234
> ---
>  src/lib/core/diag.h           |   2 +
>  src/lib/core/exception.cc     |  25 +++++
>  src/lib/core/exception.h      |   7 ++
>  src/lib/crypto/CMakeLists.txt |   2 +-
>  src/lib/crypto/crypto.c       | 144 +++++++++++++++++++++++++
>  src/lib/crypto/crypto.h       |  94 +++++++++++++++++
>  test/unit/CMakeLists.txt      |   3 +
>  test/unit/crypto.c            | 191 ++++++++++++++++++++++++++++++++++
>  test/unit/crypto.result       |  40 +++++++
>  9 files changed, 507 insertions(+), 1 deletion(-)
>  create mode 100644 test/unit/crypto.c
>  create mode 100644 test/unit/crypto.result
> 
> diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h
> index 78f0cdbdf..fd3831e66 100644
> --- a/src/lib/core/diag.h
> +++ b/src/lib/core/diag.h
> @@ -251,6 +251,8 @@ struct error *
>  BuildCollationError(const char *file, unsigned line, const char *format, ...);
>  struct error *
>  BuildSwimError(const char *file, unsigned line, const char *format, ...);
> +struct error *
> +BuildCryptoError(const char *file, unsigned line, const char *format, ...);
>  
>  struct index_def;
>  
> diff --git a/src/lib/core/exception.cc b/src/lib/core/exception.cc
> index 6124c70d0..a6999af43 100644
> --- a/src/lib/core/exception.cc
> +++ b/src/lib/core/exception.cc
> @@ -280,6 +280,19 @@ SwimError::SwimError(const char *file, unsigned line, const char *format, ...)
>  	va_end(ap);
>  }
>  
> +const struct type_info type_CryptoError =
> +	make_type("CryptoError", &type_Exception);
> +
> +CryptoError::CryptoError(const char *file, unsigned line,
> +			 const char *format, ...)
> +	: Exception(&type_CryptoError, file, line)
> +{
> +	va_list ap;
> +	va_start(ap, format);
> +	error_vformat_msg(this, format, ap);
> +	va_end(ap);
> +}
> +
>  #define BuildAlloc(type)				\
>  	void *p = malloc(sizeof(type));			\
>  	if (p == NULL)					\
> @@ -371,6 +384,18 @@ BuildSwimError(const char *file, unsigned line, const char *format, ...)
>  	return e;
>  }
>  
> +struct error *
> +BuildCryptoError(const char *file, unsigned line, const char *format, ...)
> +{
> +	BuildAlloc(CryptoError);
> +	CryptoError *e =  new (p) CryptoError(file, line, "");
> +	va_list ap;
> +	va_start(ap, format);
> +	error_vformat_msg(e, format, ap);
> +	va_end(ap);
> +	return e;
> +}
> +
>  struct error *
>  BuildSocketError(const char *file, unsigned line, const char *socketname,
>  		 const char *format, ...)
> diff --git a/src/lib/core/exception.h b/src/lib/core/exception.h
> index 4f5b66f2e..a29281427 100644
> --- a/src/lib/core/exception.h
> +++ b/src/lib/core/exception.h
> @@ -51,6 +51,7 @@ extern const struct type_info type_IllegalParams;
>  extern const struct type_info type_SystemError;
>  extern const struct type_info type_CollationError;
>  extern const struct type_info type_SwimError;
> +extern const struct type_info type_CryptoError;
>  
>  const char *
>  exception_get_string(struct error *e, const struct method_info *method);
> @@ -166,6 +167,12 @@ public:
>  	virtual void raise() { throw this; }
>  };
>  
> +class CryptoError: public Exception {
> +public:
> +	CryptoError(const char *file, unsigned line, const char *format, ...);
> +	virtual void raise() { throw this; }
> +};
> +
>  /**
>   * Initialize the exception subsystem.
>   */
> diff --git a/src/lib/crypto/CMakeLists.txt b/src/lib/crypto/CMakeLists.txt
> index 7e2c6e1d3..4e2e5e403 100644
> --- a/src/lib/crypto/CMakeLists.txt
> +++ b/src/lib/crypto/CMakeLists.txt
> @@ -2,4 +2,4 @@ set(lib_sources crypto.c)
>  
>  set_source_files_compile_flags(${lib_sources})
>  add_library(crypto STATIC ${lib_sources})
> -target_link_libraries(crypto ${OPENSSL_LIBRARIES})
> +target_link_libraries(crypto ${OPENSSL_LIBRARIES} core)
> diff --git a/src/lib/crypto/crypto.c b/src/lib/crypto/crypto.c
> index 4b192ba2d..a96963d6f 100644
> --- a/src/lib/crypto/crypto.c
> +++ b/src/lib/crypto/crypto.c
> @@ -29,12 +29,156 @@
>   * SUCH DAMAGE.
>   */
>  #include "crypto.h"
> +#include "diag.h"
> +#include "exception.h"
> +#include "core/random.h"
>  #include <openssl/crypto.h>
>  #include <openssl/evp.h>
>  #include <openssl/err.h>
>  #include <openssl/ssl.h>
>  #include <openssl/hmac.h>
>  
> +/** Set a diag error with the latest OpenSSL error message. */
> +static inline void
> +diag_set_OpenSSL(void)
> +{
> +	diag_set(CryptoError, "OpenSSL error: %s",
> +		 ERR_error_string(ERR_get_error(), NULL));
> +}
> +
> +/**
> + * OpenSSL codec. It contains only key, initial vector, and a
> + * constant cipher type, because OpenSSL does not allow
> + * long-living EVP_CIPHER_CTX contexts.
> + */
> +struct crypto_codec {
> +	/**
> +	 * Secret key, usually is unchanged among multiple data
> +	 * packets. Only AES 128 is supported now, so the buffer
> +	 * is of 16 byte size.
> +	 */
> +	unsigned char key[CRYPTO_AES128_KEY_SIZE];
> +	/**
> +	 * Initial vector, and in fact a public key. It should be
> +	 * regenerated randomly for each data packet.
> +	 */
> +	unsigned char iv[CRYPTO_AES_IV_SIZE];
> +	/** Size of block by which the algorithm operates. */
> +	uint8_t block_size;
> +	/** Cipher type. Depends on algorithm and key size. */
> +	const EVP_CIPHER *type;
> +};
> +
> +struct crypto_codec *
> +crypto_codec_new(enum crypto_algo algo, const char *key)
> +{
> +	struct crypto_codec *c = (struct crypto_codec *) malloc(sizeof(*c));
> +	if (c == NULL) {
> +		diag_set(OutOfMemory, sizeof(*c), "malloc", "c");
> +		return NULL;
> +	}
> +	switch (algo) {
> +	case CRYPTO_AES128:
> +		memcpy(c->key, key, sizeof(c->key));
> +		memset(c->iv, 0, sizeof(c->iv));
> +		c->type = EVP_aes_128_cbc();
> +		break;
> +	case CRYPTO_NONE:
> +		c->type = EVP_enc_null();
> +		break;
> +	default:
> +		free(c);
> +		diag_set(CryptoError, "only 'none' and AES 128 are supported");
> +		return NULL;
> +	}
> +	c->block_size = EVP_CIPHER_block_size(c->type);
> +	return c;
> +}
> +
> +const char *
> +crypto_codec_gen_iv(struct crypto_codec *c)
> +{
> +	random_bytes((char *) c->iv, sizeof(c->iv));
> +	return (char *) c->iv;
> +}
> +
> +int
> +crypto_codec_encrypt(struct crypto_codec *c, const char *in, int in_size,
> +		     char *out, int out_size)
> +{
> +	const unsigned char *uin = (const unsigned char *) in;
> +	unsigned char *uout = (unsigned char *) out;
> +	/*
> +	 * Note, that even if in_size is already multiple of block
> +	 * size, additional block is still needed. Result is
> +	 * almost always bigger than input. OpenSSL API advises to
> +	 * provide buffer of one block bigger than the data to
> +	 * encode.
> +	 */
> +	int len, result, need = in_size + c->block_size;
> +	if (need > out_size)
> +		return need;
> +
> +	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
> +	if (ctx == NULL)
> +		goto error;
> +	if (EVP_EncryptInit_ex(ctx, c->type, NULL, c->key, c->iv) != 1)
> +		goto error;
> +	if (EVP_EncryptUpdate(ctx, uout, &len, uin, in_size) != 1)
> +		goto error;
> +	result = len;
> +	assert(result <= need);
> +	if (EVP_EncryptFinal_ex(ctx, uout + result, &len) != 1)
> +		goto error;
> +	result += len;
> +	assert(result <= need);
> +	EVP_CIPHER_CTX_free(ctx);
> +	return result;
> +
> +error:
> +	diag_set_OpenSSL();
> +	if (ctx != NULL)
> +		EVP_CIPHER_CTX_free(ctx);
> +	return -1;
> +}
> +
> +int
> +crypto_codec_decrypt(struct crypto_codec *c, const char *iv,
> +		     const char *in, int in_size, char *out, int out_size)
> +{
> +	if (in_size > out_size)
> +		return in_size;
> +	const unsigned char *uin = (const unsigned char *) in;
> +	const unsigned char *uiv = (const unsigned char *) iv;
> +	unsigned char *uout = (unsigned char *) out;
> +	int len, result;
> +
> +	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
> +	if (ctx == NULL)
> +		goto error;
> +	if (EVP_DecryptInit_ex(ctx, c->type, NULL, c->key, uiv) != 1)
> +		goto error;
> +	if (EVP_DecryptUpdate(ctx, uout, &len, uin, in_size) != 1)
> +		goto error;
> +	result = len;
> +	if (EVP_DecryptFinal_ex(ctx, uout + result, &len) != 1)
> +		goto error;
> +	EVP_CIPHER_CTX_free(ctx);
> +	return result + len;
> +
> +error:
> +	diag_set_OpenSSL();
> +	if (ctx != NULL)
> +		EVP_CIPHER_CTX_free(ctx);
> +	return -1;
> +}
> +
> +void
> +crypto_codec_delete(struct crypto_codec *c)
> +{
> +	free(c);
> +}
> +
>  void
>  crypto_init(void)
>  {
> diff --git a/src/lib/crypto/crypto.h b/src/lib/crypto/crypto.h
> index bc807e1a2..c679c39f7 100644
> --- a/src/lib/crypto/crypto.h
> +++ b/src/lib/crypto/crypto.h
> @@ -35,6 +35,100 @@
>  extern "C" {
>  #endif
>  
> +enum crypto_algo {
> +	/** None to disable encryption. */
> +	CRYPTO_NONE,
> +	/**
> +	 * AES - Advanced Encryption Standard. It is a symmetric
> +	 * key block cipher algorithm. AES encodes data in blocks
> +	 * of 128 bits, for what it uses a key and an initial
> +	 * vector. The key is a secret information which needs to
> +	 * be shared among communicating nodes. Key size can be
> +	 * 128, 192 and 256 bits. Initial vector is an additional
> +	 * entropy factor to prevent an attack when an attacker
> +	 * somehow learns a purpose or content of one data packet
> +	 * and immediately learns purpose of all the same looking
> +	 * packets. Initial vector should be generated randomly
> +	 * for each data packet, nonetheless it is not private and
> +	 * can be sent without encryption.
> +	 */
> +	CRYPTO_AES128,
> +};
> +
> +/**
> + * Values obtained from EVP_CIPHER_*() API, but the constants are
> + * needed in some places at compilation time. For example, for
> + * statically sized buffers.
> + */
> +enum {
> +	/**
> +	 * Block size of AES operation. Encrypted data size is
> +	 * always divisible by this value.
> +	 */
> +	CRYPTO_AES_BLOCK_SIZE = 16,
> +	/**
> +	 * Size of AES initial vector. It does not depend on key
> +	 * size.
> +	 */
> +	CRYPTO_AES_IV_SIZE = 16,
> +	/**
> +	 * Obviously, 128 bits = 16 bytes always. It is just
> +	 * syntax sugar so as not to hardcode 16 everywhere.
> +	 */
> +	CRYPTO_AES128_KEY_SIZE = 16,
> +};
> +
> +struct crypto_codec;
> +
> +/**
> + * Create a new codec working with a specified @a algo algorithm
> + * and a secret @a key. Size of @a key depends on the chosen
> + * algorithm.
> + */
> +struct crypto_codec *
> +crypto_codec_new(enum crypto_algo algo, const char *key);
> +
> +/** Generate a new initial vector and return it. */
> +const char *
> +crypto_codec_gen_iv(struct crypto_codec *c);
> +
> +/**
> + * Encrypt plain data by codec @a c.
> + * @param c Codec.
> + * @param in Plain input data.
> + * @param in_size Byte size of @a in.
> + * @param out Output buffer.
> + * @param out_size Byte size of @a out.
> + *
> + * @retval -1 Error. Diag is set.
> + * @return Number of written bytes. If > @a out_size then nothing
> + *         is written, needed number of bytes is returned.
> + */
> +int
> +crypto_codec_encrypt(struct crypto_codec *c, const char *in, int in_size,
> +		     char *out, int out_size);
> +
> +/**
> + * Decrypt cipher by codec @a c.
> + * @param c Codec.
> + * @param iv Initial vector used to encode @a in.
> + * @param in Cipher to decode.
> + * @param in_size Byte size of @a in.
> + * @param out Output buffer.
> + * @param out_size Byte size of @a out.
> + *
> + * @retval -1 Error. Diag is set.
> + * @return Number of written bytes. If > @a out_size then nothing
> + *         is written, needed number of bytes is returned.
> + */
> +int
> +crypto_codec_decrypt(struct crypto_codec *c, const char *iv,
> +		     const char *in, int in_size, char *out, int out_size);
> +
> +/** Delete codec. */
> +void
> +crypto_codec_delete(struct crypto_codec *c);
> +
>  void
>  crypto_init(void);
>  
> diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
> index bb88b9c9b..368ceb649 100644
> --- a/test/unit/CMakeLists.txt
> +++ b/test/unit/CMakeLists.txt
> @@ -213,6 +213,9 @@ target_link_libraries(checkpoint_schedule.test m unit)
>  add_executable(sio.test sio.c)
>  target_link_libraries(sio.test unit core)
>  
> +add_executable(crypto.test crypto.c)
> +target_link_libraries(crypto.test crypto unit)
> +
>  add_executable(swim.test swim.c swim_test_transport.c swim_test_ev.c
>                 swim_test_utils.c ${PROJECT_SOURCE_DIR}/src/version.c)
>  target_link_libraries(swim.test unit swim)
> diff --git a/test/unit/crypto.c b/test/unit/crypto.c
> new file mode 100644
> index 000000000..092650543
> --- /dev/null
> +++ b/test/unit/crypto.c
> @@ -0,0 +1,191 @@
> +/*
> + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
> + *
> + * Redistribution and use in source and binary forms, with or
> + * without modification, are permitted provided that the following
> + * conditions are met:
> + *
> + * 1. Redistributions of source code must retain the above
> + *    copyright notice, this list of conditions and the
> + *    following disclaimer.
> + *
> + * 2. Redistributions in binary form must reproduce the above
> + *    copyright notice, this list of conditions and the following
> + *    disclaimer in the documentation and/or other materials
> + *    provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +#include "crypto/crypto.h"
> +#include "core/random.h"
> +#include "unit.h"
> +#include "trivia/util.h"
> +#include "memory.h"
> +#include "fiber.h"
> +
> +static void
> +test_aes128_codec(void)
> +{
> +	header();
> +	plan(19);
> +
> +	char key[CRYPTO_AES128_KEY_SIZE];
> +	random_bytes(key, sizeof(key));
> +	struct crypto_codec *c = crypto_codec_new(CRYPTO_AES128, key);
> +
> +	int rc = crypto_codec_encrypt(c, NULL, 10, NULL, 0);
> +	is(rc, 26, "encrypt returns needed number of bytes");
> +	rc = crypto_codec_encrypt(c, NULL, 10, NULL, 15);
> +	is(rc, 26, "encrypt does not write anything when too small "\
> +	   "buffer");
> +	rc = crypto_codec_encrypt(c, NULL, 0, NULL, 0);
> +	is(rc, 16, "encrypt does not allow 0 sized buffer");
> +	rc = crypto_codec_encrypt(c, NULL, 32, NULL, 0);
> +	is(rc, 48, "encrypt requires additional block when buffer "\
> +	   "size is multiple of block size");
> +
> +	const char *plain = "plain text";
> +	int plain_size = strlen(plain) + 1;
> +	char buffer1[128], buffer2[128];
> +	memset(buffer1, 0, sizeof(buffer1));
> +	memset(buffer2, 0, sizeof(buffer2));
> +	int buffer_size = sizeof(buffer1);
> +	const char *iv = crypto_codec_gen_iv(c);
> +
> +	rc = crypto_codec_encrypt(c, plain, plain_size, buffer1, buffer_size);
> +	is(rc, 16, "encrypt works when buffer is big enough");
> +	rc = crypto_codec_encrypt(c, plain, plain_size, buffer2, buffer_size);
> +	is(rc, 16, "encrypt returns the same on second call");
> +	is(memcmp(buffer1, buffer2, rc), 0, "encrypted data is the same");
> +	isnt(memcmp(buffer1, plain, plain_size), 0,
> +	     "and it is not just copied from the plain text");
> +
> +	rc = crypto_codec_decrypt(c, iv, NULL, 16, NULL, 0);
> +	is(rc, 16, "decrypt also checks length and returns needed number "\
> +	   "of bytes");
> +	rc = crypto_codec_decrypt(c, iv, buffer1, 16, buffer2, buffer_size);
> +	is(rc, plain_size, "decrypt returns correct number of bytes");
> +	is(memcmp(buffer2, plain, plain_size), 0,
> +	   "and correctly decrypts data");
> +
> +	rc = crypto_codec_decrypt(c, "false iv not meaning anything",
> +				  buffer1, 16, buffer2, buffer_size);
> +	is(rc, -1, "decrypt can fail with wrong IV");
> +	ok(! diag_is_empty(diag_get()), "diag error is set");
> +
> +	const char *iv2 = crypto_codec_gen_iv(c);
> +	rc = crypto_codec_encrypt(c, plain, plain_size, buffer2, buffer_size);
> +	is(rc, 16, "encrypt with different IV and the same number of written "\
> +	   "bytes returned")
> +	isnt(memcmp(buffer2, buffer1, rc), 0,
> +	     "the encrypted data looks different");
> +	rc = crypto_codec_decrypt(c, iv2, buffer2, 16, buffer1, buffer_size);
> +	is(rc, plain_size, "decrypt works with correct but another IV");
> +	is(memcmp(buffer1, plain, plain_size), 0, "data is the same");
> +
> +	struct crypto_codec *c2 = crypto_codec_new(CRYPTO_AES128, key);
> +	rc = crypto_codec_encrypt(c, plain, plain_size, buffer1, buffer_size);
> +	memset(buffer2, 0, rc);
> +	rc = crypto_codec_decrypt(c2, iv2, buffer1, rc, buffer2, buffer_size);
> +	is(rc, plain_size, "encrypt with one codec, but decrypt with another "\
> +	   "codec and the same key");
> +	is(memcmp(plain, buffer2, plain_size), 0, "data is the same");
> +
> +	crypto_codec_delete(c2);
> +	crypto_codec_delete(c);
> +
> +	check_plan();
> +	footer();
> +}
> +
> +static void
> +test_aes128_stress(void)
> +{
> +	header();
> +	plan(1);
> +	char key[CRYPTO_AES128_KEY_SIZE];
> +	random_bytes(key, sizeof(key));
> +	struct crypto_codec *c = crypto_codec_new(CRYPTO_AES128, key);
> +
> +	char plain[515], cipher[1024], result[1024];
> +	int rc, size = 10;
> +	for (int size = 10; size < (int) sizeof(plain); size += 10) {
> +		random_bytes(plain, size);
> +		const char *iv = crypto_codec_gen_iv(c);
> +		rc = crypto_codec_encrypt(c, plain, size,
> +					  cipher, sizeof(cipher));
> +		rc = crypto_codec_decrypt(c, iv, cipher, rc,
> +					  result, sizeof(result));
> +		fail_if(memcmp(result, plain, rc) != 0);
> +	}
> +	ok(true, "try encrypt/decrypt on a variety of sizes, keys, and ivs");
> +
> +	check_plan();
> +	crypto_codec_delete(c);
> +	footer();
> +}
> +
> +static void
> +test_none_codec(void)
> +{
> +	header();
> +	plan(4);
> +
> +	struct crypto_codec *c = crypto_codec_new(CRYPTO_NONE, NULL);
> +	const char *plain = "plain text";
> +	int plain_size = strlen(plain) + 1;
> +	char buffer1[128], buffer2[128];
> +	const char *iv = crypto_codec_gen_iv(c);
> +	int rc = crypto_codec_encrypt(c, plain, plain_size,
> +				      buffer1, sizeof(buffer1));
> +	is(rc, plain_size, "'none' codec does not require more space "\
> +	   "than the data");
> +	is(memcmp(buffer1, plain, plain_size), 0, "data is just copied");
> +	rc = crypto_codec_decrypt(c, iv, buffer1, rc, buffer2, sizeof(buffer2));
> +	is(rc, plain_size, "'decrypt' does the same");
> +	is(memcmp(buffer2, plain, plain_size), 0, "data is copied back");
> +
> +	crypto_codec_delete(c);
> +
> +	check_plan();
> +	footer();
> +}
> +
> +int
> +main(void)
> +{
> +	header();
> +	plan(4);
> +	random_init();
> +	crypto_init();
> +	memory_init();
> +	fiber_init(fiber_c_invoke);
> +
> +	struct crypto_codec *c = crypto_codec_new(-1, "1234");
> +	is(c, NULL, "crypto checks that algo argument is correct");
> +	crypto_codec_delete(c);
> +
> +	test_aes128_codec();
> +	test_aes128_stress();
> +	test_none_codec();
> +
> +	fiber_free();
> +	memory_free();
> +	crypto_free();
> +	random_free();
> +	int rc = check_plan();
> +	footer();
> +	return rc;
> +}
> diff --git a/test/unit/crypto.result b/test/unit/crypto.result
> new file mode 100644
> index 000000000..de55fd2e4
> --- /dev/null
> +++ b/test/unit/crypto.result
> @@ -0,0 +1,40 @@
> +	*** main ***
> +1..4
> +ok 1 - crypto checks that algo argument is correct
> +	*** test_aes128_codec ***
> +    1..19
> +    ok 1 - encrypt returns needed number of bytes
> +    ok 2 - encrypt does not write anything when too small buffer
> +    ok 3 - encrypt does not allow 0 sized buffer
> +    ok 4 - encrypt requires additional block when buffer size is multiple of block size
> +    ok 5 - encrypt works when buffer is big enough
> +    ok 6 - encrypt returns the same on second call
> +    ok 7 - encrypted data is the same
> +    ok 8 - and it is not just copied from the plain text
> +    ok 9 - decrypt also checks length and returns needed number of bytes
> +    ok 10 - decrypt returns correct number of bytes
> +    ok 11 - and correctly decrypts data
> +    ok 12 - decrypt can fail with wrong IV
> +    ok 13 - diag error is set
> +    ok 14 - encrypt with different IV and the same number of written bytes returned
> +    ok 15 - the encrypted data looks different
> +    ok 16 - decrypt works with correct but another IV
> +    ok 17 - data is the same
> +    ok 18 - encrypt with one codec, but decrypt with another codec and the same key
> +    ok 19 - data is the same
> +ok 2 - subtests
> +	*** test_aes128_codec: done ***
> +	*** test_aes128_stress ***
> +    1..1
> +    ok 1 - try encrypt/decrypt on a variety of sizes, keys, and ivs
> +ok 3 - subtests
> +	*** test_aes128_stress: done ***
> +	*** test_none_codec ***
> +    1..4
> +    ok 1 - 'none' codec does not require more space than the data
> +    ok 2 - data is just copied
> +    ok 3 - 'decrypt' does the same
> +    ok 4 - data is copied back
> +ok 4 - subtests
> +	*** test_none_codec: done ***
> +	*** main: done ***
> -- 
> 2.20.1 (Apple Git-117)
> 

-- 
Konstantin Osipov, Moscow, Russia, +7 903 626 22 32

  reply	other threads:[~2019-04-29 12:24 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-29 11:07 [tarantool-patches] [PATCH v2 0/3] swim encryption preparation Vladislav Shpilevoy
2019-04-29 11:07 ` [tarantool-patches] [PATCH v2 1/3] crypto: move crypto business into a separate library Vladislav Shpilevoy
2019-04-29 11:07 ` [tarantool-patches] [PATCH v2 2/3] crypto: make exported methods conform code style Vladislav Shpilevoy
2019-04-29 12:23   ` [tarantool-patches] " Konstantin Osipov
2019-04-29 11:07 ` [tarantool-patches] [PATCH v2 3/3] crypto: implement crypto codec API and AES 128 encryption Vladislav Shpilevoy
2019-04-29 12:24   ` Konstantin Osipov [this message]
2019-04-29 12:29 ` [tarantool-patches] Re: [PATCH v2 0/3] swim encryption preparation Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190429122447.GB25624@atlas \
    --to=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re: [PATCH v2 3/3] crypto: implement crypto codec API and AES 128 encryption' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox