[pkg-opensc-commit] [libp11] 06/86: More OpenSSL 1.1 changes and improved error handling for ECDH
Eric Dorland
eric at moszumanska.debian.org
Sun Jul 24 21:40:17 UTC 2016
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository libp11.
commit 2c6af01c264874d5968fcebb6ef035ccda9599bc
Author: Doug Engert <deengert at gmail.com>
Date: Tue Jan 19 10:02:26 2016 -0600
More OpenSSL 1.1 changes and improved error handling for ECDH
libp11.h includes pkcs11.h The CK_ECDH1_DERIVE_PARAMS structure
is defined in the OpenSC version of pkcs11.h.
This could be changed if the PKCS11_ecdh_derive was change to accept the
6 values in the structure inline.
Better error handling.
---
src/libp11.exports | 1 +
src/libp11.h | 19 ++++++++++
src/p11_ec.c | 105 ++++++++++++++++++++++++++++++++++++++++++++---------
src/p11_err.c | 1 +
src/p11_ops.c | 90 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 198 insertions(+), 18 deletions(-)
diff --git a/src/libp11.exports b/src/libp11.exports
index 95213b6..6363e0e 100644
--- a/src/libp11.exports
+++ b/src/libp11.exports
@@ -40,3 +40,4 @@ PKCS11_get_ecdsa_method
PKCS11_ecdsa_method_free
ERR_load_PKCS11_strings
PKCS11_get_ec_key_method
+PKCS11_ecdh_derive
diff --git a/src/libp11.h b/src/libp11.h
index 3a6867f..c76ca44 100644
--- a/src/libp11.h
+++ b/src/libp11.h
@@ -30,6 +30,7 @@
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
+#include <pkcs11.h>
#ifdef __cplusplus
extern "C" {
@@ -387,6 +388,23 @@ extern int PKCS11_store_certificate(PKCS11_TOKEN * token, X509 * x509,
extern int PKCS11_ecdsa_sign(const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, PKCS11_KEY * key);
+#if OPENSSL_VERSION_NUMBER >= 0x10100002L
+/**
+ * @param out returned secret
+ * @param outlen length of returned secret
+ * @param ecdh_mechanism CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE or others in future
+ * @param ec_params ptr to CK_ECDH1_DERIVE_PARAMS or in future CK_ECMQV_DERIVE_PARAMS
+ * @param outnewkey ptr to CK_OBJECT_HANDLE
+ * @param key private key object
+ */
+
+extern int PKCS11_ecdh_derive(unsigned char **out, size_t *out_len,
+ const unsigned long ecdh_mechanism,
+ const void * ec_params,
+ CK_OBJECT_HANDLE * outnewkey,
+ PKCS11_KEY * key);
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100002L */
+
/* rsa private key operations */
extern int PKCS11_sign(int type, const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, PKCS11_KEY * key);
@@ -459,6 +477,7 @@ extern void ERR_load_PKCS11_strings(void);
#define PKCS11_F_PKCS11_EC_KEY_SIGN 41
#define PKCS11_F_PKCS11_EC_KEY_VERIFY 42
#define PKCS11_F_PKCS11_GETSESSIONINFO 43
+#define PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY 44
#define PKCS11_ERR_BASE 1024
#define PKCS11_LOAD_MODULE_ERROR (PKCS11_ERR_BASE+1)
diff --git a/src/p11_ec.c b/src/p11_ec.c
index a3c5486..5895a26 100644
--- a/src/p11_ec.c
+++ b/src/p11_ec.c
@@ -1,7 +1,7 @@
/* libp11, a simple layer on to of PKCS#11 API
* Copyright (C) 2005 Olaf Kirch <okir at lst.de>
* Copyright (C) 2011, 2013 Douglas E. Engert <deengert at anl.gov>
- * Copyright (C) 2014 Douglas E. Engert <deengert at gmail.com>
+ * Copyright (C) 2014, 2016 Douglas E. Engert <deengert at gmail.com>
* Copyright (C) 2016 Michał Trojnara <Michal.Trojnara at stunnel.org>
*
* This library is free software; you can redistribute it and/or
@@ -209,10 +209,11 @@ static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen,
if (sig) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
/*
- * OpenSSL 1.1 does not have a way to alloc r and s
- * the BN in ECDSA_SIG as it is now hidden.
- * Will us dummy ASN1 seq to set it, then
- * ECDSA_SIG_get0 to get access to r and s
+ * OpenSSL 1.1 does not have a way to allocate r and s
+ * in ECDSA_SIG as it is now hidden.
+ * Will us dummy ASN1 so r and s are allocated then
+ * use ECDSA_SIG_get0 to get access to r and s
+ * can then update r annd s
*/
const unsigned char *a;
unsigned char dasn1[8] =
@@ -227,18 +228,6 @@ static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen,
#else
BN_bin2bn(&sigret[0], nLen, sig->r);
BN_bin2bn(&sigret[nLen], nLen, sig->s);
-#if 0
-/* TODO remove this gdb debugging */
- {
- int ilen = 0;
- unsigned char tmpsigbuff[512];
- unsigned char **tmpsig = &tmpsigbuff;
-
- ilen = i2d_ECDSA_SIG(sig,NULL);
- ilen = i2d_ECDSA_SIG(sig, tmpsig);
- printf("ilen=&d\n",ilen);
- }
-#endif
#endif
}
}
@@ -246,6 +235,85 @@ static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen,
}
#if OPENSSL_VERSION_NUMBER >= 0x10100002L
+/* Our version of the ossl_ecdh_compute_key replaced in the EC_KEY_METHOD */
+static int pkcs11_ec_ckey(void *out,
+ size_t outlen,
+ const EC_POINT *ecpointpeer,
+ const EC_KEY *ecdh,
+ void *(*KDF) (const void *in,
+ size_t inlen,
+ void *out,
+ size_t *outlen))
+{
+ int ret = -1;
+ size_t buflen;
+ unsigned char *buf = NULL;
+ size_t peerbuflen;
+ unsigned char *peerbuf = NULL;
+ const EC_GROUP *ecgroup = NULL;
+ const EC_POINT *ecpoint = NULL;
+ CK_ECDH1_DERIVE_PARAMS ecdh_parms;
+ PKCS11_KEY * key = NULL;
+
+ key = (PKCS11_KEY *) EC_KEY_get_ex_data(ecdh, ec_key_ex_index);
+
+ if (key == NULL) {
+ ret -1;
+ goto err;
+ }
+
+ /* assume both peer and ecdh are same group */
+ ecgroup = EC_KEY_get0_group(ecdh);
+ buflen = (EC_GROUP_get_degree(ecgroup) + 7) / 8;
+
+ buf = OPENSSL_malloc(buflen);
+ if (buf == NULL) {
+ ret = -1;
+ goto err;
+ }
+
+ peerbuflen = 2*buflen + 1;
+ peerbuf = OPENSSL_malloc(peerbuflen);
+ if (peerbuf == NULL) {
+ ret = -1;
+ goto err;
+ }
+
+ ecdh_parms.kdf = CKD_NULL;
+ ecdh_parms.ulSharedDataLen = 0;
+ ecdh_parms.pSharedData = NULL;
+ ecdh_parms.ulPublicDataLen = peerbuflen;
+ ret = EC_POINT_point2oct(ecgroup,
+ ecpointpeer,
+ POINT_CONVERSION_UNCOMPRESSED,
+ peerbuf, peerbuflen,NULL);
+ ecdh_parms.ulPublicDataLen = peerbuflen;
+ ecdh_parms.pPublicData = peerbuf;
+
+
+ ret = PKCS11_ecdh_derive(&buf, &buflen, CKM_ECDH1_DERIVE,
+ (const void *)&ecdh_parms, NULL, key);
+
+ if (KDF != 0) {
+ if (KDF(buf, buflen, out, &outlen) == NULL) {
+ ret -1;
+ goto err;
+ }
+ ret = outlen;
+ } else {
+ if (outlen > buflen)
+ outlen = buflen;
+ memcpy(out, buf, outlen);
+ ret = outlen;
+ }
+err:
+ OPENSSL_free(buf);
+ return (ret);
+}
+#endif
+
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100002L
static void alloc_ec_key_ex_index() {
if (ec_key_ex_index == 0) {
while (ec_key_ex_index == 0) /* Workaround for OpenSSL RT3710 */
@@ -319,10 +387,11 @@ EC_KEY_METHOD *PKCS11_get_ec_key_method(void)
EC_KEY_METHOD_get_sign(ops, &orig_sign,
&orig_sign_setup, &orig_sign_sig);
-/* TODO look at which routines to use */
EC_KEY_METHOD_set_sign(ops, orig_sign,
pkcs11_ecdsa_sign_setup,
pkcs11_ecdsa_do_sign);
+
+ EC_KEY_METHOD_set_compute_key(ops, pkcs11_ec_ckey);
}
return ops;
}
diff --git a/src/p11_err.c b/src/p11_err.c
index 7fb987e..46a9f80 100644
--- a/src/p11_err.c
+++ b/src/p11_err.c
@@ -47,6 +47,7 @@ static ERR_STRING_DATA PKCS11_str_functs[] = {
{ERR_PACK(0, PKCS11_F_PKCS11_STORE_PUBLIC_KEY, 0), "PKCS11_store_public_key"},
{ERR_PACK(0, PKCS11_F_PKCS11_STORE_CERTIFICATE, 0), "PKCS11_store_certificate"},
{ERR_PACK(0, PKCS11_F_PKCS11_CHANGE_PIN, 0), "PKCS11_change_pin"},
+ {ERR_PACK(0, PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, 0), "PKCS11_ecdh_derive"},
{0, NULL}
};
diff --git a/src/p11_ops.c b/src/p11_ops.c
index 516bdec..d537170 100644
--- a/src/p11_ops.c
+++ b/src/p11_ops.c
@@ -25,6 +25,96 @@
#include <openssl/ossl_typ.h>
#include <openssl/asn1.h>
+#if OPENSSL_VERSION_NUMBER >= 0x10100002L
+/* initial code will only support what what is needed for engine
+ * i.e. CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE
+ * and CK_EC_KDF_TYPE supported by token
+ */
+extern int PKCS11_ecdh_derive(unsigned char **out, size_t *outlen,
+ const unsigned long ecdh_mechanism,
+ const void * ec_params,
+ CK_OBJECT_HANDLE *outnewkey,
+ PKCS11_KEY * key)
+{
+ int rv;
+ PKCS11_KEY_private *priv;
+ PKCS11_SLOT *slot;
+ PKCS11_CTX *ctx;
+ PKCS11_TOKEN *token;
+ CK_SESSION_HANDLE session;
+ CK_MECHANISM mechanism;
+
+ CK_BBOOL true = TRUE;
+ CK_BBOOL false = FALSE;
+ CK_OBJECT_HANDLE newkey;
+ CK_OBJECT_CLASS newkey_class= CKO_SECRET_KEY;
+ CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE newkey_template[] = {
+ {CKA_TOKEN, &false, sizeof(false)}, /* session only object */
+ {CKA_CLASS, &newkey_class, sizeof(newkey_class)},
+ {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
+ {CKA_ENCRYPT, &true, sizeof(true)},
+ {CKA_DECRYPT, &true, sizeof(true)}
+ };
+
+ ctx = KEY2CTX(key);
+ priv = PRIVKEY(key);
+ token = KEY2TOKEN(key);
+ slot = KEY2SLOT(key);
+
+ CHECK_KEY_FORK(key);
+
+ session = PRIVSLOT(slot)->session;
+
+ memset(&mechanism, 0, sizeof(mechanism));
+ mechanism.mechanism = ecdh_mechanism;
+ mechanism.pParameter = (void*)ec_params;
+ switch (ecdh_mechanism) {
+ case CKM_ECDH1_DERIVE:
+ case CKM_ECDH1_COFACTOR_DERIVE:
+ mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
+ break;
+// case CK_ECMQV_DERIVE_PARAMS:
+// mechanism.ulParameterLen = sizeof(CK_ECMQV_DERIVE_PARAMS);
+// break;
+ default:
+ PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, PKCS11_NOT_SUPPORTED);
+ return -1;
+ }
+
+ CRYPTO_w_lock(PRIVSLOT(slot)->lockid);
+ rv = CRYPTOKI_call(ctx, C_DeriveKey(session, &mechanism, priv->object, newkey_template, 5, &newkey));
+ if (rv) {
+ PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(rv));
+ return -1;
+ }
+
+ /* if requested copy new secret key value */
+ /* TODO for now engine only we will assume caller provided big enough out buffer */
+ /* for libp11, we could return the secret key object, slot and session somehow. */
+ /* that would require keeping track of secret key objects too. */
+ /* we need to handle the secret object so we can free it. */
+
+ if (out && outlen) {
+ if (*out == NULL
+ && !pkcs11_getattr_var(token, newkey, CKA_VALUE, NULL, outlen)
+ && *outlen > 0) {
+ *out = OPENSSL_malloc(*outlen);
+ }
+
+ if (*out) {
+ pkcs11_getattr_var(token, newkey, CKA_VALUE, *out, outlen);
+ }
+ }
+
+ if (outnewkey) {
+ *outnewkey = newkey;
+ } /* TODO else free newkey */
+
+ return 1;
+}
+#endif
+
int
PKCS11_ecdsa_sign(const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, PKCS11_KEY * key)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/libp11.git
More information about the pkg-opensc-commit
mailing list