From 57cb4c8d2c809525897fc1ab8cba8d05ecdbc775 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 15 Nov 2018 10:20:45 +0100 Subject: [PATCH 01/12] openssl: Add support for X25519 and X448 While X25519 was already added with 1.1.0a, its use would be a lot more complicated, as the helpers like EVP_PKEY_new_raw_public_key() were only added in 1.1.1, which also added X448. --- src/libstrongswan/plugins/openssl/Makefile.am | 3 +- .../plugins/openssl/openssl_plugin.c | 10 +- .../openssl/openssl_x_diffie_hellman.c | 256 ++++++++++++++++++ .../openssl/openssl_x_diffie_hellman.h | 37 +++ 4 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.c create mode 100644 src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.h diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index 9287f788a..f2d06a5d1 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -29,7 +29,8 @@ libstrongswan_openssl_la_SOURCES = \ openssl_pkcs12.c openssl_pkcs12.h \ openssl_rng.c openssl_rng.h \ openssl_hmac.c openssl_hmac.h \ - openssl_gcm.c openssl_gcm.h + openssl_gcm.c openssl_gcm.h \ + openssl_x_diffie_hellman.c openssl_x_diffie_hellman.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = $(OPENSSL_LIB) diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index b0db9325f..ca1c9b369 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -47,6 +47,7 @@ #include "openssl_rng.h" #include "openssl_hmac.h" #include "openssl_gcm.h" +#include "openssl_x_diffie_hellman.h" #ifndef FIPS_MODE #define FIPS_MODE 0 @@ -594,7 +595,14 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(DH, ECP_384_BP), PLUGIN_PROVIDE(DH, ECP_512_BP), PLUGIN_PROVIDE(DH, ECP_224_BP), -#endif +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL + PLUGIN_REGISTER(DH, openssl_x_diffie_hellman_create), + /* available since 1.1.0a, but we require 1.1.1 features */ + PLUGIN_PROVIDE(DH, CURVE_25519), + /* available since 1.1.1 */ + PLUGIN_PROVIDE(DH, CURVE_448), +#endif /* OPENSSL_VERSION_NUMBER */ +#endif /* OPENSSL_NO_ECDH */ #ifndef OPENSSL_NO_DH /* MODP DH groups */ PLUGIN_REGISTER(DH, openssl_diffie_hellman_create), diff --git a/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.c new file mode 100644 index 000000000..37943f5bf --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +#include + +/* basic support for X25519 was added with 1.1.0a, but we require features (e.g. + * to load the keys) that were only added with 1.1.1 */ +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_ECDH) + +#include "openssl_x_diffie_hellman.h" + +#include + +typedef struct private_diffie_hellman_t private_diffie_hellman_t; + +/** + * Private data + */ +struct private_diffie_hellman_t { + /** + * Public interface. + */ + diffie_hellman_t public; + + /** + * Diffie Hellman group number. + */ + diffie_hellman_group_t group; + + /** + * Private (public) key + */ + EVP_PKEY *key; + + /** + * Shared secret + */ + chunk_t shared_secret; + + /** + * True if shared secret is computed + */ + bool computed; +}; + +/** + * Map a DH group to a key type + */ +static int map_key_type(diffie_hellman_group_t group) +{ + switch (group) + { + case CURVE_25519: + return EVP_PKEY_X25519; + case CURVE_448: + return EVP_PKEY_X448; + default: + return 0; + } +} + +/** + * Compute the shared secret + */ +static bool compute_shared_key(private_diffie_hellman_t *this, EVP_PKEY *pub, + chunk_t *shared_secret) +{ + EVP_PKEY_CTX *ctx; + bool success = FALSE; + + ctx = EVP_PKEY_CTX_new(this->key, NULL); + if (!ctx) + { + return FALSE; + } + + if (EVP_PKEY_derive_init(ctx) <= 0) + { + goto error; + } + + if (EVP_PKEY_derive_set_peer(ctx, pub) <= 0) + { + goto error; + } + + if (EVP_PKEY_derive(ctx, NULL, &shared_secret->len) <= 0) + { + goto error; + } + + *shared_secret = chunk_alloc(shared_secret->len); + + if (EVP_PKEY_derive(ctx, shared_secret->ptr, &shared_secret->len) <= 0) + { + goto error; + } + + success = TRUE; + +error: + EVP_PKEY_CTX_free(ctx); + return success; +} + +METHOD(diffie_hellman_t, set_other_public_value, bool, + private_diffie_hellman_t *this, chunk_t value) +{ + EVP_PKEY *pub; + + if (!diffie_hellman_verify_value(this->group, value)) + { + return FALSE; + } + + pub = EVP_PKEY_new_raw_public_key(map_key_type(this->group), NULL, + value.ptr, value.len); + if (!pub) + { + DBG1(DBG_LIB, "%N public value is malformed", + diffie_hellman_group_names, this->group); + return FALSE; + } + + chunk_clear(&this->shared_secret); + + if (!compute_shared_key(this, pub, &this->shared_secret)) + { + DBG1(DBG_LIB, "%N shared secret computation failed", + diffie_hellman_group_names, this->group); + EVP_PKEY_free(pub); + return FALSE; + } + this->computed = TRUE; + EVP_PKEY_free(pub); + return TRUE; +} + +METHOD(diffie_hellman_t, get_my_public_value, bool, + private_diffie_hellman_t *this, chunk_t *value) +{ + size_t len; + + if (!EVP_PKEY_get_raw_public_key(this->key, NULL, &len)) + { + return FALSE; + } + + *value = chunk_alloc(len); + + if (!EVP_PKEY_get_raw_public_key(this->key, value->ptr, &value->len)) + { + chunk_free(value); + return FALSE; + } + return TRUE; +} + +METHOD(diffie_hellman_t, set_private_value, bool, + private_diffie_hellman_t *this, chunk_t value) +{ + EVP_PKEY_free(this->key); + this->key = EVP_PKEY_new_raw_private_key(map_key_type(this->group), NULL, + value.ptr, value.len); + if (!this->key) + { + return FALSE; + } + return TRUE; +} + +METHOD(diffie_hellman_t, get_shared_secret, bool, + private_diffie_hellman_t *this, chunk_t *secret) +{ + if (!this->computed) + { + return FALSE; + } + *secret = chunk_clone(this->shared_secret); + return TRUE; +} + +METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, + private_diffie_hellman_t *this) +{ + return this->group; +} + +METHOD(diffie_hellman_t, destroy, void, + private_diffie_hellman_t *this) +{ + EVP_PKEY_free(this->key); + chunk_clear(&this->shared_secret); + free(this); +} + +/* + * Described in header + */ +diffie_hellman_t *openssl_x_diffie_hellman_create(diffie_hellman_group_t group) +{ + private_diffie_hellman_t *this; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *key = NULL; + + switch (group) + { + case CURVE_25519: + ctx = EVP_PKEY_CTX_new_id(NID_X25519, NULL); + break; + case CURVE_448: + ctx = EVP_PKEY_CTX_new_id(NID_X448, NULL); + break; + default: + break; + } + + if (!ctx || + EVP_PKEY_keygen_init(ctx) <= 0 || + EVP_PKEY_keygen(ctx, &key) <= 0) + { + DBG1(DBG_LIB, "generating key for %N failed", + diffie_hellman_group_names, group); + EVP_PKEY_CTX_free(ctx); + return NULL; + } + EVP_PKEY_CTX_free(ctx); + + INIT(this, + .public = { + .get_shared_secret = _get_shared_secret, + .set_other_public_value = _set_other_public_value, + .get_my_public_value = _get_my_public_value, + .set_private_value = _set_private_value, + .get_dh_group = _get_dh_group, + .destroy = _destroy, + }, + .group = group, + .key = key, + ); + return &this->public; +} + +#endif /* OPENSSL_NO_ECDH */ diff --git a/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.h b/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.h new file mode 100644 index 000000000..e28f38d15 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_x_diffie_hellman.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +/** + * Implementation of the X25519/X448 Diffie-Hellman algorithm using OpenSSL. + * + * @defgroup openssl_x_diffie_hellman openssl_x_diffie_hellman + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_X_DIFFIE_HELLMAN_H_ +#define OPENSSL_X_DIFFIE_HELLMAN_H_ + +#include + +/** + * Creates a new diffie_hellman_t object. + * + * @param group Diffie Hellman group number to use + * @return object, NULL if not supported + */ +diffie_hellman_t *openssl_x_diffie_hellman_create(diffie_hellman_group_t group); + +#endif /** OPENSSL_X_DIFFIE_HELLMAN_H_ @}*/ + From 9dfbe9442b675c69ffa12d1a6e971bdcf45d696f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 15 Nov 2018 11:24:53 +0100 Subject: [PATCH 02/12] test-vectors: Add vector for X448 --- .../plugins/test_vectors/Makefile.am | 1 + .../plugins/test_vectors/test_vectors.h | 1 + .../test_vectors/test_vectors/curve25519.c | 2 +- .../test_vectors/test_vectors/curve448.c | 43 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/libstrongswan/plugins/test_vectors/test_vectors/curve448.c diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am index c4d9f2fc5..3d34cf7c9 100644 --- a/src/libstrongswan/plugins/test_vectors/Makefile.am +++ b/src/libstrongswan/plugins/test_vectors/Makefile.am @@ -49,6 +49,7 @@ libstrongswan_test_vectors_la_SOURCES = \ test_vectors/ecp.c \ test_vectors/ecpbp.c \ test_vectors/curve25519.c \ + test_vectors/curve448.c \ test_vectors/rng.c libstrongswan_test_vectors_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h index ded93ac90..7c8ac0c6e 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors.h +++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h @@ -306,3 +306,4 @@ TEST_VECTOR_DH(ecp384bp) TEST_VECTOR_DH(ecp512bp) TEST_VECTOR_DH(curve25519_1) TEST_VECTOR_DH(curve25519_2) +TEST_VECTOR_DH(curve448_1) diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/curve25519.c b/src/libstrongswan/plugins/test_vectors/test_vectors/curve25519.c index 676fcfc5a..23c024a37 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors/curve25519.c +++ b/src/libstrongswan/plugins/test_vectors/test_vectors/curve25519.c @@ -16,7 +16,7 @@ #include /** - * From RFC 8037 + * From RFC 7748 */ dh_test_vector_t curve25519_1 = { .group = CURVE_25519, .priv_len = 32, .pub_len = 32, .shared_len = 32, diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/curve448.c b/src/libstrongswan/plugins/test_vectors/test_vectors/curve448.c new file mode 100644 index 000000000..fccbb808a --- /dev/null +++ b/src/libstrongswan/plugins/test_vectors/test_vectors/curve448.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the Licenseor (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be usefulbut + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include + +/** + * From RFC 7748 + */ +dh_test_vector_t curve448_1 = { + .group = CURVE_448, .priv_len = 56, .pub_len = 56, .shared_len = 56, + .priv_a = "\x9a\x8f\x49\x25\xd1\x51\x9f\x57\x75\xcf\x46\xb0\x4b\x58\x00\xd4" + "\xee\x9e\xe8\xba\xe8\xbc\x55\x65\xd4\x98\xc2\x8d\xd9\xc9\xba\xf5" + "\x74\xa9\x41\x97\x44\x89\x73\x91\x00\x63\x82\xa6\xf1\x27\xab\x1d" + "\x9a\xc2\xd8\xc0\xa5\x98\x72\x6b", + .priv_b = "\x1c\x30\x6a\x7a\xc2\xa0\xe2\xe0\x99\x0b\x29\x44\x70\xcb\xa3\x39" + "\xe6\x45\x37\x72\xb0\x75\x81\x1d\x8f\xad\x0d\x1d\x69\x27\xc1\x20" + "\xbb\x5e\xe8\x97\x2b\x0d\x3e\x21\x37\x4c\x9c\x92\x1b\x09\xd1\xb0" + "\x36\x6f\x10\xb6\x51\x73\x99\x2d", + .pub_a = "\x9b\x08\xf7\xcc\x31\xb7\xe3\xe6\x7d\x22\xd5\xae\xa1\x21\x07\x4a" + "\x27\x3b\xd2\xb8\x3d\xe0\x9c\x63\xfa\xa7\x3d\x2c\x22\xc5\xd9\xbb" + "\xc8\x36\x64\x72\x41\xd9\x53\xd4\x0c\x5b\x12\xda\x88\x12\x0d\x53" + "\x17\x7f\x80\xe5\x32\xc4\x1f\xa0", + .pub_b = "\x3e\xb7\xa8\x29\xb0\xcd\x20\xf5\xbc\xfc\x0b\x59\x9b\x6f\xec\xcf" + "\x6d\xa4\x62\x71\x07\xbd\xb0\xd4\xf3\x45\xb4\x30\x27\xd8\xb9\x72" + "\xfc\x3e\x34\xfb\x42\x32\xa1\x3c\xa7\x06\xdc\xb5\x7a\xec\x3d\xae" + "\x07\xbd\xc1\xc6\x7b\xf3\x36\x09", + .shared = "\x07\xff\xf4\x18\x1a\xc6\xcc\x95\xec\x1c\x16\xa9\x4a\x0f\x74\xd1" + "\x2d\xa2\x32\xce\x40\xa7\x75\x52\x28\x1d\x28\x2b\xb6\x0c\x0b\x56" + "\xfd\x24\x64\xc3\x35\x54\x39\x36\x52\x1c\x24\x40\x30\x85\xd5\x9a" + "\x44\x9a\x50\x37\x51\x4a\x87\x9d", +}; From d222699c78abbacd66de5bb4ee32df320464a192 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 15 Nov 2018 11:25:06 +0100 Subject: [PATCH 03/12] dh-speed: Add curve448 keyword --- scripts/dh_speed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/dh_speed.c b/scripts/dh_speed.c index f2f98d7af..235772faf 100644 --- a/scripts/dh_speed.c +++ b/scripts/dh_speed.c @@ -47,6 +47,7 @@ struct { {"ecp192", ECP_192_BIT}, {"ecp224", ECP_224_BIT}, {"curve25519", CURVE_25519}, + {"curve448", CURVE_448}, }; static void start_timing(struct timespec *start) From cbf07ab5b0b644c7bf5f7177efabc841b230b551 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 15 Nov 2018 15:54:05 +0100 Subject: [PATCH 04/12] openssl: Add support for Ed25519/Ed448 --- src/libstrongswan/plugins/openssl/Makefile.am | 4 +- .../plugins/openssl/openssl_ed_private_key.c | 356 ++++++++++++++++++ .../plugins/openssl/openssl_ed_private_key.h | 58 +++ .../plugins/openssl/openssl_ed_public_key.c | 304 +++++++++++++++ .../plugins/openssl/openssl_ed_public_key.h | 38 ++ .../plugins/openssl/openssl_plugin.c | 45 ++- src/libstrongswan/tests/suites/test_ed25519.c | 8 +- 7 files changed, 800 insertions(+), 13 deletions(-) create mode 100644 src/libstrongswan/plugins/openssl/openssl_ed_private_key.c create mode 100644 src/libstrongswan/plugins/openssl/openssl_ed_private_key.h create mode 100644 src/libstrongswan/plugins/openssl/openssl_ed_public_key.c create mode 100644 src/libstrongswan/plugins/openssl/openssl_ed_public_key.h diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index f2d06a5d1..d484092e7 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -30,7 +30,9 @@ libstrongswan_openssl_la_SOURCES = \ openssl_rng.c openssl_rng.h \ openssl_hmac.c openssl_hmac.h \ openssl_gcm.c openssl_gcm.h \ - openssl_x_diffie_hellman.c openssl_x_diffie_hellman.h + openssl_x_diffie_hellman.c openssl_x_diffie_hellman.h \ + openssl_ed_private_key.c openssl_ed_private_key.h \ + openssl_ed_public_key.c openssl_ed_public_key.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = $(OPENSSL_LIB) diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c new file mode 100644 index 000000000..b5bc9b868 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +#include + +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) + +#include "openssl_ed_private_key.h" + +#include + +typedef struct private_private_key_t private_private_key_t; + +/** + * Private data + */ +struct private_private_key_t { + + /** + * Public interface + */ + private_key_t public; + + /** + * Key object + */ + EVP_PKEY *key; + + /** + * Key type + */ + key_type_t type; + + /** + * TRUE if the key is from an OpenSSL ENGINE and might not be readable + */ + bool engine; + + /** + * reference count + */ + refcount_t ref; +}; + +/** + * We can't include asn1.h, declare function prototype directly + */ +int asn1_unwrap(chunk_t*, chunk_t*); + +/* from ed public key */ +int openssl_ed_key_type(key_type_t type); +int openssl_ed_keysize(key_type_t type); +bool openssl_ed_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp); + +METHOD(private_key_t, sign, bool, + private_private_key_t *this, signature_scheme_t scheme, + void *params, chunk_t data, chunk_t *signature) +{ + EVP_MD_CTX *ctx; + bool success = FALSE; + + if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) || + (this->type == KEY_ED448 && scheme != SIGN_ED448)) + { + DBG1(DBG_LIB, "signature scheme %N not supported by %N key", + signature_scheme_names, scheme, key_type_names, this->type); + return FALSE; + } + + ctx = EVP_MD_CTX_new(); + if (!ctx || + EVP_DigestSignInit(ctx, NULL, NULL, NULL, this->key) <= 0) + { + goto error; + } + + if (EVP_DigestSign(ctx, NULL, &signature->len, data.ptr, data.len) <= 0) + { + goto error; + } + + *signature = chunk_alloc(signature->len); + + if (EVP_DigestSign(ctx, signature->ptr, &signature->len, + data.ptr, data.len) <= 0) + { + goto error; + } + + success = TRUE; + +error: + EVP_MD_CTX_free(ctx); + return success; +} + +METHOD(private_key_t, decrypt, bool, + private_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) +{ + DBG1(DBG_LIB, "EdDSA private key decryption not implemented"); + return FALSE; +} + +METHOD(private_key_t, get_keysize, int, + private_private_key_t *this) +{ + return openssl_ed_keysize(this->type); +} + +METHOD(private_key_t, get_type, key_type_t, + private_private_key_t *this) +{ + return this->type; +} + +METHOD(private_key_t, get_public_key, public_key_t*, + private_private_key_t *this) +{ + public_key_t *public; + chunk_t key; + + if (!EVP_PKEY_get_raw_public_key(this->key, NULL, &key.len)) + { + return FALSE; + } + key = chunk_alloca(key.len); + if (!EVP_PKEY_get_raw_public_key(this->key, key.ptr, &key.len)) + { + return FALSE; + } + public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, this->type, + BUILD_EDDSA_PUB, key, BUILD_END); + return public; +} + +METHOD(private_key_t, get_fingerprint, bool, + private_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) +{ + return openssl_ed_fingerprint(this->key, type, fingerprint); +} + +METHOD(private_key_t, get_encoding, bool, + private_private_key_t *this, cred_encoding_type_t type, chunk_t *encoding) +{ + u_char *p; + + if (this->engine) + { + return FALSE; + } + + switch (type) + { + case PRIVKEY_ASN1_DER: + case PRIVKEY_PEM: + { + bool success = TRUE; + + *encoding = chunk_alloc(i2d_PrivateKey(this->key, NULL)); + p = encoding->ptr; + i2d_PrivateKey(this->key, &p); + + if (type == PRIVKEY_PEM) + { + chunk_t asn1_encoding = *encoding; + + success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, + NULL, encoding, CRED_PART_EDDSA_PRIV_ASN1_DER, + asn1_encoding, CRED_PART_END); + chunk_clear(&asn1_encoding); + } + return success; + } + default: + return FALSE; + } +} + +METHOD(private_key_t, get_ref, private_key_t*, + private_private_key_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +METHOD(private_key_t, destroy, void, + private_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + lib->encoding->clear_cache(lib->encoding, this->key); + EVP_PKEY_free(this->key); + free(this); + } +} + +/** + * Internal generic constructor + */ +static private_private_key_t *create_internal(key_type_t type, EVP_PKEY *key) +{ + private_private_key_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .sign = _sign, + .decrypt = _decrypt, + .get_keysize = _get_keysize, + .get_public_key = _get_public_key, + .equals = private_key_equals, + .belongs_to = private_key_belongs_to, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = private_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .type = type, + .key = key, + .ref = 1, + ); + + return this; +} + +/* + * Described in header + */ +private_key_t *openssl_ed_private_key_create(EVP_PKEY *key, bool engine) +{ + private_private_key_t *this; + key_type_t type; + + switch (EVP_PKEY_base_id(key)) + { + case EVP_PKEY_X25519: + type = KEY_ED25519; + break; + case EVP_PKEY_X448: + type = KEY_ED448; + break; + default: + EVP_PKEY_free(key); + return NULL; + } + + this = create_internal(type, key); + this->engine = engine; + return &this->public; +} + +/* + * Described in header + */ +private_key_t *openssl_ed_private_key_gen(key_type_t type, va_list args) +{ + private_private_key_t *this; + EVP_PKEY_CTX *ctx; + EVP_PKEY *key = NULL; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_KEY_SIZE: + /* just ignore the key size */ + va_arg(args, u_int); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + ctx = EVP_PKEY_CTX_new_id(openssl_ed_key_type(type), NULL); + if (!ctx || + EVP_PKEY_keygen_init(ctx) <= 0 || + EVP_PKEY_keygen(ctx, &key) <= 0) + { + DBG1(DBG_LIB, "generating %N key failed", key_type_names, type); + EVP_PKEY_CTX_free(ctx); + return NULL; + } + EVP_PKEY_CTX_free(ctx); + + this = create_internal(type, key); + return &this->public; +} + +/* + * Described in header + */ +private_key_t *openssl_ed_private_key_load(key_type_t type, va_list args) +{ + private_private_key_t *this; + chunk_t blob = chunk_empty, priv = chunk_empty; + EVP_PKEY *key = NULL; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); + continue; + case BUILD_EDDSA_PRIV_ASN1_DER: + priv = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + if (priv.len) + { + /* unwrap octet string */ + if (asn1_unwrap(&priv, &priv) == 0x04 && priv.len) + { + key = EVP_PKEY_new_raw_private_key(openssl_ed_key_type(type), NULL, + priv.ptr, priv.len); + } + } + else if (blob.len) + { + key = d2i_PrivateKey(openssl_ed_key_type(type), NULL, + (const u_char**)&blob.ptr, blob.len); + } + if (!key) + { + return NULL; + } + this = create_internal(type, key); + return &this->public; +} + +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_private_key.h b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.h new file mode 100644 index 000000000..ce9071348 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +/** + * @defgroup openssl_ed_private_key openssl_ed_private_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_ED_PRIVATE_KEY_H_ +#define OPENSSL_ED_PRIVATE_KEY_H_ + +#include + +#include +#include + +/** + * Generate an EdDSA private key using OpenSSL. + * + * @param type type of the key, must be KEY_ED25519 or KEY_ED448 + * @param args builder_part_t argument list + * @return generated key, NULL on failure + */ +private_key_t *openssl_ed_private_key_gen(key_type_t type, va_list args); + +/** + * Load an EdDSA private key using OpenSSL. + * + * Accepts a BUILD_BLOB_ASN1_DER argument. + * + * @param type type of the key, must be KEY_ED25519 or KEY_ED448 + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +private_key_t *openssl_ed_private_key_load(key_type_t type, va_list args); + +/** + * Wrap an EVP_PKEY object of type EVP_PKEY_ED25519/448 + * + * @param key EVP_PKEY object (adopted) + * @param engine whether the key was loaded via an engine + * @return loaded key, NULL on failure + */ +private_key_t *openssl_ed_private_key_create(EVP_PKEY *key, bool engine); + +#endif /** OPENSSL_ED_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c new file mode 100644 index 000000000..2daddc57e --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +#include + +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) + +#include + +#include "openssl_ed_public_key.h" + +#include + +typedef struct private_public_key_t private_public_key_t; + +/** + * Private data + */ +struct private_public_key_t { + + /** + * Public interface + */ + public_key_t public; + + /** + * Key object + */ + EVP_PKEY *key; + + /** + * Key type + */ + key_type_t type; + + /** + * Reference counter + */ + refcount_t ref; +}; + +/** + * Map a key type to an EVP key type + */ +int openssl_ed_key_type(key_type_t type) +{ + switch (type) + { + case KEY_ED25519: + return EVP_PKEY_ED25519; + case KEY_ED448: + return EVP_PKEY_ED448; + default: + return 0; + } +} + +/** + * Map a key type to a key size + */ +int openssl_ed_keysize(key_type_t type) +{ + switch (type) + { + case KEY_ED25519: + return 32 * 8; + case KEY_ED448: + return 57 * 8; + default: + return 0; + } +} + +METHOD(public_key_t, get_type, key_type_t, + private_public_key_t *this) +{ + return this->type; +} + +METHOD(public_key_t, verify, bool, + private_public_key_t *this, signature_scheme_t scheme, + void *params, chunk_t data, chunk_t signature) +{ + EVP_MD_CTX *ctx; + + if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) || + (this->type == KEY_ED448 && scheme != SIGN_ED448)) + { + DBG1(DBG_LIB, "signature scheme %N not supported by %N key", + signature_scheme_names, scheme, key_type_names, this->type); + return FALSE; + } + + ctx = EVP_MD_CTX_new(); + if (!ctx || + EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, this->key) <= 0 || + EVP_DigestVerify(ctx, signature.ptr, signature.len, + data.ptr, data.len) <= 0) + { + EVP_MD_CTX_free(ctx); + return FALSE; + } + EVP_MD_CTX_free(ctx); + return TRUE; +} + +METHOD(public_key_t, encrypt, bool, + private_public_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) +{ + DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names, + scheme); + return FALSE; +} + +METHOD(public_key_t, get_keysize, int, + private_public_key_t *this) +{ + return openssl_ed_keysize(this->type); +} + +/** + * Calculate fingerprint from an EdDSA key, also used in ed private key. + */ +bool openssl_ed_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, + chunk_t *fp) +{ + hasher_t *hasher; + chunk_t blob; + u_char *p; + + if (lib->encoding->get_cache(lib->encoding, type, key, fp)) + { + return TRUE; + } + switch (type) + { + case KEYID_PUBKEY_SHA1: + if (!EVP_PKEY_get_raw_public_key(key, NULL, &blob.len)) + { + return FALSE; + } + blob = chunk_alloca(blob.len); + if (!EVP_PKEY_get_raw_public_key(key, blob.ptr, &blob.len)) + { + return FALSE; + } + break; + case KEYID_PUBKEY_INFO_SHA1: + blob = chunk_alloca(i2d_PUBKEY(key, NULL)); + p = blob.ptr; + i2d_PUBKEY(key, &p); + break; + default: + return FALSE; + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher || !hasher->allocate_hash(hasher, blob, fp)) + { + DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed"); + DESTROY_IF(hasher); + return FALSE; + } + hasher->destroy(hasher); + lib->encoding->cache(lib->encoding, type, key, *fp); + return TRUE; +} + +METHOD(public_key_t, get_fingerprint, bool, + private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint) +{ + return openssl_ed_fingerprint(this->key, type, fingerprint); +} + +METHOD(public_key_t, get_encoding, bool, + private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding) +{ + bool success = TRUE; + u_char *p; + + *encoding = chunk_alloc(i2d_PUBKEY(this->key, NULL)); + p = encoding->ptr; + i2d_PUBKEY(this->key, &p); + + if (type != PUBKEY_SPKI_ASN1_DER) + { + chunk_t asn1_encoding = *encoding; + + success = lib->encoding->encode(lib->encoding, type, + NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER, + asn1_encoding, CRED_PART_END); + chunk_clear(&asn1_encoding); + } + return success; +} + +METHOD(public_key_t, get_ref, public_key_t*, + private_public_key_t *this) +{ + ref_get(&this->ref); + return &this->public; +} + +METHOD(public_key_t, destroy, void, + private_public_key_t *this) +{ + if (ref_put(&this->ref)) + { + lib->encoding->clear_cache(lib->encoding, this->key); + EVP_PKEY_free(this->key); + free(this); + } +} + +/** + * Generic private constructor + */ +static private_public_key_t *create_empty(key_type_t type) +{ + private_public_key_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .verify = _verify, + .encrypt = _encrypt, + .get_keysize = _get_keysize, + .equals = public_key_equals, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = public_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .type = type, + .ref = 1, + ); + + return this; +} + +/* + * Described in header + */ +public_key_t *openssl_ed_public_key_load(key_type_t type, va_list args) +{ + private_public_key_t *this; + chunk_t blob = chunk_empty, pub = chunk_empty; + EVP_PKEY *key = NULL; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_ASN1_DER: + blob = va_arg(args, chunk_t); + continue; + case BUILD_EDDSA_PUB: + pub = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + if (pub.len) + { + key = EVP_PKEY_new_raw_public_key(openssl_ed_key_type(type), NULL, + pub.ptr, pub.len); + } + else if (blob.len) + { + key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len); + if (key && EVP_PKEY_base_id(key) != openssl_ed_key_type(type)) + { + EVP_PKEY_free(key); + return NULL; + } + } + if (!key) + { + return NULL; + } + this = create_empty(type); + this->key = key; + return &this->public; +} + +#endif /* OPENSSL_VERSION_NUMBER */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h new file mode 100644 index 000000000..c4e1ba3ed --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +/** + * @defgroup openssl_ed_public_key openssl_ed_public_key + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_ED_PUBLIC_KEY_H_ +#define OPENSSL_ED_PUBLIC_KEY_H_ + +#include +#include + +/** + * Load an EdDSA public key using OpenSSL. + * + * Accepts a BUILD_BLOB_ASN1_DER argument. + * + * @param type type of the key, must be KEY_ED25519 or KEY_ED448 + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +public_key_t *openssl_ed_public_key_load(key_type_t type, va_list args); + +#endif /** OPENSSL_ED_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index ca1c9b369..c5f1c5b14 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2016 Tobias Brunner + * Copyright (C) 2008-2018 Tobias Brunner * Copyright (C) 2008 Martin Willi * HSR Hochschule fuer Technik Rapperswil * @@ -48,6 +48,8 @@ #include "openssl_hmac.h" #include "openssl_gcm.h" #include "openssl_x_diffie_hellman.h" +#include "openssl_ed_public_key.h" +#include "openssl_ed_private_key.h" #ifndef FIPS_MODE #define FIPS_MODE 0 @@ -308,6 +310,11 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args) case EVP_PKEY_EC: return openssl_ec_private_key_create(key, FALSE); #endif +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) + case EVP_PKEY_ED25519: + case EVP_PKEY_ED448: + return openssl_ed_private_key_create(key, FALSE); +#endif /* OPENSSL_VERSION_NUMBER */ default: EVP_PKEY_free(key); break; @@ -455,6 +462,11 @@ static private_key_t *openssl_private_key_connect(key_type_t type, case EVP_PKEY_EC: return openssl_ec_private_key_create(key, TRUE); #endif +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) + case EVP_PKEY_ED25519: + case EVP_PKEY_ED448: + return openssl_ed_private_key_create(key, TRUE); +#endif /* OPENSSL_VERSION_NUMBER */ default: EVP_PKEY_free(key); break; @@ -595,13 +607,6 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(DH, ECP_384_BP), PLUGIN_PROVIDE(DH, ECP_512_BP), PLUGIN_PROVIDE(DH, ECP_224_BP), -#if OPENSSL_VERSION_NUMBER >= 0x1010100fL - PLUGIN_REGISTER(DH, openssl_x_diffie_hellman_create), - /* available since 1.1.0a, but we require 1.1.1 features */ - PLUGIN_PROVIDE(DH, CURVE_25519), - /* available since 1.1.1 */ - PLUGIN_PROVIDE(DH, CURVE_448), -#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_NO_ECDH */ #ifndef OPENSSL_NO_DH /* MODP DH groups */ @@ -707,6 +712,30 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_521), #endif #endif /* OPENSSL_NO_ECDSA */ +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) + PLUGIN_REGISTER(DH, openssl_x_diffie_hellman_create), + /* available since 1.1.0a, but we require 1.1.1 features */ + PLUGIN_PROVIDE(DH, CURVE_25519), + /* available since 1.1.1 */ + PLUGIN_PROVIDE(DH, CURVE_448), + /* EdDSA private/public key loading */ + PLUGIN_REGISTER(PUBKEY, openssl_ed_public_key_load, TRUE), + PLUGIN_PROVIDE(PUBKEY, KEY_ED25519), + PLUGIN_PROVIDE(PUBKEY, KEY_ED448), + PLUGIN_REGISTER(PRIVKEY, openssl_ed_private_key_load, TRUE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ED25519), + PLUGIN_PROVIDE(PRIVKEY, KEY_ED448), + PLUGIN_REGISTER(PRIVKEY_GEN, openssl_ed_private_key_gen, FALSE), + PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_ED25519), + PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_ED448), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ED25519), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ED448), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ED25519), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ED448), + /* register a pro forma identity hasher, never instantiated */ + PLUGIN_REGISTER(HASHER, return_null), + PLUGIN_PROVIDE(HASHER, HASH_IDENTITY), +#endif /* OPENSSL_VERSION_NUMBER && !OPENSSL_NO_EC */ /* generic key loader */ PLUGIN_REGISTER(PRIVKEY, openssl_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), diff --git a/src/libstrongswan/tests/suites/test_ed25519.c b/src/libstrongswan/tests/suites/test_ed25519.c index 86cbb1bc0..35da95d21 100644 --- a/src/libstrongswan/tests/suites/test_ed25519.c +++ b/src/libstrongswan/tests/suites/test_ed25519.c @@ -280,7 +280,7 @@ START_TEST(test_ed25519_sign) BUILD_BLOB_ASN1_DER, sig_tests[_i].key, BUILD_END); ck_assert(key != NULL); ck_assert(key->get_encoding(key, PRIVKEY_ASN1_DER, &encoding)); - ck_assert(chunk_equals(encoding, sig_tests[_i].key)); + ck_assert_chunk_eq(encoding, sig_tests[_i].key); chunk_free(&encoding); /* load public key */ @@ -288,7 +288,7 @@ START_TEST(test_ed25519_sign) BUILD_BLOB_ASN1_DER, sig_tests[_i].pubkey, BUILD_END); ck_assert(pubkey != NULL); ck_assert(pubkey->get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &encoding)); - ck_assert(chunk_equals(encoding, sig_tests[_i].pubkey)); + ck_assert_chunk_eq(encoding, sig_tests[_i].pubkey); chunk_free(&encoding); /* compare public keys */ @@ -299,7 +299,7 @@ START_TEST(test_ed25519_sign) /* sign */ ck_assert(key->sign(key, SIGN_ED25519, NULL, sig_tests[_i].msg, &sig)); ck_assert(sig.len == 64); - ck_assert(chunk_equals(sig, sig_tests[_i].sig)); + ck_assert_chunk_eq(sig, sig_tests[_i].sig); /* verify */ ck_assert(pubkey->verify(pubkey, SIGN_ED25519, NULL, sig_tests[_i].msg, @@ -364,7 +364,7 @@ START_TEST(test_ed25519_gen) ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp_pub)); ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp_pub)); ck_assert(fp_pub.ptr != NULL); - ck_assert(chunk_equals(fp_pub, fp_priv)); + ck_assert_chunk_eq(fp_pub, fp_priv); /* clone public key */ pubkey2 = pubkey->get_ref(pubkey); From 6fc90cea74a7321b9463e60aafe68333fe05247e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 16 Nov 2018 10:57:50 +0100 Subject: [PATCH 05/12] leak-detective: Whitelist functions added in OpenSSL 1.1.1 --- src/libstrongswan/utils/leak_detective.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 07f33c83d..63b7453f3 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -587,6 +587,11 @@ static char *whitelist[] = { "OPENSSL_load_builtin_modules", "CONF_modules_load_file", "CONF_module_add", + "RAND_DRBG_bytes", + "RAND_DRBG_generate", + "RAND_DRBG_get0_master", + "RAND_DRBG_get0_private", + "RAND_DRBG_get0_public", /* OpenSSL libssl */ "SSL_COMP_get_compression_methods", /* NSPR */ From 69756c0bffb6ec905bf2008001669045b13c96ad Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 16 Nov 2018 11:11:27 +0100 Subject: [PATCH 06/12] openssl: Use separate DRBG for RNG_STRONG and RNG_TRUE with OpenSSL 1.1.1 OpenSSL 1.1.1 introduces DRGBs and provides two sources (same security profile etc. but separate internal state), which allows us to use one for RNG_WEAK (e.g. for nonces that are directly publicly visible) and the other for stronger random data like keys. --- src/libstrongswan/plugins/openssl/openssl_rng.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c index a25b6b4b6..9514ca916 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rng.c +++ b/src/libstrongswan/plugins/openssl/openssl_rng.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012-2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Aleksandr Grinberg * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,7 +27,6 @@ #include #include -#include #include "openssl_rng.h" @@ -49,6 +51,13 @@ struct private_openssl_rng_t { METHOD(rng_t, get_bytes, bool, private_openssl_rng_t *this, size_t bytes, uint8_t *buffer) { +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL + if (this->quality > RNG_WEAK) + { /* use a separate DRBG for data we wan't to keep private, compared + * to e.g. nonces */ + return RAND_priv_bytes((char*)buffer, bytes) == 1; + } +#endif return RAND_bytes((char*)buffer, bytes) == 1; } From 2571898d32609ffdd2fb8c5ce1659f3732efb026 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 16 Nov 2018 15:48:56 +0100 Subject: [PATCH 07/12] curve25519: Prevent Ed25519 signature malleability As per RFC 8032, section 5.1.7 (and section 8.4) we have to make sure s, which is the scalar in the second half of the signature value, is smaller than L. Without that check, L can be added to most signatures at least once to create another valid signature for the same public key and message. This could be problematic if, for instance, a blacklist is based on hashes of certificates. A new certificate could be created with a different signature (without knowing the signature key) by simply adding L to s. Currently, both OpenSSL 1.1.1 and Botan 2.8.0 are vulnerable to this, which is why the unit test currently only warns about it. --- .../curve25519/curve25519_public_key.c | 21 ++++++++++++++++++ src/libstrongswan/tests/suites/test_ed25519.c | 22 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c index 6eb80a119..dfc1df4d0 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c @@ -49,6 +49,13 @@ METHOD(public_key_t, get_type, key_type_t, return KEY_ED25519; } +/* L = 2^252+27742317777372353535851937790883648493 in little-endian form */ +static chunk_t curve25519_order = chunk_from_chars( + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10); + METHOD(public_key_t, verify, bool, private_curve25519_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t signature) @@ -94,6 +101,20 @@ METHOD(public_key_t, verify, bool, { return FALSE; } + /* make sure 0 <= s < L, as per RFC 8032, section 5.1.7 to prevent signature + * malleability. Due to the three-bit check above (forces s < 2^253) there + * is not that much room, but adding L once works with most signatures */ + for (i = 31; ; i--) + { + if (sig[i+32] < curve25519_order.ptr[i]) + { + break; + } + else if (sig[i+32] > curve25519_order.ptr[i] || i == 0) + { + return FALSE; + } + } hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); if (!hasher) diff --git a/src/libstrongswan/tests/suites/test_ed25519.c b/src/libstrongswan/tests/suites/test_ed25519.c index 35da95d21..d69076d7d 100644 --- a/src/libstrongswan/tests/suites/test_ed25519.c +++ b/src/libstrongswan/tests/suites/test_ed25519.c @@ -27,7 +27,7 @@ struct sig_test_t { }; /** - * Ed25519 Test Vectors from draft-irtf-cfrg-eddsa + * Ed25519 Test Vectors from RFC 8032 */ static sig_test_t sig_tests[] = { /* Test 1 */ @@ -429,6 +429,16 @@ static chunk_t zero_pk = chunk_from_chars( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +/* sig_tests[0].sig with s+L */ +static chunk_t malleable_sig = chunk_from_chars( + 0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, 0x90, 0x86, + 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a, 0x84, 0x87, 0x7f, 0x1e, + 0xb8, 0xe5, 0xd9, 0x74, 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, + 0x01, 0x55, 0x4c, 0x8c, 0x78, 0x72, 0xaa, 0x06, 0x4e, 0x04, + 0x9d, 0xbb, 0x30, 0x13, 0xfb, 0xf2, 0x93, 0x80, 0xd2, 0x5b, + 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, + 0x8e, 0x7a, 0x10, 0x1b); + START_TEST(test_ed25519_fail) { private_key_t *key; @@ -479,6 +489,16 @@ START_TEST(test_ed25519_fail) ck_assert(!pubkey->verify(pubkey, SIGN_ED25519, NULL, chunk_empty, chunk_empty)); + /* RFC 8032, section 5.1.7 requires that 0 <= s < L to prevent signature + * malleability. Only a warning because Botan and OpenSSL are both + * vulnerable to this. */ + if (pubkey->verify(pubkey, SIGN_ED25519, NULL, sig_tests[0].msg, + malleable_sig)) + { + warn("Ed25519 signature verification is vulnerable to malleable " + "signatures"); + } + /* malformed signature */ sig = chunk_create(sig1, 64); memcpy(sig1, sig_tests[0].sig.ptr, 64); From 8d7bf5b039bb0e0576bdee269b03490fbeee0211 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 30 Nov 2018 15:34:32 +0100 Subject: [PATCH 08/12] unit-tests: Add fingerprint test vectors for Ed25519 --- src/libstrongswan/tests/suites/test_ed25519.c | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/libstrongswan/tests/suites/test_ed25519.c b/src/libstrongswan/tests/suites/test_ed25519.c index d69076d7d..c52b90885 100644 --- a/src/libstrongswan/tests/suites/test_ed25519.c +++ b/src/libstrongswan/tests/suites/test_ed25519.c @@ -24,6 +24,8 @@ struct sig_test_t { chunk_t pubkey; chunk_t msg; chunk_t sig; + chunk_t fp_pk; + chunk_t fp_spki; }; /** @@ -51,7 +53,13 @@ static sig_test_t sig_tests[] = { 0x01, 0x55, 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, 0x65, 0x51, 0x41, 0x43, - 0x8e, 0x7a, 0x10, 0x0b) + 0x8e, 0x7a, 0x10, 0x0b), + chunk_from_chars( + 0x5b, 0x27, 0xaa, 0x55, 0x89, 0x17, 0x97, 0x70, 0xe4, 0x75, + 0x75, 0xb1, 0x62, 0xa1, 0xde, 0xd9, 0x7b, 0x8b, 0xfc, 0x6d), + chunk_from_chars( + 0xa5, 0x66, 0xbe, 0x19, 0x84, 0x01, 0x73, 0x41, 0x3a, 0x61, + 0x04, 0x83, 0x50, 0xef, 0xf2, 0x3e, 0x8f, 0xe2, 0x22, 0x66), }, /* Test 2 */ { chunk_from_chars( @@ -75,7 +83,13 @@ static sig_test_t sig_tests[] = { 0x69, 0xda, 0x08, 0x5a, 0xc1, 0xe4, 0x3e, 0x15, 0x99, 0x6e, 0x45, 0x8f, 0x36, 0x13, 0xd0, 0xf1, 0x1d, 0x8c, 0x38, 0x7b, 0x2e, 0xae, 0xb4, 0x30, 0x2a, 0xee, 0xb0, 0x0d, 0x29, 0x16, - 0x12, 0xbb, 0x0c, 0x00) + 0x12, 0xbb, 0x0c, 0x00), + chunk_from_chars( + 0x13, 0xf7, 0x72, 0x66, 0x9e, 0x15, 0x2a, 0xe6, 0xa6, 0x2a, + 0x60, 0xa3, 0x48, 0x8a, 0x6f, 0x29, 0x7d, 0x06, 0x13, 0xdd), + chunk_from_chars( + 0xbd, 0xae, 0x41, 0xeb, 0x5d, 0xbf, 0x88, 0xb9, 0xdf, 0x18, + 0xda, 0xbb, 0x2d, 0xee, 0xa9, 0x1a, 0x4e, 0x03, 0x38, 0xe4), }, /* Test 3 */ { chunk_from_chars( @@ -99,7 +113,13 @@ static sig_test_t sig_tests[] = { 0xc3, 0xac, 0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59, 0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, 0xc0, 0x27, 0xbe, 0xce, - 0xea, 0x1e, 0xc4, 0x0a) + 0xea, 0x1e, 0xc4, 0x0a), + chunk_from_chars( + 0x88, 0xc7, 0x64, 0xc8, 0xbe, 0x44, 0x37, 0x4a, 0x7d, 0x2f, + 0x5d, 0x84, 0x72, 0x1f, 0x8e, 0x32, 0x5e, 0x5b, 0xd6, 0x4c), + chunk_from_chars( + 0xad, 0x01, 0x30, 0xb1, 0x2b, 0x48, 0x62, 0x9b, 0xb9, 0xad, + 0xea, 0x92, 0x1f, 0xfe, 0xd2, 0x9a, 0x42, 0xf0, 0xad, 0xe6), }, /* Test 1024 */ { chunk_from_chars( @@ -235,7 +255,13 @@ static sig_test_t sig_tests[] = { 0xc3, 0x50, 0xaa, 0x53, 0x71, 0xb1, 0x50, 0x8f, 0x9f, 0x45, 0x28, 0xec, 0xea, 0x23, 0xc4, 0x36, 0xd9, 0x4b, 0x5e, 0x8f, 0xcd, 0x4f, 0x68, 0x1e, 0x30, 0xa6, 0xac, 0x00, 0xa9, 0x70, - 0x4a, 0x18, 0x8a, 0x03) + 0x4a, 0x18, 0x8a, 0x03), + chunk_from_chars( + 0x11, 0x2d, 0xb3, 0x08, 0x97, 0x6e, 0x38, 0x8f, 0x5f, 0x5e, + 0xb0, 0xae, 0x8f, 0x5f, 0x59, 0x1d, 0xff, 0x74, 0xf4, 0x44), + chunk_from_chars( + 0xcb, 0x36, 0xcc, 0x6a, 0x82, 0x2c, 0x49, 0x40, 0xfb, 0x08, + 0x04, 0xf6, 0x3a, 0x4f, 0x20, 0x2b, 0xe5, 0x73, 0x43, 0x2f), }, /* Test SHA(abc) */ { chunk_from_chars( @@ -265,7 +291,13 @@ static sig_test_t sig_tests[] = { 0xb5, 0x89, 0x09, 0x35, 0x1f, 0xc9, 0xac, 0x90, 0xb3, 0xec, 0xfd, 0xfb, 0xc7, 0xc6, 0x64, 0x31, 0xe0, 0x30, 0x3d, 0xca, 0x17, 0x9c, 0x13, 0x8a, 0xc1, 0x7a, 0xd9, 0xbe, 0xf1, 0x17, - 0x73, 0x31, 0xa7, 0x04) + 0x73, 0x31, 0xa7, 0x04), + chunk_from_chars( + 0x26, 0x4c, 0xa5, 0x7f, 0x89, 0x6d, 0x64, 0x81, 0xd1, 0x87, + 0xe9, 0x89, 0x47, 0x29, 0x5a, 0xfe, 0xe3, 0x6d, 0x82, 0x44), + chunk_from_chars( + 0x27, 0x88, 0xfc, 0x14, 0xb1, 0xcd, 0xd0, 0x24, 0xd5, 0x9d, + 0x31, 0x65, 0x59, 0x63, 0x69, 0xcf, 0xaf, 0x50, 0x10, 0xe7), } }; @@ -273,7 +305,7 @@ START_TEST(test_ed25519_sign) { private_key_t *key; public_key_t *pubkey, *public; - chunk_t sig, encoding; + chunk_t sig, encoding, fp; /* load private key */ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED25519, @@ -283,6 +315,11 @@ START_TEST(test_ed25519_sign) ck_assert_chunk_eq(encoding, sig_tests[_i].key); chunk_free(&encoding); + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_pk, fp); + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_spki, fp); + /* load public key */ pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED25519, BUILD_BLOB_ASN1_DER, sig_tests[_i].pubkey, BUILD_END); @@ -291,6 +328,11 @@ START_TEST(test_ed25519_sign) ck_assert_chunk_eq(encoding, sig_tests[_i].pubkey); chunk_free(&encoding); + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_pk, fp); + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_INFO_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_spki, fp); + /* compare public keys */ public = key->get_public_key(key); ck_assert(public != NULL); From 25e62f01ea750d56042ec6261a7d11c1a68f785c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 16 Nov 2018 11:44:17 +0100 Subject: [PATCH 09/12] unit-tests: Add test suite for Ed448 Same issue with signature malleability as with Ed25519 and apparently OpenSSL doesn't even explicitly verify that the most significant 10 bits are all zero. --- src/libstrongswan/tests/Makefile.am | 1 + src/libstrongswan/tests/suites/test_ed448.c | 654 ++++++++++++++++++++ src/libstrongswan/tests/tests.h | 1 + 3 files changed, 656 insertions(+) create mode 100644 src/libstrongswan/tests/suites/test_ed448.c diff --git a/src/libstrongswan/tests/Makefile.am b/src/libstrongswan/tests/Makefile.am index 5737e7a17..d4cac5a3b 100644 --- a/src/libstrongswan/tests/Makefile.am +++ b/src/libstrongswan/tests/Makefile.am @@ -58,6 +58,7 @@ libstrongswan_tests_SOURCES = tests.h tests.c \ suites/test_mgf1.c \ suites/test_ntru.c \ suites/test_ed25519.c \ + suites/test_ed448.c \ suites/test_signature_params.c libstrongswan_tests_CFLAGS = \ diff --git a/src/libstrongswan/tests/suites/test_ed448.c b/src/libstrongswan/tests/suites/test_ed448.c new file mode 100644 index 000000000..288da19a0 --- /dev/null +++ b/src/libstrongswan/tests/suites/test_ed448.c @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2016 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program 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 General Public License + * for more details. + */ + +#include "test_suite.h" + +#include + +typedef struct sig_test_t sig_test_t; + +struct sig_test_t { + chunk_t key; + chunk_t pubkey; + chunk_t msg; + chunk_t sig; + chunk_t fp_pk; + chunk_t fp_spki; +}; + +/** + * Ed448 Test Vectors from RFC 8032 + */ +static sig_test_t sig_tests[] = { + /* Blank */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0x6c,0x82,0xa5,0x62,0xcb,0x80,0x8d,0x10,0xd6,0x32,0xbe,0x89,0xc8,0x51,0x3e,0xbf, + 0x6c,0x92,0x9f,0x34,0xdd,0xfa,0x8c,0x9f,0x63,0xc9,0x96,0x0e,0xf6,0xe3,0x48,0xa3, + 0x52,0x8c,0x8a,0x3f,0xcc,0x2f,0x04,0x4e,0x39,0xa3,0xfc,0x5b,0x94,0x49,0x2f,0x8f, + 0x03,0x2e,0x75,0x49,0xa2,0x00,0x98,0xf9,0x5b), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0x5f,0xd7,0x44,0x9b, + 0x59,0xb4,0x61,0xfd,0x2c,0xe7,0x87,0xec,0x61,0x6a,0xd4,0x6a,0x1d,0xa1,0x34,0x24, + 0x85,0xa7,0x0e,0x1f,0x8a,0x0e,0xa7,0x5d,0x80,0xe9,0x67,0x78,0xed,0xf1,0x24,0x76, + 0x9b,0x46,0xc7,0x06,0x1b,0xd6,0x78,0x3d,0xf1,0xe5,0x0f,0x6c,0xd1,0xfa,0x1a,0xbe, + 0xaf,0xe8,0x25,0x61,0x80), + { NULL, 0 }, + chunk_from_chars( + 0x53,0x3a,0x37,0xf6,0xbb,0xe4,0x57,0x25,0x1f,0x02,0x3c,0x0d,0x88,0xf9,0x76,0xae, + 0x2d,0xfb,0x50,0x4a,0x84,0x3e,0x34,0xd2,0x07,0x4f,0xd8,0x23,0xd4,0x1a,0x59,0x1f, + 0x2b,0x23,0x3f,0x03,0x4f,0x62,0x82,0x81,0xf2,0xfd,0x7a,0x22,0xdd,0xd4,0x7d,0x78, + 0x28,0xc5,0x9b,0xd0,0xa2,0x1b,0xfd,0x39,0x80,0xff,0x0d,0x20,0x28,0xd4,0xb1,0x8a, + 0x9d,0xf6,0x3e,0x00,0x6c,0x5d,0x1c,0x2d,0x34,0x5b,0x92,0x5d,0x8d,0xc0,0x0b,0x41, + 0x04,0x85,0x2d,0xb9,0x9a,0xc5,0xc7,0xcd,0xda,0x85,0x30,0xa1,0x13,0xa0,0xf4,0xdb, + 0xb6,0x11,0x49,0xf0,0x5a,0x73,0x63,0x26,0x8c,0x71,0xd9,0x58,0x08,0xff,0x2e,0x65, + 0x26,0x00), + chunk_from_chars( + 0x6d,0xe0,0x8a,0x72,0x35,0x1e,0xf1,0xad,0xeb,0xca,0x2c,0xd7,0xf1,0xfd,0xa6,0x91, + 0x54,0xad,0xfa,0x4f), + chunk_from_chars( + 0x1b,0x7a,0x47,0x56,0x91,0xb8,0x41,0x33,0x0d,0x2e,0x4d,0xa5,0xe6,0x13,0xb9,0x89, + 0xda,0xce,0xc5,0x8e), + }, + /* 1 octet */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0xc4,0xea,0xb0,0x5d,0x35,0x70,0x07,0xc6,0x32,0xf3,0xdb,0xb4,0x84,0x89,0x92,0x4d, + 0x55,0x2b,0x08,0xfe,0x0c,0x35,0x3a,0x0d,0x4a,0x1f,0x00,0xac,0xda,0x2c,0x46,0x3a, + 0xfb,0xea,0x67,0xc5,0xe8,0xd2,0x87,0x7c,0x5e,0x3b,0xc3,0x97,0xa6,0x59,0x94,0x9e, + 0xf8,0x02,0x1e,0x95,0x4e,0x0a,0x12,0x27,0x4e), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0x43,0xba,0x28,0xf4, + 0x30,0xcd,0xff,0x45,0x6a,0xe5,0x31,0x54,0x5f,0x7e,0xcd,0x0a,0xc8,0x34,0xa5,0x5d, + 0x93,0x58,0xc0,0x37,0x2b,0xfa,0x0c,0x6c,0x67,0x98,0xc0,0x86,0x6a,0xea,0x01,0xeb, + 0x00,0x74,0x28,0x02,0xb8,0x43,0x8e,0xa4,0xcb,0x82,0x16,0x9c,0x23,0x51,0x60,0x62, + 0x7b,0x4c,0x3a,0x94,0x80), + chunk_from_chars( + 0x03), + chunk_from_chars( + 0x26,0xb8,0xf9,0x17,0x27,0xbd,0x62,0x89,0x7a,0xf1,0x5e,0x41,0xeb,0x43,0xc3,0x77, + 0xef,0xb9,0xc6,0x10,0xd4,0x8f,0x23,0x35,0xcb,0x0b,0xd0,0x08,0x78,0x10,0xf4,0x35, + 0x25,0x41,0xb1,0x43,0xc4,0xb9,0x81,0xb7,0xe1,0x8f,0x62,0xde,0x8c,0xcd,0xf6,0x33, + 0xfc,0x1b,0xf0,0x37,0xab,0x7c,0xd7,0x79,0x80,0x5e,0x0d,0xbc,0xc0,0xaa,0xe1,0xcb, + 0xce,0xe1,0xaf,0xb2,0xe0,0x27,0xdf,0x36,0xbc,0x04,0xdc,0xec,0xbf,0x15,0x43,0x36, + 0xc1,0x9f,0x0a,0xf7,0xe0,0xa6,0x47,0x29,0x05,0xe7,0x99,0xf1,0x95,0x3d,0x2a,0x0f, + 0xf3,0x34,0x8a,0xb2,0x1a,0xa4,0xad,0xaf,0xd1,0xd2,0x34,0x44,0x1c,0xf8,0x07,0xc0, + 0x3a,0x00), + chunk_from_chars( + 0x74,0xa7,0x4b,0x23,0x69,0x98,0x17,0x46,0x1f,0xca,0xcf,0x84,0xf7,0xc6,0x3e,0x05, + 0x2a,0x1b,0xf9,0xb8), + chunk_from_chars( + 0xf6,0x76,0xf7,0x63,0x82,0x2b,0x53,0x5c,0x61,0x9c,0xfa,0x4a,0x59,0x7d,0xdd,0xae, + 0x13,0x34,0xf0,0xb1), + }, + /* 11 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0xcd,0x23,0xd2,0x4f,0x71,0x42,0x74,0xe7,0x44,0x34,0x32,0x37,0xb9,0x32,0x90,0xf5, + 0x11,0xf6,0x42,0x5f,0x98,0xe6,0x44,0x59,0xff,0x20,0x3e,0x89,0x85,0x08,0x3f,0xfd, + 0xf6,0x05,0x00,0x55,0x3a,0xbc,0x0e,0x05,0xcd,0x02,0x18,0x4b,0xdb,0x89,0xc4,0xcc, + 0xd6,0x7e,0x18,0x79,0x51,0x26,0x7e,0xb3,0x28), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0xdc,0xea,0x9e,0x78, + 0xf3,0x5a,0x1b,0xf3,0x49,0x9a,0x83,0x1b,0x10,0xb8,0x6c,0x90,0xaa,0xc0,0x1c,0xd8, + 0x4b,0x67,0xa0,0x10,0x9b,0x55,0xa3,0x6e,0x93,0x28,0xb1,0xe3,0x65,0xfc,0xe1,0x61, + 0xd7,0x1c,0xe7,0x13,0x1a,0x54,0x3e,0xa4,0xcb,0x5f,0x7e,0x9f,0x1d,0x8b,0x00,0x69, + 0x64,0x47,0x00,0x14,0x00), + chunk_from_chars( + 0x0c,0x3e,0x54,0x40,0x74,0xec,0x63,0xb0,0x26,0x5e,0x0c), + chunk_from_chars( + 0x1f,0x0a,0x88,0x88,0xce,0x25,0xe8,0xd4,0x58,0xa2,0x11,0x30,0x87,0x9b,0x84,0x0a, + 0x90,0x89,0xd9,0x99,0xaa,0xba,0x03,0x9e,0xaf,0x3e,0x3a,0xfa,0x09,0x0a,0x09,0xd3, + 0x89,0xdb,0xa8,0x2c,0x4f,0xf2,0xae,0x8a,0xc5,0xcd,0xfb,0x7c,0x55,0xe9,0x4d,0x5d, + 0x96,0x1a,0x29,0xfe,0x01,0x09,0x94,0x1e,0x00,0xb8,0xdb,0xde,0xea,0x6d,0x3b,0x05, + 0x10,0x68,0xdf,0x72,0x54,0xc0,0xcd,0xc1,0x29,0xcb,0xe6,0x2d,0xb2,0xdc,0x95,0x7d, + 0xbb,0x47,0xb5,0x1f,0xd3,0xf2,0x13,0xfb,0x86,0x98,0xf0,0x64,0x77,0x42,0x50,0xa5, + 0x02,0x89,0x61,0xc9,0xbf,0x8f,0xfd,0x97,0x3f,0xe5,0xd5,0xc2,0x06,0x49,0x2b,0x14, + 0x0e,0x00), + chunk_from_chars( + 0x3b,0x56,0x55,0xa4,0xce,0x4c,0xec,0x67,0x77,0x9c,0x9f,0xeb,0xfe,0x6f,0x38,0xba, + 0x88,0xc2,0x25,0x10), + chunk_from_chars( + 0x71,0xcb,0xf2,0xb7,0x1b,0x3b,0x77,0xcb,0xd6,0x41,0x05,0x02,0x72,0x31,0xa6,0x91, + 0x27,0x3f,0xe5,0x51), + }, + /* 12 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0x25,0x8c,0xdd,0x4a,0xda,0x32,0xed,0x9c,0x9f,0xf5,0x4e,0x63,0x75,0x6a,0xe5,0x82, + 0xfb,0x8f,0xab,0x2a,0xc7,0x21,0xf2,0xc8,0xe6,0x76,0xa7,0x27,0x68,0x51,0x3d,0x93, + 0x9f,0x63,0xdd,0xdb,0x55,0x60,0x91,0x33,0xf2,0x9a,0xdf,0x86,0xec,0x99,0x29,0xdc, + 0xcb,0x52,0xc1,0xc5,0xfd,0x2f,0xf7,0xe2,0x1b), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0x3b,0xa1,0x6d,0xa0, + 0xc6,0xf2,0xcc,0x1f,0x30,0x18,0x77,0x40,0x75,0x6f,0x5e,0x79,0x8d,0x6b,0xc5,0xfc, + 0x01,0x5d,0x7c,0x63,0xcc,0x95,0x10,0xee,0x3f,0xd4,0x4a,0xdc,0x24,0xd8,0xe9,0x68, + 0xb6,0xe4,0x6e,0x6f,0x94,0xd1,0x9b,0x94,0x53,0x61,0x72,0x6b,0xd7,0x5e,0x14,0x9e, + 0xf0,0x98,0x17,0xf5,0x80), + chunk_from_chars( + 0x64,0xa6,0x5f,0x3c,0xde,0xdc,0xdd,0x66,0x81,0x1e,0x29,0x15), + chunk_from_chars( + 0x7e,0xee,0xab,0x7c,0x4e,0x50,0xfb,0x79,0x9b,0x41,0x8e,0xe5,0xe3,0x19,0x7f,0xf6, + 0xbf,0x15,0xd4,0x3a,0x14,0xc3,0x43,0x89,0xb5,0x9d,0xd1,0xa7,0xb1,0xb8,0x5b,0x4a, + 0xe9,0x04,0x38,0xac,0xa6,0x34,0xbe,0xa4,0x5e,0x3a,0x26,0x95,0xf1,0x27,0x0f,0x07, + 0xfd,0xcd,0xf7,0xc6,0x2b,0x8e,0xfe,0xaf,0x00,0xb4,0x5c,0x2c,0x96,0xba,0x45,0x7e, + 0xb1,0xa8,0xbf,0x07,0x5a,0x3d,0xb2,0x8e,0x5c,0x24,0xf6,0xb9,0x23,0xed,0x4a,0xd7, + 0x47,0xc3,0xc9,0xe0,0x3c,0x70,0x79,0xef,0xb8,0x7c,0xb1,0x10,0xd3,0xa9,0x98,0x61, + 0xe7,0x20,0x03,0xcb,0xae,0x6d,0x6b,0x8b,0x82,0x7e,0x4e,0x6c,0x14,0x30,0x64,0xff, + 0x3c,0x00), + chunk_from_chars( + 0x56,0x8e,0xad,0x67,0xa7,0x83,0x78,0xfe,0x8f,0xaf,0xa7,0x87,0x2e,0xc8,0x95,0xa0, + 0xde,0x05,0x37,0x4c), + chunk_from_chars( + 0xed,0x1b,0xe5,0xa1,0x97,0x23,0x59,0x4d,0x86,0x6b,0x6b,0xef,0xfb,0x81,0xe4,0x8e, + 0xf7,0x42,0xe0,0x81), + }, + /* 13 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0x7e,0xf4,0xe8,0x45,0x44,0x23,0x67,0x52,0xfb,0xb5,0x6b,0x8f,0x31,0xa2,0x3a,0x10, + 0xe4,0x28,0x14,0xf5,0xf5,0x5c,0xa0,0x37,0xcd,0xcc,0x11,0xc6,0x4c,0x9a,0x3b,0x29, + 0x49,0xc1,0xbb,0x60,0x70,0x03,0x14,0x61,0x17,0x32,0xa6,0xc2,0xfe,0xa9,0x8e,0xeb, + 0xc0,0x26,0x6a,0x11,0xa9,0x39,0x70,0x10,0x0e), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0xb3,0xda,0x07,0x9b, + 0x0a,0xa4,0x93,0xa5,0x77,0x20,0x29,0xf0,0x46,0x7b,0xae,0xbe,0xe5,0xa8,0x11,0x2d, + 0x9d,0x3a,0x22,0x53,0x23,0x61,0xda,0x29,0x4f,0x7b,0xb3,0x81,0x5c,0x5d,0xc5,0x9e, + 0x17,0x6b,0x4d,0x9f,0x38,0x1c,0xa0,0x93,0x8e,0x13,0xc6,0xc0,0x7b,0x17,0x4b,0xe6, + 0x5d,0xfa,0x57,0x8e,0x80), + chunk_from_chars( + 0x64,0xa6,0x5f,0x3c,0xde,0xdc,0xdd,0x66,0x81,0x1e,0x29,0x15,0xe7), + chunk_from_chars( + 0x6a,0x12,0x06,0x6f,0x55,0x33,0x1b,0x6c,0x22,0xac,0xd5,0xd5,0xbf,0xc5,0xd7,0x12, + 0x28,0xfb,0xda,0x80,0xae,0x8d,0xec,0x26,0xbd,0xd3,0x06,0x74,0x3c,0x50,0x27,0xcb, + 0x48,0x90,0x81,0x0c,0x16,0x2c,0x02,0x74,0x68,0x67,0x5e,0xcf,0x64,0x5a,0x83,0x17, + 0x6c,0x0d,0x73,0x23,0xa2,0xcc,0xde,0x2d,0x80,0xef,0xe5,0xa1,0x26,0x8e,0x8a,0xca, + 0x1d,0x6f,0xbc,0x19,0x4d,0x3f,0x77,0xc4,0x49,0x86,0xeb,0x4a,0xb4,0x17,0x79,0x19, + 0xad,0x8b,0xec,0x33,0xeb,0x47,0xbb,0xb5,0xfc,0x6e,0x28,0x19,0x6f,0xd1,0xca,0xf5, + 0x6b,0x4e,0x7e,0x0b,0xa5,0x51,0x92,0x34,0xd0,0x47,0x15,0x5a,0xc7,0x27,0xa1,0x05, + 0x31,0x00), + chunk_from_chars( + 0x6e,0xb1,0xb6,0x33,0x76,0xa8,0x0f,0x84,0x26,0x23,0xfb,0xaa,0x9e,0xaa,0x1d,0x8d, + 0x6d,0xa5,0x75,0x4e), + chunk_from_chars( + 0xfa,0x2f,0xeb,0xff,0x13,0xc0,0xee,0xd0,0x3b,0xc6,0xf2,0x7d,0xb8,0x61,0xe5,0x9d, + 0x16,0x53,0xb1,0x11), + }, + /* 64 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0xd6,0x5d,0xf3,0x41,0xad,0x13,0xe0,0x08,0x56,0x76,0x88,0xba,0xed,0xda,0x8e,0x9d, + 0xcd,0xc1,0x7d,0xc0,0x24,0x97,0x4e,0xa5,0xb4,0x22,0x7b,0x65,0x30,0xe3,0x39,0xbf, + 0xf2,0x1f,0x99,0xe6,0x8c,0xa6,0x96,0x8f,0x3c,0xca,0x6d,0xfe,0x0f,0xb9,0xf4,0xfa, + 0xb4,0xfa,0x13,0x5d,0x55,0x42,0xea,0x3f,0x01), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0xdf,0x97,0x05,0xf5, + 0x8e,0xdb,0xab,0x80,0x2c,0x7f,0x83,0x63,0xcf,0xe5,0x56,0x0a,0xb1,0xc6,0x13,0x2c, + 0x20,0xa9,0xf1,0xdd,0x16,0x34,0x83,0xa2,0x6f,0x8a,0xc5,0x3a,0x39,0xd6,0x80,0x8b, + 0xf4,0xa1,0xdf,0xbd,0x26,0x1b,0x09,0x9b,0xb0,0x3b,0x3f,0xb5,0x09,0x06,0xcb,0x28, + 0xbd,0x8a,0x08,0x1f,0x00), + chunk_from_chars( + 0xbd,0x0f,0x6a,0x37,0x47,0xcd,0x56,0x1b,0xdd,0xdf,0x46,0x40,0xa3,0x32,0x46,0x1a, + 0x4a,0x30,0xa1,0x2a,0x43,0x4c,0xd0,0xbf,0x40,0xd7,0x66,0xd9,0xc6,0xd4,0x58,0xe5, + 0x51,0x22,0x04,0xa3,0x0c,0x17,0xd1,0xf5,0x0b,0x50,0x79,0x63,0x1f,0x64,0xeb,0x31, + 0x12,0x18,0x2d,0xa3,0x00,0x58,0x35,0x46,0x11,0x13,0x71,0x8d,0x1a,0x5e,0xf9,0x44), + chunk_from_chars( + 0x55,0x4b,0xc2,0x48,0x08,0x60,0xb4,0x9e,0xab,0x85,0x32,0xd2,0xa5,0x33,0xb7,0xd5, + 0x78,0xef,0x47,0x3e,0xeb,0x58,0xc9,0x8b,0xb2,0xd0,0xe1,0xce,0x48,0x8a,0x98,0xb1, + 0x8d,0xfd,0xe9,0xb9,0xb9,0x07,0x75,0xe6,0x7f,0x47,0xd4,0xa1,0xc3,0x48,0x20,0x58, + 0xef,0xc9,0xf4,0x0d,0x2c,0xa0,0x33,0xa0,0x80,0x1b,0x63,0xd4,0x5b,0x3b,0x72,0x2e, + 0xf5,0x52,0xba,0xd3,0xb4,0xcc,0xb6,0x67,0xda,0x35,0x01,0x92,0xb6,0x1c,0x50,0x8c, + 0xf7,0xb6,0xb5,0xad,0xad,0xc2,0xc8,0xd9,0xa4,0x46,0xef,0x00,0x3f,0xb0,0x5c,0xba, + 0x5f,0x30,0xe8,0x8e,0x36,0xec,0x27,0x03,0xb3,0x49,0xca,0x22,0x9c,0x26,0x70,0x83, + 0x39,0x00), + chunk_from_chars( + 0x2b,0xb0,0xd4,0x29,0xb8,0x51,0x3f,0xb5,0x9d,0x07,0xd0,0xb0,0x1f,0x4a,0x39,0x25, + 0x33,0xae,0x3e,0x64), + chunk_from_chars( + 0x79,0xbb,0x37,0xe4,0x2a,0xf9,0x58,0xb7,0xa4,0x58,0x18,0x88,0x4b,0x82,0x8f,0xfb, + 0x9c,0x74,0xce,0x9d), + }, + /* 256 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0x2e,0xc5,0xfe,0x3c,0x17,0x04,0x5a,0xbd,0xb1,0x36,0xa5,0xe6,0xa9,0x13,0xe3,0x2a, + 0xb7,0x5a,0xe6,0x8b,0x53,0xd2,0xfc,0x14,0x9b,0x77,0xe5,0x04,0x13,0x2d,0x37,0x56, + 0x9b,0x7e,0x76,0x6b,0xa7,0x4a,0x19,0xbd,0x61,0x62,0x34,0x3a,0x21,0xc8,0x59,0x0a, + 0xa9,0xce,0xbc,0xa9,0x01,0x4c,0x63,0x6d,0xf5), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0x79,0x75,0x6f,0x01, + 0x4d,0xcf,0xe2,0x07,0x9f,0x5d,0xd9,0xe7,0x18,0xbe,0x41,0x71,0xe2,0xef,0x24,0x86, + 0xa0,0x8f,0x25,0x18,0x6f,0x6b,0xff,0x43,0xa9,0x93,0x6b,0x9b,0xfe,0x12,0x40,0x2b, + 0x08,0xae,0x65,0x79,0x8a,0x3d,0x81,0xe2,0x2e,0x9e,0xc8,0x0e,0x76,0x90,0x86,0x2e, + 0xf3,0xd4,0xed,0x3a,0x00), + chunk_from_chars( + 0x15,0x77,0x75,0x32,0xb0,0xbd,0xd0,0xd1,0x38,0x9f,0x63,0x6c,0x5f,0x6b,0x9b,0xa7, + 0x34,0xc9,0x0a,0xf5,0x72,0x87,0x7e,0x2d,0x27,0x2d,0xd0,0x78,0xaa,0x1e,0x56,0x7c, + 0xfa,0x80,0xe1,0x29,0x28,0xbb,0x54,0x23,0x30,0xe8,0x40,0x9f,0x31,0x74,0x50,0x41, + 0x07,0xec,0xd5,0xef,0xac,0x61,0xae,0x75,0x04,0xda,0xbe,0x2a,0x60,0x2e,0xde,0x89, + 0xe5,0xcc,0xa6,0x25,0x7a,0x7c,0x77,0xe2,0x7a,0x70,0x2b,0x3a,0xe3,0x9f,0xc7,0x69, + 0xfc,0x54,0xf2,0x39,0x5a,0xe6,0xa1,0x17,0x8c,0xab,0x47,0x38,0xe5,0x43,0x07,0x2f, + 0xc1,0xc1,0x77,0xfe,0x71,0xe9,0x2e,0x25,0xbf,0x03,0xe4,0xec,0xb7,0x2f,0x47,0xb6, + 0x4d,0x04,0x65,0xaa,0xea,0x4c,0x7f,0xad,0x37,0x25,0x36,0xc8,0xba,0x51,0x6a,0x60, + 0x39,0xc3,0xc2,0xa3,0x9f,0x0e,0x4d,0x83,0x2b,0xe4,0x32,0xdf,0xa9,0xa7,0x06,0xa6, + 0xe5,0xc7,0xe1,0x9f,0x39,0x79,0x64,0xca,0x42,0x58,0x00,0x2f,0x7c,0x05,0x41,0xb5, + 0x90,0x31,0x6d,0xbc,0x56,0x22,0xb6,0xb2,0xa6,0xfe,0x7a,0x4a,0xbf,0xfd,0x96,0x10, + 0x5e,0xca,0x76,0xea,0x7b,0x98,0x81,0x6a,0xf0,0x74,0x8c,0x10,0xdf,0x04,0x8c,0xe0, + 0x12,0xd9,0x01,0x01,0x5a,0x51,0xf1,0x89,0xf3,0x88,0x81,0x45,0xc0,0x36,0x50,0xaa, + 0x23,0xce,0x89,0x4c,0x3b,0xd8,0x89,0xe0,0x30,0xd5,0x65,0x07,0x1c,0x59,0xf4,0x09, + 0xa9,0x98,0x1b,0x51,0x87,0x8f,0xd6,0xfc,0x11,0x06,0x24,0xdc,0xbc,0xde,0x0b,0xf7, + 0xa6,0x9c,0xcc,0xe3,0x8f,0xab,0xdf,0x86,0xf3,0xbe,0xf6,0x04,0x48,0x19,0xde,0x11), + chunk_from_chars( + 0xc6,0x50,0xdd,0xbb,0x06,0x01,0xc1,0x9c,0xa1,0x14,0x39,0xe1,0x64,0x0d,0xd9,0x31, + 0xf4,0x3c,0x51,0x8e,0xa5,0xbe,0xa7,0x0d,0x3d,0xcd,0xe5,0xf4,0x19,0x1f,0xe5,0x3f, + 0x00,0xcf,0x96,0x65,0x46,0xb7,0x2b,0xcc,0x7d,0x58,0xbe,0x2b,0x9b,0xad,0xef,0x28, + 0x74,0x39,0x54,0xe3,0xa4,0x4a,0x23,0xf8,0x80,0xe8,0xd4,0xf1,0xcf,0xce,0x2d,0x7a, + 0x61,0x45,0x2d,0x26,0xda,0x05,0x89,0x6f,0x0a,0x50,0xda,0x66,0xa2,0x39,0xa8,0xa1, + 0x88,0xb6,0xd8,0x25,0xb3,0x30,0x5a,0xd7,0x7b,0x73,0xfb,0xac,0x08,0x36,0xec,0xc6, + 0x09,0x87,0xfd,0x08,0x52,0x7c,0x1a,0x8e,0x80,0xd5,0x82,0x3e,0x65,0xca,0xfe,0x2a, + 0x3d,0x00), + chunk_from_chars( + 0xfc,0x02,0xc5,0x25,0x74,0x09,0x8f,0xbb,0xaf,0x8c,0xad,0x02,0x14,0x9d,0xef,0x0d, + 0x94,0xb7,0x96,0x5f), + chunk_from_chars( + 0x63,0x03,0x8e,0x1f,0xcc,0x69,0x1e,0x2f,0x9d,0xb3,0x57,0x0f,0xad,0xbc,0x01,0x35, + 0x63,0xdb,0x06,0xba), + }, + /* 1023 octets */ + { chunk_from_chars( + 0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39, + 0x87,0x2d,0x09,0x37,0x80,0xf5,0xd3,0x73,0x0d,0xf7,0xc2,0x12,0x66,0x4b,0x37,0xb8, + 0xa0,0xf2,0x4f,0x56,0x81,0x0d,0xaa,0x83,0x82,0xcd,0x4f,0xa3,0xf7,0x76,0x34,0xec, + 0x44,0xdc,0x54,0xf1,0xc2,0xed,0x9b,0xea,0x86,0xfa,0xfb,0x76,0x32,0xd8,0xbe,0x19, + 0x9e,0xa1,0x65,0xf5,0xad,0x55,0xdd,0x9c,0xe8), + chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0xa8,0x1b,0x2e,0x8a, + 0x70,0xa5,0xac,0x94,0xff,0xdb,0xcc,0x9b,0xad,0xfc,0x3f,0xeb,0x08,0x01,0xf2,0x58, + 0x57,0x8b,0xb1,0x14,0xad,0x44,0xec,0xe1,0xec,0x0e,0x79,0x9d,0xa0,0x8e,0xff,0xb8, + 0x1c,0x5d,0x68,0x5c,0x0c,0x56,0xf6,0x4e,0xec,0xae,0xf8,0xcd,0xf1,0x1c,0xc3,0x87, + 0x37,0x83,0x8c,0xf4,0x00), + chunk_from_chars( + 0x6d,0xdf,0x80,0x2e,0x1a,0xae,0x49,0x86,0x93,0x5f,0x7f,0x98,0x1b,0xa3,0xf0,0x35, + 0x1d,0x62,0x73,0xc0,0xa0,0xc2,0x2c,0x9c,0x0e,0x83,0x39,0x16,0x8e,0x67,0x54,0x12, + 0xa3,0xde,0xbf,0xaf,0x43,0x5e,0xd6,0x51,0x55,0x80,0x07,0xdb,0x43,0x84,0xb6,0x50, + 0xfc,0xc0,0x7e,0x3b,0x58,0x6a,0x27,0xa4,0xf7,0xa0,0x0a,0xc8,0xa6,0xfe,0xc2,0xcd, + 0x86,0xae,0x4b,0xf1,0x57,0x0c,0x41,0xe6,0xa4,0x0c,0x93,0x1d,0xb2,0x7b,0x2f,0xaa, + 0x15,0xa8,0xce,0xdd,0x52,0xcf,0xf7,0x36,0x2c,0x4e,0x6e,0x23,0xda,0xec,0x0f,0xbc, + 0x3a,0x79,0xb6,0x80,0x6e,0x31,0x6e,0xfc,0xc7,0xb6,0x81,0x19,0xbf,0x46,0xbc,0x76, + 0xa2,0x60,0x67,0xa5,0x3f,0x29,0x6d,0xaf,0xdb,0xdc,0x11,0xc7,0x7f,0x77,0x77,0xe9, + 0x72,0x66,0x0c,0xf4,0xb6,0xa9,0xb3,0x69,0xa6,0x66,0x5f,0x02,0xe0,0xcc,0x9b,0x6e, + 0xdf,0xad,0x13,0x6b,0x4f,0xab,0xe7,0x23,0xd2,0x81,0x3d,0xb3,0x13,0x6c,0xfd,0xe9, + 0xb6,0xd0,0x44,0x32,0x2f,0xee,0x29,0x47,0x95,0x2e,0x03,0x1b,0x73,0xab,0x5c,0x60, + 0x33,0x49,0xb3,0x07,0xbd,0xc2,0x7b,0xc6,0xcb,0x8b,0x8b,0xbd,0x7b,0xd3,0x23,0x21, + 0x9b,0x80,0x33,0xa5,0x81,0xb5,0x9e,0xad,0xeb,0xb0,0x9b,0x3c,0x4f,0x3d,0x22,0x77, + 0xd4,0xf0,0x34,0x36,0x24,0xac,0xc8,0x17,0x80,0x47,0x28,0xb2,0x5a,0xb7,0x97,0x17, + 0x2b,0x4c,0x5c,0x21,0xa2,0x2f,0x9c,0x78,0x39,0xd6,0x43,0x00,0x23,0x2e,0xb6,0x6e, + 0x53,0xf3,0x1c,0x72,0x3f,0xa3,0x7f,0xe3,0x87,0xc7,0xd3,0xe5,0x0b,0xdf,0x98,0x13, + 0xa3,0x0e,0x5b,0xb1,0x2c,0xf4,0xcd,0x93,0x0c,0x40,0xcf,0xb4,0xe1,0xfc,0x62,0x25, + 0x92,0xa4,0x95,0x88,0x79,0x44,0x94,0xd5,0x6d,0x24,0xea,0x4b,0x40,0xc8,0x9f,0xc0, + 0x59,0x6c,0xc9,0xeb,0xb9,0x61,0xc8,0xcb,0x10,0xad,0xde,0x97,0x6a,0x5d,0x60,0x2b, + 0x1c,0x3f,0x85,0xb9,0xb9,0xa0,0x01,0xed,0x3c,0x6a,0x4d,0x3b,0x14,0x37,0xf5,0x20, + 0x96,0xcd,0x19,0x56,0xd0,0x42,0xa5,0x97,0xd5,0x61,0xa5,0x96,0xec,0xd3,0xd1,0x73, + 0x5a,0x8d,0x57,0x0e,0xa0,0xec,0x27,0x22,0x5a,0x2c,0x4a,0xaf,0xf2,0x63,0x06,0xd1, + 0x52,0x6c,0x1a,0xf3,0xca,0x6d,0x9c,0xf5,0xa2,0xc9,0x8f,0x47,0xe1,0xc4,0x6d,0xb9, + 0xa3,0x32,0x34,0xcf,0xd4,0xd8,0x1f,0x2c,0x98,0x53,0x8a,0x09,0xeb,0xe7,0x69,0x98, + 0xd0,0xd8,0xfd,0x25,0x99,0x7c,0x7d,0x25,0x5c,0x6d,0x66,0xec,0xe6,0xfa,0x56,0xf1, + 0x11,0x44,0x95,0x0f,0x02,0x77,0x95,0xe6,0x53,0x00,0x8f,0x4b,0xd7,0xca,0x2d,0xee, + 0x85,0xd8,0xe9,0x0f,0x3d,0xc3,0x15,0x13,0x0c,0xe2,0xa0,0x03,0x75,0xa3,0x18,0xc7, + 0xc3,0xd9,0x7b,0xe2,0xc8,0xce,0x5b,0x6d,0xb4,0x1a,0x62,0x54,0xff,0x26,0x4f,0xa6, + 0x15,0x5b,0xae,0xe3,0xb0,0x77,0x3c,0x0f,0x49,0x7c,0x57,0x3f,0x19,0xbb,0x4f,0x42, + 0x40,0x28,0x1f,0x0b,0x1f,0x4f,0x7b,0xe8,0x57,0xa4,0xe5,0x9d,0x41,0x6c,0x06,0xb4, + 0xc5,0x0f,0xa0,0x9e,0x18,0x10,0xdd,0xc6,0xb1,0x46,0x7b,0xae,0xac,0x5a,0x36,0x68, + 0xd1,0x1b,0x6e,0xca,0xa9,0x01,0x44,0x00,0x16,0xf3,0x89,0xf8,0x0a,0xcc,0x4d,0xb9, + 0x77,0x02,0x5e,0x7f,0x59,0x24,0x38,0x8c,0x7e,0x34,0x0a,0x73,0x2e,0x55,0x44,0x40, + 0xe7,0x65,0x70,0xf8,0xdd,0x71,0xb7,0xd6,0x40,0xb3,0x45,0x0d,0x1f,0xd5,0xf0,0x41, + 0x0a,0x18,0xf9,0xa3,0x49,0x4f,0x70,0x7c,0x71,0x7b,0x79,0xb4,0xbf,0x75,0xc9,0x84, + 0x00,0xb0,0x96,0xb2,0x16,0x53,0xb5,0xd2,0x17,0xcf,0x35,0x65,0xc9,0x59,0x74,0x56, + 0xf7,0x07,0x03,0x49,0x7a,0x07,0x87,0x63,0x82,0x9b,0xc0,0x1b,0xb1,0xcb,0xc8,0xfa, + 0x04,0xea,0xdc,0x9a,0x6e,0x3f,0x66,0x99,0x58,0x7a,0x9e,0x75,0xc9,0x4e,0x5b,0xab, + 0x00,0x36,0xe0,0xb2,0xe7,0x11,0x39,0x2c,0xff,0x00,0x47,0xd0,0xd6,0xb0,0x5b,0xd2, + 0xa5,0x88,0xbc,0x10,0x97,0x18,0x95,0x42,0x59,0xf1,0xd8,0x66,0x78,0xa5,0x79,0xa3, + 0x12,0x0f,0x19,0xcf,0xb2,0x96,0x3f,0x17,0x7a,0xeb,0x70,0xf2,0xd4,0x84,0x48,0x26, + 0x26,0x2e,0x51,0xb8,0x02,0x71,0x27,0x20,0x68,0xef,0x5b,0x38,0x56,0xfa,0x85,0x35, + 0xaa,0x2a,0x88,0xb2,0xd4,0x1f,0x2a,0x0e,0x2f,0xda,0x76,0x24,0xc2,0x85,0x02,0x72, + 0xac,0x4a,0x2f,0x56,0x1f,0x8f,0x2f,0x7a,0x31,0x8b,0xfd,0x5c,0xaf,0x96,0x96,0x14, + 0x9e,0x4a,0xc8,0x24,0xad,0x34,0x60,0x53,0x8f,0xdc,0x25,0x42,0x1b,0xee,0xc2,0xcc, + 0x68,0x18,0x16,0x2d,0x06,0xbb,0xed,0x0c,0x40,0xa3,0x87,0x19,0x23,0x49,0xdb,0x67, + 0xa1,0x18,0xba,0xda,0x6c,0xd5,0xab,0x01,0x40,0xee,0x27,0x32,0x04,0xf6,0x28,0xaa, + 0xd1,0xc1,0x35,0xf7,0x70,0x27,0x9a,0x65,0x1e,0x24,0xd8,0xc1,0x4d,0x75,0xa6,0x05, + 0x9d,0x76,0xb9,0x6a,0x6f,0xd8,0x57,0xde,0xf5,0xe0,0xb3,0x54,0xb2,0x7a,0xb9,0x37, + 0xa5,0x81,0x5d,0x16,0xb5,0xfa,0xe4,0x07,0xff,0x18,0x22,0x2c,0x6d,0x1e,0xd2,0x63, + 0xbe,0x68,0xc9,0x5f,0x32,0xd9,0x08,0xbd,0x89,0x5c,0xd7,0x62,0x07,0xae,0x72,0x64, + 0x87,0x56,0x7f,0x9a,0x67,0xda,0xd7,0x9a,0xbe,0xc3,0x16,0xf6,0x83,0xb1,0x7f,0x2d, + 0x02,0xbf,0x07,0xe0,0xac,0x8b,0x5b,0xc6,0x16,0x2c,0xf9,0x46,0x97,0xb3,0xc2,0x7c, + 0xd1,0xfe,0xa4,0x9b,0x27,0xf2,0x3b,0xa2,0x90,0x18,0x71,0x96,0x25,0x06,0x52,0x0c, + 0x39,0x2d,0xa8,0xb6,0xad,0x0d,0x99,0xf7,0x01,0x3f,0xbc,0x06,0xc2,0xc1,0x7a,0x56, + 0x95,0x00,0xc8,0xa7,0x69,0x64,0x81,0xc1,0xcd,0x33,0xe9,0xb1,0x4e,0x40,0xb8,0x2e, + 0x79,0xa5,0xf5,0xdb,0x82,0x57,0x1b,0xa9,0x7b,0xae,0x3a,0xd3,0xe0,0x47,0x95,0x15, + 0xbb,0x0e,0x2b,0x0f,0x3b,0xfc,0xd1,0xfd,0x33,0x03,0x4e,0xfc,0x62,0x45,0xed,0xdd, + 0x7e,0xe2,0x08,0x6d,0xda,0xe2,0x60,0x0d,0x8c,0xa7,0x3e,0x21,0x4e,0x8c,0x2b,0x0b, + 0xdb,0x2b,0x04,0x7c,0x6a,0x46,0x4a,0x56,0x2e,0xd7,0x7b,0x73,0xd2,0xd8,0x41,0xc4, + 0xb3,0x49,0x73,0x55,0x12,0x57,0x71,0x3b,0x75,0x36,0x32,0xef,0xba,0x34,0x81,0x69, + 0xab,0xc9,0x0a,0x68,0xf4,0x26,0x11,0xa4,0x01,0x26,0xd7,0xcb,0x21,0xb5,0x86,0x95, + 0x56,0x81,0x86,0xf7,0xe5,0x69,0xd2,0xff,0x0f,0x9e,0x74,0x5d,0x04,0x87,0xdd,0x2e, + 0xb9,0x97,0xca,0xfc,0x5a,0xbf,0x9d,0xd1,0x02,0xe6,0x2f,0xf6,0x6c,0xba,0x87), + chunk_from_chars( + 0xe3,0x01,0x34,0x5a,0x41,0xa3,0x9a,0x4d,0x72,0xff,0xf8,0xdf,0x69,0xc9,0x80,0x75, + 0xa0,0xcc,0x08,0x2b,0x80,0x2f,0xc9,0xb2,0xb6,0xbc,0x50,0x3f,0x92,0x6b,0x65,0xbd, + 0xdf,0x7f,0x4c,0x8f,0x1c,0xb4,0x9f,0x63,0x96,0xaf,0xc8,0xa7,0x0a,0xbe,0x6d,0x8a, + 0xef,0x0d,0xb4,0x78,0xd4,0xc6,0xb2,0x97,0x00,0x76,0xc6,0xa0,0x48,0x4f,0xe7,0x6d, + 0x76,0xb3,0xa9,0x76,0x25,0xd7,0x9f,0x1c,0xe2,0x40,0xe7,0xc5,0x76,0x75,0x0d,0x29, + 0x55,0x28,0x28,0x6f,0x71,0x9b,0x41,0x3d,0xe9,0xad,0xa3,0xe8,0xeb,0x78,0xed,0x57, + 0x36,0x03,0xce,0x30,0xd8,0xbb,0x76,0x17,0x85,0xdc,0x30,0xdb,0xc3,0x20,0x86,0x9e, + 0x1a,0x00), + chunk_from_chars( + 0x89,0x30,0xb4,0x62,0xe0,0x28,0x45,0xf1,0x37,0xc0,0x0e,0x47,0xfe,0x64,0x3d,0x07, + 0x02,0x7b,0x66,0xec), + chunk_from_chars( + 0xc1,0x6c,0x19,0x0e,0x3e,0xe9,0x2c,0x5e,0xd0,0x35,0x19,0x93,0x77,0x2c,0xd6,0x38, + 0xf0,0xbc,0xe1,0x62), + }, +}; + +START_TEST(test_ed448_sign) +{ + private_key_t *key; + public_key_t *pubkey, *public; + chunk_t sig, encoding, fp; + + /* load private key */ + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, sig_tests[_i].key, BUILD_END); + ck_assert(key != NULL); + ck_assert(key->get_encoding(key, PRIVKEY_ASN1_DER, &encoding)); + ck_assert_chunk_eq(encoding, sig_tests[_i].key); + chunk_free(&encoding); + + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_pk, fp); + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_spki, fp); + + /* load public key */ + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, sig_tests[_i].pubkey, BUILD_END); + ck_assert(pubkey != NULL); + ck_assert(pubkey->get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &encoding)); + ck_assert_chunk_eq(encoding, sig_tests[_i].pubkey); + chunk_free(&encoding); + + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_pk, fp); + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_INFO_SHA1, &fp)); + ck_assert_chunk_eq(sig_tests[_i].fp_spki, fp); + + /* compare public keys */ + public = key->get_public_key(key); + ck_assert(public != NULL); + ck_assert(public->equals(public, pubkey)); + + /* sign */ + ck_assert(key->sign(key, SIGN_ED448, NULL, sig_tests[_i].msg, &sig)); + ck_assert_chunk_eq(sig, sig_tests[_i].sig); + + /* verify */ + ck_assert(pubkey->verify(pubkey, SIGN_ED448, NULL, sig_tests[_i].msg, + sig_tests[_i].sig)); + + /* cleanup */ + key->destroy(key); + pubkey->destroy(pubkey); + public->destroy(public); + chunk_free(&sig); +} +END_TEST + +START_TEST(test_ed448_gen) +{ + private_key_t *key, *key2; + public_key_t *pubkey, *pubkey2; + chunk_t msg = chunk_from_str("Ed448"), sig, encoding, fp_priv, fp_pub; + + /* generate private key */ + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_KEY_SIZE, 456, BUILD_END); + ck_assert(key != NULL); + ck_assert(key->get_type(key) == KEY_ED448); + ck_assert(key->get_keysize(key) == 456); + ck_assert(!key->get_encoding(key, PRIVKEY_PGP, &encoding)); + ck_assert(key->get_encoding(key, PRIVKEY_PEM, &encoding)); + ck_assert(encoding.ptr != NULL); + ck_assert(strstr(encoding.ptr, "PRIVATE KEY")); + chunk_free(&encoding); + + /* clone private key */ + key2 = key->get_ref(key); + ck_assert(key2); + key2->destroy(key2); + + /* decryption not supported */ + ck_assert(!key->decrypt(key, ENCRYPT_UNKNOWN, msg, NULL)); + + /* wrong signature scheme */ + ck_assert(!key->sign(key, SIGN_ED25519, NULL, msg, &sig)); + + /* correct signature scheme*/ + ck_assert(key->sign(key, SIGN_ED448, NULL, msg, &sig)); + + /* export public key */ + pubkey = key->get_public_key(key); + ck_assert(pubkey != NULL); + ck_assert(pubkey->get_type(pubkey) == KEY_ED448); + ck_assert(pubkey->get_keysize(pubkey) == 456); + ck_assert(pubkey->get_encoding(pubkey, PUBKEY_PEM, &encoding)); + ck_assert(encoding.ptr != NULL); + ck_assert(strstr(encoding.ptr, "PUBLIC KEY")); + chunk_free(&encoding); + + /* generate and compare public and private key fingerprints */ + ck_assert(!key->get_fingerprint(key, KEYID_PGPV4, &fp_priv)); + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp_priv)); + ck_assert(key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp_priv)); + ck_assert(fp_priv.ptr != NULL); + ck_assert(!pubkey->get_fingerprint(pubkey, KEYID_PGPV4, &fp_pub)); + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp_pub)); + ck_assert(pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp_pub)); + ck_assert(fp_pub.ptr != NULL); + ck_assert_chunk_eq(fp_pub, fp_priv); + + /* clone public key */ + pubkey2 = pubkey->get_ref(pubkey); + ck_assert(pubkey2 != NULL); + pubkey2->destroy(pubkey2); + + /* encryption not supported */ + ck_assert(!pubkey->encrypt(pubkey, ENCRYPT_UNKNOWN, msg, NULL)); + + /* verify with wrong signature scheme */ + ck_assert(!pubkey->verify(pubkey, SIGN_ED25519, NULL, msg, sig)); + + /* verify with correct signature scheme */ + ck_assert(pubkey->verify(pubkey, SIGN_ED448, NULL, msg, sig)); + + /* cleanup */ + key->destroy(key); + pubkey->destroy(pubkey); + chunk_free(&sig); +} +END_TEST + +START_TEST(test_ed448_speed) +{ + private_key_t *key; + public_key_t *pubkey; + chunk_t msg = chunk_from_str("Hello Ed448"), sig; + int i, count = 500; + +#ifdef HAVE_CLOCK_GETTIME + struct timespec start, stop; + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); +#endif + + for (i = 0; i < count; i++) + { + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_KEY_SIZE, 456, BUILD_END); + ck_assert(key != NULL); + ck_assert(key->sign(key, SIGN_ED448, NULL, msg, &sig)); + pubkey = key->get_public_key(key); + ck_assert(pubkey != NULL); + ck_assert(pubkey->verify(pubkey, SIGN_ED448, NULL, msg, sig)); + key->destroy(key); + pubkey->destroy(pubkey); + chunk_free(&sig); + } + +#ifdef HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stop); + DBG0(DBG_LIB, "%d Ed448 keys and signatures in %d ms\n", count, + (stop.tv_nsec - start.tv_nsec) / 1000000 + + (stop.tv_sec - start.tv_sec) * 1000); +#endif +} +END_TEST + +static chunk_t zero_pk = chunk_from_chars( + 0x30,0x43,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00); + +/* sig_tests[0].sig with s+L, note that only the 9 most significant bits are 0 */ +static chunk_t malleable_sig = chunk_from_chars( + 0x53,0x3a,0x37,0xf6,0xbb,0xe4,0x57,0x25,0x1f,0x02,0x3c,0x0d,0x88,0xf9,0x76,0xae, + 0x2d,0xfb,0x50,0x4a,0x84,0x3e,0x34,0xd2,0x07,0x4f,0xd8,0x23,0xd4,0x1a,0x59,0x1f, + 0x2b,0x23,0x3f,0x03,0x4f,0x62,0x82,0x81,0xf2,0xfd,0x7a,0x22,0xdd,0xd4,0x7d,0x78, + 0x28,0xc5,0x9b,0xd0,0xa2,0x1b,0xfd,0x39,0x80,0xf2,0x52,0x78,0xd3,0x66,0x74,0x03, + 0xc1,0x4b,0xce,0xc5,0xf9,0xcf,0xde,0x99,0x55,0xeb,0xc8,0x33,0x3c,0x0a,0xe7,0x8f, + 0xc8,0x6e,0x51,0x83,0x17,0xc5,0xc7,0xcd,0xda,0x85,0x30,0xa1,0x13,0xa0,0xf4,0xdb, + 0xb6,0x11,0x49,0xf0,0x5a,0x73,0x63,0x26,0x8c,0x71,0xd9,0x58,0x08,0xff,0x2e,0x65, + 0x66,0x00); + +START_TEST(test_ed448_fail) +{ + private_key_t *key; + public_key_t *pubkey; + chunk_t blob, sig; + uint8_t sig1[114]; + + /* Invalid private key format */ + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, chunk_empty, BUILD_END); + ck_assert(key == NULL); + + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_EDDSA_PRIV_ASN1_DER, chunk_empty, BUILD_END); + ck_assert(key == NULL); + + blob = chunk_from_chars(0x04, 0x01, 0x9d); + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ED448, + BUILD_EDDSA_PRIV_ASN1_DER, blob, BUILD_END); + ck_assert(key == NULL); + + /* Invalid public key format */ + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, chunk_empty, BUILD_END); + ck_assert(pubkey == NULL); + + blob = chunk_from_chars(0x30, 0x0b, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, + 0x71, 0x03, 0x02, 0x00, 0xd7); + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, blob, BUILD_END); + ck_assert(pubkey == NULL); + + blob = chunk_from_chars(0x30, 0x0b, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x00, + 0x71, 0x03, 0x02, 0x00, 0xd7); + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, blob, BUILD_END); + ck_assert(pubkey == NULL); + + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_KEY_SIZE, 456, BUILD_BLOB_ASN1_DER, blob, BUILD_END); + ck_assert(pubkey == NULL); + + /* Invalid signature format */ + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, sig_tests[0].pubkey, BUILD_END); + ck_assert(pubkey != NULL); + + ck_assert(!pubkey->verify(pubkey, SIGN_ED448, NULL, chunk_empty, + chunk_empty)); + + /* RFC 8032, section 5.2.7 requires that 0 <= s < L to prevent signature + * malleability. Only a warning because OpenSSL is vulnerable to this. */ + if (pubkey->verify(pubkey, SIGN_ED448, NULL, sig_tests[0].msg, + malleable_sig)) + { + warn("Ed448 signature verification is vulnerable to malleable " + "signatures"); + } + + /* malformed signature */ + sig = chunk_from_thing(sig1); + memcpy(sig1, sig_tests[0].sig.ptr, sig_tests[0].sig.len); + sig1[113] |= 0xFF; + ck_assert(!pubkey->verify(pubkey, SIGN_ED448, NULL, sig_tests[0].msg, + sig)); + + /* wrong signature */ + memcpy(sig1, sig_tests[0].sig.ptr, sig_tests[0].sig.len); + sig1[0] = 0xe4; + ck_assert(!pubkey->verify(pubkey, SIGN_ED448, NULL, sig_tests[0].msg, + sig)); + + /* detect all-zeroes public key */ + pubkey->destroy(pubkey); + pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_BLOB_ASN1_DER, zero_pk, BUILD_END); + ck_assert(pubkey != NULL); + ck_assert(!pubkey->verify(pubkey, SIGN_ED448, NULL, sig_tests[0].msg, + sig)); + pubkey->destroy(pubkey); +} +END_TEST + +Suite *ed448_suite_create() +{ + Suite *s; + TCase *tc; + + s = suite_create("ed448"); + + tc = tcase_create("ed448_sign"); + tcase_add_loop_test(tc, test_ed448_sign, 0, countof(sig_tests)); + suite_add_tcase(s, tc); + + tc = tcase_create("ed448_gen"); + tcase_add_test(tc, test_ed448_gen); + suite_add_tcase(s, tc); + + tc = tcase_create("ed448_fail"); + tcase_add_test(tc, test_ed448_fail); + suite_add_tcase(s, tc); + + tc = tcase_create("ed448_speed"); + test_case_set_timeout(tc, 10); + tcase_add_test(tc, test_ed448_speed); + suite_add_tcase(s, tc); + + return s; +} diff --git a/src/libstrongswan/tests/tests.h b/src/libstrongswan/tests/tests.h index 9fc38d480..26ff161a4 100644 --- a/src/libstrongswan/tests/tests.h +++ b/src/libstrongswan/tests/tests.h @@ -52,5 +52,6 @@ TEST_SUITE_DEPEND(mgf1_sha256_suite_create, XOF, XOF_MGF1_SHA256) TEST_SUITE_DEPEND(ntru_suite_create, DH, NTRU_112_BIT) TEST_SUITE_DEPEND(fetch_http_suite_create, FETCHER, "http://") TEST_SUITE_DEPEND(ed25519_suite_create, PRIVKEY_GEN, KEY_ED25519) +TEST_SUITE_DEPEND(ed448_suite_create, PRIVKEY_GEN, KEY_ED448) TEST_SUITE(signature_params_suite_create) From 7195914dafb2f14d2c365fd521553ebca5884b70 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 22 Nov 2018 18:30:46 +0100 Subject: [PATCH 10/12] travis: Only use GCC for crypto plugin tests They are already build-tested with Clang via "all" and others. --- .travis.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98804f2c6..84ff11482 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,22 +78,11 @@ matrix: - env: TEST=printf-builtin LEAK_DETECTIVE=yes - env: TEST=printf-builtin LEAK_DETECTIVE=yes compiler: clang + # the crypto plugins are build-tested with clang via "all" above - env: TEST=botan - - env: TEST=botan - compiler: clang - env: TEST=botan LEAK_DETECTIVE=yes - - env: TEST=botan LEAK_DETECTIVE=yes - compiler: clang - env: TEST=openssl - - env: TEST=openssl - compiler: clang - env: TEST=openssl LEAK_DETECTIVE=yes - - env: TEST=openssl LEAK_DETECTIVE=yes - compiler: clang - env: TEST=gcrypt - - env: TEST=gcrypt - compiler: clang - env: TEST=gcrypt LEAK_DETECTIVE=yes - - env: TEST=gcrypt LEAK_DETECTIVE=yes - compiler: clang - env: TEST=apidoc From 2a58030b78525f241a58eece509e490a46304b2f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 22 Nov 2018 15:38:49 +0100 Subject: [PATCH 11/12] travis: Use the latest OpenSSL release for unit tests But also run the unit tests against the 1.0 version installed with Ubuntu 16.04. --- .travis.yml | 2 ++ scripts/test.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 84ff11482..31f4a2a62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -83,6 +83,8 @@ matrix: - env: TEST=botan LEAK_DETECTIVE=yes - env: TEST=openssl - env: TEST=openssl LEAK_DETECTIVE=yes + - env: TEST=openssl-1.0 + - env: TEST=openssl-1.0 LEAK_DETECTIVE=yes - env: TEST=gcrypt - env: TEST=gcrypt LEAK_DETECTIVE=yes - env: TEST=apidoc diff --git a/scripts/test.sh b/scripts/test.sh index 1998f2178..fbf76b5f0 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -11,6 +11,8 @@ build_botan() return fi + echo "$ build_botan()" + # if the leak detective is enabled we have to disable threading support # (used for std::async) as that causes invalid frees somehow, the # locking allocator causes a static leak via the first function that @@ -43,7 +45,9 @@ build_tss2() return fi - # the default version of libgcrypt in Ubuntu 14.04 is too old + echo "$ build_tss2()" + + # the default version of libgcrypt in Ubuntu 16.04 is too old sudo apt-get update -qq && \ sudo apt-get install -qq libgcrypt20-dev && curl -L $TSS2_SRC | tar xz -C $TRAVIS_BUILD_DIR/.. && @@ -55,6 +59,42 @@ build_tss2() cd - } +build_openssl() +{ + SSL_REV=1.1.1a + SSL_PKG=openssl-$SSL_REV + SSL_DIR=$TRAVIS_BUILD_DIR/../$SSL_PKG + SSL_SRC=https://www.openssl.org/source/$SSL_PKG.tar.gz + SSL_INS=/usr/local/ssl + SSL_OPT="shared no-tls no-dtls no-ssl3 no-zlib no-comp no-idea no-psk no-srp + no-stdio no-tests enable-rfc3779 enable-ec_nistp_64_gcc_128" + + if test -d "$SSL_DIR"; then + return + fi + + echo "$ build_openssl()" + + curl -L $SSL_SRC | tar xz -C $TRAVIS_BUILD_DIR/.. && + cd $SSL_DIR && + ./config --prefix=$SSL_INS --openssldir=$SSL_INS $SSL_OPT && + make -j4 >/dev/null && + sudo make install_sw >/dev/null && + echo $SSL_INS/lib | sudo tee /etc/ld.so.conf.d/openssl-$SSL_REV.conf >/dev/null && + sudo ldconfig || exit $? + cd - +} + +use_custom_openssl() +{ + CFLAGS="$CFLAGS -I/usr/local/ssl/include" + LDFLAGS="$LDFLAGS -L/usr/local/ssl/lib" + export LDFLAGS + if test "$1" = "deps"; then + build_openssl + fi +} + if test -z $TRAVIS_BUILD_DIR; then TRAVIS_BUILD_DIR=$PWD fi @@ -72,9 +112,13 @@ default) # should be the default, but lets make sure CONFIG="--with-printf-hooks=glibc" ;; -openssl) - CONFIG="--disable-defaults --enable-pki --enable-openssl" +openssl*) + CONFIG="--disable-defaults --enable-pki --enable-openssl --enable-pem" DEPS="libssl-dev" + if test "$TEST" != "openssl-1.0"; then + DEPS="" + use_custom_openssl $1 + fi ;; gcrypt) CONFIG="--disable-defaults --enable-pki --enable-gcrypt --enable-pkcs1" @@ -119,6 +163,7 @@ all|coverage|sonarcloud) build_botan build_tss2 fi + use_custom_openssl $1 ;; win*) CONFIG="--disable-defaults --enable-svc --enable-ikev2 From a4e698b6f946ca6ac742d83203d74fda9d955012 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Nov 2018 09:37:07 +0100 Subject: [PATCH 12/12] travis: Don't run sonarcloud in forked repositories --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31f4a2a62..7e70df553 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ env: matrix: include: - env: TEST=sonarcloud - if: type = push + if: type = push AND env(SONAR_TOKEN) IS present git: depth: false addons: