diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2019-01-02 10:45:36 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2019-01-02 11:07:05 +0100 |
commit | 918094fde55fa0dbfd59a5f88d576efb513a88db (patch) | |
tree | 61e31656c60a6cc928c50cd633568043673e2cbd /src/libstrongswan | |
parent | 69bc96f6b0b388d35e983f8d27224fa49d92918c (diff) | |
download | vyos-strongswan-918094fde55fa0dbfd59a5f88d576efb513a88db.tar.gz vyos-strongswan-918094fde55fa0dbfd59a5f88d576efb513a88db.zip |
New upstream version 5.7.2
Diffstat (limited to 'src/libstrongswan')
69 files changed, 3947 insertions, 705 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 278c67405..b04627e63 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -551,6 +551,7 @@ static signature_params_t *create_rsa_pss_constraint(char *token) .scheme = SIGN_RSA_EMSA_PSS, .params = &pss, }; + rsa_pss_params_set_salt_len(&pss, 0); params = signature_params_clone(&pss_params); } return params; diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 0239ee17e..61dfbbcad 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -73,6 +73,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_SAFE_PRIMES", "BUILD_SHARES", "BUILD_THRESHOLD", + "BUILD_EDDSA_PUB", "BUILD_EDDSA_PRIV_ASN1_DER", "BUILD_END", ); diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index 7928ef487..b283bd166 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -156,6 +156,8 @@ enum builder_part_t { BUILD_SHARES, /** minimum number of participating private key shares */ BUILD_THRESHOLD, + /** EdDSA public key blob */ + BUILD_EDDSA_PUB, /** DER encoded ASN.1 EdDSA private key */ BUILD_EDDSA_PRIV_ASN1_DER, /** end of variable argument builder list */ diff --git a/src/libstrongswan/credentials/keys/private_key.h b/src/libstrongswan/credentials/keys/private_key.h index d7cfdd74d..5cf8641ad 100644 --- a/src/libstrongswan/credentials/keys/private_key.h +++ b/src/libstrongswan/credentials/keys/private_key.h @@ -40,6 +40,19 @@ struct private_key_t { key_type_t (*get_type)(private_key_t *this); /** + * Get signature schemes supported by this key. + * + * This is useful for keys that only support certain hash algorithms or + * require specific parameters for RSA/PSS signatures. + * + * @note Implementing this method is optional. If multiple schemes are + * returned, they should be ordered by decreasing preference. + * + * @return enumerator over signature_params_t* + */ + enumerator_t *(*supported_signature_schemes)(private_key_t *this); + + /** * Create a signature over a chunk of data. * * @param scheme signature scheme to use diff --git a/src/libstrongswan/credentials/keys/public_key.c b/src/libstrongswan/credentials/keys/public_key.c index 89fa9b348..3ef6981f6 100644 --- a/src/libstrongswan/credentials/keys/public_key.c +++ b/src/libstrongswan/credentials/keys/public_key.c @@ -250,7 +250,7 @@ int signature_scheme_to_oid(signature_scheme_t scheme) #define PSS_PARAMS(bits) static rsa_pss_params_t pss_params_sha##bits = { \ .hash = HASH_SHA##bits, \ .mgf1_hash = HASH_SHA##bits, \ - .salt_len = RSA_PSS_SALT_LEN_DEFAULT, \ + .salt_len = HASH_SIZE_SHA##bits, \ } PSS_PARAMS(256); diff --git a/src/libstrongswan/credentials/keys/signature_params.c b/src/libstrongswan/credentials/keys/signature_params.c index 8f42fb940..d89bd2c96 100644 --- a/src/libstrongswan/credentials/keys/signature_params.c +++ b/src/libstrongswan/credentials/keys/signature_params.c @@ -18,22 +18,43 @@ #include <asn1/oid.h> #include <asn1/asn1_parser.h> -/** - * Determine the salt length in case it is not configured +/* + * Described in header */ -static ssize_t rsa_pss_salt_length(rsa_pss_params_t *pss) +bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits) { - ssize_t salt_len = pss->salt_len; + size_t hash_len; - if (salt_len <= RSA_PSS_SALT_LEN_DEFAULT) + if (params->salt_len < 0) { - salt_len = hasher_hash_size(pss->hash); - if (!salt_len) + hash_len = hasher_hash_size(params->hash); + if (!hash_len) + { + return FALSE; + } + + switch (params->salt_len) { - return -1; + case RSA_PSS_SALT_LEN_DEFAULT: + params->salt_len = hash_len; + break; + case RSA_PSS_SALT_LEN_MAX: + if (modbits) + { + /* emBits = modBits - 1 */ + modbits -= 1; + /* emLen = ceil(emBits/8) */ + modbits = (modbits+7) / BITS_PER_BYTE; + /* account for 0x01 separator in DB, 0xbc trailing byte */ + params->salt_len = max(0, (ssize_t)(modbits - hash_len - 2)); + break; + } + return FALSE; + default: + return FALSE; } } - return salt_len; + return TRUE; } /** @@ -68,8 +89,7 @@ static bool compare_params(signature_params_t *a, signature_params_t *b, return pss_a->hash == pss_b->hash && pss_a->mgf1_hash == pss_b->mgf1_hash && - (!strict || - rsa_pss_salt_length(pss_a) == rsa_pss_salt_length(pss_b)); + (!strict || pss_a->salt_len == pss_b->salt_len); } default: break; @@ -328,7 +348,6 @@ end: bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1) { chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty; - ssize_t salt_len; int alg; if (params->hash != HASH_SHA1) @@ -351,16 +370,15 @@ bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1) mgf = asn1_algorithmIdentifier_params(OID_MGF1, asn1_algorithmIdentifier(alg)); } - salt_len = rsa_pss_salt_length(params); - if (salt_len < 0) + if (params->salt_len < 0) { chunk_free(&hash); chunk_free(&mgf); return FALSE; } - else if (salt_len != HASH_SIZE_SHA1) + else if (params->salt_len != HASH_SIZE_SHA1) { - slen = asn1_integer("m", asn1_integer_from_uint64(salt_len)); + slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len)); } *asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm", hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty, diff --git a/src/libstrongswan/credentials/keys/signature_params.h b/src/libstrongswan/credentials/keys/signature_params.h index 6934c5e88..b4169a829 100644 --- a/src/libstrongswan/credentials/keys/signature_params.h +++ b/src/libstrongswan/credentials/keys/signature_params.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Tobias Brunner + * Copyright (C) 2017-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -100,11 +100,15 @@ struct rsa_pss_params_t { hash_algorithm_t hash; /** Hash for the MGF1 function */ hash_algorithm_t mgf1_hash; - /** Salt length, use RSA_PSS_SALT_LEN_DEFAULT for length equal to hash */ + /** Salt length, use the constants below for special lengths resolved + * via rsa_pss_params_set_salt_len() */ ssize_t salt_len; /** Salt value, for unit tests (not all implementations support this) */ chunk_t salt; +/** Use a salt length equal to the length of the hash */ #define RSA_PSS_SALT_LEN_DEFAULT -1 +/** Use the maximum salt length depending on the hash and key length */ +#define RSA_PSS_SALT_LEN_MAX -2 }; /** @@ -126,4 +130,15 @@ bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params); */ bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1); +/** + * Determine and set the salt length for the given params in case constants + * are used + * + * @param params parameters to update + * @param modbits RSA modulus length in bits (required if RSA_PSS_SALT_LEN_MAX + * is used) + * @return salt length to use, negative on error + */ +bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits); + #endif /** SIGNATURE_PARAMS_H_ @}*/ diff --git a/src/libstrongswan/crypto/mac.h b/src/libstrongswan/crypto/mac.h index 50dc4c73a..97cb7e352 100644 --- a/src/libstrongswan/crypto/mac.h +++ b/src/libstrongswan/crypto/mac.h @@ -39,12 +39,12 @@ struct mac_t { * * If out is NULL, no result is given back. A next call will * append the data to already supplied data. If out is not NULL, - * the mac of all apended data is calculated, written to out and the + * the MAC of all appended data is calculated, written to out and the * internal state is reset. * * @param data chunk of data to authenticate * @param out pointer where the generated bytes will be written - * @return TRUE if mac generated successfully + * @return TRUE if MAC generated successfully */ bool (*get_mac)(mac_t *this, chunk_t data, uint8_t *out) __attribute__((warn_unused_result)); diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c index cad94aa82..a078d3b30 100644 --- a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c +++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c @@ -1,4 +1,4 @@ -/* C code produced by gperf version 3.0.4 */ +/* ANSI-C code produced by gperf version 3.1 */ /* Command-line: /usr/bin/gperf -N proposal_get_token_static -m 10 -C -G -c -t -D */ /* Computed positions: -k'1,5-7,10,15,$' */ @@ -26,7 +26,7 @@ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ -error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." #endif @@ -74,9 +74,7 @@ inline #endif #endif static unsigned int -hash (str, len) - register const char *str; - register unsigned int len; +hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { @@ -107,7 +105,7 @@ hash (str, len) 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251 }; - register int hval = len; + register unsigned int hval = len; switch (hval) { @@ -320,22 +318,14 @@ static const short lookup[] = 143 }; -#ifdef __GNUC__ -__inline -#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif -#endif const struct proposal_token * -proposal_get_token_static (str, len) - register const char *str; - register unsigned int len; +proposal_get_token_static (register const char *str, register size_t len) { if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - register int key = hash (str, len); + register unsigned int key = hash (str, len); - if (key <= MAX_HASH_VALUE && key >= 0) + if (key <= MAX_HASH_VALUE) { register int index = lookup[key]; diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.h b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h index 1345f36bb..a0beec0bb 100644 --- a/src/libstrongswan/crypto/proposal/proposal_keywords_static.h +++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h @@ -19,7 +19,7 @@ #include "proposal_keywords.h" const proposal_token_t* proposal_get_token_static(register const char *str, - register unsigned len); + register size_t len); #endif /* PROPOSAL_KEYWORDS_STATIC_H_ */ diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index 77c29916c..db87affc9 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -82,6 +82,14 @@ enum agent_msg_type_t { }; /** + * Flags for signatures + */ +enum agent_signature_flags_t { + SSH_AGENT_FLAG_SHA2_256 = 2, + SSH_AGENT_FLAG_SHA2_512 = 4, +}; + +/** * read a byte from a blob */ static u_char read_byte(chunk_t *blob) @@ -217,12 +225,35 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) } static bool scheme_supported(private_agent_private_key_t *this, - signature_scheme_t scheme) + signature_scheme_t scheme, uint32_t *flags, + char **prefix) { switch (this->pubkey->get_type(this->pubkey)) { case KEY_RSA: - return scheme == SIGN_RSA_EMSA_PKCS1_SHA1; + switch (scheme) + { + case SIGN_RSA_EMSA_PKCS1_SHA1: + *prefix = "ssh-rsa"; + return TRUE; + case SIGN_RSA_EMSA_PKCS1_SHA2_256: + *flags |= SSH_AGENT_FLAG_SHA2_256; + *prefix = "rsa-sha2-256"; + return TRUE; + case SIGN_RSA_EMSA_PKCS1_SHA2_512: + *flags |= SSH_AGENT_FLAG_SHA2_512; + *prefix = "rsa-sha2-512"; + return TRUE; + default: + break; + } + return FALSE; + case KEY_ED25519: + *prefix = "ssh-ed25519"; + return scheme == SIGN_ED25519; + case KEY_ED448: + *prefix = "ssh-ed448"; + return scheme == SIGN_ED448; case KEY_ECDSA: return scheme == SIGN_ECDSA_256 || scheme == SIGN_ECDSA_384 || @@ -236,11 +267,12 @@ METHOD(private_key_t, sign, bool, private_agent_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { - uint32_t len, flags; - char buf[2048]; + key_type_t type; + uint32_t len, flags = 0; + char buf[2048], *prefix = NULL; chunk_t blob; - if (!scheme_supported(this, scheme)) + if (!scheme_supported(this, scheme, &flags, &prefix)) { DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent", signature_scheme_names, scheme); @@ -272,7 +304,7 @@ METHOD(private_key_t, sign, bool, return FALSE; } - flags = htonl(0); + flags = htonl(flags); if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags)) { DBG1(DBG_LIB, "writing to ssh-agent failed"); @@ -290,9 +322,15 @@ METHOD(private_key_t, sign, bool, } /* parse length */ blob = read_string(&blob); - /* check sig type */ - if (chunk_equals(read_string(&blob), chunk_from_str("ssh-rsa"))) - { /* for RSA the signature has no special encoding */ + /* verify type */ + if (prefix && !chunk_equals(read_string(&blob), chunk_from_str(prefix))) + { + DBG1(DBG_LIB, "ssh-agent didn't return requested %s signature", prefix); + return FALSE; + } + type = this->pubkey->get_type(this->pubkey); + if (type == KEY_RSA || type == KEY_ED25519 || type == KEY_ED448) + { /* for RSA/EdDSA, the signature has no special encoding */ blob = read_string(&blob); if (blob.len) { @@ -301,7 +339,7 @@ METHOD(private_key_t, sign, bool, } } else - { /* anything else is treated as ECSDA for now */ + { /* parse ECDSA signatures */ blob = read_string(&blob); if (blob.len) { @@ -340,6 +378,80 @@ METHOD(private_key_t, get_keysize, int, return this->pubkey->get_keysize(this->pubkey); } +/** + * Private data for RSA scheme enumerator + */ +typedef struct { + enumerator_t public; + int index; + bool reverse; +} scheme_enumerator_t; + +static signature_params_t rsa_schemes[] = { + { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 }, + { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512 }, +}; + +METHOD(enumerator_t, enumerate_rsa_scheme, bool, + scheme_enumerator_t *this, va_list args) +{ + signature_params_t **params; + + VA_ARGS_VGET(args, params); + + if ((this->reverse && --this->index >= 0) || + (!this->reverse && ++this->index < countof(rsa_schemes))) + { + *params = &rsa_schemes[this->index]; + return TRUE; + } + return FALSE; +} + +/** + * Create an enumerator for the supported RSA signature schemes + */ +static enumerator_t *create_rsa_enumerator(private_agent_private_key_t *this) +{ + scheme_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = enumerator_enumerate_default, + .venumerate = _enumerate_rsa_scheme, + .destroy = (void*)free, + }, + .index = -1, + .reverse = FALSE, + ); + /* propose SHA-512 first for larger keys */ + if (get_keysize(this) > 3072) + { + enumerator->index = countof(rsa_schemes); + enumerator->reverse = TRUE; + } + return &enumerator->public; +} + +METHOD(private_key_t, supported_signature_schemes, enumerator_t*, + private_agent_private_key_t *this) +{ + key_type_t type = get_type(this); + + switch (type) + { + case KEY_RSA: + return create_rsa_enumerator(this); + case KEY_ED25519: + case KEY_ED448: + case KEY_ECDSA: + return signature_schemes_for_key(type, get_keysize(this)); + default: + break; + } + return enumerator_create_empty(); +} + METHOD(private_key_t, get_public_key, public_key_t*, private_agent_private_key_t *this) { @@ -413,6 +525,7 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args) .public = { .key = { .get_type = _get_type, + .supported_signature_schemes = _supported_signature_schemes, .sign = _sign, .decrypt = _decrypt, .get_keysize = _get_keysize, diff --git a/src/libstrongswan/plugins/botan/Makefile.am b/src/libstrongswan/plugins/botan/Makefile.am index c1160145a..30d3e601c 100644 --- a/src/libstrongswan/plugins/botan/Makefile.am +++ b/src/libstrongswan/plugins/botan/Makefile.am @@ -23,9 +23,11 @@ libstrongswan_botan_la_SOURCES = \ botan_ec_diffie_hellman.h botan_ec_diffie_hellman.c \ botan_ec_public_key.h botan_ec_public_key.c \ botan_ec_private_key.h botan_ec_private_key.c \ + botan_ed_public_key.h botan_ed_public_key.c \ + botan_ed_private_key.h botan_ed_private_key.c \ botan_util.h botan_util.c \ botan_util_keys.h botan_util_keys.c \ - botan_gcm.h botan_gcm.c \ + botan_aead.h botan_aead.c \ botan_x25519.h botan_x25519.c libstrongswan_botan_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/botan/Makefile.in b/src/libstrongswan/plugins/botan/Makefile.in index ef9f88610..3bb3e22f4 100644 --- a/src/libstrongswan/plugins/botan/Makefile.in +++ b/src/libstrongswan/plugins/botan/Makefile.in @@ -142,8 +142,9 @@ am_libstrongswan_botan_la_OBJECTS = botan_plugin.lo botan_rng.lo \ botan_hasher.lo botan_hmac.lo botan_crypter.lo \ botan_rsa_public_key.lo botan_rsa_private_key.lo \ botan_diffie_hellman.lo botan_ec_diffie_hellman.lo \ - botan_ec_public_key.lo botan_ec_private_key.lo botan_util.lo \ - botan_util_keys.lo botan_gcm.lo botan_x25519.lo + botan_ec_public_key.lo botan_ec_private_key.lo \ + botan_ed_public_key.lo botan_ed_private_key.lo botan_util.lo \ + botan_util_keys.lo botan_aead.lo botan_x25519.lo libstrongswan_botan_la_OBJECTS = $(am_libstrongswan_botan_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -478,9 +479,11 @@ libstrongswan_botan_la_SOURCES = \ botan_ec_diffie_hellman.h botan_ec_diffie_hellman.c \ botan_ec_public_key.h botan_ec_public_key.c \ botan_ec_private_key.h botan_ec_private_key.c \ + botan_ed_public_key.h botan_ed_public_key.c \ + botan_ed_private_key.h botan_ed_private_key.c \ botan_util.h botan_util.c \ botan_util_keys.h botan_util_keys.c \ - botan_gcm.h botan_gcm.c \ + botan_aead.h botan_aead.c \ botan_x25519.h botan_x25519.c libstrongswan_botan_la_LDFLAGS = -module -avoid-version @@ -574,12 +577,14 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_aead.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_crypter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_diffie_hellman.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_ec_diffie_hellman.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_ec_private_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_ec_public_key.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_gcm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_ed_private_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_ed_public_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_hasher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_hmac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/botan_plugin.Plo@am__quote@ diff --git a/src/libstrongswan/plugins/botan/botan_gcm.c b/src/libstrongswan/plugins/botan/botan_aead.c index 7e0fc1468..40006ae77 100644 --- a/src/libstrongswan/plugins/botan/botan_gcm.c +++ b/src/libstrongswan/plugins/botan/botan_aead.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 Atanas Filyanov * Rohde & Schwarz Cybersecurity GmbH * @@ -21,23 +24,28 @@ * THE SOFTWARE. */ -#include "botan_gcm.h" +#include "botan_aead.h" #include <botan/build.h> -#ifdef BOTAN_HAS_AES -#ifdef BOTAN_HAS_AEAD_GCM +#if (defined(BOTAN_HAS_AES) && \ + (defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_CCM))) || \ + defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) #include <crypto/iv/iv_gen_seq.h> #include <botan/ffi.h> /** - * as defined in RFC 4106 + * As defined in RFC 4106 (GCM) and RFC 7634 (ChaPoly) */ -#define IV_LEN 8 -#define SALT_LEN 4 -#define NONCE_LEN (IV_LEN + SALT_LEN) +#define IV_LEN 8 +#define SALT_LEN 4 +#define CHAPOLY_KEY_LEN 32 +/** + * As defined in RFC 4309 + */ +#define CCM_SALT_LEN 3 typedef struct private_aead_t private_aead_t; @@ -56,7 +64,7 @@ struct private_aead_t { /** * Salt value */ - char salt[SALT_LEN]; + chunk_t salt; /** * Size of the integrity check value @@ -77,15 +85,12 @@ struct private_aead_t { /** * Do the actual en/decryption */ -static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, - u_char *out, uint32_t init_flag) +static bool do_crypt(private_aead_t *this, chunk_t data, chunk_t assoc, + chunk_t iv, u_char *out, uint32_t init_flag) { botan_cipher_t cipher; - uint8_t nonce[NONCE_LEN]; size_t output_written = 0, input_consumed = 0; - - memcpy(nonce, this->salt, SALT_LEN); - memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); + chunk_t nonce; if (botan_cipher_init(&cipher, this->cipher_name, init_flag)) { @@ -105,7 +110,9 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, return FALSE; } - if (botan_cipher_start(cipher, nonce, NONCE_LEN)) + nonce = chunk_cata("cc", this->salt, iv); + + if (botan_cipher_start(cipher, nonce.ptr, nonce.len)) { botan_cipher_destroy(cipher); return FALSE; @@ -149,7 +156,8 @@ METHOD(aead_t, encrypt, bool, *encrypted = chunk_alloc(plain.len + this->icv_size); out = encrypted->ptr; } - return crypt(this, plain, assoc, iv, out, BOTAN_CIPHER_INIT_FLAG_ENCRYPT); + return do_crypt(this, plain, assoc, iv, out, + BOTAN_CIPHER_INIT_FLAG_ENCRYPT); } METHOD(aead_t, decrypt, bool, @@ -170,8 +178,8 @@ METHOD(aead_t, decrypt, bool, *plain = chunk_alloc(encrypted.len); out = plain->ptr; } - return crypt(this, encrypted, assoc, iv, out, - BOTAN_CIPHER_INIT_FLAG_DECRYPT); + return do_crypt(this, encrypted, assoc, iv, out, + BOTAN_CIPHER_INIT_FLAG_DECRYPT); } METHOD(aead_t, get_block_size, size_t, @@ -201,7 +209,7 @@ METHOD(aead_t, get_iv_gen, iv_gen_t*, METHOD(aead_t, get_key_size, size_t, private_aead_t *this) { - return this->key.len + SALT_LEN; + return this->key.len + this->salt.len; } METHOD(aead_t, set_key, bool, @@ -211,7 +219,7 @@ METHOD(aead_t, set_key, bool, { return FALSE; } - memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN); + memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len); memcpy(this->key.ptr, key.ptr, this->key.len); return TRUE; } @@ -220,15 +228,82 @@ METHOD(aead_t, destroy, void, private_aead_t *this) { chunk_clear(&this->key); + chunk_clear(&this->salt); this->iv_gen->destroy(this->iv_gen); free(this); } +#ifdef BOTAN_HAS_AES +#if defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_GCM) + +static struct { + encryption_algorithm_t algo; + size_t key_size; + char *name; + size_t icv_size; +} aes_modes[] = { + { ENCR_AES_GCM_ICV8, 16, "AES-128/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV8, 24, "AES-192/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV8, 32, "AES-256/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV12, 16, "AES-128/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV12, 24, "AES-192/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV12, 32, "AES-256/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV16, 16, "AES-128/GCM(16)", 16 }, + { ENCR_AES_GCM_ICV16, 24, "AES-192/GCM(16)", 16 }, + { ENCR_AES_GCM_ICV16, 32, "AES-256/GCM(16)", 16 }, + { ENCR_AES_CCM_ICV8, 16, "AES-128/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV8, 24, "AES-192/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV8, 32, "AES-256/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV12, 16, "AES-128/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV12, 24, "AES-192/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV12, 32, "AES-256/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV16, 16, "AES-128/CCM(16,4)", 16 }, + { ENCR_AES_CCM_ICV16, 24, "AES-192/CCM(16,4)", 16 }, + { ENCR_AES_CCM_ICV16, 32, "AES-256/CCM(16,4)", 16 }, +}; + +/** + * Determine the cipher name and ICV size for the given algorithm and key size + */ +static bool determine_aes_params(private_aead_t *this, + encryption_algorithm_t algo, size_t key_size) +{ + int i; + + for (i = 0; i < countof(aes_modes); i++) + { + if (aes_modes[i].algo == algo && + aes_modes[i].key_size == key_size) + { + this->cipher_name = aes_modes[i].name; + this->icv_size = aes_modes[i].icv_size; + return TRUE; + } + } + return FALSE; +} + +#endif +#endif + +/** + * Check the given salt size, set it if not set + */ +static bool check_salt_size(size_t expected, size_t *salt_size) +{ + if (*salt_size) + { + return *salt_size == expected; + } + *salt_size = expected; + return TRUE; +} + /* * Described in header */ -aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size, - size_t salt_size) +aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size, + size_t salt_size) { private_aead_t *this; @@ -246,88 +321,68 @@ aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size, }, ); - if (salt_size && salt_size != SALT_LEN) - { - /* currently not supported */ - free(this); - return NULL; - } - switch (algo) { +#ifdef BOTAN_HAS_AES +#ifdef BOTAN_HAS_AEAD_GCM case ENCR_AES_GCM_ICV8: - switch (key_size) + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + if (!key_size) { - case 0: - key_size = 16; - /* FALL */ - case 16: - this->cipher_name = "AES-128/GCM(8)"; - break; - case 24: - this->cipher_name = "AES-192/GCM(8)"; - break; - case 32: - this->cipher_name = "AES-256/GCM(8)"; - break; - default: - free(this); - return NULL; + key_size = 16; + } + if (!check_salt_size(SALT_LEN, &salt_size) || + !determine_aes_params(this, algo, key_size)) + { + free(this); + return NULL; } - this->icv_size = 8; break; - case ENCR_AES_GCM_ICV12: - switch (key_size) +#endif +#ifdef BOTAN_HAS_AEAD_CCM + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + if (!key_size) { - case 0: - key_size = 16; - /* FALL */ - case 16: - this->cipher_name = "AES-128/GCM(12)"; - break; - case 24: - this->cipher_name = "AES-192/GCM(12)"; - break; - case 32: - this->cipher_name = "AES-256/GCM(12)"; - break; - default: - free(this); - return NULL; + key_size = 16; + } + if (!check_salt_size(CCM_SALT_LEN, &salt_size) || + !determine_aes_params(this, algo, key_size)) + { + free(this); + return NULL; } - this->icv_size = 12; break; - case ENCR_AES_GCM_ICV16: - switch (key_size) +#endif +#endif +#ifdef BOTAN_HAS_AEAD_CHACHA20_POLY1305 + case ENCR_CHACHA20_POLY1305: + if (!key_size) + { + key_size = CHAPOLY_KEY_LEN; + } + if (key_size != CHAPOLY_KEY_LEN || + !check_salt_size(SALT_LEN, &salt_size)) { - case 0: - key_size = 16; - /* FALL */ - case 16: - this->cipher_name = "AES-128/GCM"; - break; - case 24: - this->cipher_name = "AES-192/GCM"; - break; - case 32: - this->cipher_name = "AES-256/GCM"; - break; - default: - free(this); - return NULL; + free(this); + return NULL; } + this->cipher_name = "ChaCha20Poly1305"; this->icv_size = 16; break; +#endif default: free(this); return NULL; } this->key = chunk_alloc(key_size); + this->salt = chunk_alloc(salt_size); this->iv_gen = iv_gen_seq_create(); return &this->public; } #endif -#endif diff --git a/src/libstrongswan/plugins/botan/botan_gcm.h b/src/libstrongswan/plugins/botan/botan_aead.h index b2053cb4d..00a2ba4bc 100644 --- a/src/libstrongswan/plugins/botan/botan_gcm.h +++ b/src/libstrongswan/plugins/botan/botan_aead.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 Atanas Filyanov * Rohde & Schwarz Cybersecurity GmbH * @@ -22,14 +25,14 @@ */ /** - * Implements the aead_t interface using Botan in GCM mode. + * Implements the aead_t interface using Botan. * - * @defgroup botan_gcm botan_gcm + * @defgroup botan_aead botan_aead * @{ @ingroup botan_p */ -#ifndef BOTAN_GCM_H_ -#define BOTAN_GCM_H_ +#ifndef BOTAN_AEAD_H_ +#define BOTAN_AEAD_H_ #include <crypto/aead.h> @@ -41,7 +44,7 @@ * @param salt_size size of implicit salt length * @return aead_t object, NULL if not supported */ -aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size, - size_t salt_size); +aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size, + size_t salt_size); -#endif /** BOTAN_GCM_H_ @}*/ +#endif /** BOTAN_AEAD_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_crypter.c b/src/libstrongswan/plugins/botan/botan_crypter.c index 002be6ea8..3ec5c4d5e 100644 --- a/src/libstrongswan/plugins/botan/botan_crypter.c +++ b/src/libstrongswan/plugins/botan/botan_crypter.c @@ -25,6 +25,10 @@ #include "botan_crypter.h" +#include <botan/build.h> + +#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC) + #include <botan/ffi.h> typedef struct private_botan_crypter_t private_botan_crypter_t; @@ -189,3 +193,5 @@ botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo, this->key = chunk_alloc(key_size); return &this->public; } + +#endif diff --git a/src/libstrongswan/plugins/botan/botan_ec_public_key.c b/src/libstrongswan/plugins/botan/botan_ec_public_key.c index 4c85dbcec..095ae3f20 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_ec_public_key.c @@ -69,9 +69,7 @@ static bool verify_signature(private_botan_ec_public_key_t *this, const char* hash_and_padding, int signature_format, size_t keylen, chunk_t data, chunk_t signature) { - botan_pk_op_verify_t verify_op; chunk_t sig = signature; - bool valid = FALSE; if (signature_format == SIG_FORMAT_DER_SEQUENCE) { @@ -104,22 +102,7 @@ static bool verify_signature(private_botan_ec_public_key_t *this, memcpy(sig.ptr + (keylen - r.len), r.ptr, r.len); memcpy(sig.ptr + keylen + (keylen - s.len), s.ptr, s.len); } - - if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding, 0)) - { - return FALSE; - } - - if (botan_pk_op_verify_update(verify_op, data.ptr, data.len)) - { - botan_pk_op_verify_destroy(verify_op); - return FALSE; - } - - valid = !(botan_pk_op_verify_finish(verify_op, sig.ptr, sig.len)); - - botan_pk_op_verify_destroy(verify_op); - return valid; + return botan_verify_signature(this->key, hash_and_padding, data, sig); } METHOD(public_key_t, get_type, key_type_t, diff --git a/src/libstrongswan/plugins/botan/botan_ed_private_key.c b/src/libstrongswan/plugins/botan/botan_ed_private_key.c new file mode 100644 index 000000000..3f0f54222 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_ed_private_key.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "botan_ed_private_key.h" +#include "botan_ed_public_key.h" +#include "botan_util.h" + +#include <botan/build.h> + +#ifdef BOTAN_HAS_ED25519 + +#include <asn1/asn1.h> +#include <utils/debug.h> + +typedef struct private_private_key_t private_private_key_t; + +#define ED25519_KEY_LEN 32 + +/** + * Private data + */ +struct private_private_key_t { + + /** + * Public interface + */ + private_key_t public; + + /** + * Botan private key object + */ + botan_privkey_t key; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(private_key_t, sign, bool, + private_private_key_t *this, signature_scheme_t scheme, + void *params, chunk_t data, chunk_t *signature) +{ + switch (scheme) + { + case SIGN_ED25519: + return botan_get_signature(this->key, "Pure", data, signature); + default: + DBG1(DBG_LIB, "signature scheme %N not supported via botan", + signature_scheme_names, scheme); + return FALSE; + } +} + +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 ED25519_KEY_LEN * 8; +} + +METHOD(private_key_t, get_type, key_type_t, + private_private_key_t *this) +{ + return KEY_ED25519; +} + +METHOD(private_key_t, get_public_key, public_key_t*, + private_private_key_t *this) +{ + botan_pubkey_t pubkey; + + if (botan_privkey_export_pubkey(&pubkey, this->key)) + { + return NULL; + } + return botan_ed_public_key_adopt(pubkey); +} + +METHOD(private_key_t, get_fingerprint, bool, + private_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) +{ + botan_pubkey_t pubkey; + bool success = FALSE; + + /* check the cache before doing the export */ + if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) + { + return TRUE; + } + + if (botan_privkey_export_pubkey(&pubkey, this->key)) + { + return FALSE; + } + success = botan_get_fingerprint(pubkey, this, type, fingerprint); + botan_pubkey_destroy(pubkey); + return success; +} + +METHOD(private_key_t, get_encoding, bool, + private_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return botan_get_privkey_encoding(this->key, type, encoding); +} + +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); + botan_privkey_destroy(this->key); + free(this); + } +} + +/** + * Internal generic constructor + */ +static private_private_key_t *create_empty() +{ + 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, + }, + .ref = 1, + ); + + return this; +} + +/* + * Described in header + */ +private_key_t *botan_ed_private_key_adopt(botan_privkey_t key) +{ + private_private_key_t *this; + + this = create_empty(); + this->key = key; + + return &this->public; +} + +/* + * Described in header + */ +private_key_t *botan_ed_private_key_gen(key_type_t type, va_list args) +{ + private_private_key_t *this; + botan_rng_t rng; + + 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; + } + + if (botan_rng_init(&rng, "system")) + { + return NULL; + } + + this = create_empty(); + + if (botan_privkey_create(&this->key, "Ed25519", NULL, rng)) + { + DBG1(DBG_LIB, "EdDSA private key generation failed"); + botan_rng_destroy(rng); + free(this); + return NULL; + } + + botan_rng_destroy(rng); + return &this->public; +} + +/* + * Described in header + */ +private_key_t *botan_ed_private_key_load(key_type_t type, va_list args) +{ + private_private_key_t *this; + chunk_t key = chunk_empty; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_EDDSA_PRIV_ASN1_DER: + key = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + /* PKCS#8-encoded keys are handled generically, so we only handle the + * explicit case */ + if (asn1_unwrap(&key, &key) != ASN1_OCTET_STRING || + key.len != ED25519_KEY_LEN) + { + return NULL; + } + + this = create_empty(); + + if (botan_privkey_load_ed25519(&this->key, key.ptr)) + { + free(this); + return NULL; + } + return &this->public; +} + +#endif diff --git a/src/libstrongswan/plugins/botan/botan_ed_private_key.h b/src/libstrongswan/plugins/botan/botan_ed_private_key.h new file mode 100644 index 000000000..f7f32e8f3 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_ed_private_key.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup botan_ed_private_key botan_ed_private_key + * @{ @ingroup botan_p + */ + +#ifndef BOTAN_ED_PRIVATE_KEY_H_ +#define BOTAN_ED_PRIVATE_KEY_H_ + +#include <botan/ffi.h> + +#include <credentials/builder.h> +#include <credentials/keys/private_key.h> + +/** + * Generate an EdDSA private key using Botan. + * + * @param type type of the key, must be KEY_ED25519 + * @param args builder_part_t argument list + * @return generated key, NULL on failure + */ +private_key_t *botan_ed_private_key_gen(key_type_t type, va_list args); + +/** + * Load an EdDSA private key using Botan. + * + * @param type type of the key, must be KEY_ED25519 + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +private_key_t *botan_ed_private_key_load(key_type_t type, va_list args); + +/** + * Load an EdDSA private key by adopting a botan_privkey_t object. + * + * @param key private key object (adopted) + * @return loaded key, NULL on failure + */ +private_key_t *botan_ed_private_key_adopt(botan_privkey_t key); + +#endif /** BOTAN_ED_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_ed_public_key.c b/src/libstrongswan/plugins/botan/botan_ed_public_key.c new file mode 100644 index 000000000..41d2baae8 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_ed_public_key.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "botan_ed_public_key.h" +#include "botan_util.h" + +#include <botan/build.h> + +#ifdef BOTAN_HAS_ED25519 + +#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; + + /** + * Botan public key object + */ + botan_pubkey_t key; + + /** + * Reference counter + */ + refcount_t ref; +}; + +METHOD(public_key_t, get_type, key_type_t, + private_public_key_t *this) +{ + return KEY_ED25519; +} + +METHOD(public_key_t, get_keysize, int, + private_public_key_t *this) +{ + return ED25519_KEY_LEN * 8; +} + +METHOD(public_key_t, verify, bool, + private_public_key_t *this, signature_scheme_t scheme, + void *params, chunk_t data, chunk_t signature) +{ + switch (scheme) + { + case SIGN_ED25519: + return botan_verify_signature(this->key, "Pure", data, signature); + default: + DBG1(DBG_LIB, "signature scheme %N not supported via botan", + signature_scheme_names, scheme); + return FALSE; + } +} + +METHOD(public_key_t, encrypt, bool, + private_public_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) +{ + DBG1(DBG_LIB, "EdDSA public key encryption not implemented"); + return FALSE; +} + +METHOD(public_key_t, get_fingerprint, bool, + private_public_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) +{ + return botan_get_fingerprint(this->key, this, type, fingerprint); +} + +METHOD(public_key_t, get_encoding, bool, + private_public_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return botan_get_encoding(this->key, type, encoding); +} + +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); + botan_pubkey_destroy(this->key); + free(this); + } +} + +/** + * Internal generic constructor + */ +static private_public_key_t *create_empty() +{ + 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, + }, + .ref = 1, + ); + + return this; +} + +/* + * Described in header + */ +public_key_t *botan_ed_public_key_adopt(botan_pubkey_t key) +{ + private_public_key_t *this; + + this = create_empty(); + this->key = key; + + return &this->public; +} + +/* + * Described in header + */ +public_key_t *botan_ed_public_key_load(key_type_t type, va_list args) +{ + private_public_key_t *this; + chunk_t key = chunk_empty; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_EDDSA_PUB: + key = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + /* ASN.1-encoded keys are handled generically, so we only handle the + * explicit case */ + if (key.len != ED25519_KEY_LEN) + { + return NULL; + } + + this = create_empty(); + + if (botan_pubkey_load_ed25519(&this->key, key.ptr)) + { + free(this); + return NULL; + } + return &this->public; +} + +#endif diff --git a/src/libstrongswan/plugins/botan/botan_ed_public_key.h b/src/libstrongswan/plugins/botan/botan_ed_public_key.h new file mode 100644 index 000000000..0f44b1afb --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_ed_public_key.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BOTAN_ED_PUBLIC_KEY_H_ +#define BOTAN_ED_PUBLIC_KEY_H_ + +#include <botan/ffi.h> + +#include <credentials/builder.h> +#include <credentials/keys/public_key.h> + +#define ED25519_KEY_LEN 32 + +/** + * Load an EdDSA public key by adopting a botan_pubkey_t object. + * + * @param key public key object (adopted) + * @return loaded key, NULL on failure + */ +public_key_t *botan_ed_public_key_adopt(botan_pubkey_t key); + +/** + * Load an EdDSA public key using Botan. + * + * @param type type of the key, must be KEY_ED25519 + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +public_key_t *botan_ed_public_key_load(key_type_t type, va_list args); + +#endif /** BOTAN_ED_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_plugin.c b/src/libstrongswan/plugins/botan/botan_plugin.c index fd8e5f5a6..f045ba074 100644 --- a/src/libstrongswan/plugins/botan/botan_plugin.c +++ b/src/libstrongswan/plugins/botan/botan_plugin.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2018 René Korthaus @@ -36,7 +37,9 @@ #include "botan_ec_diffie_hellman.h" #include "botan_ec_public_key.h" #include "botan_ec_private_key.h" -#include "botan_gcm.h" +#include "botan_ed_public_key.h" +#include "botan_ed_private_key.h" +#include "botan_aead.h" #include "botan_util_keys.h" #include "botan_x25519.h" @@ -101,6 +104,7 @@ METHOD(plugin_t, get_features, int, #endif /* crypters */ +#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC) PLUGIN_REGISTER(CRYPTER, botan_crypter_create), #ifdef BOTAN_HAS_AES #ifdef BOTAN_HAS_MODE_CBC @@ -108,17 +112,43 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24), PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32), #endif +#endif +#endif + + /* AEAD */ +#if (defined(BOTAN_HAS_AES) && \ + (defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_CCM))) || \ + defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) + PLUGIN_REGISTER(AEAD, botan_aead_create), +#ifdef BOTAN_HAS_AES #ifdef BOTAN_HAS_AEAD_GCM - /* AES GCM */ - PLUGIN_REGISTER(AEAD, botan_gcm_create), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32), #endif + #ifdef BOTAN_HAS_AEAD_CCM + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 32), + #endif +#endif +#ifdef BOTAN_HAS_AEAD_CHACHA20_POLY1305 + PLUGIN_PROVIDE(AEAD, ENCR_CHACHA20_POLY1305, 32), #endif +#endif + /* hashers */ PLUGIN_REGISTER(HASHER, botan_hasher_create), #ifdef BOTAN_HAS_MD5 @@ -135,6 +165,13 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(HASHER, HASH_SHA384), PLUGIN_PROVIDE(HASHER, HASH_SHA512), #endif +#ifdef BOTAN_HAS_SHA3 + PLUGIN_PROVIDE(HASHER, HASH_SHA3_224), + PLUGIN_PROVIDE(HASHER, HASH_SHA3_256), + PLUGIN_PROVIDE(HASHER, HASH_SHA3_384), + PLUGIN_PROVIDE(HASHER, HASH_SHA3_512), +#endif + /* prfs */ #ifdef BOTAN_HAS_HMAC PLUGIN_REGISTER(PRF, botan_hmac_prf_create), @@ -168,7 +205,8 @@ METHOD(plugin_t, get_features, int, #endif /* BOTAN_HAS_HMAC */ /* generic key loaders */ -#if defined (BOTAN_HAS_RSA) || defined(BOTAN_HAS_ECDSA) +#if defined (BOTAN_HAS_RSA) || defined(BOTAN_HAS_ECDSA) || \ + defined(BOTAN_HAS_ED25519) PLUGIN_REGISTER(PUBKEY, botan_public_key_load, TRUE), PLUGIN_PROVIDE(PUBKEY, KEY_ANY), #ifdef BOTAN_HAS_RSA @@ -177,6 +215,9 @@ METHOD(plugin_t, get_features, int, #ifdef BOTAN_HAS_ECDSA PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA), #endif +#ifdef BOTAN_HAS_ED25519 + PLUGIN_PROVIDE(PUBKEY, KEY_ED25519), +#endif PLUGIN_REGISTER(PRIVKEY, botan_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), #ifdef BOTAN_HAS_RSA @@ -185,6 +226,9 @@ METHOD(plugin_t, get_features, int, #ifdef BOTAN_HAS_ECDSA PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA), #endif +#ifdef BOTAN_HAS_ED25519 + PLUGIN_PROVIDE(PRIVKEY, KEY_ED25519), +#endif #endif /* RSA */ #ifdef BOTAN_HAS_RSA @@ -218,6 +262,16 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_384), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_512), #endif +#ifdef BOTAN_HAS_SHA3 + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA3_224), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA3_256), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA3_384), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA3_512), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA3_224), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA3_256), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA3_384), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA3_512), +#endif #endif #ifdef BOTAN_HAS_EMSA_PSSR PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS), @@ -272,6 +326,21 @@ METHOD(plugin_t, get_features, int, #endif /* BOTAN_HAS_EMSA1 */ #endif /* BOTAN_HAS_ECDSA */ +#ifdef BOTAN_HAS_ED25519 + /* EdDSA private/public key loading */ + PLUGIN_REGISTER(PUBKEY, botan_ed_public_key_load, TRUE), + PLUGIN_PROVIDE(PUBKEY, KEY_ED25519), + PLUGIN_REGISTER(PRIVKEY, botan_ed_private_key_load, TRUE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ED25519), + PLUGIN_REGISTER(PRIVKEY_GEN, botan_ed_private_key_gen, FALSE), + PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_ED25519), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ED25519), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ED25519), + /* register a pro forma identity hasher, never instantiated */ + PLUGIN_REGISTER(HASHER, return_null), + PLUGIN_PROVIDE(HASHER, HASH_IDENTITY), +#endif + /* random numbers */ #if BOTAN_HAS_SYSTEM_RNG #if BOTAN_HAS_HMAC_DRBG diff --git a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c index bb723ff95..02820b297 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2018 René Korthaus @@ -84,13 +85,8 @@ bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len) { return FALSE; } - - if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash, - params->salt_len) < len; - } - return snprintf(id, len, "EMSA-PSS(%s,MGF1)", hash) < len; + return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash, + params->salt_len) < len; } /** @@ -140,6 +136,18 @@ METHOD(private_key_t, sign, bool, case SIGN_RSA_EMSA_PKCS1_SHA2_512: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-512)", data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_224: + return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(224))", data, + signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_256: + return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(256))", data, + signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_384: + return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(384))", data, + signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_512: + return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(512))", data, + signature); case SIGN_RSA_EMSA_PSS: return build_emsa_pss_signature(this, params, data, signature); default: @@ -617,7 +625,7 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type, if (n.ptr && e.ptr && d.ptr) { - botan_mp_t n_mp, e_mp, d_mp, p_mp, q_mp; + botan_mp_t n_mp, e_mp, d_mp, p_mp = NULL, q_mp = NULL; if (!chunk_to_botan_mp(n, &n_mp)) { diff --git a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c index c6e2e8861..244caa585 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2018 René Korthaus @@ -69,33 +70,6 @@ struct private_botan_rsa_public_key_t { bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len); /** - * Verify RSA signature - */ -static bool verify_rsa_signature(private_botan_rsa_public_key_t *this, - const char* hash_and_padding, chunk_t data, - chunk_t signature) -{ - botan_pk_op_verify_t verify_op; - bool valid = FALSE; - - if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding, 0)) - { - return FALSE; - } - - if (botan_pk_op_verify_update(verify_op, data.ptr, data.len)) - { - botan_pk_op_verify_destroy(verify_op); - return FALSE; - } - - valid = !botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len); - - botan_pk_op_verify_destroy(verify_op); - return valid; -} - -/** * Verification of an EMSA PSS signature described in PKCS#1 */ static bool verify_emsa_pss_signature(private_botan_rsa_public_key_t *this, @@ -109,7 +83,7 @@ static bool verify_emsa_pss_signature(private_botan_rsa_public_key_t *this, { return FALSE; } - return verify_rsa_signature(this, hash_and_padding, data, signature); + return botan_verify_signature(this->key, hash_and_padding, data, signature); } METHOD(public_key_t, get_type, key_type_t, @@ -125,23 +99,35 @@ METHOD(public_key_t, verify, bool, switch (scheme) { case SIGN_RSA_EMSA_PKCS1_NULL: - return verify_rsa_signature(this, "EMSA_PKCS1(Raw)", data, - signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(Raw)", data, + signature); case SIGN_RSA_EMSA_PKCS1_SHA1: - return verify_rsa_signature(this, "EMSA_PKCS1(SHA-1)", data, - signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-1)", data, + signature); case SIGN_RSA_EMSA_PKCS1_SHA2_224: - return verify_rsa_signature(this, "EMSA_PKCS1(SHA-224)", - data, signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-224)", + data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_256: - return verify_rsa_signature(this, "EMSA_PKCS1(SHA-256)", - data, signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-256)", + data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_384: - return verify_rsa_signature(this, "EMSA_PKCS1(SHA-384)", - data, signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-384)", + data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_512: - return verify_rsa_signature(this, "EMSA_PKCS1(SHA-512)", - data, signature); + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-512)", + data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_224: + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(224)", + data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_256: + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(256))", + data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_384: + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(384))", + data, signature); + case SIGN_RSA_EMSA_PKCS1_SHA3_512: + return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(512))", + data, signature); case SIGN_RSA_EMSA_PSS: return verify_emsa_pss_signature(this, params, data, signature); default: diff --git a/src/libstrongswan/plugins/botan/botan_util.c b/src/libstrongswan/plugins/botan/botan_util.c index 5e18405d7..f5728e43e 100644 --- a/src/libstrongswan/plugins/botan/botan_util.c +++ b/src/libstrongswan/plugins/botan/botan_util.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner + * Copyright (C) 2018 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2018 René Korthaus @@ -67,6 +68,14 @@ const char *botan_get_hash(hash_algorithm_t hash) return "SHA-384"; case HASH_SHA512: return "SHA-512"; + case HASH_SHA3_224: + return "SHA-3(224)"; + case HASH_SHA3_256: + return "SHA-3(256)"; + case HASH_SHA3_384: + return "SHA-3(384)"; + case HASH_SHA3_512: + return "SHA-3(512)"; default: return NULL; } @@ -252,6 +261,32 @@ bool botan_get_signature(botan_privkey_t key, const char *scheme, /* * Described in header */ +bool botan_verify_signature(botan_pubkey_t key, const char *scheme, + chunk_t data, chunk_t signature) +{ + botan_pk_op_verify_t verify_op; + bool valid = FALSE; + + if (botan_pk_op_verify_create(&verify_op, key, scheme, 0)) + { + return FALSE; + } + + if (botan_pk_op_verify_update(verify_op, data.ptr, data.len)) + { + botan_pk_op_verify_destroy(verify_op); + return FALSE; + } + + valid = !botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len); + + botan_pk_op_verify_destroy(verify_op); + return valid; +} + +/* + * Described in header + */ bool botan_dh_key_derivation(botan_privkey_t key, chunk_t pub, chunk_t *secret) { botan_pk_op_ka_t ka; diff --git a/src/libstrongswan/plugins/botan/botan_util.h b/src/libstrongswan/plugins/botan/botan_util.h index 08830356e..7fb74ec5d 100644 --- a/src/libstrongswan/plugins/botan/botan_util.h +++ b/src/libstrongswan/plugins/botan/botan_util.h @@ -101,6 +101,18 @@ bool botan_get_signature(botan_privkey_t key, const char *scheme, chunk_t data, chunk_t *signature); /** + * Verify the given signature using the provided data and key with the specified + * signature scheme (hash/padding). + * + * @param key private key object + * @param scheme hash/padding algorithm + * @param data signed data + * @param signature signature to verify + */ +bool botan_verify_signature(botan_pubkey_t key, const char* scheme, + chunk_t data, chunk_t signature); + +/** * Do the Diffie-Hellman key derivation using the given private key and public * value. * diff --git a/src/libstrongswan/plugins/botan/botan_util_keys.c b/src/libstrongswan/plugins/botan/botan_util_keys.c index 176c2caf9..dc4031491 100644 --- a/src/libstrongswan/plugins/botan/botan_util_keys.c +++ b/src/libstrongswan/plugins/botan/botan_util_keys.c @@ -24,6 +24,8 @@ #include "botan_util_keys.h" #include "botan_ec_public_key.h" #include "botan_ec_private_key.h" +#include "botan_ed_public_key.h" +#include "botan_ed_private_key.h" #include "botan_rsa_public_key.h" #include "botan_rsa_private_key.h" @@ -104,15 +106,27 @@ public_key_t *botan_public_key_load(key_type_t type, va_list args) return NULL; } +#ifdef BOTAN_HAS_RSA if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA)) { this = (public_key_t*)botan_rsa_public_key_adopt(pubkey); } - else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) + else +#endif +#ifdef BOTAN_HAS_ECDSA + if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) { this = (public_key_t*)botan_ec_public_key_adopt(pubkey); } else +#endif +#ifdef BOTAN_HAS_ED25519 + if (streq(name, "Ed25519") && (type == KEY_ANY || type == KEY_ED25519)) + { + this = botan_ed_public_key_adopt(pubkey); + } + else +#endif { botan_pubkey_destroy(pubkey); } @@ -120,6 +134,7 @@ public_key_t *botan_public_key_load(key_type_t type, va_list args) return this; } +#ifdef BOTAN_HAS_ECDSA /** * Determine the curve OID from a PKCS#8 structure */ @@ -139,6 +154,7 @@ static int determine_ec_oid(chunk_t pkcs8) } return oid; } +#endif /* * Described in header @@ -151,7 +167,6 @@ private_key_t *botan_private_key_load(key_type_t type, va_list args) chunk_t blob = chunk_empty; botan_rng_t rng; char *name; - int oid; while (TRUE) { @@ -188,20 +203,35 @@ private_key_t *botan_private_key_load(key_type_t type, va_list args) botan_pubkey_destroy(pubkey); if (!name) { + botan_privkey_destroy(key); return NULL; } + +#ifdef BOTAN_HAS_RSA if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA)) { this = (private_key_t*)botan_rsa_private_key_adopt(key); } - else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) + else +#endif +#ifdef BOTAN_HAS_ECDSA + if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) { - oid = determine_ec_oid(blob); + int oid = determine_ec_oid(blob); if (oid != OID_UNKNOWN) { this = (private_key_t*)botan_ec_private_key_adopt(key, oid); } } + else +#endif +#ifdef BOTAN_HAS_ED25519 + if (streq(name, "Ed25519") && (type == KEY_ANY || type == KEY_ED25519)) + { + this = botan_ed_private_key_adopt(key); + } +#endif + if (!this) { botan_privkey_destroy(key); diff --git a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c index 1d4dec565..dfc1df4d0 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Tobias Brunner * Copyright (C) 2016 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -48,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) @@ -93,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) @@ -200,22 +222,68 @@ static const asn1Object_t pubkeyObjects[] = { #define ED25519_SUBJECT_PUBLIC_KEY 2 /** + * Parse the ASN.1-encoded subjectPublicKeyInfo + */ +static bool parse_public_key_info(private_curve25519_public_key_t *this, + chunk_t blob) +{ + asn1_parser_t *parser; + chunk_t object; + bool success = FALSE; + int objectID, oid; + + parser = asn1_parser_create(pubkeyObjects, blob); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM: + { + oid = asn1_parse_algorithmIdentifier(object, + parser->get_level(parser) + 1, NULL); + if (oid != OID_ED25519) + { + goto end; + } + break; + } + case ED25519_SUBJECT_PUBLIC_KEY: + { + /* encoded as an ASN1 BIT STRING */ + if (object.len != 1 + ED25519_KEY_LEN) + { + goto end; + } + this->pubkey = chunk_clone(chunk_skip(object, 1)); + break; + } + } + } + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; +} + +/** * See header. */ curve25519_public_key_t *curve25519_public_key_load(key_type_t type, va_list args) { private_curve25519_public_key_t *this; - chunk_t blob = chunk_empty, object; - asn1_parser_t *parser; - bool success = FALSE; - int objectID, oid; + chunk_t asn1 = chunk_empty, blob = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) { case BUILD_BLOB_ASN1_DER: + asn1 = va_arg(args, chunk_t); + continue; + case BUILD_EDDSA_PUB: blob = va_arg(args, chunk_t); continue; case BUILD_END: @@ -244,39 +312,11 @@ curve25519_public_key_t *curve25519_public_key_load(key_type_t type, .ref = 1, ); - parser = asn1_parser_create(pubkeyObjects, blob); - - while (parser->iterate(parser, &objectID, &object)) + if (blob.len == ED25519_KEY_LEN) { - switch (objectID) - { - case ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM: - { - oid = asn1_parse_algorithmIdentifier(object, - parser->get_level(parser) + 1, NULL); - if (oid != OID_ED25519) - { - goto end; - } - break; - } - case ED25519_SUBJECT_PUBLIC_KEY: - { - /* encoded as an ASN1 BIT STRING */ - if (object.len != 1 + ED25519_KEY_LEN) - { - goto end; - } - this->pubkey = chunk_clone(chunk_skip(object, 1)); - break; - } - } + this->pubkey = chunk_clone(blob); } - success = parser->success(parser); - -end: - parser->destroy(parser); - if (!success) + else if (!asn1.len || !parse_public_key_info(this, asn1)) { destroy(this); return NULL; diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c index 45fba242b..6946e4576 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c @@ -43,10 +43,12 @@ struct private_gcrypt_plugin_t { gcrypt_plugin_t public; }; +#if GCRYPT_VERSION_NUMBER < 0x010600 /** * Define gcrypt multi-threading callbacks as gcry_threads_pthread */ GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif METHOD(plugin_t, get_name, char*, private_gcrypt_plugin_t *this) @@ -163,7 +165,9 @@ plugin_t *gcrypt_plugin_create() { private_gcrypt_plugin_t *this; +#if GCRYPT_VERSION_NUMBER < 0x010600 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); +#endif if (!gcry_check_version(GCRYPT_VERSION)) { diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c index c06f43348..394b87c27 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c @@ -187,11 +187,7 @@ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this, } else { - u_int slen = hasher_hash_size(hash_algorithm); - if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - slen = pss->salt_len; - } + u_int slen = pss->salt_len; err = gcry_sexp_build(&in, NULL, "(data(flags pss)(salt-length %u)(hash %s %b))", slen, hash_name, hash.len, hash.ptr); diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c index 9e2ac1287..bbfa5e298 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c @@ -139,11 +139,7 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, if (pss) { - u_int slen = hasher_hash_size(algorithm); - if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - slen = pss->salt_len; - } + u_int slen = pss->salt_len; err = gcry_sexp_build(&in, NULL, "(data(flags pss)(salt-length %u)(hash %s %b))", slen, hash_name, hash.len, hash.ptr); diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index a255a40ab..2d2d5c6fb 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -393,15 +393,11 @@ static bool build_emsa_pss_signature(private_gmp_rsa_private_key_t *this, goto error; } - salt.len = hash.len; + salt.len = params->salt_len; if (params->salt.len) { salt = params->salt; } - else if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - salt.len = params->salt_len; - } if (emlen < (hash.len + salt.len + 2)) { /* too long */ goto error; diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c index 9b5ee67fa..f9bd1d314 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c @@ -205,12 +205,7 @@ static bool verify_emsa_pss_signature(private_gmp_rsa_public_key_t *this, { goto error; } - /* determine salt length */ - salt.len = hash.len; - if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - salt.len = params->salt_len; - } + salt.len = params->salt_len; /* verify general structure of EM */ maskbits = (8 * em.len) - embits; if (em.len < (hash.len + salt.len + 2) || em.ptr[em.len-1] != 0xbc || diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c index d7e35d9fd..90f8185b0 100644 --- a/src/libstrongswan/plugins/mysql/mysql_database.c +++ b/src/libstrongswan/plugins/mysql/mysql_database.c @@ -131,9 +131,13 @@ typedef struct { */ static void conn_release(private_mysql_database_t *this, conn_t *conn) { - this->mutex->lock(this->mutex); - conn->in_use = FALSE; - this->mutex->unlock(this->mutex); + /* do not release the connection while transactions are using it */ + if (!this->transaction->get(this->transaction)) + { + this->mutex->lock(this->mutex); + conn->in_use = FALSE; + this->mutex->unlock(this->mutex); + } } /** diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index 9287f788a..d484092e7 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -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) diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index 79be2e670..da04d17cf 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -145,7 +145,8 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \ openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \ openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo \ openssl_pkcs7.lo openssl_pkcs12.lo openssl_rng.lo \ - openssl_hmac.lo openssl_gcm.lo + openssl_hmac.lo openssl_gcm.lo openssl_x_diffie_hellman.lo \ + openssl_ed_private_key.lo openssl_ed_public_key.lo libstrongswan_openssl_la_OBJECTS = \ $(am_libstrongswan_openssl_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -487,7 +488,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) @@ -586,6 +590,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_diffie_hellman.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_private_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_public_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ed_private_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ed_public_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_gcm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hasher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hmac.Plo@am__quote@ @@ -598,6 +604,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_x509.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_x_diffie_hellman.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index bb5f20dcf..3e7490dc6 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -57,6 +57,9 @@ static inline void X509_CRL_get0_signature(const X509_CRL *crl, ASN1_BIT_STRING #define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; }) #define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; }) #define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; }) +#define ASN1_STRING_get0_data(a) ASN1_STRING_data(a) +#define X509_CRL_get0_lastUpdate(c) X509_CRL_get_lastUpdate(c) +#define X509_CRL_get0_nextUpdate(c) X509_CRL_get_nextUpdate(c) #endif typedef struct private_openssl_crl_t private_openssl_crl_t; @@ -193,7 +196,7 @@ METHOD(enumerator_t, crl_enumerate, bool, if (ASN1_STRING_type(crlrsn) == V_ASN1_ENUMERATED && ASN1_STRING_length(crlrsn) == 1) { - *reason = *ASN1_STRING_data(crlrsn); + *reason = *ASN1_STRING_get0_data(crlrsn); } ASN1_STRING_free(crlrsn); } @@ -288,7 +291,11 @@ METHOD(certificate_t, issued_by, bool, chunk_t fingerprint, tbs; public_key_t *key; x509_t *x509; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const ASN1_BIT_STRING *sig; +#else ASN1_BIT_STRING *sig; +#endif bool valid; if (issuer->get_type(issuer) != CERT_X509) @@ -509,7 +516,7 @@ static bool parse_extensions(private_openssl_crl_t *this) bool ok; int i, num; X509_EXTENSION *ext; - STACK_OF(X509_EXTENSION) *extensions; + const STACK_OF(X509_EXTENSION) *extensions; extensions = X509_CRL_get0_extensions(this->crl); if (extensions) @@ -564,7 +571,11 @@ static bool parse_crl(private_openssl_crl_t *this) { const unsigned char *ptr = this->encoding.ptr; chunk_t sig_scheme; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const X509_ALGOR *alg; +#else X509_ALGOR *alg; +#endif this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len); if (!this->crl) @@ -573,7 +584,7 @@ static bool parse_crl(private_openssl_crl_t *this) } X509_CRL_get0_signature(this->crl, NULL, &alg); - sig_scheme = openssl_i2chunk(X509_ALGOR, alg); + sig_scheme = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg); INIT(this->scheme); if (!signature_params_parse(sig_scheme, 0, this->scheme)) { @@ -588,8 +599,8 @@ static bool parse_crl(private_openssl_crl_t *this) { return FALSE; } - this->thisUpdate = openssl_asn1_to_time(X509_CRL_get_lastUpdate(this->crl)); - this->nextUpdate = openssl_asn1_to_time(X509_CRL_get_nextUpdate(this->crl)); + this->thisUpdate = openssl_asn1_to_time(X509_CRL_get0_lastUpdate(this->crl)); + this->nextUpdate = openssl_asn1_to_time(X509_CRL_get0_nextUpdate(this->crl)); return parse_extensions(this); } 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 <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 */ 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 <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_ @}*/ 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 <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 */ 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 <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_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 8b0a7c5c7..cbeb6c3b7 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 * @@ -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; @@ -370,7 +378,7 @@ static private_key_t *openssl_private_key_connect(key_type_t type, #ifndef OPENSSL_NO_ENGINE char *engine_id = NULL; char keyname[BUF_LEN]; - chunk_t keyid = chunk_empty;; + chunk_t keyid = chunk_empty; EVP_PKEY *key; ENGINE *engine; int slot = -1; @@ -395,7 +403,7 @@ static private_key_t *openssl_private_key_connect(key_type_t type, } break; } - if (!keyid.len || keyid.len > 40) + if (!keyid.len) { return NULL; } @@ -405,7 +413,7 @@ static private_key_t *openssl_private_key_connect(key_type_t type, { snprintf(keyname, sizeof(keyname), "%d:", slot); } - if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) + if (sizeof(keyname) - strlen(keyname) <= keyid.len * 2 + 1) { return NULL; } @@ -428,21 +436,21 @@ static private_key_t *openssl_private_key_connect(key_type_t type, ENGINE_free(engine); return NULL; } + ENGINE_free(engine); if (!login(engine, keyid)) { DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); - ENGINE_free(engine); + ENGINE_finish(engine); return NULL; } key = ENGINE_load_private_key(engine, keyname, NULL, NULL); + ENGINE_finish(engine); if (!key) { DBG1(DBG_LIB, "failed to load private key with ID '%s' from " "engine '%s'", keyname, engine_id); - ENGINE_free(engine); return NULL; } - ENGINE_free(engine); switch (EVP_PKEY_base_id(key)) { @@ -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), diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c index a25b6b4b6..d3993749f 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 <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 want to keep private, compared + * to e.g. nonces */ + return RAND_priv_bytes((char*)buffer, bytes) == 1; + } +#endif return RAND_bytes((char*)buffer, bytes) == 1; } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 401a51a0b..8a9fdfe25 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -103,13 +103,8 @@ static bool build_signature(private_openssl_rsa_private_key_t *this, if (pss) { const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash); - int slen = EVP_MD_size(md); - if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - slen = pss->salt_len; - } if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 || - EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 || + EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss->salt_len) <= 0 || EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0) { goto error; diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 20bf30ae9..38b4eda35 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -95,13 +95,8 @@ static bool verify_signature(private_openssl_rsa_public_key_t *this, if (pss) { const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash); - int slen = EVP_MD_size(md); - if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) - { - slen = pss->salt_len; - } if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 || - EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 || + EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss->salt_len) <= 0 || EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0) { goto error; diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index b7f969f73..f99dcd6b1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -26,6 +26,7 @@ #if OPENSSL_VERSION_NUMBER < 0x10100000L #define OBJ_get0_data(o) ((o)->data) #define OBJ_length(o) ((o)->length) +#define ASN1_STRING_get0_data(a) ASN1_STRING_data((ASN1_STRING*)a) #endif /** @@ -164,11 +165,12 @@ chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1) /** * Described in header. */ -chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1) +chunk_t openssl_asn1_str2chunk(const ASN1_STRING *asn1) { if (asn1) { - return chunk_create(ASN1_STRING_data(asn1), ASN1_STRING_length(asn1)); + return chunk_create((u_char*)ASN1_STRING_get0_data(asn1), + ASN1_STRING_length(asn1)); } return chunk_empty; } @@ -212,7 +214,7 @@ int openssl_asn1_known_oid(ASN1_OBJECT *obj) /** * Described in header. */ -time_t openssl_asn1_to_time(ASN1_TIME *time) +time_t openssl_asn1_to_time(const ASN1_TIME *time) { chunk_t chunk; diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h index 80e557fa8..4afe76bf2 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.h +++ b/src/libstrongswan/plugins/openssl/openssl_util.h @@ -109,7 +109,7 @@ chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1); * @param asn1 asn1 string to convert * @return chunk, pointing into asn1 string */ -chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1); +chunk_t openssl_asn1_str2chunk(const ASN1_STRING *asn1); /** * Convert an openssl X509_NAME to a identification_t of type ID_DER_ASN1_DN. @@ -133,7 +133,7 @@ int openssl_asn1_known_oid(ASN1_OBJECT *obj); * @param time openssl ASN1_TIME * @returns time_t, 0 on error */ -time_t openssl_asn1_to_time(ASN1_TIME *time); +time_t openssl_asn1_to_time(const ASN1_TIME *time); /** * Compatibility macros diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index fae2d678f..fe21b0221 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -389,7 +389,11 @@ METHOD(certificate_t, issued_by, bool, public_key_t *key; bool valid; x509_t *x509 = (x509_t*)issuer; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const ASN1_BIT_STRING *sig; +#else ASN1_BIT_STRING *sig; +#endif chunk_t tbs; if (&this->public.x509.interface == issuer) @@ -993,7 +997,7 @@ static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this, */ static bool parse_extensions(private_openssl_x509_t *this) { - STACK_OF(X509_EXTENSION) *extensions; + const STACK_OF(X509_EXTENSION) *extensions; int i, num; /* unless we see a keyUsage extension we are compliant with RFC 4945 */ @@ -1077,7 +1081,11 @@ static bool parse_certificate(private_openssl_x509_t *this) hasher_t *hasher; chunk_t chunk, sig_scheme, sig_scheme_tbs; ASN1_OBJECT *oid; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const X509_ALGOR *alg; +#else X509_ALGOR *alg; +#endif this->x509 = d2i_X509(NULL, &ptr, this->encoding.len); if (!this->x509) @@ -1135,9 +1143,9 @@ static bool parse_certificate(private_openssl_x509_t *this) /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL * versions, at least on Ubuntu 14.04 it is not actually defined */ X509_get0_signature(NULL, &alg, this->x509); - sig_scheme = openssl_i2chunk(X509_ALGOR, alg); + sig_scheme = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg); alg = X509_get0_tbs_sigalg(this->x509); - sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, alg); + sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg); if (!chunk_equals(sig_scheme, sig_scheme_tbs)) { free(sig_scheme_tbs.ptr); 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 <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 */ 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 <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_ @}*/ + diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c index eab6559b3..934514249 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Tobias Brunner + * Copyright (C) 2013-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -89,6 +89,34 @@ static sshkey_public_key_t *parse_public_key(chunk_t blob) return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } + else if (chunk_equals(format, chunk_from_str("ssh-ed25519"))) + { + chunk_t blob; + + if (!reader->read_data32(reader, &blob)) + { + DBG1(DBG_LIB, "invalid Ed25519 key in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED25519, + BUILD_EDDSA_PUB, blob, BUILD_END); + } + else if (chunk_equals(format, chunk_from_str("ssh-ed448"))) + { + chunk_t blob; + + if (!reader->read_data32(reader, &blob)) + { + DBG1(DBG_LIB, "invalid Ed448 key in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_EDDSA_PUB, blob, BUILD_END); + } else if (format.len > strlen(ECDSA_PREFIX) && strpfx(format.ptr, ECDSA_PREFIX)) { @@ -140,8 +168,9 @@ static sshkey_public_key_t *load_from_stream(FILE *file) char line[1024], *token; while (!public && fgets(line, sizeof(line), file)) - { /* the format is: ssh-rsa|ecdsa-... <key(base64)> <identifier> */ - if (!strpfx(line, "ssh-rsa") && !strpfx(line, ECDSA_PREFIX)) + { /* the format is: ssh-<key-type> <key(base64)> <identifier> */ + if (!strpfx(line, "ssh-rsa") && !strpfx(line, ECDSA_PREFIX) && + !strpfx(line, "ssh-ed25519") && !strpfx(line, "ssh-ed448")) { continue; } diff --git a/src/libstrongswan/plugins/sshkey/sshkey_encoder.c b/src/libstrongswan/plugins/sshkey/sshkey_encoder.c index 9f5f8bd1f..ed35fc010 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_encoder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2013-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -72,6 +72,42 @@ static bool build_public_key(chunk_t *encoding, va_list args) writer->destroy(writer); return TRUE; } + else if (cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER, &n, + CRED_PART_END)) + { + chunk_t alg; + char *prefix; + int oid; + + /* parse subjectPublicKeyInfo */ + if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE) + { + return FALSE; + } + oid = asn1_parse_algorithmIdentifier(n, 1, NULL); + switch (oid) + { + case OID_ED25519: + prefix = "ssh-ed25519"; + break; + case OID_ED448: + prefix = "ssh-ed448"; + break; + default: + return FALSE; + } + if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE || + asn1_unwrap(&n, &n) != ASN1_BIT_STRING || !n.len) + { + return FALSE; + } + writer = bio_writer_create(0); + writer->write_data32(writer, chunk_from_str(prefix)); + writer->write_data32(writer, chunk_skip(n, 1)); + *encoding = chunk_to_base64(writer->get_buf(writer), NULL); + writer->destroy(writer); + return TRUE; + } else if (cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER, &n, CRED_PART_END)) { 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/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in index 7f6c319c6..ed3ae0f40 100644 --- a/src/libstrongswan/plugins/test_vectors/Makefile.in +++ b/src/libstrongswan/plugins/test_vectors/Makefile.in @@ -156,7 +156,8 @@ am_libstrongswan_test_vectors_la_OBJECTS = test_vectors_plugin.lo \ test_vectors/sha3_shake.lo test_vectors/fips_prf.lo \ test_vectors/modp.lo test_vectors/modpsub.lo \ test_vectors/ecp.lo test_vectors/ecpbp.lo \ - test_vectors/curve25519.lo test_vectors/rng.lo + test_vectors/curve25519.lo test_vectors/curve448.lo \ + test_vectors/rng.lo libstrongswan_test_vectors_la_OBJECTS = \ $(am_libstrongswan_test_vectors_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -518,6 +519,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 @@ -680,6 +682,8 @@ test_vectors/ecpbp.lo: test_vectors/$(am__dirstamp) \ test_vectors/$(DEPDIR)/$(am__dirstamp) test_vectors/curve25519.lo: test_vectors/$(am__dirstamp) \ test_vectors/$(DEPDIR)/$(am__dirstamp) +test_vectors/curve448.lo: test_vectors/$(am__dirstamp) \ + test_vectors/$(DEPDIR)/$(am__dirstamp) test_vectors/rng.lo: test_vectors/$(am__dirstamp) \ test_vectors/$(DEPDIR)/$(am__dirstamp) @@ -710,6 +714,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/chacha20_xof.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/chacha20poly1305.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/curve25519.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/curve448.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/des.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/ecp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/ecpbp.Plo@am__quote@ diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h index 7ab965a82..7c8ac0c6e 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors.h +++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h @@ -116,6 +116,7 @@ TEST_VECTOR_AEAD(aes_gcm23) TEST_VECTOR_AEAD(chacha20poly1305_1) TEST_VECTOR_AEAD(chacha20poly1305_2) TEST_VECTOR_AEAD(chacha20poly1305_3) +TEST_VECTOR_AEAD(chacha20poly1305_4) TEST_VECTOR_SIGNER(aes_xcbc_s1) TEST_VECTOR_SIGNER(aes_xcbc_s2) @@ -305,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/chacha20poly1305.c b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c index 21726cbbb..dcbfe5ca3 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c +++ b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c @@ -16,10 +16,40 @@ #include <crypto/crypto_tester.h> /** - * From draft-irtf-cfrg-chacha20-poly1305 + * From RFC 7539 */ aead_test_vector_t chacha20poly1305_1 = { .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4, + .len = 114, .alen = 12, + .key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\x07\x00\x00\x00", + .iv = "\x40\x41\x42\x43\x44\x45\x46\x47", + .adata = "\x50\x51\x52\x53\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", + .plain = "\x4c\x61\x64\x69\x65\x73\x20\x61\x6e\x64\x20\x47\x65\x6e\x74\x6c" + "\x65\x6d\x65\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x63\x6c\x61\x73" + "\x73\x20\x6f\x66\x20\x27\x39\x39\x3a\x20\x49\x66\x20\x49\x20\x63" + "\x6f\x75\x6c\x64\x20\x6f\x66\x66\x65\x72\x20\x79\x6f\x75\x20\x6f" + "\x6e\x6c\x79\x20\x6f\x6e\x65\x20\x74\x69\x70\x20\x66\x6f\x72\x20" + "\x74\x68\x65\x20\x66\x75\x74\x75\x72\x65\x2c\x20\x73\x75\x6e\x73" + "\x63\x72\x65\x65\x6e\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x20\x69" + "\x74\x2e", + .cipher = "\xd3\x1a\x8d\x34\x64\x8e\x60\xdb\x7b\x86\xaf\xbc\x53\xef\x7e\xc2" + "\xa4\xad\xed\x51\x29\x6e\x08\xfe\xa9\xe2\xb5\xa7\x36\xee\x62\xd6" + "\x3d\xbe\xa4\x5e\x8c\xa9\x67\x12\x82\xfa\xfb\x69\xda\x92\x72\x8b" + "\x1a\x71\xde\x0a\x9e\x06\x0b\x29\x05\xd6\xa5\xb6\x7e\xcd\x3b\x36" + "\x92\xdd\xbd\x7f\x2d\x77\x8b\x8c\x98\x03\xae\xe3\x28\x09\x1b\x58" + "\xfa\xb3\x24\xe4\xfa\xd6\x75\x94\x55\x85\x80\x8b\x48\x31\xd7\xbc" + "\x3f\xf4\xde\xf0\x8e\x4b\x7a\x9d\xe5\x76\xd2\x65\x86\xce\xc6\x4b" + "\x61\x16\x1a\xe1\x0b\x59\x4f\x09\xe2\x6a\x7e\x90\x2e\xcb\xd0\x60" + "\x06\x91", +}; + +/** + * Additional test vector from RFC 7539 + */ +aead_test_vector_t chacha20poly1305_2 = { + .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4, .len = 265, .alen = 12, .key = "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0" "\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0" @@ -64,9 +94,9 @@ aead_test_vector_t chacha20poly1305_1 = { }; /** - * ESP example from draft-ietf-ipsecme-chacha20-poly1305-06 + * ESP example from RFC 7634 */ -aead_test_vector_t chacha20poly1305_2 = { +aead_test_vector_t chacha20poly1305_3 = { .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4, .len = 88, .alen = 8, .key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" @@ -90,9 +120,9 @@ aead_test_vector_t chacha20poly1305_2 = { }; /** - * IKEv2 example from draft-ietf-ipsecme-chacha20-poly1305-06 + * IKEv2 example from RFC 7634 */ -aead_test_vector_t chacha20poly1305_3 = { +aead_test_vector_t chacha20poly1305_4 = { .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4, .len = 13, .alen = 32, .key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" 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 <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, 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 <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", +}; diff --git a/src/libstrongswan/settings/settings_lexer.c b/src/libstrongswan/settings/settings_lexer.c index c29dfa57b..a88a58f0e 100644 --- a/src/libstrongswan/settings/settings_lexer.c +++ b/src/libstrongswan/settings/settings_lexer.c @@ -7,7 +7,6 @@ /* A lexical scanner generated by flex */ /* %not-for-header */ - /* %if-c-only */ /* %if-not-reentrant */ /* %endif */ @@ -17,7 +16,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 0 +#define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -26,9 +25,230 @@ /* %endif */ /* %if-c-only */ - +#ifdef yy_create_buffer +#define settings_parser__create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer settings_parser__create_buffer +#endif + +#ifdef yy_delete_buffer +#define settings_parser__delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer settings_parser__delete_buffer +#endif + +#ifdef yy_scan_buffer +#define settings_parser__scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer settings_parser__scan_buffer +#endif + +#ifdef yy_scan_string +#define settings_parser__scan_string_ALREADY_DEFINED +#else +#define yy_scan_string settings_parser__scan_string +#endif + +#ifdef yy_scan_bytes +#define settings_parser__scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes settings_parser__scan_bytes +#endif + +#ifdef yy_init_buffer +#define settings_parser__init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer settings_parser__init_buffer +#endif + +#ifdef yy_flush_buffer +#define settings_parser__flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer settings_parser__flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define settings_parser__load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state settings_parser__load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define settings_parser__switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer settings_parser__switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define settings_parser_push_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state settings_parser_push_buffer_state +#endif + +#ifdef yypop_buffer_state +#define settings_parser_pop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state settings_parser_pop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define settings_parser_ensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack settings_parser_ensure_buffer_stack +#endif + +#ifdef yylex +#define settings_parser_lex_ALREADY_DEFINED +#else +#define yylex settings_parser_lex +#endif + +#ifdef yyrestart +#define settings_parser_restart_ALREADY_DEFINED +#else +#define yyrestart settings_parser_restart +#endif + +#ifdef yylex_init +#define settings_parser_lex_init_ALREADY_DEFINED +#else +#define yylex_init settings_parser_lex_init +#endif + +#ifdef yylex_init_extra +#define settings_parser_lex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra settings_parser_lex_init_extra +#endif + +#ifdef yylex_destroy +#define settings_parser_lex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy settings_parser_lex_destroy +#endif + +#ifdef yyget_debug +#define settings_parser_get_debug_ALREADY_DEFINED +#else +#define yyget_debug settings_parser_get_debug +#endif + +#ifdef yyset_debug +#define settings_parser_set_debug_ALREADY_DEFINED +#else +#define yyset_debug settings_parser_set_debug +#endif + +#ifdef yyget_extra +#define settings_parser_get_extra_ALREADY_DEFINED +#else +#define yyget_extra settings_parser_get_extra +#endif + +#ifdef yyset_extra +#define settings_parser_set_extra_ALREADY_DEFINED +#else +#define yyset_extra settings_parser_set_extra +#endif + +#ifdef yyget_in +#define settings_parser_get_in_ALREADY_DEFINED +#else +#define yyget_in settings_parser_get_in +#endif + +#ifdef yyset_in +#define settings_parser_set_in_ALREADY_DEFINED +#else +#define yyset_in settings_parser_set_in +#endif + +#ifdef yyget_out +#define settings_parser_get_out_ALREADY_DEFINED +#else +#define yyget_out settings_parser_get_out +#endif + +#ifdef yyset_out +#define settings_parser_set_out_ALREADY_DEFINED +#else +#define yyset_out settings_parser_set_out +#endif + +#ifdef yyget_leng +#define settings_parser_get_leng_ALREADY_DEFINED +#else +#define yyget_leng settings_parser_get_leng +#endif + +#ifdef yyget_text +#define settings_parser_get_text_ALREADY_DEFINED +#else +#define yyget_text settings_parser_get_text +#endif + +#ifdef yyget_lineno +#define settings_parser_get_lineno_ALREADY_DEFINED +#else +#define yyget_lineno settings_parser_get_lineno +#endif + +#ifdef yyset_lineno +#define settings_parser_set_lineno_ALREADY_DEFINED +#else +#define yyset_lineno settings_parser_set_lineno +#endif + +#ifdef yyget_column +#define settings_parser_get_column_ALREADY_DEFINED +#else +#define yyget_column settings_parser_get_column +#endif + +#ifdef yyset_column +#define settings_parser_set_column_ALREADY_DEFINED +#else +#define yyset_column settings_parser_set_column +#endif + +#ifdef yywrap +#define settings_parser_wrap_ALREADY_DEFINED +#else +#define yywrap settings_parser_wrap +#endif + /* %endif */ +#ifdef yyget_lval +#define settings_parser_get_lval_ALREADY_DEFINED +#else +#define yyget_lval settings_parser_get_lval +#endif + +#ifdef yyset_lval +#define settings_parser_set_lval_ALREADY_DEFINED +#else +#define yyset_lval settings_parser_set_lval +#endif + +#ifdef yyalloc +#define settings_parser_alloc_ALREADY_DEFINED +#else +#define yyalloc settings_parser_alloc +#endif + +#ifdef yyrealloc +#define settings_parser_realloc_ALREADY_DEFINED +#else +#define yyrealloc settings_parser_realloc +#endif + +#ifdef yyfree +#define settings_parser_free_ALREADY_DEFINED +#else +#define yyfree settings_parser_free +#endif + /* %if-c-only */ /* %endif */ @@ -108,50 +328,39 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + #endif /* ! C99 */ #endif /* ! FLEXINT_H */ /* %endif */ +/* begin standard C++ headers. */ /* %if-c++-only */ /* %endif */ -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST +/* TODO: this is always defined, so inline it */ #define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) #else -#define yyconst +#define yynoreturn #endif /* %not-for-header */ - /* Returned upon end-of-file. */ #define YY_NULL 0 /* %ok-for-header */ /* %not-for-header */ - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* %ok-for-header */ /* %if-reentrant */ @@ -183,20 +392,16 @@ typedef void* yyscan_t; * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * - /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START - /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE settings_parser_restart(yyin ,yyscanner ) - +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ @@ -237,10 +442,10 @@ typedef size_t yy_size_t; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE settings_parser_lex. + * existing scanners that call yyless() from OUTSIDE yylex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. @@ -273,7 +478,6 @@ typedef size_t yy_size_t; YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) - #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_STRUCT_YY_BUFFER_STATE @@ -293,7 +497,7 @@ struct yy_buffer_state /* Size of input buffer in bytes, not including room for EOB * characters. */ - yy_size_t yy_buf_size; + int yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. @@ -321,7 +525,7 @@ struct yy_buffer_state int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ - + /* Whether to try to fill the input buffer when we reach the * end of it. */ @@ -338,7 +542,7 @@ struct yy_buffer_state * possible backing-up. * * When we actually see the EOF, we change the status to "new" - * (via settings_parser_restart()), so that the user can continue scanning by + * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 @@ -348,7 +552,6 @@ struct yy_buffer_state /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ - /* %if-not-reentrant */ /* %endif */ /* %ok-for-header */ @@ -364,7 +567,6 @@ struct yy_buffer_state #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) - /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ @@ -374,57 +576,52 @@ struct yy_buffer_state /* %if-not-reentrant */ /* %not-for-header */ - /* %ok-for-header */ /* %endif */ -void settings_parser_restart (FILE *input_file ,yyscan_t yyscanner ); -void settings_parser__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE settings_parser__create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void settings_parser__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void settings_parser__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void settings_parser_pop_buffer_state (yyscan_t yyscanner ); - -static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner ); -static void settings_parser__load_buffer_state (yyscan_t yyscanner ); -static void settings_parser__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); -#define YY_FLUSH_BUFFER settings_parser__flush_buffer(YY_CURRENT_BUFFER ,yyscanner) +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) -YY_BUFFER_STATE settings_parser__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE settings_parser__scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE settings_parser__scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); /* %endif */ -void *settings_parser_alloc (yy_size_t ,yyscan_t yyscanner ); -void *settings_parser_realloc (void *,yy_size_t ,yyscan_t yyscanner ); -void settings_parser_free (void * ,yyscan_t yyscanner ); - -#define yy_new_buffer settings_parser__create_buffer +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); +#define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ - settings_parser_ensure_buffer_stack (yyscanner); \ + yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } - #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ - settings_parser_ensure_buffer_stack (yyscanner); \ + yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } - #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ @@ -434,8 +631,7 @@ void settings_parser_free (void * ,yyscan_t yyscanner ); #define YY_SKIP_YYWRAP #define FLEX_DEBUG - -typedef unsigned char YY_CHAR; +typedef flex_uint8_t YY_CHAR; typedef int yy_state_type; @@ -445,13 +641,10 @@ typedef int yy_state_type; /* %if-c-only Standard (non-C++) definition */ -static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); -static int yy_get_next_buffer (yyscan_t yyscanner ); -#if defined(__GNUC__) && __GNUC__ >= 3 -__attribute__((__noreturn__)) -#endif -static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); /* %endif */ @@ -461,12 +654,11 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ - yyleng = (size_t) (yy_cp - yy_bp); \ + yyleng = (int) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ yyg->yy_c_buf_p = yy_cp; - /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ #define YY_NUM_RULES 39 #define YY_END_OF_BUFFER 40 @@ -477,7 +669,7 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[85] = +static const flex_int16_t yy_accept[85] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 12, 2, 3, 2, 11, 1, 7, 6, 8, @@ -490,7 +682,7 @@ static yyconst flex_int16_t yy_accept[85] = 0, 10, 10, 0 } ; -static yyconst YY_CHAR yy_ec[256] = +static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, @@ -522,14 +714,14 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst YY_CHAR yy_meta[24] = +static const YY_CHAR yy_meta[24] = { 0, 1, 2, 3, 4, 5, 6, 5, 7, 8, 7, 9, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 5 } ; -static yyconst flex_uint16_t yy_base[103] = +static const flex_int16_t yy_base[103] = { 0, 0, 0, 23, 0, 45, 67, 89, 111, 49, 50, 124, 0, 133, 335, 55, 335, 60, 335, 335, 335, @@ -545,7 +737,7 @@ static yyconst flex_uint16_t yy_base[103] = 314, 324 } ; -static yyconst flex_int16_t yy_def[103] = +static const flex_int16_t yy_def[103] = { 0, 84, 1, 84, 3, 85, 85, 86, 86, 87, 87, 84, 88, 84, 84, 84, 84, 89, 84, 84, 84, @@ -561,7 +753,7 @@ static yyconst flex_int16_t yy_def[103] = 84, 84 } ; -static yyconst flex_uint16_t yy_nxt[359] = +static const flex_int16_t yy_nxt[359] = { 0, 12, 13, 14, 15, 13, 16, 17, 18, 19, 20, 21, 12, 12, 12, 12, 22, 12, 12, 12, 12, @@ -604,7 +796,7 @@ static yyconst flex_uint16_t yy_nxt[359] = 84, 84, 84, 84, 84, 84, 84, 84 } ; -static yyconst flex_int16_t yy_chk[359] = +static const flex_int16_t yy_chk[359] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -648,18 +840,18 @@ static yyconst flex_int16_t yy_chk[359] = } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[40] = +static const flex_int32_t yy_rule_can_match_eol[40] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, }; -static yyconst flex_int16_t yy_rule_linenum[39] = +static const flex_int16_t yy_rule_linenum[39] = { 0, - 66, 67, 68, 70, 71, 73, 74, 76, 81, 86, - 91, 96, 102, 103, 104, 106, 108, 113, 120, 121, - 123, 144, 150, 157, 160, 180, 183, 186, 189, 195, - 196, 198, 218, 219, 220, 221, 222, 223 + 71, 72, 73, 75, 76, 78, 79, 81, 86, 91, + 96, 101, 107, 108, 109, 111, 113, 118, 125, 126, + 128, 149, 155, 162, 165, 185, 188, 191, 194, 200, + 201, 203, 223, 224, 225, 226, 227, 228 } ; /* The intent behind this definition is that it'll catch @@ -694,9 +886,13 @@ bool settings_parser_open_next_file(parser_helper_t *ctx); static void include_files(parser_helper_t *ctx); +#line 890 "settings/settings_lexer.c" /* use start conditions stack */ /* do not declare unneeded functions */ #define YY_NO_INPUT 1 +/* do not include unistd.h as it might conflict with our scanner states */ +#define YY_NO_UNISTD_H 1 +/* due to that disable interactive mode, which requires isatty() */ /* don't use global variables, and interact properly with bison */ /* maintain the line number */ /* don't generate a default rule */ @@ -712,7 +908,7 @@ static void include_files(parser_helper_t *ctx); /* state used to scan quoted strings */ /* pattern for section/key names */ -#line 716 "settings/settings_lexer.c" +#line 912 "settings/settings_lexer.c" #define INITIAL 0 #define ref 1 @@ -751,7 +947,7 @@ struct yyguts_t YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; - yy_size_t yyleng_r; + int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; @@ -775,7 +971,7 @@ struct yyguts_t /* %if-c-only */ -static int yy_init_globals (yyscan_t yyscanner ); +static int yy_init_globals ( yyscan_t yyscanner ); /* %endif */ @@ -785,9 +981,9 @@ static int yy_init_globals (yyscan_t yyscanner ); * from bison output in section 1.*/ # define yylval yyg->yylval_r -int settings_parser_lex_init (yyscan_t* scanner); +int yylex_init (yyscan_t* scanner); -int settings_parser_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); /* %endif */ @@ -796,41 +992,41 @@ int settings_parser_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int settings_parser_lex_destroy (yyscan_t yyscanner ); +int yylex_destroy ( yyscan_t yyscanner ); -int settings_parser_get_debug (yyscan_t yyscanner ); +int yyget_debug ( yyscan_t yyscanner ); -void settings_parser_set_debug (int debug_flag ,yyscan_t yyscanner ); +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); -YY_EXTRA_TYPE settings_parser_get_extra (yyscan_t yyscanner ); +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); -void settings_parser_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); -FILE *settings_parser_get_in (yyscan_t yyscanner ); +FILE *yyget_in ( yyscan_t yyscanner ); -void settings_parser_set_in (FILE * _in_str ,yyscan_t yyscanner ); +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); -FILE *settings_parser_get_out (yyscan_t yyscanner ); +FILE *yyget_out ( yyscan_t yyscanner ); -void settings_parser_set_out (FILE * _out_str ,yyscan_t yyscanner ); +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); -yy_size_t settings_parser_get_leng (yyscan_t yyscanner ); + int yyget_leng ( yyscan_t yyscanner ); -char *settings_parser_get_text (yyscan_t yyscanner ); +char *yyget_text ( yyscan_t yyscanner ); -int settings_parser_get_lineno (yyscan_t yyscanner ); +int yyget_lineno ( yyscan_t yyscanner ); -void settings_parser_set_lineno (int _line_number ,yyscan_t yyscanner ); +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); -int settings_parser_get_column (yyscan_t yyscanner ); +int yyget_column ( yyscan_t yyscanner ); -void settings_parser_set_column (int _column_no ,yyscan_t yyscanner ); +void yyset_column ( int _column_no , yyscan_t yyscanner ); /* %if-bison-bridge */ -YYSTYPE * settings_parser_get_lval (yyscan_t yyscanner ); +YYSTYPE * yyget_lval ( yyscan_t yyscanner ); -void settings_parser_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); +void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); /* %endif */ @@ -840,17 +1036,16 @@ void settings_parser_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int settings_parser_wrap (yyscan_t yyscanner ); +extern "C" int yywrap ( yyscan_t yyscanner ); #else -extern int settings_parser_wrap (yyscan_t yyscanner ); +extern int yywrap ( yyscan_t yyscanner ); #endif #endif /* %not-for-header */ - #ifndef YY_NO_UNPUT - static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); + static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner); #endif /* %ok-for-header */ @@ -858,21 +1053,20 @@ extern int settings_parser_wrap (yyscan_t yyscanner ); /* %endif */ #ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT /* %if-c-only Standard (non-C++) definition */ /* %not-for-header */ - #ifdef __cplusplus -static int yyinput (yyscan_t yyscanner ); +static int yyinput ( yyscan_t yyscanner ); #else -static int input (yyscan_t yyscanner ); +static int input ( yyscan_t yyscanner ); #endif /* %ok-for-header */ @@ -881,11 +1075,11 @@ static int input (yyscan_t yyscanner ); /* %if-c-only */ - static void yy_push_state (int _new_state ,yyscan_t yyscanner); + static void yy_push_state ( int _new_state , yyscan_t yyscanner); - static void yy_pop_state (yyscan_t yyscanner ); + static void yy_pop_state ( yyscan_t yyscanner ); - static int yy_top_state (yyscan_t yyscanner ); + static int yy_top_state ( yyscan_t yyscanner ); /* %endif */ @@ -905,7 +1099,7 @@ static int input (yyscan_t yyscanner ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) /* %endif */ /* %if-c++-only C++ definition */ /* %endif */ @@ -920,7 +1114,7 @@ static int input (yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -933,7 +1127,7 @@ static int input (yyscan_t yyscanner ); else \ { \ errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ @@ -974,11 +1168,9 @@ static int input (yyscan_t yyscanner ); /* %if-tables-serialization structures and prototypes */ /* %not-for-header */ - /* %ok-for-header */ /* %not-for-header */ - /* %tables-yydmap generated elements */ /* %endif */ /* end tables serialization structures and prototypes */ @@ -992,10 +1184,10 @@ static int input (yyscan_t yyscanner ); #define YY_DECL_IS_OURS 1 /* %if-c-only Standard (non-C++) definition */ -extern int settings_parser_lex \ - (YYSTYPE * yylval_param ,yyscan_t yyscanner); +extern int yylex \ + (YYSTYPE * yylval_param , yyscan_t yyscanner); -#define YY_DECL int settings_parser_lex \ +#define YY_DECL int yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) /* %endif */ /* %if-c++-only C++ definition */ @@ -1019,7 +1211,6 @@ extern int settings_parser_lex \ YY_USER_ACTION /* %not-for-header */ - /** The main scanner function which does all the work. */ YY_DECL @@ -1057,20 +1248,20 @@ YY_DECL /* %endif */ if ( ! YY_CURRENT_BUFFER ) { - settings_parser_ensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } - settings_parser__load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); } { /* %% [7.0] user's declarations go here */ -#line 64 "settings/settings_lexer.l" +#line 69 "settings/settings_lexer.l" -#line 1074 "settings/settings_lexer.c" +#line 1265 "settings/settings_lexer.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1100,22 +1291,18 @@ yy_match: { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 85 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 335 ); + while ( yy_current_state != 84 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; yy_find_action: /* %% [10.0] code to find the action number goes here */ yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } YY_DO_BEFORE_ACTION; @@ -1123,10 +1310,10 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { - yy_size_t yyl; + int yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) - + do{ yylineno++; yycolumn=0; }while(0) @@ -1164,40 +1351,40 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 66 "settings/settings_lexer.l" +#line 71 "settings/settings_lexer.l" /* eat comments */ YY_BREAK case 2: YY_RULE_SETUP -#line 67 "settings/settings_lexer.l" +#line 72 "settings/settings_lexer.l" /* eat whitespace */ YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 68 "settings/settings_lexer.l" +#line 73 "settings/settings_lexer.l" /* eat newlines and comments at the end of a line */ YY_BREAK case 4: -#line 71 "settings/settings_lexer.l" +#line 76 "settings/settings_lexer.l" case 5: YY_RULE_SETUP -#line 71 "settings/settings_lexer.l" +#line 76 "settings/settings_lexer.l" return yytext[0]; YY_BREAK case 6: YY_RULE_SETUP -#line 73 "settings/settings_lexer.l" +#line 78 "settings/settings_lexer.l" return DOT; YY_BREAK case 7: YY_RULE_SETUP -#line 74 "settings/settings_lexer.l" +#line 79 "settings/settings_lexer.l" return COMMA; YY_BREAK case 8: YY_RULE_SETUP -#line 76 "settings/settings_lexer.l" +#line 81 "settings/settings_lexer.l" { yy_push_state(ref, yyscanner); return COLON; @@ -1205,7 +1392,7 @@ YY_RULE_SETUP YY_BREAK case 9: YY_RULE_SETUP -#line 81 "settings/settings_lexer.l" +#line 86 "settings/settings_lexer.l" { yy_push_state(val, yyscanner); return yytext[0]; @@ -1218,7 +1405,7 @@ YY_LINENO_REWIND_TO(yy_cp - 1); yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP -#line 86 "settings/settings_lexer.l" +#line 91 "settings/settings_lexer.l" { yyextra->string_init(yyextra); yy_push_state(inc, yyscanner); @@ -1226,7 +1413,7 @@ YY_RULE_SETUP YY_BREAK case 11: YY_RULE_SETUP -#line 91 "settings/settings_lexer.l" +#line 96 "settings/settings_lexer.l" { PARSER_DBG1(yyextra, "unexpected string detected"); return STRING_ERROR; @@ -1234,7 +1421,7 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 96 "settings/settings_lexer.l" +#line 101 "settings/settings_lexer.l" { yylval->s = strdup(yytext); return NAME; @@ -1243,28 +1430,28 @@ YY_RULE_SETUP case 13: YY_RULE_SETUP -#line 102 "settings/settings_lexer.l" +#line 107 "settings/settings_lexer.l" /* eat comments */ YY_BREAK case 14: YY_RULE_SETUP -#line 103 "settings/settings_lexer.l" +#line 108 "settings/settings_lexer.l" /* eat whitespace */ YY_BREAK case 15: /* rule 15 can match eol */ YY_RULE_SETUP -#line 104 "settings/settings_lexer.l" +#line 109 "settings/settings_lexer.l" /* eat newlines and comments at the end of a line */ YY_BREAK case 16: YY_RULE_SETUP -#line 106 "settings/settings_lexer.l" +#line 111 "settings/settings_lexer.l" return COMMA; YY_BREAK case 17: YY_RULE_SETUP -#line 108 "settings/settings_lexer.l" +#line 113 "settings/settings_lexer.l" { yylval->s = strdup(yytext); return NAME; @@ -1272,7 +1459,7 @@ YY_RULE_SETUP YY_BREAK case 18: YY_RULE_SETUP -#line 113 "settings/settings_lexer.l" +#line 118 "settings/settings_lexer.l" { unput(yytext[0]); yy_pop_state(yyscanner); @@ -1282,20 +1469,20 @@ YY_RULE_SETUP case 19: YY_RULE_SETUP -#line 120 "settings/settings_lexer.l" +#line 125 "settings/settings_lexer.l" /* just ignore these */ YY_BREAK case 20: YY_RULE_SETUP -#line 121 "settings/settings_lexer.l" +#line 126 "settings/settings_lexer.l" YY_BREAK case YY_STATE_EOF(val): -#line 122 "settings/settings_lexer.l" +#line 127 "settings/settings_lexer.l" case 21: /* rule 21 can match eol */ YY_RULE_SETUP -#line 123 "settings/settings_lexer.l" +#line 128 "settings/settings_lexer.l" { if (*yytext) { @@ -1319,7 +1506,7 @@ YY_RULE_SETUP YY_BREAK case 22: YY_RULE_SETUP -#line 144 "settings/settings_lexer.l" +#line 149 "settings/settings_lexer.l" { yyextra->string_init(yyextra); yy_push_state(str, yyscanner); @@ -1328,7 +1515,7 @@ YY_RULE_SETUP /* same as above, but allow more characters */ case 23: YY_RULE_SETUP -#line 150 "settings/settings_lexer.l" +#line 155 "settings/settings_lexer.l" { yylval->s = strdup(yytext); return NAME; @@ -1338,16 +1525,16 @@ YY_RULE_SETUP case 24: YY_RULE_SETUP -#line 157 "settings/settings_lexer.l" +#line 162 "settings/settings_lexer.l" /* just ignore these */ YY_BREAK /* we allow all characters except #, } and spaces, they can be escaped */ case YY_STATE_EOF(inc): -#line 159 "settings/settings_lexer.l" +#line 164 "settings/settings_lexer.l" case 25: /* rule 25 can match eol */ YY_RULE_SETUP -#line 160 "settings/settings_lexer.l" +#line 165 "settings/settings_lexer.l" { if (*yytext) { @@ -1371,28 +1558,28 @@ YY_RULE_SETUP YY_BREAK case 26: YY_RULE_SETUP -#line 180 "settings/settings_lexer.l" +#line 185 "settings/settings_lexer.l" { /* string include */ yy_push_state(str, yyscanner); } YY_BREAK case 27: YY_RULE_SETUP -#line 183 "settings/settings_lexer.l" +#line 188 "settings/settings_lexer.l" { yyextra->string_add(yyextra, yytext); } YY_BREAK case 28: YY_RULE_SETUP -#line 186 "settings/settings_lexer.l" +#line 191 "settings/settings_lexer.l" { yyextra->string_add(yyextra, yytext+1); } YY_BREAK case 29: YY_RULE_SETUP -#line 189 "settings/settings_lexer.l" +#line 194 "settings/settings_lexer.l" { yyextra->string_add(yyextra, yytext); } @@ -1401,17 +1588,17 @@ YY_RULE_SETUP case 30: YY_RULE_SETUP -#line 195 "settings/settings_lexer.l" +#line 200 "settings/settings_lexer.l" /* just ignore these */ YY_BREAK case 31: -#line 197 "settings/settings_lexer.l" +#line 202 "settings/settings_lexer.l" YY_RULE_SETUP case YY_STATE_EOF(str): -#line 197 "settings/settings_lexer.l" +#line 202 "settings/settings_lexer.l" case 32: YY_RULE_SETUP -#line 198 "settings/settings_lexer.l" +#line 203 "settings/settings_lexer.l" { if (!streq(yytext, "\"")) { @@ -1434,34 +1621,34 @@ YY_RULE_SETUP YY_BREAK case 33: YY_RULE_SETUP -#line 218 "settings/settings_lexer.l" +#line 223 "settings/settings_lexer.l" yyextra->string_add(yyextra, "\n"); YY_BREAK case 34: YY_RULE_SETUP -#line 219 "settings/settings_lexer.l" +#line 224 "settings/settings_lexer.l" yyextra->string_add(yyextra, "\r"); YY_BREAK case 35: YY_RULE_SETUP -#line 220 "settings/settings_lexer.l" +#line 225 "settings/settings_lexer.l" yyextra->string_add(yyextra, "\t"); YY_BREAK case 36: /* rule 36 can match eol */ YY_RULE_SETUP -#line 221 "settings/settings_lexer.l" +#line 226 "settings/settings_lexer.l" /* merge lines that end with escaped EOL characters */ YY_BREAK case 37: YY_RULE_SETUP -#line 222 "settings/settings_lexer.l" +#line 227 "settings/settings_lexer.l" yyextra->string_add(yyextra, yytext+1); YY_BREAK case 38: /* rule 38 can match eol */ YY_RULE_SETUP -#line 223 "settings/settings_lexer.l" +#line 228 "settings/settings_lexer.l" { yyextra->string_add(yyextra, yytext); } @@ -1469,7 +1656,7 @@ YY_RULE_SETUP case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(ref): -#line 228 "settings/settings_lexer.l" +#line 233 "settings/settings_lexer.l" { settings_parser_pop_buffer_state(yyscanner); if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER) @@ -1480,10 +1667,10 @@ case YY_STATE_EOF(ref): YY_BREAK case 39: YY_RULE_SETUP -#line 236 "settings/settings_lexer.l" +#line 241 "settings/settings_lexer.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1487 "settings/settings_lexer.c" +#line 1674 "settings/settings_lexer.c" case YY_END_OF_BUFFER: { @@ -1499,7 +1686,7 @@ YY_FATAL_ERROR( "flex scanner jammed" ); /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called - * settings_parser_lex(). If so, then we have to assure + * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a @@ -1553,7 +1740,8 @@ YY_FATAL_ERROR( "flex scanner jammed" ); else { /* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ - yy_cp = yyg->yy_c_buf_p; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; } } @@ -1564,7 +1752,7 @@ YY_FATAL_ERROR( "flex scanner jammed" ); { yyg->yy_did_buffer_switch_on_eof = 0; - if ( settings_parser_wrap(yyscanner ) ) + if ( yywrap( yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -1618,12 +1806,11 @@ YY_FATAL_ERROR( "flex scanner jammed" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ -} /* end of settings_parser_lex */ +} /* end of yylex */ /* %ok-for-header */ /* %if-c++-only */ /* %not-for-header */ - /* %ok-for-header */ /* %endif */ @@ -1644,7 +1831,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = yyg->yytext_ptr; - yy_size_t number_to_move, i; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1673,7 +1860,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -1686,7 +1873,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { - yy_size_t num_to_read = + int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -1700,7 +1887,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( b->yy_is_our_buffer ) { - yy_size_t new_size = b->yy_buf_size * 2; + int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; @@ -1709,11 +1896,12 @@ static int yy_get_next_buffer (yyscan_t yyscanner) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - settings_parser_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); } else /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; + b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( @@ -1741,7 +1929,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - settings_parser_restart(yyin ,yyscanner); + yyrestart( yyin , yyscanner); } else @@ -1755,12 +1943,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else ret_val = EOB_ACT_CONTINUE_SCAN; - if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) settings_parser_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } yyg->yy_n_chars += number_to_move; @@ -1776,7 +1967,6 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* %if-c-only */ /* %not-for-header */ - static yy_state_type yy_get_previous_state (yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ @@ -1802,9 +1992,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 85 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; @@ -1836,9 +2026,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 85 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 84); (void)yyg; @@ -1864,7 +2054,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - yy_size_t number_to_move = yyg->yy_n_chars + 2; + int number_to_move = yyg->yy_n_chars + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = @@ -1876,7 +2066,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); @@ -1928,7 +2118,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { /* need more input */ - yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) @@ -1945,14 +2135,14 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ /* Reset buffer status. */ - settings_parser_restart(yyin ,yyscanner); + yyrestart( yyin , yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( settings_parser_wrap(yyscanner ) ) - return EOF; + if ( yywrap( yyscanner ) ) + return 0; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; @@ -1976,7 +2166,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* %% [19.0] update BOL and yylineno */ if ( c == '\n' ) - + do{ yylineno++; yycolumn=0; }while(0) @@ -1994,7 +2184,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) * @note This function does not reset the start condition to @c INITIAL . */ /* %if-c-only */ - void settings_parser_restart (FILE * input_file , yyscan_t yyscanner) + void yyrestart (FILE * input_file , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2002,13 +2192,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ - settings_parser_ensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } - settings_parser__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - settings_parser__load_buffer_state(yyscanner ); + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); } /* %if-c++-only */ @@ -2019,7 +2209,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) * @param yyscanner The scanner object. */ /* %if-c-only */ - void settings_parser__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2028,10 +2218,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* TODO. We should be able to replace this entire function body * with - * settings_parser_pop_buffer_state(); - * settings_parser_push_buffer_state(new_buffer); + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); */ - settings_parser_ensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; @@ -2044,18 +2234,18 @@ static int yy_get_next_buffer (yyscan_t yyscanner) } YY_CURRENT_BUFFER_LVALUE = new_buffer; - settings_parser__load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); /* We don't actually know whether we did this switch during - * EOF (settings_parser_wrap()) processing, but the only time this flag - * is looked at is after settings_parser_wrap() is called, so it's safe + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } /* %if-c-only */ -static void settings_parser__load_buffer_state (yyscan_t yyscanner) +static void yy_load_buffer_state (yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2078,29 +2268,29 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) * @return the allocated buffer state. */ /* %if-c-only */ - YY_BUFFER_STATE settings_parser__create_buffer (FILE * file, int size , yyscan_t yyscanner) + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ { YY_BUFFER_STATE b; - b = (YY_BUFFER_STATE) settings_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser__create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - b->yy_buf_size = (yy_size_t)size; + b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) settings_parser_alloc(b->yy_buf_size + 2 ,yyscanner ); + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser__create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - settings_parser__init_buffer(b,file ,yyscanner); + yy_init_buffer( b, file , yyscanner); return b; } @@ -2109,11 +2299,11 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) /* %endif */ /** Destroy the buffer. - * @param b a buffer created with settings_parser__create_buffer() + * @param b a buffer created with yy_create_buffer() * @param yyscanner The scanner object. */ /* %if-c-only */ - void settings_parser__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2127,17 +2317,17 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - settings_parser_free((void *) b->yy_ch_buf ,yyscanner ); + yyfree( (void *) b->yy_ch_buf , yyscanner ); - settings_parser_free((void *) b ,yyscanner ); + yyfree( (void *) b , yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, - * such as during a settings_parser_restart() or at EOF. + * such as during a yyrestart() or at EOF. */ /* %if-c-only */ - static void settings_parser__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2146,7 +2336,7 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - settings_parser__flush_buffer(b ,yyscanner); + yy_flush_buffer( b , yyscanner); /* %if-c-only */ b->yy_input_file = file; @@ -2155,8 +2345,8 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) /* %endif */ b->yy_fill_buffer = 1; - /* If b is the current buffer, then settings_parser__init_buffer was _probably_ - * called from settings_parser_restart() or through yy_get_next_buffer. + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ @@ -2166,7 +2356,7 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) /* %if-c-only */ - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + b->yy_is_interactive = 0; /* %endif */ /* %if-c++-only */ @@ -2179,7 +2369,7 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) * @param yyscanner The scanner object. */ /* %if-c-only */ - void settings_parser__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2203,7 +2393,7 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) - settings_parser__load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); } /* %if-c-or-c++ */ @@ -2214,7 +2404,7 @@ static void settings_parser__load_buffer_state (yyscan_t yyscanner) * @param yyscanner The scanner object. */ /* %if-c-only */ -void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2223,9 +2413,9 @@ void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy if (new_buffer == NULL) return; - settings_parser_ensure_buffer_stack(yyscanner); + yyensure_buffer_stack(yyscanner); - /* This block is copied from settings_parser__switch_to_buffer. */ + /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ @@ -2239,8 +2429,8 @@ void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; - /* copied from settings_parser__switch_to_buffer. */ - settings_parser__load_buffer_state(yyscanner ); + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } /* %endif */ @@ -2251,7 +2441,7 @@ void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy * @param yyscanner The scanner object. */ /* %if-c-only */ -void settings_parser_pop_buffer_state (yyscan_t yyscanner) +void yypop_buffer_state (yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2260,13 +2450,13 @@ void settings_parser_pop_buffer_state (yyscan_t yyscanner) if (!YY_CURRENT_BUFFER) return; - settings_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { - settings_parser__load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } @@ -2277,7 +2467,7 @@ void settings_parser_pop_buffer_state (yyscan_t yyscanner) * Guarantees space for at least one push. */ /* %if-c-only */ -static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner) +static void yyensure_buffer_stack (yyscan_t yyscanner) /* %endif */ /* %if-c++-only */ /* %endif */ @@ -2291,15 +2481,15 @@ static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner) * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - yyg->yy_buffer_stack = (struct yy_buffer_state**)settings_parser_alloc + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser_ensure_buffer_stack()" ); - + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - + yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; @@ -2311,12 +2501,12 @@ static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner) yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)settings_parser_realloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser_ensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -2330,9 +2520,9 @@ static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner) * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. + * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE settings_parser__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; @@ -2340,73 +2530,73 @@ YY_BUFFER_STATE settings_parser__scan_buffer (char * base, yy_size_t size , yy base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ - return 0; + return NULL; - b = (YY_BUFFER_STATE) settings_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser__scan_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; - b->yy_input_file = 0; + b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - settings_parser__switch_to_buffer(b ,yyscanner ); + yy_switch_to_buffer( b , yyscanner ); return b; } /* %endif */ /* %if-c-only */ -/** Setup the input buffer state to scan a string. The next call to settings_parser_lex() will +/** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use - * settings_parser__scan_bytes() instead. + * yy_scan_bytes() instead. */ -YY_BUFFER_STATE settings_parser__scan_string (yyconst char * yystr , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) { - return settings_parser__scan_bytes(yystr,strlen(yystr) ,yyscanner); + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); } /* %endif */ /* %if-c-only */ -/** Setup the input buffer state to scan the given bytes. The next call to settings_parser_lex() will +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE settings_parser__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; - yy_size_t i; + int i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) settings_parser_alloc(n ,yyscanner ); + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in settings_parser__scan_bytes()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = settings_parser__scan_buffer(buf,n ,yyscanner); + b = yy_scan_buffer( buf, n , yyscanner); if ( ! b ) - YY_FATAL_ERROR( "bad buffer in settings_parser__scan_bytes()" ); + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -2429,13 +2619,14 @@ YY_BUFFER_STATE settings_parser__scan_bytes (yyconst char * yybytes, yy_size_t yy_size_t new_size; yyg->yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yyg->yy_start_stack_depth * sizeof( int ); + new_size = (yy_size_t) yyg->yy_start_stack_depth * sizeof( int ); if ( ! yyg->yy_start_stack ) - yyg->yy_start_stack = (int *) settings_parser_alloc(new_size ,yyscanner ); + yyg->yy_start_stack = (int *) yyalloc( new_size , yyscanner ); else - yyg->yy_start_stack = (int *) settings_parser_realloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); + yyg->yy_start_stack = (int *) yyrealloc( + (void *) yyg->yy_start_stack, new_size , yyscanner ); if ( ! yyg->yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); @@ -2474,11 +2665,11 @@ YY_BUFFER_STATE settings_parser__scan_bytes (yyconst char * yybytes, yy_size_t #endif /* %if-c-only */ -static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; - (void) fprintf( stderr, "%s\n", msg ); + fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* %endif */ @@ -2510,7 +2701,7 @@ static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ -YY_EXTRA_TYPE settings_parser_get_extra (yyscan_t yyscanner) +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; @@ -2521,10 +2712,10 @@ YY_EXTRA_TYPE settings_parser_get_extra (yyscan_t yyscanner) /** Get the current line number. * @param yyscanner The scanner object. */ -int settings_parser_get_lineno (yyscan_t yyscanner) +int yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -2534,10 +2725,10 @@ int settings_parser_get_lineno (yyscan_t yyscanner) /** Get the current column number. * @param yyscanner The scanner object. */ -int settings_parser_get_column (yyscan_t yyscanner) +int yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -2547,7 +2738,7 @@ int settings_parser_get_column (yyscan_t yyscanner) /** Get the input stream. * @param yyscanner The scanner object. */ -FILE *settings_parser_get_in (yyscan_t yyscanner) +FILE *yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; @@ -2556,7 +2747,7 @@ FILE *settings_parser_get_in (yyscan_t yyscanner) /** Get the output stream. * @param yyscanner The scanner object. */ -FILE *settings_parser_get_out (yyscan_t yyscanner) +FILE *yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; @@ -2565,7 +2756,7 @@ FILE *settings_parser_get_out (yyscan_t yyscanner) /** Get the length of the current token. * @param yyscanner The scanner object. */ -yy_size_t settings_parser_get_leng (yyscan_t yyscanner) +int yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; @@ -2575,7 +2766,7 @@ yy_size_t settings_parser_get_leng (yyscan_t yyscanner) * @param yyscanner The scanner object. */ -char *settings_parser_get_text (yyscan_t yyscanner) +char *yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; @@ -2587,7 +2778,7 @@ char *settings_parser_get_text (yyscan_t yyscanner) * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ -void settings_parser_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; @@ -2599,13 +2790,13 @@ void settings_parser_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner * @param _line_number line number * @param yyscanner The scanner object. */ -void settings_parser_set_lineno (int _line_number , yyscan_t yyscanner) +void yyset_lineno (int _line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "settings_parser_set_lineno called with no buffer" ); + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); yylineno = _line_number; } @@ -2614,13 +2805,13 @@ void settings_parser_set_lineno (int _line_number , yyscan_t yyscanner) * @param _column_no column number * @param yyscanner The scanner object. */ -void settings_parser_set_column (int _column_no , yyscan_t yyscanner) +void yyset_column (int _column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "settings_parser_set_column called with no buffer" ); + YY_FATAL_ERROR( "yyset_column called with no buffer" ); yycolumn = _column_no; } @@ -2629,27 +2820,27 @@ void settings_parser_set_column (int _column_no , yyscan_t yyscanner) * input buffer. * @param _in_str A readable stream. * @param yyscanner The scanner object. - * @see settings_parser__switch_to_buffer + * @see yy_switch_to_buffer */ -void settings_parser_set_in (FILE * _in_str , yyscan_t yyscanner) +void yyset_in (FILE * _in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = _in_str ; } -void settings_parser_set_out (FILE * _out_str , yyscan_t yyscanner) +void yyset_out (FILE * _out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = _out_str ; } -int settings_parser_get_debug (yyscan_t yyscanner) +int yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } -void settings_parser_set_debug (int _bdebug , yyscan_t yyscanner) +void yyset_debug (int _bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = _bdebug ; @@ -2662,13 +2853,13 @@ void settings_parser_set_debug (int _bdebug , yyscan_t yyscanner) /* %if-bison-bridge */ -YYSTYPE * settings_parser_get_lval (yyscan_t yyscanner) +YYSTYPE * yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } -void settings_parser_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; @@ -2678,20 +2869,18 @@ void settings_parser_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) /* User-visible API */ -/* settings_parser_lex_init is special because it creates the scanner itself, so it is +/* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ - -int settings_parser_lex_init(yyscan_t* ptr_yy_globals) - +int yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - *ptr_yy_globals = (yyscan_t) settings_parser_alloc ( sizeof( struct yyguts_t ), NULL ); + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -2704,39 +2893,37 @@ int settings_parser_lex_init(yyscan_t* ptr_yy_globals) return yy_init_globals ( *ptr_yy_globals ); } -/* settings_parser_lex_init_extra has the same functionality as settings_parser_lex_init, but follows the +/* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to settings_parser_alloc in + * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ - -int settings_parser_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) - +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; - settings_parser_set_extra (yy_user_defined, &dummy_yyguts); + yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - - *ptr_yy_globals = (yyscan_t) settings_parser_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } - + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - settings_parser_set_extra (yy_user_defined, *ptr_yy_globals); - + + yyset_extra (yy_user_defined, *ptr_yy_globals); + return yy_init_globals ( *ptr_yy_globals ); } @@ -2747,13 +2934,13 @@ static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. - * This function is called from settings_parser_lex_destroy(), so don't allocate here. + * This function is called from yylex_destroy(), so don't allocate here. */ - yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack = NULL; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = (char *) 0; + yyg->yy_c_buf_p = NULL; yyg->yy_init = 0; yyg->yy_start = 0; @@ -2766,45 +2953,45 @@ static int yy_init_globals (yyscan_t yyscanner) yyin = stdin; yyout = stdout; #else - yyin = (FILE *) 0; - yyout = (FILE *) 0; + yyin = NULL; + yyout = NULL; #endif /* For future reference: Set errno on error, since we are called by - * settings_parser_lex_init() + * yylex_init() */ return 0; } /* %endif */ /* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ -/* settings_parser_lex_destroy is for both reentrant and non-reentrant scanners. */ -int settings_parser_lex_destroy (yyscan_t yyscanner) +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ - settings_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; - settings_parser_pop_buffer_state(yyscanner); + yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ - settings_parser_free(yyg->yy_buffer_stack ,yyscanner); + yyfree(yyg->yy_buffer_stack , yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ - settings_parser_free(yyg->yy_start_stack ,yyscanner ); + yyfree( yyg->yy_start_stack , yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time - * settings_parser_lex() is called, initialization will occur. */ + * yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* %if-reentrant */ /* Destroy the main struct (reentrant only). */ - settings_parser_free ( yyscanner , yyscanner ); + yyfree ( yyscanner , yyscanner ); yyscanner = NULL; /* %endif */ return 0; @@ -2816,7 +3003,7 @@ int settings_parser_lex_destroy (yyscan_t yyscanner) */ #ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; @@ -2828,7 +3015,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) { int n; for ( n = 0; s[n]; ++n ) @@ -2838,14 +3025,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) } #endif -void *settings_parser_alloc (yy_size_t size , yyscan_t yyscanner) +void *yyalloc (yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; - return (void *) malloc( size ); + return malloc(size); } -void *settings_parser_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; @@ -2857,14 +3044,14 @@ void *settings_parser_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ - return (void *) realloc( (char *) ptr, size ); + return realloc(ptr, size); } -void settings_parser_free (void * ptr , yyscan_t yyscanner) +void yyfree (void * ptr , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; - free( (char *) ptr ); /* see settings_parser_realloc() for (char *) cast */ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } /* %if-tables-serialization definitions */ @@ -2874,8 +3061,7 @@ void settings_parser_free (void * ptr , yyscan_t yyscanner) /* %ok-for-header */ -#line 236 "settings/settings_lexer.l" - +#line 241 "settings/settings_lexer.l" /** diff --git a/src/libstrongswan/settings/settings_lexer.l b/src/libstrongswan/settings/settings_lexer.l index 19ab8d7b2..e8c2b9884 100644 --- a/src/libstrongswan/settings/settings_lexer.l +++ b/src/libstrongswan/settings/settings_lexer.l @@ -32,6 +32,11 @@ static void include_files(parser_helper_t *ctx); /* do not declare unneeded functions */ %option noinput noyywrap +/* do not include unistd.h as it might conflict with our scanner states */ +%option nounistd +/* due to that disable interactive mode, which requires isatty() */ +%option never-interactive + /* don't use global variables, and interact properly with bison */ %option reentrant bison-bridge 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/Makefile.in b/src/libstrongswan/tests/Makefile.in index c5b943572..664c84f3f 100644 --- a/src/libstrongswan/tests/Makefile.in +++ b/src/libstrongswan/tests/Makefile.in @@ -163,6 +163,7 @@ am_libstrongswan_tests_OBJECTS = libstrongswan_tests-tests.$(OBJEXT) \ suites/libstrongswan_tests-test_mgf1.$(OBJEXT) \ suites/libstrongswan_tests-test_ntru.$(OBJEXT) \ suites/libstrongswan_tests-test_ed25519.$(OBJEXT) \ + suites/libstrongswan_tests-test_ed448.$(OBJEXT) \ suites/libstrongswan_tests-test_signature_params.$(OBJEXT) libstrongswan_tests_OBJECTS = $(am_libstrongswan_tests_OBJECTS) libstrongswan_tests_DEPENDENCIES = \ @@ -548,6 +549,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 = \ @@ -708,6 +710,8 @@ suites/libstrongswan_tests-test_ntru.$(OBJEXT): \ suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp) suites/libstrongswan_tests-test_ed25519.$(OBJEXT): \ suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp) +suites/libstrongswan_tests-test_ed448.$(OBJEXT): \ + suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp) suites/libstrongswan_tests-test_signature_params.$(OBJEXT): \ suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp) @@ -740,6 +744,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_crypto_factory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_ecdsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_ed25519.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_enum.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_enumerator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libstrongswan_tests-test_fetch_http.Po@am__quote@ @@ -1359,6 +1364,20 @@ suites/libstrongswan_tests-test_ed25519.obj: suites/test_ed25519.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -c -o suites/libstrongswan_tests-test_ed25519.obj `if test -f 'suites/test_ed25519.c'; then $(CYGPATH_W) 'suites/test_ed25519.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ed25519.c'; fi` +suites/libstrongswan_tests-test_ed448.o: suites/test_ed448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -MT suites/libstrongswan_tests-test_ed448.o -MD -MP -MF suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Tpo -c -o suites/libstrongswan_tests-test_ed448.o `test -f 'suites/test_ed448.c' || echo '$(srcdir)/'`suites/test_ed448.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Tpo suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ed448.c' object='suites/libstrongswan_tests-test_ed448.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -c -o suites/libstrongswan_tests-test_ed448.o `test -f 'suites/test_ed448.c' || echo '$(srcdir)/'`suites/test_ed448.c + +suites/libstrongswan_tests-test_ed448.obj: suites/test_ed448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -MT suites/libstrongswan_tests-test_ed448.obj -MD -MP -MF suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Tpo -c -o suites/libstrongswan_tests-test_ed448.obj `if test -f 'suites/test_ed448.c'; then $(CYGPATH_W) 'suites/test_ed448.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ed448.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Tpo suites/$(DEPDIR)/libstrongswan_tests-test_ed448.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ed448.c' object='suites/libstrongswan_tests-test_ed448.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -c -o suites/libstrongswan_tests-test_ed448.obj `if test -f 'suites/test_ed448.c'; then $(CYGPATH_W) 'suites/test_ed448.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ed448.c'; fi` + suites/libstrongswan_tests-test_signature_params.o: suites/test_signature_params.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libstrongswan_tests_CFLAGS) $(CFLAGS) -MT suites/libstrongswan_tests-test_signature_params.o -MD -MP -MF suites/$(DEPDIR)/libstrongswan_tests-test_signature_params.Tpo -c -o suites/libstrongswan_tests-test_signature_params.o `test -f 'suites/test_signature_params.c' || echo '$(srcdir)/'`suites/test_signature_params.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libstrongswan_tests-test_signature_params.Tpo suites/$(DEPDIR)/libstrongswan_tests-test_signature_params.Po diff --git a/src/libstrongswan/tests/suites/test_ed25519.c b/src/libstrongswan/tests/suites/test_ed25519.c index 86cbb1bc0..c52b90885 100644 --- a/src/libstrongswan/tests/suites/test_ed25519.c +++ b/src/libstrongswan/tests/suites/test_ed25519.c @@ -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); 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 <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; +} diff --git a/src/libstrongswan/tests/suites/test_rsa.c b/src/libstrongswan/tests/suites/test_rsa.c index e6dc7744a..a71fa0ce5 100644 --- a/src/libstrongswan/tests/suites/test_rsa.c +++ b/src/libstrongswan/tests/suites/test_rsa.c @@ -40,7 +40,7 @@ static signature_scheme_t schemes[] = { static rsa_pss_params_t default_pss_params = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, - .salt_len = RSA_PSS_SALT_LEN_DEFAULT, + .salt_len = HASH_SIZE_SHA256, }; /** diff --git a/src/libstrongswan/tests/suites/test_signature_params.c b/src/libstrongswan/tests/suites/test_signature_params.c index 38cb5803f..cbf1a2861 100644 --- a/src/libstrongswan/tests/suites/test_signature_params.c +++ b/src/libstrongswan/tests/suites/test_signature_params.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Tobias Brunner + * Copyright (C) 2017-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -138,27 +138,27 @@ static struct { 0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30, 0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03, 0x02,0x01,0x20), - { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }}, /* default salt length: SHA-1 */ { chunk_from_chars(0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x00), - { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }}, /* default salt length: SHA-224 */ { chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0, 0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00, 0xa2,0x03,0x02,0x01,0x1c), - { .hash = HASH_SHA224, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { .hash = HASH_SHA224, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA224, }}, /* default salt length: SHA-384 */ { chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0, 0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00, 0xa2,0x03,0x02,0x01,0x30), - { .hash = HASH_SHA384, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { .hash = HASH_SHA384, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA384, }}, /* SHA-512 */ { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0, 0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00, 0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30, 0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0xa2,0x03, 0x02,0x01,0x40), - { .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA512, }}, /* SHA-256, no salt */ { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0, 0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00, @@ -199,6 +199,8 @@ rsa_pss_params_t rsa_pss_build_invalid_tests[] = { { .hash = HASH_UNKNOWN, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }, /* invalid mgf */ { .hash = HASH_SHA256, .mgf1_hash = HASH_UNKNOWN, .salt_len = HASH_SIZE_SHA256, }, + /* undetermined salt */ + { .hash = HASH_UNKNOWN, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }, }; START_TEST(test_rsa_pss_params_build_invalid) @@ -209,6 +211,49 @@ START_TEST(test_rsa_pss_params_build_invalid) } END_TEST + +static struct { + ssize_t expected; + size_t modbits; + rsa_pss_params_t params; +} rsa_pss_salt_len_tests[] = { + { HASH_SIZE_SHA256, 0, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { HASH_SIZE_SHA256, 3072, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }}, + { -1, 0, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 0, 256, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 350, 3071, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 350, 3072, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 350, 3073, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 478, 4096, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_MAX, }}, + { 10, 0, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, }}, + { 10, 3072, + { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, }}, +}; + +START_TEST(test_rsa_pss_params_set_salt_len) +{ + if (rsa_pss_params_set_salt_len(&rsa_pss_salt_len_tests[_i].params, + rsa_pss_salt_len_tests[_i].modbits)) + { + ck_assert_int_eq(rsa_pss_salt_len_tests[_i].expected, + rsa_pss_salt_len_tests[_i].params.salt_len); + } + else + { + ck_assert(rsa_pss_salt_len_tests[_i].expected < 0); + } +} +END_TEST + static rsa_pss_params_t rsa_pss_params_sha1 = { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }; static rsa_pss_params_t rsa_pss_params_sha256 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }; static rsa_pss_params_t rsa_pss_params_sha256_mgf1 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA256, }; @@ -430,6 +475,10 @@ Suite *signature_params_suite_create() tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests)); suite_add_tcase(s, tc); + tc = tcase_create("rsa/pss salt len"); + tcase_add_loop_test(tc, test_rsa_pss_params_set_salt_len, 0, countof(rsa_pss_salt_len_tests)); + suite_add_tcase(s, tc); + tc = tcase_create("params compare"); tcase_add_loop_test(tc, test_params_compare, 0, countof(params_compare_tests)); tcase_add_test(tc, test_params_compare_null); 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) diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index e60cd8ad0..0dbe9dc80 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -332,7 +332,7 @@ static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b) } /** - * Increment a chunk, as it would reprensent a network order integer. + * Increment a chunk, as it would represent a network order integer. * * @param chunk chunk to increment * @return TRUE if an overflow occurred diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index efeb0f478..63b7453f3 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -582,6 +582,16 @@ static char *whitelist[] = { "OPENSSL_init_crypto", "CRYPTO_THREAD_lock_new", "ERR_add_error_data", + "ERR_set_mark", + "ENGINE_load_builtin_engines", + "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 */ @@ -619,6 +629,7 @@ static char *whitelist[] = { "botan_privkey_create_ecdsa", "botan_privkey_create_ecdh", "botan_privkey_load_ecdh", + "botan_privkey_load", }; /** @@ -673,7 +684,8 @@ static int print_traces(private_leak_detective_t *this, int leaks = 0; memory_header_t *hdr; enumerator_t *enumerator; - hashtable_t *entries; + hashtable_t *entries, *ignored = NULL; + backtrace_t *bt; struct { /** associated backtrace */ backtrace_t *backtrace; @@ -688,15 +700,32 @@ static int print_traces(private_leak_detective_t *this, entries = hashtable_create((hashtable_hash_t)hash, (hashtable_equals_t)equals, 1024); + if (whitelisted) + { + ignored = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 1024); + } + lock->lock(lock); for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - if (whitelisted && - hdr->backtrace->contains_function(hdr->backtrace, - whitelist, countof(whitelist))) + if (whitelisted) { - (*whitelisted)++; - continue; + bt = ignored->get(ignored, hdr->backtrace); + if (!bt) + { + if (hdr->backtrace->contains_function(hdr->backtrace, whitelist, + countof(whitelist))) + { + bt = hdr->backtrace; + ignored->put(ignored, bt, bt); + } + } + if (bt) + { + (*whitelisted)++; + continue; + } } entry = entries->get(entries, hdr->backtrace); if (entry) @@ -720,6 +749,7 @@ static int print_traces(private_leak_detective_t *this, leaks++; } lock->unlock(lock); + DESTROY_IF(ignored); enumerator = entries->create_enumerator(entries); while (enumerator->enumerate(enumerator, NULL, &entry)) |