diff options
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
20 files changed, 651 insertions, 477 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index de9df7271..a32418b16 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -44,6 +44,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/config/lt~obsolete.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -171,6 +172,8 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREADLIB = @PTHREADLIB@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ @@ -202,14 +205,17 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +c_plugins = @c_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ default_pkcs11 = @default_pkcs11@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -224,24 +230,31 @@ ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ -libhydra_plugins = @libhydra_plugins@ -libstrongswan_plugins = @libstrongswan_plugins@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ pdfdir = @pdfdir@ piddir = @piddir@ +pki_plugins = @pki_plugins@ plugindir = @plugindir@ pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ @@ -249,7 +262,10 @@ random_device = @random_device@ resolv_conf = @resolv_conf@ routing_table = @routing_table@ routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index 5645d72d7..b9d97a901 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -416,10 +416,19 @@ static bool parse_authKeyIdentifier_ext(private_openssl_crl_t *this, static bool parse_crlNumber_ext(private_openssl_crl_t *this, X509_EXTENSION *ext) { - free(this->serial.ptr); - this->serial = chunk_clone( - openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext))); - return this->serial.len != 0; + chunk_t chunk; + + chunk = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext)); + /* quick and dirty INTEGER unwrap */ + if (chunk.len > 1 && chunk.ptr[0] == V_ASN1_INTEGER && + chunk.ptr[1] == chunk.len - 2) + { + chunk = chunk_skip(chunk, 2); + free(this->serial.ptr); + this->serial = chunk_clone(chunk); + return TRUE; + } + return FALSE; } /** diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c index a8923ab56..2ed07ff0c 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crypter.c +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -41,85 +41,57 @@ struct private_openssl_crypter_t { }; /** - * Mapping from the algorithms defined in IKEv2 to - * OpenSSL algorithm names and their key length - */ -typedef struct { - /** - * Identifier specified in IKEv2 - */ - int ikev2_id; - - /** - * Name of the algorithm, as used in OpenSSL - */ - char *name; - - /** - * Minimum valid key length in bytes - */ - size_t key_size_min; - - /** - * Maximum valid key length in bytes - */ - size_t key_size_max; -} openssl_algorithm_t; - -#define END_OF_LIST -1 - -/** - * Algorithms for encryption - */ -static openssl_algorithm_t encryption_algs[] = { -/* {ENCR_DES_IV64, "***", 0, 0}, */ - {ENCR_DES, "des", 8, 8}, /* 64 bits */ - {ENCR_3DES, "des3", 24, 24}, /* 192 bits */ - {ENCR_RC5, "rc5", 5, 255}, /* 40 to 2040 bits, RFC 2451 */ - {ENCR_IDEA, "idea", 16, 16}, /* 128 bits, RFC 2451 */ - {ENCR_CAST, "cast", 5, 16}, /* 40 to 128 bits, RFC 2451 */ - {ENCR_BLOWFISH, "blowfish", 5, 56}, /* 40 to 448 bits, RFC 2451 */ -/* {ENCR_3IDEA, "***", 0, 0}, */ -/* {ENCR_DES_IV32, "***", 0, 0}, */ -/* {ENCR_NULL, "***", 0, 0}, */ /* handled separately */ -/* {ENCR_AES_CBC, "***", 0, 0}, */ /* handled separately */ -/* {ENCR_CAMELLIA_CBC, "***", 0, 0}, */ /* handled separately */ -/* {ENCR_AES_CTR, "***", 0, 0}, */ /* disabled in evp.h */ - {END_OF_LIST, NULL, 0, 0}, -}; - -/** * Look up an OpenSSL algorithm name and validate its key size */ -static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, - u_int16_t ikev2_algo, size_t *key_size) +static char* lookup_algorithm(u_int16_t ikev2_algo, size_t *key_size) { - while (openssl_algo->ikev2_id != END_OF_LIST) + struct { + /* identifier specified in IKEv2 */ + int ikev2_id; + /* name of the algorithm, as used in OpenSSL */ + char *name; + /* default key size in bytes */ + size_t key_def; + /* minimum key size */ + size_t key_min; + /* maximum key size */ + size_t key_max; + } mappings[] = { + {ENCR_DES, "des", 8, 8, 8}, + {ENCR_3DES, "des3", 24, 24, 24}, + {ENCR_RC5, "rc5", 16, 5, 255}, + {ENCR_IDEA, "idea", 16, 16, 16}, + {ENCR_CAST, "cast", 16, 5, 16}, + {ENCR_BLOWFISH, "blowfish", 16, 5, 56}, + }; + int i; + + for (i = 0; i < countof(mappings); i++) { - if (ikev2_algo == openssl_algo->ikev2_id) + if (ikev2_algo == mappings[i].ikev2_id) { /* set the key size if it is not set */ - if (*key_size == 0 && - (openssl_algo->key_size_min == openssl_algo->key_size_max)) + if (*key_size == 0) { - *key_size = openssl_algo->key_size_min; + *key_size = mappings[i].key_def; } - /* validate key size */ - if (*key_size < openssl_algo->key_size_min || - *key_size > openssl_algo->key_size_max) + if (*key_size < mappings[i].key_min || + *key_size > mappings[i].key_max) { return NULL; } - return openssl_algo->name; + return mappings[i].name; } - openssl_algo++; } return NULL; } -static void crypt(private_openssl_crypter_t *this, chunk_t data, - chunk_t iv, chunk_t *dst, int enc) +/** + * Do the actual en/decryption in an EVP context + */ +static void crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, + chunk_t *dst, int enc) { int len; u_char *out; @@ -141,53 +113,44 @@ static void crypt(private_openssl_crypter_t *this, chunk_t data, EVP_CIPHER_CTX_cleanup(&ctx); } -/** - * Implementation of crypter_t.decrypt. - */ -static void decrypt(private_openssl_crypter_t *this, chunk_t data, - chunk_t iv, chunk_t *dst) +METHOD(crypter_t, decrypt, void, + private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) { crypt(this, data, iv, dst, 0); } - -/** - * Implementation of crypter_t.encrypt. - */ -static void encrypt (private_openssl_crypter_t *this, chunk_t data, - chunk_t iv, chunk_t *dst) +METHOD(crypter_t, encrypt, void, + private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) { crypt(this, data, iv, dst, 1); } -/** - * Implementation of crypter_t.get_block_size. - */ -static size_t get_block_size(private_openssl_crypter_t *this) +METHOD(crypter_t, get_block_size, size_t, + private_openssl_crypter_t *this) { return this->cipher->block_size; } -/** - * Implementation of crypter_t.get_key_size. - */ -static size_t get_key_size(private_openssl_crypter_t *this) +METHOD(crypter_t, get_iv_size, size_t, + private_openssl_crypter_t *this) +{ + return this->cipher->block_size; +} + +METHOD(crypter_t, get_key_size, size_t, + private_openssl_crypter_t *this) { return this->key.len; } -/** - * Implementation of crypter_t.set_key. - */ -static void set_key(private_openssl_crypter_t *this, chunk_t key) +METHOD(crypter_t, set_key, void, + private_openssl_crypter_t *this, chunk_t key) { memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); } -/** - * Implementation of crypter_t.destroy. - */ -static void destroy (private_openssl_crypter_t *this) +METHOD(crypter_t, destroy, void, + private_openssl_crypter_t *this) { free(this->key.ptr); free(this); @@ -201,16 +164,32 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, { private_openssl_crypter_t *this; - this = malloc_thing(private_openssl_crypter_t); + INIT(this, + .public = { + .crypter = { + .encrypt = _encrypt, + .decrypt = _decrypt, + .get_block_size = _get_block_size, + .get_iv_size = _get_iv_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + ); switch (algo) { case ENCR_NULL: this->cipher = EVP_enc_null(); + key_size = 0; break; case ENCR_AES_CBC: switch (key_size) { + case 0: + key_size = 16; + /* FALL */ case 16: /* AES 128 */ this->cipher = EVP_get_cipherbyname("aes128"); break; @@ -228,6 +207,9 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, case ENCR_CAMELLIA_CBC: switch (key_size) { + case 0: + key_size = 16; + /* FALL */ case 16: /* CAMELLIA 128 */ this->cipher = EVP_get_cipherbyname("camellia128"); break; @@ -243,11 +225,14 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, } break; case ENCR_DES_ECB: + key_size = 8; this->cipher = EVP_des_ecb(); break; default: { - char* name = lookup_algorithm(encryption_algs, algo, &key_size); + char* name; + + name = lookup_algorithm(algo, &key_size); if (!name) { /* algo unavailable or key_size invalid */ @@ -268,12 +253,5 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, this->key = chunk_alloc(key_size); - this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; - this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; - this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; - this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; - this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key; - this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; - return &this->public; } diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.h b/src/libstrongswan/plugins/openssl/openssl_crypter.h index 7e30ae03c..b12e7a6ab 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crypter.h +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.h @@ -31,9 +31,9 @@ typedef struct openssl_crypter_t openssl_crypter_t; struct openssl_crypter_t { /** - * The crypter_t interface. + * Implements crypter_t interface. */ - crypter_t crypter_interface; + crypter_t crypter; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 9a032c54f..b27aa3391 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -57,11 +57,8 @@ struct private_openssl_diffie_hellman_t { bool computed; }; -/** - * Implementation of openssl_diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(private_openssl_diffie_hellman_t *this, - chunk_t *value) +METHOD(diffie_hellman_t, get_my_public_value, void, + private_openssl_diffie_hellman_t *this, chunk_t *value) { *value = chunk_alloc(DH_size(this->dh)); memset(value->ptr, 0, value->len); @@ -69,11 +66,8 @@ static void get_my_public_value(private_openssl_diffie_hellman_t *this, value->ptr + value->len - BN_num_bytes(this->dh->pub_key)); } -/** - * Implementation of openssl_diffie_hellman_t.get_shared_secret. - */ -static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, - chunk_t *secret) +METHOD(diffie_hellman_t, get_shared_secret, status_t, + private_openssl_diffie_hellman_t *this, chunk_t *secret) { if (!this->computed) { @@ -88,11 +82,8 @@ static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, } -/** - * Implementation of openssl_diffie_hellman_t.set_other_public_value. - */ -static void set_other_public_value(private_openssl_diffie_hellman_t *this, - chunk_t value) +METHOD(diffie_hellman_t, set_other_public_value, void, + private_openssl_diffie_hellman_t *this, chunk_t value) { int len; @@ -110,10 +101,8 @@ static void set_other_public_value(private_openssl_diffie_hellman_t *this, this->computed = TRUE; } -/** - * Implementation of openssl_diffie_hellman_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *this) +METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, + private_openssl_diffie_hellman_t *this) { return this->group; } @@ -137,10 +126,8 @@ static status_t set_modulus(private_openssl_diffie_hellman_t *this) return SUCCESS; } -/** - * Implementation of openssl_diffie_hellman_t.destroy. - */ -static void destroy(private_openssl_diffie_hellman_t *this) +METHOD(diffie_hellman_t, destroy, void, + private_openssl_diffie_hellman_t *this) { BN_clear_free(this->pub_key); DH_free(this->dh); @@ -151,15 +138,22 @@ static void destroy(private_openssl_diffie_hellman_t *this) /* * Described in header. */ -openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t group) +openssl_diffie_hellman_t *openssl_diffie_hellman_create( + diffie_hellman_group_t group, chunk_t g, chunk_t p) { - private_openssl_diffie_hellman_t *this = malloc_thing(private_openssl_diffie_hellman_t); - - this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; - this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; - this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; - this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; + private_openssl_diffie_hellman_t *this; + + INIT(this, + .public = { + .dh = { + .get_shared_secret = _get_shared_secret, + .set_other_public_value = _set_other_public_value, + .get_my_public_value = _get_my_public_value, + .get_dh_group = _get_dh_group, + .destroy = _destroy, + }, + }, + ); this->dh = DH_new(); if (!this->dh) @@ -173,11 +167,19 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g this->pub_key = BN_new(); this->shared_secret = chunk_empty; - /* find a modulus according to group */ - if (set_modulus(this) != SUCCESS) + if (group == MODP_CUSTOM) { - destroy(this); - return NULL; + this->dh->p = BN_bin2bn(p.ptr, p.len, NULL); + this->dh->g = BN_bin2bn(g.ptr, g.len, NULL); + } + else + { + /* find a modulus according to group */ + if (set_modulus(this) != SUCCESS) + { + destroy(this); + return NULL; + } } /* generate my public and private values */ diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h index 6c4b4fe81..53dc59c78 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h @@ -40,9 +40,12 @@ struct openssl_diffie_hellman_t { * Creates a new openssl_diffie_hellman_t object. * * @param group Diffie Hellman group number to use + * @param g custom generator, if MODP_CUSTOM + * @param p custom prime, if MODP_CUSTOM * @return openssl_diffie_hellman_t object, NULL if not supported */ -openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t group); +openssl_diffie_hellman_t *openssl_diffie_hellman_create( + diffie_hellman_group_t group, chunk_t g, chunk_t p); #endif /** OPENSSL_DIFFIE_HELLMAN_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c index a53e8aea0..32fc2bccd 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c @@ -165,7 +165,8 @@ error: * of the Diffie-Hellman shared secret value is the same as that of the * Diffie-Hellman public value." */ -static bool compute_shared_key(private_openssl_ec_diffie_hellman_t *this, chunk_t *shared_secret) +static bool compute_shared_key(private_openssl_ec_diffie_hellman_t *this, + chunk_t *shared_secret) { const BIGNUM *priv_key; EC_POINT *secret = NULL; @@ -209,10 +210,8 @@ error: return ret; } -/** - * Implementation of openssl_ec_diffie_hellman_t.set_other_public_value. - */ -static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, chunk_t value) +METHOD(diffie_hellman_t, set_other_public_value, void, + private_openssl_ec_diffie_hellman_t *this, chunk_t value) { if (!chunk2ecp(this->ec_group, value, this->pub_key)) { @@ -230,18 +229,14 @@ static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, ch this->computed = TRUE; } -/** - * Implementation of openssl_ec_diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(private_openssl_ec_diffie_hellman_t *this,chunk_t *value) +METHOD(diffie_hellman_t, get_my_public_value, void, + private_openssl_ec_diffie_hellman_t *this,chunk_t *value) { ecp2chunk(this->ec_group, EC_KEY_get0_public_key(this->key), value, FALSE); } -/** - * Implementation of openssl_ec_diffie_hellman_t.get_shared_secret. - */ -static status_t get_shared_secret(private_openssl_ec_diffie_hellman_t *this, chunk_t *secret) +METHOD(diffie_hellman_t, get_shared_secret, status_t, + private_openssl_ec_diffie_hellman_t *this, chunk_t *secret) { if (!this->computed) { @@ -251,18 +246,14 @@ static status_t get_shared_secret(private_openssl_ec_diffie_hellman_t *this, chu return SUCCESS; } -/** - * Implementation of openssl_ec_diffie_hellman_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(private_openssl_ec_diffie_hellman_t *this) +METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, + private_openssl_ec_diffie_hellman_t *this) { return this->group; } -/** - * Implementation of openssl_ec_diffie_hellman_t.destroy. - */ -static void destroy(private_openssl_ec_diffie_hellman_t *this) +METHOD(diffie_hellman_t, destroy, void, + private_openssl_ec_diffie_hellman_t *this) { EC_POINT_clear_free(this->pub_key); EC_KEY_free(this->key); @@ -275,13 +266,20 @@ static void destroy(private_openssl_ec_diffie_hellman_t *this) */ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_group_t group) { - private_openssl_ec_diffie_hellman_t *this = malloc_thing(private_openssl_ec_diffie_hellman_t); - - this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; - this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; - this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; - this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; + private_openssl_ec_diffie_hellman_t *this; + + INIT(this, + .public = { + .dh = { + .get_shared_secret = _get_shared_secret, + .set_other_public_value = _set_other_public_value, + .get_my_public_value = _get_my_public_value, + .get_dh_group = _get_dh_group, + .destroy = _destroy, + }, + }, + .group = group, + ); switch (group) { @@ -328,11 +326,6 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro return NULL; } - this->group = group; - this->computed = FALSE; - - this->shared_secret = chunk_empty; - return &this->public; } #endif /* OPENSSL_NO_EC */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index 281155913..f4c4759bf 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -138,11 +138,9 @@ static bool build_der_signature(private_openssl_ec_private_key_t *this, return built; } -/** - * Implementation of private_key_t.sign. - */ -static bool sign(private_openssl_ec_private_key_t *this, - signature_scheme_t scheme, chunk_t data, chunk_t *signature) +METHOD(private_key_t, sign, bool, + private_openssl_ec_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) { switch (scheme) { @@ -172,36 +170,38 @@ static bool sign(private_openssl_ec_private_key_t *this, } } -/** - * Implementation of private_key_t.destroy. - */ -static bool decrypt(private_openssl_ec_private_key_t *this, - chunk_t crypto, chunk_t *plain) +METHOD(private_key_t, decrypt, bool, + private_openssl_ec_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) { DBG1(DBG_LIB, "EC private key decryption not implemented"); return FALSE; } -/** - * Implementation of private_key_t.get_keysize. - */ -static size_t get_keysize(private_openssl_ec_private_key_t *this) +METHOD(private_key_t, get_keysize, int, + private_openssl_ec_private_key_t *this) { - return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)); + switch (EC_GROUP_get_curve_name(EC_KEY_get0_group(this->ec))) + { + case NID_X9_62_prime256v1: + return 256; + case NID_secp384r1: + return 384; + case NID_secp521r1: + return 521; + default: + return 0; + } } -/** - * Implementation of private_key_t.get_type. - */ -static key_type_t get_type(private_openssl_ec_private_key_t *this) +METHOD(private_key_t, get_type, key_type_t, + private_openssl_ec_private_key_t *this) { return KEY_ECDSA; } -/** - * Implementation of private_key_t.get_public_key. - */ -static public_key_t* get_public_key(private_openssl_ec_private_key_t *this) +METHOD(private_key_t, get_public_key, public_key_t*, + private_openssl_ec_private_key_t *this) { public_key_t *public; chunk_t key; @@ -217,20 +217,16 @@ static public_key_t* get_public_key(private_openssl_ec_private_key_t *this) return public; } -/** - * Implementation of private_key_t.get_fingerprint. - */ -static bool get_fingerprint(private_openssl_ec_private_key_t *this, - cred_encoding_type_t type, chunk_t *fingerprint) +METHOD(private_key_t, get_fingerprint, bool, + private_openssl_ec_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) { return openssl_ec_fingerprint(this->ec, type, fingerprint); } -/** - * Implementation of private_key_t.get_encoding. - */ -static bool get_encoding(private_openssl_ec_private_key_t *this, - cred_encoding_type_t type, chunk_t *encoding) +METHOD(private_key_t, get_encoding, bool, + private_openssl_ec_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) { u_char *p; @@ -261,19 +257,15 @@ static bool get_encoding(private_openssl_ec_private_key_t *this, } } -/** - * Implementation of private_key_t.get_ref. - */ -static private_key_t* get_ref(private_openssl_ec_private_key_t *this) +METHOD(private_key_t, get_ref, private_key_t*, + private_openssl_ec_private_key_t *this) { ref_get(&this->ref); - return &this->public.interface; + return &this->public.key; } -/** - * Implementation of private_key_t.destroy. - */ -static void destroy(private_openssl_ec_private_key_t *this) +METHOD(private_key_t, destroy, void, + private_openssl_ec_private_key_t *this) { if (ref_put(&this->ref)) { @@ -291,23 +283,27 @@ static void destroy(private_openssl_ec_private_key_t *this) */ static private_openssl_ec_private_key_t *create_empty(void) { - private_openssl_ec_private_key_t *this = malloc_thing(private_openssl_ec_private_key_t); - - this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type; - this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign; - this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt; - this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize; - this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key; - this->public.interface.equals = private_key_equals; - this->public.interface.belongs_to = private_key_belongs_to; - this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint; - this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint; - this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding; - this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref; - this->public.interface.destroy = (void (*)(private_key_t *this))destroy; - - this->ec = NULL; - this->ref = 1; + private_openssl_ec_private_key_t *this; + + INIT(this, + .public = { + .key = { + .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; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h index 720c63f90..f56c95aa1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h @@ -34,7 +34,7 @@ struct openssl_ec_private_key_t { /** * Implements private_key_t interface */ - private_key_t interface; + private_key_t key; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index def36c92f..7461695ad 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -130,19 +130,15 @@ static bool verify_der_signature(private_openssl_ec_public_key_t *this, return valid; } -/** - * Implementation of public_key_t.get_type. - */ -static key_type_t get_type(private_openssl_ec_public_key_t *this) +METHOD(public_key_t, get_type, key_type_t, + private_openssl_ec_public_key_t *this) { return KEY_ECDSA; } -/** - * Implementation of public_key_t.verify. - */ -static bool verify(private_openssl_ec_public_key_t *this, - signature_scheme_t scheme, chunk_t data, chunk_t signature) +METHOD(public_key_t, verify, bool, + private_openssl_ec_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t signature) { switch (scheme) { @@ -172,22 +168,28 @@ static bool verify(private_openssl_ec_public_key_t *this, } } -/** - * Implementation of public_key_t.get_keysize. - */ -static bool encrypt_(private_openssl_ec_public_key_t *this, - chunk_t crypto, chunk_t *plain) +METHOD(public_key_t, encrypt, bool, + private_openssl_ec_public_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) { DBG1(DBG_LIB, "EC public key encryption not implemented"); return FALSE; } -/** - * Implementation of public_key_t.get_keysize. - */ -static size_t get_keysize(private_openssl_ec_public_key_t *this) +METHOD(public_key_t, get_keysize, int, + private_openssl_ec_public_key_t *this) { - return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)); + switch (EC_GROUP_get_curve_name(EC_KEY_get0_group(this->ec))) + { + case NID_X9_62_prime256v1: + return 256; + case NID_secp384r1: + return 384; + case NID_secp521r1: + return 521; + default: + return 0; + } } /** @@ -232,20 +234,16 @@ bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp) return TRUE; } -/** - * Implementation of private_key_t.get_fingerprint. - */ -static bool get_fingerprint(private_openssl_ec_public_key_t *this, - cred_encoding_type_t type, chunk_t *fingerprint) +METHOD(public_key_t, get_fingerprint, bool, + private_openssl_ec_public_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) { return openssl_ec_fingerprint(this->ec, type, fingerprint); } -/** - * Implementation of private_key_t.get_encoding. - */ -static bool get_encoding(private_openssl_ec_public_key_t *this, - cred_encoding_type_t type, chunk_t *encoding) +METHOD(public_key_t, get_encoding, bool, + private_openssl_ec_public_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) { u_char *p; @@ -276,19 +274,15 @@ static bool get_encoding(private_openssl_ec_public_key_t *this, } } -/** - * Implementation of public_key_t.get_ref. - */ -static public_key_t* get_ref(private_openssl_ec_public_key_t *this) +METHOD(public_key_t, get_ref, public_key_t*, + private_openssl_ec_public_key_t *this) { ref_get(&this->ref); - return &this->public.interface; + return &this->public.key; } -/** - * Implementation of openssl_ec_public_key.destroy. - */ -static void destroy(private_openssl_ec_public_key_t *this) +METHOD(public_key_t, destroy, void, + private_openssl_ec_public_key_t *this) { if (ref_put(&this->ref)) { @@ -306,21 +300,25 @@ static void destroy(private_openssl_ec_public_key_t *this) */ static private_openssl_ec_public_key_t *create_empty() { - private_openssl_ec_public_key_t *this = malloc_thing(private_openssl_ec_public_key_t); - - this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type; - this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify; - this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_; - this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize; - this->public.interface.equals = public_key_equals; - this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint; - this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint; - this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding; - this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref; - this->public.interface.destroy = (void (*)(public_key_t *this))destroy; - - this->ec = NULL; - this->ref = 1; + private_openssl_ec_public_key_t *this; + + INIT(this, + .public = { + .key = { + .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; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h index 29d607d38..8094083a7 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h @@ -34,7 +34,7 @@ struct openssl_ec_public_key_t { /** * Implements the public_key_t interface */ - public_key_t interface; + public_key_t key; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c index 7556bc594..d81f4b21e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.c +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c @@ -90,27 +90,20 @@ static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, return NULL; } -/** - * Implementation of hasher_t.get_hash_size. - */ -static size_t get_hash_size(private_openssl_hasher_t *this) +METHOD(hasher_t, get_hash_size, size_t, + private_openssl_hasher_t *this) { return this->hasher->md_size; } -/** - * Implementation of hasher_t.reset. - */ -static void reset(private_openssl_hasher_t *this) +METHOD(hasher_t, reset, void, + private_openssl_hasher_t *this) { EVP_DigestInit_ex(this->ctx, this->hasher, NULL); } -/** - * Implementation of hasher_t.get_hash. - */ -static void get_hash(private_openssl_hasher_t *this, chunk_t chunk, - u_int8_t *hash) +METHOD(hasher_t, get_hash, void, + private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash) { EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len); if (hash) @@ -120,11 +113,8 @@ static void get_hash(private_openssl_hasher_t *this, chunk_t chunk, } } -/** - * Implementation of hasher_t.allocate_hash. - */ -static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk, - chunk_t *hash) +METHOD(hasher_t, allocate_hash, void, + private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash) { if (hash) { @@ -137,10 +127,8 @@ static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk, } } -/** - * Implementation of hasher_t.destroy. - */ -static void destroy (private_openssl_hasher_t *this) +METHOD(hasher_t, destroy, void, + private_openssl_hasher_t *this) { EVP_MD_CTX_destroy(this->ctx); free(this); @@ -160,7 +148,17 @@ openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) return NULL; } - this = malloc_thing(private_openssl_hasher_t); + INIT(this, + .public = { + .hasher = { + .get_hash = _get_hash, + .allocate_hash = _allocate_hash, + .get_hash_size = _get_hash_size, + .reset = _reset, + .destroy = _destroy, + }, + }, + ); this->hasher = EVP_get_digestbyname(name); if (!this->hasher) @@ -170,12 +168,6 @@ openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) return NULL; } - this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash; - this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash; - this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size; - this->public.hasher_interface.reset = (void (*) (hasher_t*))reset; - this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy; - this->ctx = EVP_MD_CTX_create(); /* initialization */ diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.h b/src/libstrongswan/plugins/openssl/openssl_hasher.h index fd7a043d1..b03f6891b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.h +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.h @@ -31,9 +31,9 @@ typedef struct openssl_hasher_t openssl_hasher_t; struct openssl_hasher_t { /** - * The hasher_t interface. + * Implements hasher_t interface. */ - hasher_t hasher_interface; + hasher_t hasher; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 31697dcb8..0ab4eda9c 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -16,6 +16,7 @@ #include <openssl/evp.h> #include <openssl/conf.h> +#include <openssl/rand.h> #include <openssl/crypto.h> #ifndef OPENSSL_NO_ENGINE #include <openssl/engine.h> @@ -24,6 +25,7 @@ #include "openssl_plugin.h" #include <library.h> +#include <debug.h> #include <threading/thread.h> #include <threading/mutex.h> #include "openssl_util.h" @@ -151,6 +153,31 @@ static void threading_init() } /** + * Seed the OpenSSL RNG, if required + */ +static bool seed_rng() +{ + rng_t *rng = NULL; + char buf[32]; + + while (RAND_status() != 1) + { + if (!rng) + { + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (!rng) + { + return FALSE; + } + } + rng->get_bytes(rng, sizeof(buf), buf); + RAND_seed(buf, sizeof(buf)); + } + DESTROY_IF(rng); + return TRUE; +} + +/** * cleanup OpenSSL threading locks */ static void threading_cleanup() @@ -166,10 +193,8 @@ static void threading_cleanup() mutex = NULL; } -/** - * Implementation of openssl_plugin_t.destroy - */ -static void destroy(private_openssl_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_openssl_plugin_t *this) { lib->crypto->remove_crypter(lib->crypto, (crypter_constructor_t)openssl_crypter_create); @@ -218,9 +243,15 @@ static void destroy(private_openssl_plugin_t *this) */ plugin_t *openssl_plugin_create() { - private_openssl_plugin_t *this = malloc_thing(private_openssl_plugin_t); + private_openssl_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); threading_init(); @@ -233,6 +264,13 @@ plugin_t *openssl_plugin_create() ENGINE_register_all_complete(); #endif /* OPENSSL_NO_ENGINE */ + if (!seed_rng()) + { + DBG1(DBG_CFG, "no RNG found to seed OpenSSL"); + destroy(this); + return NULL; + } + /* crypter */ lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, (crypter_constructor_t)openssl_crypter_create); @@ -312,33 +350,35 @@ plugin_t *openssl_plugin_create() (dh_constructor_t)openssl_diffie_hellman_create); lib->crypto->add_dh(lib->crypto, MODP_768_BIT, (dh_constructor_t)openssl_diffie_hellman_create); + lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, + (dh_constructor_t)openssl_diffie_hellman_create); /* rsa */ - lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, TRUE, (builder_function_t)openssl_rsa_private_key_load); - lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, FALSE, (builder_function_t)openssl_rsa_private_key_gen); - lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, FALSE, (builder_function_t)openssl_rsa_private_key_connect); - lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, TRUE, (builder_function_t)openssl_rsa_public_key_load); - lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, FALSE, (builder_function_t)openssl_rsa_public_key_load); #ifndef OPENSSL_NO_EC /* ecdsa */ - lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, TRUE, (builder_function_t)openssl_ec_private_key_load); - lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, FALSE, (builder_function_t)openssl_ec_private_key_gen); - lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, + lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, TRUE, (builder_function_t)openssl_ec_public_key_load); #endif /* OPENSSL_NO_EC */ /* X509 certificates */ - lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, TRUE, (builder_function_t)openssl_x509_load); - lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, TRUE, (builder_function_t)openssl_crl_load); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 5817ade9e..0b607c386 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -131,19 +131,16 @@ error: return success; } -/** - * Implementation of openssl_rsa_private_key.get_type. - */ -static key_type_t get_type(private_openssl_rsa_private_key_t *this) + +METHOD(private_key_t, get_type, key_type_t, + private_openssl_rsa_private_key_t *this) { return KEY_RSA; } -/** - * Implementation of openssl_rsa_private_key.sign. - */ -static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) +METHOD(private_key_t, sign, bool, + private_openssl_rsa_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) { switch (scheme) { @@ -168,28 +165,47 @@ static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t sch } } -/** - * Implementation of openssl_rsa_private_key.decrypt. - */ -static bool decrypt(private_openssl_rsa_private_key_t *this, - chunk_t crypto, chunk_t *plain) +METHOD(private_key_t, decrypt, bool, + private_openssl_rsa_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) { - DBG1(DBG_LIB, "RSA private key decryption not implemented"); - return FALSE; + int padding, len; + char *decrypted; + + switch (scheme) + { + case ENCRYPT_RSA_PKCS1: + padding = RSA_PKCS1_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA1: + padding = RSA_PKCS1_OAEP_PADDING; + break; + default: + DBG1(DBG_LIB, "encryption scheme %N not supported via openssl", + encryption_scheme_names, scheme); + return FALSE; + } + decrypted = malloc(RSA_size(this->rsa)); + len = RSA_private_decrypt(crypto.len, crypto.ptr, decrypted, + this->rsa, padding); + if (len < 0) + { + DBG1(DBG_LIB, "RSA decryption failed"); + free(decrypted); + return FALSE; + } + *plain = chunk_create(decrypted, len); + return TRUE; } -/** - * Implementation of openssl_rsa_private_key.get_keysize. - */ -static size_t get_keysize(private_openssl_rsa_private_key_t *this) +METHOD(private_key_t, get_keysize, int, + private_openssl_rsa_private_key_t *this) { - return RSA_size(this->rsa); + return RSA_size(this->rsa) * 8; } -/** - * Implementation of openssl_rsa_private_key.get_public_key. - */ -static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this) +METHOD(private_key_t, get_public_key, public_key_t*, + private_openssl_rsa_private_key_t *this) { chunk_t enc; public_key_t *key; @@ -204,20 +220,16 @@ static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this) return key; } -/** - * Implementation of public_key_t.get_fingerprint. - */ -static bool get_fingerprint(private_openssl_rsa_private_key_t *this, - cred_encoding_type_t type, chunk_t *fingerprint) +METHOD(private_key_t, get_fingerprint, bool, + private_openssl_rsa_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) { return openssl_rsa_fingerprint(this->rsa, type, fingerprint); } -/* - * Implementation of public_key_t.get_encoding. - */ -static bool get_encoding(private_openssl_rsa_private_key_t *this, - cred_encoding_type_t type, chunk_t *encoding) +METHOD(private_key_t, get_encoding, bool, + private_openssl_rsa_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) { u_char *p; @@ -252,19 +264,15 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this, } } -/** - * Implementation of openssl_rsa_private_key.get_ref. - */ -static private_openssl_rsa_private_key_t* get_ref(private_openssl_rsa_private_key_t *this) +METHOD(private_key_t, get_ref, private_key_t*, + private_openssl_rsa_private_key_t *this) { ref_get(&this->ref); - return this; + return &this->public.key; } -/** - * Implementation of openssl_rsa_private_key.destroy. - */ -static void destroy(private_openssl_rsa_private_key_t *this) +METHOD(private_key_t, destroy, void, + private_openssl_rsa_private_key_t *this) { if (ref_put(&this->ref)) { @@ -280,25 +288,29 @@ static void destroy(private_openssl_rsa_private_key_t *this) /** * Internal generic constructor */ -static private_openssl_rsa_private_key_t *create_empty(void) +static private_openssl_rsa_private_key_t *create_empty() { - private_openssl_rsa_private_key_t *this = malloc_thing(private_openssl_rsa_private_key_t); - - this->public.interface.get_type = (key_type_t (*) (private_key_t*))get_type; - this->public.interface.sign = (bool (*) (private_key_t*, signature_scheme_t, chunk_t, chunk_t*))sign; - this->public.interface.decrypt = (bool (*) (private_key_t*, chunk_t, chunk_t*))decrypt; - this->public.interface.get_keysize = (size_t (*) (private_key_t*))get_keysize; - this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key; - this->public.interface.equals = private_key_equals; - this->public.interface.belongs_to = private_key_belongs_to; - this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint; - this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint; - this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding; - this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref; - this->public.interface.destroy = (void (*) (private_key_t*))destroy; - - this->engine = FALSE; - this->ref = 1; + private_openssl_rsa_private_key_t *this; + + INIT(this, + .public = { + .key = { + .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; } @@ -444,6 +456,48 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, } /** + * Login to engine with a PIN specified for a keyid + */ +static bool login(ENGINE *engine, chunk_t keyid) +{ + enumerator_t *enumerator; + shared_key_t *shared; + identification_t *id; + chunk_t key; + char pin[64]; + bool found = FALSE, success = FALSE; + + id = identification_create_from_encoding(ID_KEY_ID, keyid); + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, id, NULL); + while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + found = TRUE; + key = shared->get_key(shared); + if (snprintf(pin, sizeof(pin), "%.*s", key.len, key.ptr) >= sizeof(pin)) + { + continue; + } + if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) + { + success = TRUE; + break; + } + else + { + DBG1(DBG_CFG, "setting PIN on engine failed"); + } + } + enumerator->destroy(enumerator); + id->destroy(id); + if (!found) + { + DBG1(DBG_CFG, "no PIN found for %#B", &keyid); + } + return success; +} + +/** * See header. */ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, @@ -451,20 +505,25 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, { #ifndef OPENSSL_NO_ENGINE private_openssl_rsa_private_key_t *this; - char *keyid = NULL, *pin = NULL; + char *engine_id = NULL; + char keyname[64]; + chunk_t keyid = chunk_empty;; EVP_PKEY *key; - char *engine_id; ENGINE *engine; + int slot = -1; while (TRUE) { switch (va_arg(args, builder_part_t)) { - case BUILD_SMARTCARD_KEYID: - keyid = va_arg(args, char*); + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); continue; - case BUILD_SMARTCARD_PIN: - pin = va_arg(args, char*); + case BUILD_PKCS11_SLOT: + slot = va_arg(args, int); + continue; + case BUILD_PKCS11_MODULE: + engine_id = va_arg(args, char*); continue; case BUILD_END: break; @@ -473,17 +532,31 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, } break; } - if (!keyid || !pin) + if (!keyid.len || keyid.len > 40) { return NULL; } - engine_id = lib->settings->get_str(lib->settings, + memset(keyname, 0, sizeof(keyname)); + if (slot != -1) + { + snprintf(keyname, sizeof(keyname), "%d:", slot); + } + if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) + { + return NULL; + } + chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); + + if (!engine_id) + { + engine_id = lib->settings->get_str(lib->settings, "libstrongswan.plugins.openssl.engine_id", "pkcs11"); + } engine = ENGINE_by_id(engine_id); if (!engine) { - DBG1(DBG_LIB, "engine '%s' is not available", engine_id); + DBG2(DBG_LIB, "engine '%s' is not available", engine_id); return NULL; } if (!ENGINE_init(engine)) @@ -492,18 +565,17 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, ENGINE_free(engine); return NULL; } - if (!ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) + if (!login(engine, keyid)) { - DBG1(DBG_LIB, "failed to set PIN on engine '%s'", engine_id); + DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); ENGINE_free(engine); return NULL; } - - key = ENGINE_load_private_key(engine, keyid, NULL, NULL); + key = ENGINE_load_private_key(engine, keyname, NULL, NULL); if (!key) { DBG1(DBG_LIB, "failed to load private key with ID '%s' from " - "engine '%s'", keyid, engine_id); + "engine '%s'", keyname, engine_id); ENGINE_free(engine); return NULL; } @@ -512,6 +584,11 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, this = create_empty(); this->rsa = EVP_PKEY_get1_RSA(key); this->engine = TRUE; + if (!this->rsa) + { + destroy(this); + return NULL; + } return &this->public; #else /* OPENSSL_NO_ENGINE */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h index 079dfa46a..60889d651 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h @@ -34,7 +34,7 @@ struct openssl_rsa_private_key_t { /** * Implements private_key_t interface */ - private_key_t interface; + private_key_t key; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 6ac61a65c..422e31521 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -114,19 +114,15 @@ error: return valid; } -/** - * Implementation of public_key_t.get_type. - */ -static key_type_t get_type(private_openssl_rsa_public_key_t *this) +METHOD(public_key_t, get_type, key_type_t, + private_openssl_rsa_public_key_t *this) { return KEY_RSA; } -/** - * Implementation of public_key_t.verify. - */ -static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) +METHOD(public_key_t, verify, bool, + private_openssl_rsa_public_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t signature) { switch (scheme) { @@ -151,22 +147,43 @@ static bool verify(private_openssl_rsa_public_key_t *this, signature_scheme_t sc } } -/** - * Implementation of public_key_t.get_keysize. - */ -static bool encrypt_(private_openssl_rsa_public_key_t *this, - chunk_t crypto, chunk_t *plain) +METHOD(public_key_t, encrypt, bool, + private_openssl_rsa_public_key_t *this, encryption_scheme_t scheme, + chunk_t plain, chunk_t *crypto) { - DBG1(DBG_LIB, "RSA public key encryption not implemented"); - return FALSE; + int padding, len; + char *encrypted; + + switch (scheme) + { + case ENCRYPT_RSA_PKCS1: + padding = RSA_PKCS1_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA1: + padding = RSA_PKCS1_OAEP_PADDING; + break; + default: + DBG1(DBG_LIB, "decryption scheme %N not supported via openssl", + encryption_scheme_names, scheme); + return FALSE; + } + encrypted = malloc(RSA_size(this->rsa)); + len = RSA_public_encrypt(plain.len, plain.ptr, encrypted, + this->rsa, padding); + if (len < 0) + { + DBG1(DBG_LIB, "RSA decryption failed"); + free(encrypted); + return FALSE; + } + *crypto = chunk_create(encrypted, len); + return TRUE; } -/** - * Implementation of public_key_t.get_keysize. - */ -static size_t get_keysize(private_openssl_rsa_public_key_t *this) +METHOD(public_key_t, get_keysize, int, + private_openssl_rsa_public_key_t *this) { - return RSA_size(this->rsa); + return RSA_size(this->rsa) * 8; } /** @@ -211,20 +228,16 @@ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp) return TRUE; } -/** - * Implementation of public_key_t.get_fingerprint. - */ -static bool get_fingerprint(private_openssl_rsa_public_key_t *this, - cred_encoding_type_t type, chunk_t *fingerprint) +METHOD(public_key_t, get_fingerprint, bool, + private_openssl_rsa_public_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) { return openssl_rsa_fingerprint(this->rsa, type, fingerprint); } -/* - * Implementation of public_key_t.get_encoding. - */ -static bool get_encoding(private_openssl_rsa_public_key_t *this, - cred_encoding_type_t type, chunk_t *encoding) +METHOD(public_key_t, get_encoding, bool, + private_openssl_rsa_public_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) { u_char *p; @@ -262,19 +275,15 @@ static bool get_encoding(private_openssl_rsa_public_key_t *this, } } -/** - * Implementation of public_key_t.get_ref. - */ -static public_key_t* get_ref(private_openssl_rsa_public_key_t *this) +METHOD(public_key_t, get_ref, public_key_t*, + private_openssl_rsa_public_key_t *this) { ref_get(&this->ref); - return &this->public.interface; + return &this->public.key; } -/** - * Implementation of openssl_rsa_public_key.destroy. - */ -static void destroy(private_openssl_rsa_public_key_t *this) +METHOD(public_key_t, destroy, void, + private_openssl_rsa_public_key_t *this) { if (ref_put(&this->ref)) { @@ -292,21 +301,25 @@ static void destroy(private_openssl_rsa_public_key_t *this) */ static private_openssl_rsa_public_key_t *create_empty() { - private_openssl_rsa_public_key_t *this = malloc_thing(private_openssl_rsa_public_key_t); - - this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type; - this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify; - this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_; - this->public.interface.equals = public_key_equals; - this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize; - this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint; - this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint; - this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding; - this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref; - this->public.interface.destroy = (void (*)(public_key_t *this))destroy; - - this->rsa = NULL; - this->ref = 1; + private_openssl_rsa_public_key_t *this; + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .verify = _verify, + .encrypt = _encrypt, + .equals = public_key_equals, + .get_keysize = _get_keysize, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = public_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .ref = 1, + ); return this; } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h index 620aa51ce..021257d3c 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h @@ -33,7 +33,7 @@ struct openssl_rsa_public_key_t { /** * Implements the public_key_t interface */ - public_key_t interface; + public_key_t key; }; /** diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index b65388010..20f2fa984 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -124,13 +124,15 @@ openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo) } INIT(this, - .public.prf = { - .get_block_size = _get_block_size, - .get_bytes = _get_bytes, - .allocate_bytes = _allocate_bytes, - .get_key_size = _get_key_size, - .set_key = _set_key, - .destroy = _destroy, + .public = { + .prf = { + .get_block_size = _get_block_size, + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, }, ); diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index 1c9bb699e..aa39bc93d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -187,6 +187,15 @@ static identification_t *general_name2id(GENERAL_NAME *name) } case GEN_DIRNAME : return openssl_x509_name2id(name->d.directoryName); + case GEN_OTHERNAME: + if (OBJ_obj2nid(name->d.otherName->type_id) == NID_ms_upn && + name->d.otherName->value->type == V_ASN1_UTF8STRING) + { + return identification_create_from_encoding(ID_RFC822_ADDR, + openssl_asn1_str2chunk( + name->d.otherName->value->value.utf8string)); + } + return NULL; default: return NULL; } @@ -286,10 +295,23 @@ METHOD(certificate_t, has_subject, id_match_t, identification_t *current; enumerator_t *enumerator; id_match_t match, best; + chunk_t encoding; if (subject->get_type(subject) == ID_KEY_ID) { - if (chunk_equals(this->hash, subject->get_encoding(subject))) + encoding = subject->get_encoding(subject); + + if (chunk_equals(this->hash, encoding)) + { + return ID_MATCH_PERFECT; + } + if (this->subjectKeyIdentifier.len && + chunk_equals(this->subjectKeyIdentifier, encoding)) + { + return ID_MATCH_PERFECT; + } + if (this->pubkey && + this->pubkey->has_fingerprint(this->pubkey, encoding)) { return ID_MATCH_PERFECT; } @@ -756,6 +778,38 @@ static bool parse_extensions(private_openssl_x509_t *this) } /** + * Parse ExtendedKeyUsage + */ +static void parse_extKeyUsage(private_openssl_x509_t *this) +{ + EXTENDED_KEY_USAGE *usage; + int i; + + usage = X509_get_ext_d2i(this->x509, NID_ext_key_usage, NULL, NULL); + if (usage) + { + for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++) + { + switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i))) + { + case NID_server_auth: + this->flags |= X509_SERVER_AUTH; + break; + case NID_client_auth: + this->flags |= X509_CLIENT_AUTH; + break; + case NID_OCSP_sign: + this->flags |= X509_OCSP_SIGNER; + break; + default: + break; + } + } + sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free); + } +} + +/** * Parse a DER encoded x509 certificate */ static bool parse_certificate(private_openssl_x509_t *this) @@ -814,6 +868,7 @@ static bool parse_certificate(private_openssl_x509_t *this) { return TRUE; } + parse_extKeyUsage(this); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); if (!hasher) |