Merge branch 'openssl-25519/448'

Adds support for X25519/448 and Ed25519/448 via OpenSSL 1.1.1.
This commit is contained in:
Tobias Brunner
2018-11-30 16:48:02 +01:00
22 changed files with 1956 additions and 32 deletions
+4 -13
View File
@@ -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:
@@ -78,22 +78,13 @@ 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=openssl-1.0
- env: TEST=openssl-1.0 LEAK_DETECTIVE=yes
- 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
+1
View File
@@ -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)
+48 -3
View File
@@ -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
@@ -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)
@@ -29,7 +29,10 @@ 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 \
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)
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC)
#include "openssl_ed_private_key.h"
#include <utils/debug.h>
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 */
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <openssl/evp.h>
#include <credentials/builder.h>
#include <credentials/keys/private_key.h>
/**
* 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_ @}*/
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC)
#include <openssl/x509.h>
#include "openssl_ed_public_key.h"
#include <utils/debug.h>
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 */
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <credentials/builder.h>
#include <credentials/keys/public_key.h>
/**
* 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_ @}*/
@@ -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
*
@@ -47,6 +47,9 @@
#include "openssl_rng.h"
#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
@@ -307,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;
@@ -454,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;
@@ -594,7 +607,7 @@ 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
#endif /* OPENSSL_NO_ECDH */
#ifndef OPENSSL_NO_DH
/* MODP DH groups */
PLUGIN_REGISTER(DH, openssl_diffie_hellman_create),
@@ -699,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),
@@ -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 <utils/debug.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#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;
}
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <openssl/evp.h>
/* 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 <utils/debug.h>
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 */
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <library.h>
/**
* 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_ @}*/
@@ -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
@@ -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)
@@ -16,7 +16,7 @@
#include <crypto/crypto_tester.h>
/**
* From RFC 8037
* From RFC 7748
*/
dh_test_vector_t curve25519_1 = {
.group = CURVE_25519, .priv_len = 32, .pub_len = 32, .shared_len = 32,
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <crypto/crypto_tester.h>
/**
* 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",
};
+1
View File
@@ -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 = \
+73 -11
View File
@@ -24,10 +24,12 @@ struct sig_test_t {
chunk_t pubkey;
chunk_t msg;
chunk_t sig;
chunk_t fp_pk;
chunk_t fp_spki;
};
/**
* Ed25519 Test Vectors from draft-irtf-cfrg-eddsa
* Ed25519 Test Vectors from RFC 8032
*/
static sig_test_t sig_tests[] = {
/* Test 1 */
@@ -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,24 +305,34 @@ 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,
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);
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);
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);
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);
@@ -299,7 +341,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 +406,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);
@@ -429,6 +471,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 +531,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);
+654
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <time.h>
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;
}
+1
View File
@@ -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)
+5
View File
@@ -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 */