ECP_224_BIT = 26,
/** insecure NULL diffie hellman group for testing, in PRIVATE USE */
MODP_NULL = 1024,
- /** MODP group with custon generator, prime */
+ /** MODP group with custom generator/prime */
MODP_CUSTOM = 1025,
};
pkcs11_hasher.h pkcs11_hasher.c \
pkcs11_rng.h pkcs11_rng.c \
pkcs11_dh.h pkcs11_dh.c \
- pkcs11_ec_dh.h pkcs11_ec_dh.c \
pkcs11_manager.h pkcs11_manager.c
libstrongswan_pkcs11_la_LDFLAGS = -module -avoid-version
#include <debug.h>
#include <library.h>
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
#include "pkcs11_manager.h"
*/
chunk_t secret;
+ /**
+ * Mechanism to use to generate a key pair
+ */
+ CK_MECHANISM_TYPE mech_key;
+
+ /**
+ * Mechanism to use to derive a shared secret
+ */
+ CK_MECHANISM_TYPE mech_derive;
+
};
-METHOD(diffie_hellman_t, set_other_public_value, void,
- private_pkcs11_dh_t *this, chunk_t value)
+/**
+ * Derive a DH/ECDH shared secret.
+ *
+ * If this succeeds the shared secret is stored in this->secret.
+ */
+static void derive_secret(private_pkcs11_dh_t *this, chunk_t other)
{
CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
CK_KEY_TYPE type = CKK_GENERIC_SECRET;
{ CKA_KEY_TYPE, &type, sizeof(type) },
};
CK_MECHANISM mech = {
- CKM_DH_PKCS_DERIVE,
- value.ptr,
- value.len,
+ this->mech_derive,
+ other.ptr,
+ other.len,
};
CK_OBJECT_HANDLE secret;
CK_RV rv;
}
}
+METHOD(diffie_hellman_t, set_other_public_value, void,
+ private_pkcs11_dh_t *this, chunk_t value)
+{
+ switch (this->group)
+ {
+ case ECP_192_BIT:
+ case ECP_224_BIT:
+ case ECP_256_BIT:
+ case ECP_384_BIT:
+ case ECP_521_BIT:
+ { /* we expect the public value to just be the concatenated x and y
+ * coordinates, so we tag the value as an uncompressed ECPoint */
+ chunk_t tag = chunk_from_chars(0x04);
+ chunk_t pubkey = chunk_cata("cc", tag, value);
+ CK_ECDH1_DERIVE_PARAMS params = {
+ CKD_NULL,
+ 0,
+ NULL,
+ pubkey.len,
+ pubkey.ptr,
+ };
+
+ if (!lib->settings->get_bool(lib->settings,
+ "libstrongswan.ecp_x_coordinate_only", TRUE))
+ { /* we only get the x coordinate back */
+ return;
+ }
+ value = chunk_from_thing(params);
+ break;
+ }
+ default:
+ break;
+ }
+ derive_secret(this, value);
+}
+
METHOD(diffie_hellman_t, get_my_public_value, void,
private_pkcs11_dh_t *this, chunk_t *value)
{
}
/**
- * Generate DH key pair
+ * Generate a DH/ECDH key pair.
+ *
+ * If this succeeds, this->pri_key has a handle to the private key and
+ * this->pub_key stores the public key.
*/
-static bool generate_key_pair(private_pkcs11_dh_t *this, size_t exp_len,
- chunk_t g, chunk_t p)
+static bool generate_key_pair(private_pkcs11_dh_t *this, CK_ATTRIBUTE_PTR pub,
+ int pub_len, CK_ATTRIBUTE_PTR pri, int pri_len,
+ CK_ATTRIBUTE_TYPE attr)
{
- CK_ULONG bits = exp_len * 8;
- CK_ATTRIBUTE pub_attr[] = {
- { CKA_PRIME, p.ptr, p.len },
- { CKA_BASE, g.ptr, g.len },
- };
- CK_ATTRIBUTE pri_attr[] = {
- { CKA_VALUE_BITS, &bits, sizeof(bits) },
- };
CK_MECHANISM mech = {
- CKM_DH_PKCS_KEY_PAIR_GEN,
+ this->mech_key,
NULL,
0,
};
CK_OBJECT_HANDLE pub_key;
CK_RV rv;
- rv = this->lib->f->C_GenerateKeyPair(this->session, &mech, pub_attr,
- countof(pub_attr), pri_attr, countof(pri_attr),
- &pub_key, &this->pri_key);
+ rv = this->lib->f->C_GenerateKeyPair(this->session, &mech, pub, pub_len,
+ pri, pri_len, &pub_key, &this->pri_key);
if (rv != CKR_OK)
{
DBG1(DBG_CFG, "C_GenerateKeyPair() error: %N", ck_rv_names, rv);
return FALSE;
}
-
if (!this->lib->get_ck_attribute(this->lib, this->session, pub_key,
- CKA_VALUE, &this->pub_key))
+ attr, &this->pub_key))
{
chunk_free(&this->pub_key);
return FALSE;
}
/**
- * Find a token we can use for DH algorithm
+ * Generate DH key pair.
+ */
+static bool generate_key_pair_modp(private_pkcs11_dh_t *this, size_t exp_len,
+ chunk_t g, chunk_t p)
+{
+ CK_ATTRIBUTE pub_attr[] = {
+ { CKA_PRIME, p.ptr, p.len },
+ { CKA_BASE, g.ptr, g.len },
+ };
+ CK_ULONG bits = exp_len * 8;
+ CK_ATTRIBUTE pri_attr[] = {
+ { CKA_VALUE_BITS, &bits, sizeof(bits) },
+ };
+ return generate_key_pair(this, pub_attr, countof(pub_attr), pri_attr,
+ countof(pri_attr), CKA_VALUE);
+}
+
+/**
+ * Generate ECDH key pair.
*/
-static pkcs11_library_t *find_token(CK_SESSION_HANDLE *session)
+static bool generate_key_pair_ecp(private_pkcs11_dh_t *this,
+ chunk_t ecparams)
+{
+ CK_ATTRIBUTE pub_attr[] = {
+ { CKA_EC_PARAMS, ecparams.ptr, ecparams.len },
+ };
+ if (!generate_key_pair(this, pub_attr, countof(pub_attr), NULL, 0,
+ CKA_EC_POINT))
+ {
+ return FALSE;
+ }
+ if (this->pub_key.len <= 0 || this->pub_key.ptr[0] != 0x04)
+ { /* we currently only support the point in uncompressed form which
+ * looks like this: 0x04 || x || y */
+ chunk_clear(&this->pub_key);
+ return FALSE;
+ }
+ this->pub_key = chunk_skip(this->pub_key, 1);
+ return TRUE;
+}
+
+/**
+ * Find a token we can use for DH/ECDH algorithm
+ */
+static pkcs11_library_t *find_token(private_pkcs11_dh_t *this,
+ CK_SESSION_HANDLE *session)
{
enumerator_t *tokens, *mechs;
pkcs11_manager_t *manager;
{
mechs = current->create_mechanism_enumerator(current, slot);
while (mechs->enumerate(mechs, &type, NULL))
- {
- /* we assume CKM_DH_PKCS_DERIVE is supported too */
- if (type == CKM_DH_PKCS_KEY_PAIR_GEN)
+ { /* we assume we can generate key pairs if the derive mechanism
+ * is supported */
+ if (type == this->mech_derive)
{
if (current->f->C_OpenSession(slot, CKF_SERIAL_SESSION,
NULL, NULL, session) == CKR_OK)
return found;
}
-/*
+/**
* Generic internal constructor
*/
-pkcs11_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
- chunk_t g, chunk_t p)
+static private_pkcs11_dh_t *create_generic(diffie_hellman_group_t group,
+ CK_MECHANISM_TYPE key,
+ CK_MECHANISM_TYPE derive)
{
private_pkcs11_dh_t *this;
},
},
.group = group,
+ .mech_key = key,
+ .mech_derive = derive,
);
- this->lib = find_token(&this->session);
+ this->lib = find_token(this, &this->session);
if (!this->lib)
{
free(this);
return NULL;
}
+ return this;
+}
- if (!generate_key_pair(this, exp_len, g, p))
+static pkcs11_dh_t *create_ecp(diffie_hellman_group_t group, chunk_t ecparam)
+{
+ private_pkcs11_dh_t *this = create_generic(group, CKM_EC_KEY_PAIR_GEN,
+ CKM_ECDH1_DERIVE);
+
+ if (this)
{
+ if (generate_key_pair_ecp(this, ecparam))
+ {
+ return &this->public;
+ }
free(this);
- return NULL;
}
- return &this->public;
+ return NULL;
}
-
-/*
- * Described in header.
+/**
+ * Constructor for MODP DH
*/
-pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group,
- chunk_t g, chunk_t p)
+static pkcs11_dh_t *create_modp(diffie_hellman_group_t group, size_t exp_len,
+ chunk_t g, chunk_t p)
{
- diffie_hellman_params_t *params;
+ private_pkcs11_dh_t *this = create_generic(group, CKM_DH_PKCS_KEY_PAIR_GEN,
+ CKM_DH_PKCS_DERIVE);
+
+ if (this)
+ {
+ if (generate_key_pair_modp(this, exp_len, g, p))
+ {
+ return &this->public;
+ }
+ free(this);
+ }
+ return NULL;
+}
- if (group == MODP_CUSTOM)
+/**
+ * Lookup the EC params for the given group.
+ */
+static chunk_t ecparams_lookup(diffie_hellman_group_t group)
+{
+ switch (group)
{
- return create_generic(group, p.len, g, p);
+ case ECP_192_BIT:
+ return asn1_build_known_oid(OID_PRIME192V1);
+ case ECP_224_BIT:
+ return asn1_build_known_oid(OID_SECT224R1);
+ case ECP_256_BIT:
+ return asn1_build_known_oid(OID_PRIME256V1);
+ case ECP_384_BIT:
+ return asn1_build_known_oid(OID_SECT384R1);
+ case ECP_521_BIT:
+ return asn1_build_known_oid(OID_SECT521R1);
+ default:
+ break;
}
+ return chunk_empty;
+}
- params = diffie_hellman_get_params(group);
- if (!params)
+/**
+ * Described in header.
+ */
+pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group,
+ chunk_t g, chunk_t p)
+{
+ switch (group)
{
- return NULL;
+ case MODP_CUSTOM:
+ {
+ return create_modp(group, p.len, g, p);
+ }
+ case ECP_192_BIT:
+ case ECP_224_BIT:
+ case ECP_256_BIT:
+ case ECP_384_BIT:
+ case ECP_521_BIT:
+ {
+ chunk_t params = ecparams_lookup(group);
+ if (params.ptr)
+ {
+ return create_ecp(group, params);
+ }
+ break;
+ }
+ default:
+ {
+ diffie_hellman_params_t *params = diffie_hellman_get_params(group);
+ if (params)
+ {
+ return create_modp(group, params->exp_len, params->generator,
+ params->prime);
+ }
+ break;
+ }
}
- return create_generic(group, params->exp_len,
- params->generator, params->prime);
+ return NULL;
}
+++ /dev/null
-/*
- * Copyright (C) 2011 Tobias Brunner
- * 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 "pkcs11_ec_dh.h"
-
-#include <debug.h>
-#include <library.h>
-#include <chunk.h>
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
-
-#include "pkcs11_manager.h"
-
-typedef struct private_pkcs11_ec_dh_t private_pkcs11_ec_dh_t;
-
-/**
- * Private data of an pkcs11_ec_dh_t object.
- */
-struct private_pkcs11_ec_dh_t {
-
- /**
- * Public pkcs11_ec_dh_t interface
- */
- pkcs11_ec_dh_t public;
-
- /**
- * PKCS#11 library
- */
- pkcs11_library_t *lib;
-
- /**
- * Session handle for this objct
- */
- CK_SESSION_HANDLE session;
-
- /**
- * Diffie Hellman group number.
- */
- u_int16_t group;
-
- /**
- * EC params (DER-encoded ANSI x9.62 Parameters value)
- */
- chunk_t ecparams;
-
- /**
- * Handle for own private value
- */
- CK_OBJECT_HANDLE pri_key;
-
- /**
- * Own public value
- */
- chunk_t pub_key;
-
- /**
- * Shared secret
- */
- chunk_t secret;
-
-};
-
-METHOD(diffie_hellman_t, set_other_public_value, void,
- private_pkcs11_ec_dh_t *this, chunk_t value)
-{
- chunk_t pubkey = chunk_alloca(value.len + 1);
- CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
- CK_KEY_TYPE type = CKK_GENERIC_SECRET;
- CK_ATTRIBUTE attr[] = {
- { CKA_CLASS, &klass, sizeof(klass) },
- { CKA_KEY_TYPE, &type, sizeof(type) },
- };
- CK_ECDH1_DERIVE_PARAMS params = {
- CKD_NULL,
- 0,
- NULL,
- pubkey.len,
- pubkey.ptr,
- };
- CK_MECHANISM mech = {
- CKM_ECDH1_DERIVE,
- ¶ms,
- sizeof(params),
- };
- CK_OBJECT_HANDLE secret;
- CK_RV rv;
-
- if (!lib->settings->get_bool(lib->settings,
- "libstrongswan.ecp_x_coordinate_only", TRUE))
- { /* we only get the x coordinate back */
- return;
- }
-
- /* we expect the public value to just be the concatenated x and y
- * coordinates, so we have to specify that it is an uncompressed ECPoint */
- pubkey.ptr[0] = 0x04;
- memcpy(pubkey.ptr + 1, value.ptr, value.len);
-
- rv = this->lib->f->C_DeriveKey(this->session, &mech, this->pri_key,
- attr, countof(attr), &secret);
- if (rv != CKR_OK)
- {
- DBG1(DBG_CFG, "C_DeriveKey() error: %N", ck_rv_names, rv);
- return;
- }
- if (!this->lib->get_ck_attribute(this->lib, this->session, secret,
- CKA_VALUE, &this->secret))
- {
- chunk_free(&this->secret);
- return;
- }
-}
-
-METHOD(diffie_hellman_t, get_my_public_value, void,
- private_pkcs11_ec_dh_t *this, chunk_t *value)
-{
- *value = chunk_clone(this->pub_key);
-}
-
-METHOD(diffie_hellman_t, get_shared_secret, status_t,
- private_pkcs11_ec_dh_t *this, chunk_t *secret)
-{
- if (!this->secret.ptr)
- {
- return FAILED;
- }
- *secret = chunk_clone(this->secret);
- return SUCCESS;
-}
-
-METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
- private_pkcs11_ec_dh_t *this)
-{
- return this->group;
-}
-
-METHOD(diffie_hellman_t, destroy, void,
- private_pkcs11_ec_dh_t *this)
-{
- this->lib->f->C_CloseSession(this->session);
- chunk_clear(&this->pub_key);
- chunk_clear(&this->secret);
- free(this);
-}
-
-/**
- * Generate ECDH key pair
- */
-static bool generate_key_pair(private_pkcs11_ec_dh_t *this)
-{
- CK_ATTRIBUTE pub_attr[] = {
- { CKA_EC_PARAMS, this->ecparams.ptr, this->ecparams.len },
- };
- CK_MECHANISM mech = {
- CKM_EC_KEY_PAIR_GEN,
- NULL,
- 0,
- };
- CK_OBJECT_HANDLE pub_key;
- CK_RV rv;
-
- rv = this->lib->f->C_GenerateKeyPair(this->session, &mech, pub_attr,
- countof(pub_attr), NULL, 0, &pub_key,
- &this->pri_key);
- if (rv != CKR_OK)
- {
- DBG1(DBG_CFG, "C_GenerateKeyPair() error: %N", ck_rv_names, rv);
- return FALSE;
- }
-
- if (!this->lib->get_ck_attribute(this->lib, this->session, pub_key,
- CKA_EC_POINT, &this->pub_key))
- {
- chunk_free(&this->pub_key);
- return FALSE;
- }
- if (this->pub_key.len <= 0 || this->pub_key.ptr[0] != 0x04)
- { /* we currently only support the point in uncompressed form which
- * looks like this: 0x04 || x || y */
- chunk_clear(&this->pub_key);
- return FALSE;
- }
- this->pub_key = chunk_skip(this->pub_key, 1);
- return TRUE;
-}
-
-/**
- * Find a token we can use for DH algorithm
- */
-static pkcs11_library_t *find_token(CK_SESSION_HANDLE *session)
-{
- enumerator_t *tokens, *mechs;
- pkcs11_manager_t *manager;
- pkcs11_library_t *current, *found = NULL;
- CK_MECHANISM_TYPE type;
- CK_SLOT_ID slot;
-
- manager = lib->get(lib, "pkcs11-manager");
- if (!manager)
- {
- return NULL;
- }
- tokens = manager->create_token_enumerator(manager);
- while (tokens->enumerate(tokens, ¤t, &slot))
- {
- mechs = current->create_mechanism_enumerator(current, slot);
- while (mechs->enumerate(mechs, &type, NULL))
- {
- /* we assume CKM_EC_KEY_PAIR_GEN is supported too */
- if (type == CKM_ECDH1_DERIVE)
- {
- if (current->f->C_OpenSession(slot, CKF_SERIAL_SESSION,
- NULL, NULL, session) == CKR_OK)
- {
- found = current;
- break;
- }
- }
- }
- mechs->destroy(mechs);
- if (found)
- {
- break;
- }
- }
- tokens->destroy(tokens);
- return found;
-}
-
-/**
- * Lookup the EC params matching the given group
- */
-static chunk_t lookup_ecparams(diffie_hellman_group_t group)
-{
- switch (group)
- {
- case ECP_192_BIT:
- return asn1_build_known_oid(OID_PRIME192V1);
- case ECP_224_BIT:
- return asn1_build_known_oid(OID_SECT224R1);
- case ECP_256_BIT:
- return asn1_build_known_oid(OID_PRIME256V1);
- case ECP_384_BIT:
- return asn1_build_known_oid(OID_SECT384R1);
- case ECP_521_BIT:
- return asn1_build_known_oid(OID_SECT521R1);
- default:
- break;
- }
- return chunk_empty;
-}
-
-/*
- * Described in header.
- */
-pkcs11_ec_dh_t *pkcs11_ec_dh_create(diffie_hellman_group_t group)
-{
- private_pkcs11_ec_dh_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,
- );
-
- this->ecparams = lookup_ecparams(group);
- if (!this->ecparams.ptr)
- {
- free(this);
- return NULL;
- }
-
- this->lib = find_token(&this->session);
- if (!this->lib)
- {
- free(this);
- return NULL;
- }
-
- if (!generate_key_pair(this))
- {
- free(this);
- return NULL;
- }
- return &this->public;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011 Tobias Brunner
- * 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 pkcs11_ec_dh pkcs11_ec_dh
- * @{ @ingroup pkcs11_p
- */
-
-#ifndef PKCS11_EC_DH_H_
-#define PKCS11_EC_DH_H_
-
-typedef struct pkcs11_ec_dh_t pkcs11_ec_dh_t;
-
-#include <library.h>
-
-/**
- * Implementation of the EC Diffie-Hellman algorithm via PKCS#11.
- */
-struct pkcs11_ec_dh_t {
-
- /**
- * Implements diffie_hellman_t interface.
- */
- diffie_hellman_t dh;
-};
-
-/**
- * Creates a new pkcs11_ec_dh_t object.
- *
- * @param group EC Diffie Hellman group number to use
- * @return pkcs11_ec_dh_t object, NULL if not supported
- */
-pkcs11_ec_dh_t *pkcs11_ec_dh_create(diffie_hellman_group_t group);
-
-#endif /** PKCS11_EC_DH_H_ @}*/
-
#include "pkcs11_hasher.h"
#include "pkcs11_rng.h"
#include "pkcs11_dh.h"
-#include "pkcs11_ec_dh.h"
typedef struct private_pkcs11_plugin_t private_pkcs11_plugin_t;
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
};
static plugin_feature_t f_ecdh[] = {
- PLUGIN_REGISTER(DH, pkcs11_ec_dh_create),
+ PLUGIN_REGISTER(DH, pkcs11_dh_create),
PLUGIN_PROVIDE(DH, ECP_192_BIT),
PLUGIN_PROVIDE(DH, ECP_224_BIT),
PLUGIN_PROVIDE(DH, ECP_256_BIT),