Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
0 contributors

Users who have contributed to this file

diff -ru openssh-7.6p1.orig/ssh-pkcs11-client.c openssh-7.6p1/ssh-pkcs11-client.c
--- openssh-7.6p1.orig/ssh-pkcs11-client.c 2017-10-02 12:34:26.000000000 -0700
+++ openssh-7.6p1/ssh-pkcs11-client.c 2017-11-24 23:21:57.000000000 -0800
@@ -31,6 +31,14 @@
#include <errno.h>
#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW))
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
#include "pathnames.h"
#include "xmalloc.h"
@@ -139,9 +147,9 @@
return (ret);
}
-/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
+/* redirect the RSA private key encrypt operation to the ssh-pkcs11-helper */
static int
-wrap_key(RSA *rsa)
+wrap_rsa_key(RSA *rsa)
{
static RSA_METHOD helper_rsa;
@@ -152,6 +160,67 @@
return (0);
}
+#ifdef ENABLE_PKCS11_ECDSA
+static ECDSA_SIG *
+pkcs11_ecdsa_private_sign(const unsigned char *from, int flen,
+ const BIGNUM *inv, const BIGNUM *r, EC_KEY * ecdsa)
+{
+ Key key;
+ u_char *blob, *signature = NULL;
+ u_int blen, slen = 0;
+ Buffer msg;
+ ECDSA_SIG *ret = NULL;
+
+ key.type = KEY_ECDSA;
+ key.ecdsa = ecdsa;
+ key.ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
+ if (key_to_blob(&key, &blob, &blen) == 0)
+ return NULL;
+ buffer_init(&msg);
+ buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
+ buffer_put_string(&msg, blob, blen);
+ buffer_put_string(&msg, from, flen);
+ buffer_put_int(&msg, 0);
+ free(blob);
+ send_msg(&msg);
+ buffer_clear(&msg);
+
+ if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) {
+ signature = buffer_get_string(&msg, &slen);
+ if (slen <= (u_int)ECDSA_size(ecdsa)) {
+ int nlen = slen / 2;
+ ret = ECDSA_SIG_new();
+ BN_bin2bn(&signature[0], nlen, ret->r);
+ BN_bin2bn(&signature[nlen], nlen, ret->s);
+ }
+ free(signature);
+ }
+ buffer_free(&msg);
+ return (ret);
+}
+
+/* redirect the ECDSA private key encrypt operation to the ssh-pkcs11-helper */
+static int
+wrap_ecdsa_key(EC_KEY *ecdsa) {
+ static ECDSA_METHOD *helper_ecdsa = NULL;
+ if(helper_ecdsa == NULL) {
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
+#ifdef ECDSA_F_ECDSA_METHOD_NEW
+ helper_ecdsa = ECDSA_METHOD_new((ECDSA_METHOD *)def);
+ ECDSA_METHOD_set_name(helper_ecdsa, "ssh-pkcs11-helper-ecdsa");
+ ECDSA_METHOD_set_sign(helper_ecdsa, pkcs11_ecdsa_private_sign);
+#else
+ helper_ecdsa = xcalloc(1, sizeof(*helper_ecdsa));
+ memcpy(helper_ecdsa, def, sizeof(*helper_ecdsa));
+ helper_ecdsa->name = "ssh-pkcs11-helper-ecdsa";
+ helper_ecdsa->ecdsa_do_sign = pkcs11_ecdsa_private_sign;
+#endif
+ }
+ ECDSA_set_method(ecdsa, helper_ecdsa);
+ return (0);
+}
+#endif
+
static int
pkcs11_start_helper(void)
{
@@ -209,7 +278,15 @@
blob = buffer_get_string(&msg, &blen);
free(buffer_get_string(&msg, NULL));
k = key_from_blob(blob, blen);
- wrap_key(k->rsa);
+ if(k->type == KEY_RSA) {
+ wrap_rsa_key(k->rsa);
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(k->type == KEY_ECDSA) {
+ wrap_ecdsa_key(k->ecdsa);
+#endif /* ENABLE_PKCS11_ECDSA */
+ } else {
+ /* Unsupported type */
+ }
(*keysp)[i] = k;
free(blob);
}
diff -ru openssh-7.6p1.orig/ssh-pkcs11-helper.c openssh-7.6p1/ssh-pkcs11-helper.c
--- openssh-7.6p1.orig/ssh-pkcs11-helper.c 2017-10-02 12:34:26.000000000 -0700
+++ openssh-7.6p1/ssh-pkcs11-helper.c 2017-11-24 23:21:57.000000000 -0800
@@ -24,6 +24,16 @@
#include "openbsd-compat/sys-queue.h"
+#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW))
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
+
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
@@ -80,7 +90,7 @@
if (!strcmp(ki->providername, name)) {
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
free(ki->providername);
- key_free(ki->key);
+ pkcs11_del_key(ki->key);
free(ki);
}
}
@@ -180,14 +190,31 @@
if ((key = key_from_blob(blob, blen)) != NULL) {
if ((found = lookup_key(key)) != NULL) {
#ifdef WITH_OPENSSL
- int ret;
-
- slen = RSA_size(key->rsa);
- signature = xmalloc(slen);
- if ((ret = RSA_private_encrypt(dlen, data, signature,
- found->rsa, RSA_PKCS1_PADDING)) != -1) {
- slen = ret;
- ok = 0;
+ if(found->type == KEY_RSA) {
+ int ret;
+ slen = RSA_size(key->rsa);
+ signature = xmalloc(slen);
+ if ((ret = RSA_private_encrypt(dlen, data, signature,
+ found->rsa, RSA_PKCS1_PADDING)) != -1) {
+ slen = ret;
+ ok = 0;
+ }
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(found->type == KEY_ECDSA) {
+ ECDSA_SIG *sig = NULL;
+ if ((sig = ECDSA_do_sign(data, dlen, found->ecdsa)) != NULL) {
+ int rlen = BN_num_bytes(sig->r);
+ slen = BN_num_bytes(sig->s);
+ signature = xmalloc(slen + rlen);
+ BN_bn2bin(sig->r, signature);
+ BN_bn2bin(sig->s, signature + rlen);
+ ECDSA_SIG_free(sig);
+ slen += rlen;
+ ok = 0;
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
+ } else {
+ /* Unsupported type */
}
#endif /* WITH_OPENSSL */
}
diff -ru openssh-7.6p1.orig/ssh-pkcs11.c openssh-7.6p1/ssh-pkcs11.c
--- openssh-7.6p1.orig/ssh-pkcs11.c 2017-10-02 12:34:26.000000000 -0700
+++ openssh-7.6p1/ssh-pkcs11.c 2017-11-24 23:23:46.000000000 -0800
@@ -32,6 +32,15 @@
#include "openbsd-compat/sys-queue.h"
#include <openssl/x509.h>
+#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW))
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
#define CRYPTOKI_COMPAT
#include "pkcs11.h"
@@ -66,6 +75,7 @@
struct pkcs11_key {
struct pkcs11_provider *provider;
CK_ULONG slotidx;
+ CK_ULONG key_type;
int (*orig_finish)(RSA *rsa);
RSA_METHOD rsa_method;
char *keyid;
@@ -73,6 +83,9 @@
};
int pkcs11_interactive = 0;
+#ifdef ENABLE_PKCS11_ECDSA
+static int pkcs11_key_idx = -1;
+#endif /* ENABLE_PKCS11_ECDSA */
int
pkcs11_init(int interactive)
@@ -216,6 +229,40 @@
return (ret);
}
+int pkcs11_login(struct pkcs11_key *k11, CK_FUNCTION_LIST *f, struct pkcs11_slotinfo *si) {
+ char *pin = NULL, prompt[1024];
+ CK_RV rv;
+ if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
+ if (!pkcs11_interactive) {
+ error("need pin entry%s", (si->token.flags &
+ CKF_PROTECTED_AUTHENTICATION_PATH) ?
+ " on reader keypad" : "");
+ return (-1);
+ }
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+ verbose("Deferring PIN entry to reader keypad.");
+ else {
+ snprintf(prompt, sizeof(prompt),
+ "Enter PIN for '%s': ", si->token.label);
+ pin = read_passphrase(prompt, RP_ALLOW_EOF);
+ if (pin == NULL)
+ return (-1); /* bail out */
+ }
+ rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
+ (pin != NULL) ? strlen(pin) : 0);
+ if (pin != NULL) {
+ explicit_bzero(pin, strlen(pin));
+ free(pin);
+ }
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+ error("C_Login failed: %lu", rv);
+ return (-1);
+ }
+ si->logged_in = 1;
+ }
+ return 0;
+}
+
/* openssl callback doing the actual signing operation */
static int
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
@@ -237,7 +284,6 @@
{CKA_ID, NULL, 0},
{CKA_SIGN, NULL, sizeof(true_val) }
};
- char *pin = NULL, prompt[1024];
int rval = -1;
key_filter[0].pValue = &private_key_class;
@@ -253,33 +299,8 @@
}
f = k11->provider->function_list;
si = &k11->provider->slotinfo[k11->slotidx];
- if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
- if (!pkcs11_interactive) {
- error("need pin entry%s", (si->token.flags &
- CKF_PROTECTED_AUTHENTICATION_PATH) ?
- " on reader keypad" : "");
- return (-1);
- }
- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- verbose("Deferring PIN entry to reader keypad.");
- else {
- snprintf(prompt, sizeof(prompt),
- "Enter PIN for '%s': ", si->token.label);
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
- if (pin == NULL)
- return (-1); /* bail out */
- }
- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
- (pin != NULL) ? strlen(pin) : 0);
- if (pin != NULL) {
- explicit_bzero(pin, strlen(pin));
- free(pin);
- }
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
- error("C_Login failed: %lu", rv);
- return (-1);
- }
- si->logged_in = 1;
+ if(pkcs11_login(k11, f, si)) {
+ return (-1);
}
key_filter[1].pValue = k11->keyid;
key_filter[1].ulValueLen = k11->keyid_len;
@@ -317,6 +338,7 @@
const RSA_METHOD *def = RSA_get_default_method();
k11 = xcalloc(1, sizeof(*k11));
+ k11->key_type = CKK_RSA;
k11->provider = provider;
provider->refcount++; /* provider referenced by RSA key */
k11->slotidx = slotidx;
@@ -337,6 +359,148 @@
return (0);
}
+#ifdef ENABLE_PKCS11_ECDSA
+static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *inv, const BIGNUM *rp,
+ EC_KEY *ecdsa) {
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG tlen = 0;
+ CK_RV rv;
+ CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
+ CK_BBOOL true_val = CK_TRUE;
+ CK_MECHANISM mech = {
+ CKM_ECDSA, NULL_PTR, 0
+ };
+ CK_ATTRIBUTE key_filter[] = {
+ {CKA_CLASS, NULL, sizeof(private_key_class) },
+ {CKA_ID, NULL, 0},
+ {CKA_SIGN, NULL, sizeof(true_val) }
+ };
+ ECDSA_SIG *rval = NULL;
+ key_filter[0].pValue = &private_key_class;
+ key_filter[2].pValue = &true_val;
+
+ if ((k11 = (struct pkcs11_key *)ECDSA_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {
+ error("ECDSA_get_ex_data failed for ecdsa %p", ecdsa);
+ return NULL;
+ }
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider for ecdsa %p", ecdsa);
+ return NULL;
+ }
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+ if(pkcs11_login(k11, f, si)) {
+ return NULL;
+ }
+ key_filter[1].pValue = k11->keyid;
+ key_filter[1].ulValueLen = k11->keyid_len;
+ /* try to find object w/CKA_SIGN first, retry w/o */
+ if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
+ pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
+ error("cannot find private key");
+ } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
+ error("C_SignInit failed: %lu", rv);
+ } else {
+ CK_BYTE_PTR buf = NULL;
+ int nlen;
+ /* Make a call to C_Sign to find out the size of the signature */
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ return NULL;
+ }
+ if ((buf = xmalloc(tlen)) == NULL) {
+ error("failure to allocate signature buffer");
+ return NULL;
+ }
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ }
+
+ if ((rval = ECDSA_SIG_new()) == NULL) {
+ error("failure to allocate ECDSA signature");
+ } else {
+ /*
+ * ECDSA signature is 2 large integers of same size returned
+ * concatenated by PKCS#11, we separate them to create an
+ * ECDSA_SIG for OpenSSL.
+ */
+ nlen = tlen / 2;
+ BN_bin2bn(&buf[0], nlen, rval->r);
+ BN_bin2bn(&buf[nlen], nlen, rval->s);
+ }
+ free(buf);
+ }
+ return (rval);
+}
+
+static ECDSA_METHOD *get_pkcs11_ecdsa_method(void) {
+ static ECDSA_METHOD *pkcs11_ecdsa_method = NULL;
+ if(pkcs11_key_idx == -1) {
+ pkcs11_key_idx = ECDSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
+ }
+ if(pkcs11_ecdsa_method == NULL) {
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
+#ifdef ECDSA_F_ECDSA_METHOD_NEW
+ pkcs11_ecdsa_method = ECDSA_METHOD_new((ECDSA_METHOD *)def);
+ ECDSA_METHOD_set_name(pkcs11_ecdsa_method, "pkcs11");
+ ECDSA_METHOD_set_sign(pkcs11_ecdsa_method, pkcs11_ecdsa_sign);
+#else
+ pkcs11_ecdsa_method = xcalloc(1, sizeof(*pkcs11_ecdsa_method));
+ memcpy(pkcs11_ecdsa_method, def, sizeof(*pkcs11_ecdsa_method));
+ pkcs11_ecdsa_method->name = "pkcs11";
+ pkcs11_ecdsa_method->ecdsa_do_sign = pkcs11_ecdsa_sign;
+#endif
+ }
+ return pkcs11_ecdsa_method;
+}
+
+static int
+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
+ CK_ATTRIBUTE *keyid_attrib, EC_KEY *ecdsa)
+{
+ struct pkcs11_key *k11;
+ k11 = xcalloc(1, sizeof(*k11));
+ k11->key_type = CKK_EC;
+ k11->provider = provider;
+ provider->refcount++; /* provider referenced by ECDSA key */
+ k11->slotidx = slotidx;
+ /* identify key object on smartcard */
+ if (k11->keyid_len > 0) {
+ k11->keyid_len = keyid_attrib->ulValueLen;
+ k11->keyid = xmalloc(k11->keyid_len);
+ }
+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
+ ECDSA_set_method(ecdsa, get_pkcs11_ecdsa_method());
+ ECDSA_set_ex_data(ecdsa, pkcs11_key_idx, k11);
+ return (0);
+}
+#endif /* ENABLE_PKCS11_ECDSA */
+
+int pkcs11_del_key(struct sshkey *key) {
+#ifdef ENABLE_PKCS11_ECDSA
+ if(key->type == KEY_ECDSA) {
+ struct pkcs11_key *k11 = (struct pkcs11_key *)
+ ECDSA_get_ex_data(key->ecdsa, pkcs11_key_idx);
+ if (k11 == NULL) {
+ error("ECDSA_get_ex_data failed for ecdsa %p", key->ecdsa);
+ } else {
+ if (k11->provider)
+ pkcs11_provider_unref(k11->provider);
+ free(k11->keyid);
+ free(k11);
+ }
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
+ sshkey_free(key);
+ return (0);
+}
+
/* remove trailing spaces */
static void
rmspace(u_char *buf, size_t len)
@@ -397,17 +561,19 @@
* keysp points to an (possibly empty) array with *nkeys keys.
*/
static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,
- CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)
+ CK_ATTRIBUTE [], int, CK_ATTRIBUTE [3], struct sshkey ***, int *)
__attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
static int
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
struct sshkey ***keysp, int *nkeys)
{
- CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
- CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
+ CK_KEY_TYPE pubkey_type = CKK_RSA;
+ CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
+ CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
CK_ATTRIBUTE pubkey_filter[] = {
- { CKA_CLASS, NULL, sizeof(pubkey_class) }
+ { CKA_CLASS, NULL, sizeof(pubkey_class) },
+ { CKA_KEY_TYPE, NULL, sizeof(pubkey_type) }
};
CK_ATTRIBUTE cert_filter[] = {
{ CKA_CLASS, NULL, sizeof(cert_class) }
@@ -422,12 +588,31 @@
{ CKA_SUBJECT, NULL, 0 },
{ CKA_VALUE, NULL, 0 }
};
+#ifdef ENABLE_PKCS11_ECDSA
+ CK_KEY_TYPE ecdsa_type = CKK_EC;
+ CK_ATTRIBUTE ecdsa_filter[] = {
+ { CKA_CLASS, NULL, sizeof(pubkey_class) },
+ { CKA_KEY_TYPE, NULL, sizeof(ecdsa_type) }
+ };
+ CK_ATTRIBUTE ecdsa_attribs[] = {
+ { CKA_ID, NULL, 0 },
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_EC_POINT, NULL, 0 }
+ };
+ ecdsa_filter[0].pValue = &pubkey_class;
+ ecdsa_filter[1].pValue = &ecdsa_type;
+#endif /* ENABLE_PKCS11_ECDSA */
pubkey_filter[0].pValue = &pubkey_class;
+ pubkey_filter[1].pValue = &pubkey_type;
cert_filter[0].pValue = &cert_class;
- if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,
+ if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, 2, pubkey_attribs,
keysp, nkeys) < 0 ||
- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,
+#ifdef ENABLE_PKCS11_ECDSA
+ pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, 2, ecdsa_attribs,
+ keysp, nkeys) < 0||
+#endif /* ENABLE_PKCS11_ECDSA */
+ pkcs11_fetch_keys_filter(p, slotidx, cert_filter, 1, cert_attribs,
keysp, nkeys) < 0)
return (-1);
return (0);
@@ -446,11 +631,16 @@
static int
pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
- CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
+ CK_ATTRIBUTE filter[], int nfilter, CK_ATTRIBUTE attribs[3],
struct sshkey ***keysp, int *nkeys)
{
struct sshkey *key;
RSA *rsa;
+#ifdef ENABLE_PKCS11_ECDSA
+ EC_KEY *ecdsa;
+#else
+ void *ecdsa;
+#endif /* ENABLE_PKCS11_ECDSA */
X509 *x509;
EVP_PKEY *evp;
int i;
@@ -464,7 +654,7 @@
f = p->function_list;
session = p->slotinfo[slotidx].session;
/* setup a filter the looks for public keys */
- if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) {
+ if ((rv = f->C_FindObjectsInit(session, filter, nfilter)) != CKR_OK) {
error("C_FindObjectsInit failed: %lu", rv);
return (-1);
}
@@ -505,6 +695,9 @@
* or ID, subject and value for certificates.
*/
rsa = NULL;
+#ifdef ENABLE_PKCS11_ECDSA
+ ecdsa = NULL;
+#endif /* ENABLE_PKCS11_ECDSA */
if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
!= CKR_OK) {
error("C_GetAttributeValue failed: %lu", rv);
@@ -517,6 +710,45 @@
rsa->e = BN_bin2bn(attribs[2].pValue,
attribs[2].ulValueLen, NULL);
}
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if (attribs[1].type == CKA_EC_PARAMS ) {
+ if ((ecdsa = EC_KEY_new()) == NULL) {
+ error("EC_KEY_new failed");
+ } else {
+ const unsigned char *ptr1 = attribs[1].pValue;
+ const unsigned char *ptr2 = attribs[2].pValue;
+ CK_ULONG len1 = attribs[1].ulValueLen;
+ CK_ULONG len2 = attribs[2].ulValueLen;
+ ASN1_OCTET_STRING *point = NULL;
+
+ /*
+ * CKA_EC_PARAMS contains the curve parameters of the key
+ * either referenced as an OID or directly with all values.
+ * CKA_EC_POINT contains the point (public key) on the curve.
+ * The point is should be returned inside a DER-encoded
+ * ASN.1 OCTET STRING value (but some implementation).
+ */
+ if ((point = d2i_ASN1_OCTET_STRING(NULL, &ptr2, len2))) {
+ /* Pointing to OCTET STRING content */
+ ptr2 = point->data;
+ len2 = point->length;
+ } else {
+ /* No OCTET STRING */
+ ptr2 = attribs[2].pValue;
+ }
+
+ if((d2i_ECParameters(&ecdsa, &ptr1, len1) == NULL) ||
+ (o2i_ECPublicKey(&ecdsa, &ptr2, len2) == NULL)) {
+ EC_KEY_free(ecdsa);
+ ecdsa = NULL;
+ error("EC public key parsing failed");
+ }
+
+ if(point) {
+ M_ASN1_OCTET_STRING_free(point);
+ }
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
} else {
cp = attribs[2].pValue;
if ((x509 = X509_new()) == NULL) {
@@ -535,13 +767,28 @@
if (x509)
X509_free(x509);
}
- if (rsa && rsa->n && rsa->e &&
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
- if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("sshkey_new failed");
- key->rsa = rsa;
- key->type = KEY_RSA;
- key->flags |= SSHKEY_FLAG_EXT;
+ key = NULL;
+ if (rsa || ecdsa) {
+ if (rsa && rsa->n && rsa->e &&
+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new failed");
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(ecdsa && pkcs11_ecdsa_wrap(p, slotidx, &attribs[0], ecdsa) == 0) {
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new failed");
+ key->ecdsa = ecdsa;
+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+#endif /* ENABLE_PKCS11_ECDSA */
+ }
+ }
+
+ if(key) {
if (pkcs11_key_included(keysp, nkeys, key)) {
sshkey_free(key);
} else {
@@ -554,6 +801,10 @@
}
} else if (rsa) {
RSA_free(rsa);
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if (ecdsa) {
+ EC_KEY_free(ecdsa);
+#endif /* ENABLE_PKCS11_ECDSA */
}
for (i = 0; i < 3; i++)
free(attribs[i].pValue);
Only in openssh-7.6p1: ssh-pkcs11.c~
diff -ru openssh-7.6p1.orig/ssh-pkcs11.h openssh-7.6p1/ssh-pkcs11.h
--- openssh-7.6p1.orig/ssh-pkcs11.h 2017-10-02 12:34:26.000000000 -0700
+++ openssh-7.6p1/ssh-pkcs11.h 2017-11-24 23:21:57.000000000 -0800
@@ -17,6 +17,7 @@
int pkcs11_init(int);
void pkcs11_terminate(void);
int pkcs11_add_provider(char *, char *, struct sshkey ***);
+int pkcs11_del_key(struct sshkey *);
int pkcs11_del_provider(char *);
#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)