mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-27 07:44:29 +02:00
- markus@cvs.openbsd.org 2013/11/02 20:03:54
[ssh-pkcs11.c] support pkcs#11 tokes that only provide x509 zerts instead of raw pubkeys; fixes bz#1908; based on patch from Laurent Barbe; ok djm
This commit is contained in:
parent
007e3b357e
commit
d2252c7919
@ -1,3 +1,10 @@
|
|||||||
|
20131104
|
||||||
|
- (djm) OpenBSD CVS Sync
|
||||||
|
- markus@cvs.openbsd.org 2013/11/02 20:03:54
|
||||||
|
[ssh-pkcs11.c]
|
||||||
|
support pkcs#11 tokes that only provide x509 zerts instead of raw pubkeys;
|
||||||
|
fixes bz#1908; based on patch from Laurent Barbe; ok djm
|
||||||
|
|
||||||
20131103
|
20131103
|
||||||
- (dtucker) [openbsd-compat/bsd-misc.c] Include time.h for nanosleep.
|
- (dtucker) [openbsd-compat/bsd-misc.c] Include time.h for nanosleep.
|
||||||
From OpenSMTPD where it prevents "implicit declaration" warnings (it's
|
From OpenSMTPD where it prevents "implicit declaration" warnings (it's
|
||||||
|
141
ssh-pkcs11.c
141
ssh-pkcs11.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-pkcs11.c,v 1.8 2013/07/12 00:20:00 djm Exp $ */
|
/* $OpenBSD: ssh-pkcs11.c,v 1.9 2013/11/02 20:03:54 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include "openbsd-compat/sys-queue.h"
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
#define CRYPTOKI_COMPAT
|
#define CRYPTOKI_COMPAT
|
||||||
#include "pkcs11.h"
|
#include "pkcs11.h"
|
||||||
|
|
||||||
@ -225,24 +227,19 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
|||||||
CK_OBJECT_HANDLE obj;
|
CK_OBJECT_HANDLE obj;
|
||||||
CK_ULONG tlen = 0;
|
CK_ULONG tlen = 0;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
|
CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
|
||||||
CK_BBOOL true_val = CK_TRUE;
|
CK_BBOOL true_val = CK_TRUE;
|
||||||
CK_MECHANISM mech = {
|
CK_MECHANISM mech = {
|
||||||
CKM_RSA_PKCS, NULL_PTR, 0
|
CKM_RSA_PKCS, NULL_PTR, 0
|
||||||
};
|
};
|
||||||
CK_ATTRIBUTE key_filter[] = {
|
CK_ATTRIBUTE key_filter[] = {
|
||||||
{CKA_CLASS, NULL, sizeof(private_key_class) },
|
{CKA_CLASS, &private_key_class, sizeof(private_key_class) },
|
||||||
{CKA_ID, NULL, 0},
|
{CKA_ID, NULL, 0},
|
||||||
{CKA_SIGN, NULL, sizeof(true_val) }
|
{CKA_SIGN, &true_val, sizeof(true_val) }
|
||||||
};
|
};
|
||||||
char *pin, prompt[1024];
|
char *pin, prompt[1024];
|
||||||
int rval = -1;
|
int rval = -1;
|
||||||
|
|
||||||
/* some compilers complain about non-constant initializer so we
|
|
||||||
use NULL in CK_ATTRIBUTE above and set the values here */
|
|
||||||
key_filter[0].pValue = &private_key_class;
|
|
||||||
key_filter[2].pValue = &true_val;
|
|
||||||
|
|
||||||
if ((k11 = RSA_get_app_data(rsa)) == NULL) {
|
if ((k11 = RSA_get_app_data(rsa)) == NULL) {
|
||||||
error("RSA_get_app_data failed for rsa %p", rsa);
|
error("RSA_get_app_data failed for rsa %p", rsa);
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -384,36 +381,73 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin)
|
|||||||
* add 'wrapped' public keys to the 'keysp' array and increment nkeys.
|
* add 'wrapped' public keys to the 'keysp' array and increment nkeys.
|
||||||
* keysp points to an (possibly empty) array with *nkeys keys.
|
* 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], Key ***, int *)
|
||||||
|
__attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp,
|
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||||
int *nkeys)
|
Key ***keysp, int *nkeys)
|
||||||
|
{
|
||||||
|
CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
|
||||||
|
CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
|
||||||
|
CK_ATTRIBUTE pubkey_filter[] = {
|
||||||
|
{ CKA_CLASS, &pubkey_class, sizeof(pubkey_class) }
|
||||||
|
};
|
||||||
|
CK_ATTRIBUTE cert_filter[] = {
|
||||||
|
{ CKA_CLASS, &cert_class, sizeof(cert_class) }
|
||||||
|
};
|
||||||
|
CK_ATTRIBUTE pubkey_attribs[] = {
|
||||||
|
{ CKA_ID, NULL, 0 },
|
||||||
|
{ CKA_MODULUS, NULL, 0 },
|
||||||
|
{ CKA_PUBLIC_EXPONENT, NULL, 0 }
|
||||||
|
};
|
||||||
|
CK_ATTRIBUTE cert_attribs[] = {
|
||||||
|
{ CKA_ID, NULL, 0 },
|
||||||
|
{ CKA_SUBJECT, NULL, 0 },
|
||||||
|
{ CKA_VALUE, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,
|
||||||
|
keysp, nkeys) < 0 ||
|
||||||
|
pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,
|
||||||
|
keysp, nkeys) < 0)
|
||||||
|
return (-1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pkcs11_key_included(Key ***keysp, int *nkeys, Key *key)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < *nkeys; i++)
|
||||||
|
if (key_equal(key, *keysp[i]))
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||||
|
CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
|
||||||
|
Key ***keysp, int *nkeys)
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
RSA *rsa;
|
RSA *rsa;
|
||||||
|
X509 *x509;
|
||||||
|
EVP_PKEY *evp;
|
||||||
int i;
|
int i;
|
||||||
|
const u_char *cp;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
CK_OBJECT_HANDLE obj;
|
CK_OBJECT_HANDLE obj;
|
||||||
CK_ULONG nfound;
|
CK_ULONG nfound;
|
||||||
CK_SESSION_HANDLE session;
|
CK_SESSION_HANDLE session;
|
||||||
CK_FUNCTION_LIST *f;
|
CK_FUNCTION_LIST *f;
|
||||||
CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
|
|
||||||
CK_ATTRIBUTE pubkey_filter[] = {
|
|
||||||
{ CKA_CLASS, NULL, sizeof(pubkey_class) }
|
|
||||||
};
|
|
||||||
CK_ATTRIBUTE attribs[] = {
|
|
||||||
{ CKA_ID, NULL, 0 },
|
|
||||||
{ CKA_MODULUS, NULL, 0 },
|
|
||||||
{ CKA_PUBLIC_EXPONENT, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* some compilers complain about non-constant initializer so we
|
|
||||||
use NULL in CK_ATTRIBUTE above and set the value here */
|
|
||||||
pubkey_filter[0].pValue = &pubkey_class;
|
|
||||||
|
|
||||||
f = p->function_list;
|
f = p->function_list;
|
||||||
session = p->slotinfo[slotidx].session;
|
session = p->slotinfo[slotidx].session;
|
||||||
/* setup a filter the looks for public keys */
|
/* setup a filter the looks for public keys */
|
||||||
if ((rv = f->C_FindObjectsInit(session, pubkey_filter, 1)) != CKR_OK) {
|
if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) {
|
||||||
error("C_FindObjectsInit failed: %lu", rv);
|
error("C_FindObjectsInit failed: %lu", rv);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -441,32 +475,59 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp,
|
|||||||
/* allocate buffers for attributes */
|
/* allocate buffers for attributes */
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
|
attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
|
||||||
/* retrieve ID, modulus and public exponent of RSA key */
|
/*
|
||||||
|
* retrieve ID, modulus and public exponent of RSA key,
|
||||||
|
* or ID, subject and value for certificates.
|
||||||
|
*/
|
||||||
|
rsa = NULL;
|
||||||
if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
|
if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
|
||||||
!= CKR_OK) {
|
!= CKR_OK) {
|
||||||
error("C_GetAttributeValue failed: %lu", rv);
|
error("C_GetAttributeValue failed: %lu", rv);
|
||||||
} else if ((rsa = RSA_new()) == NULL) {
|
} else if (attribs[1].type == CKA_MODULUS ) {
|
||||||
error("RSA_new failed");
|
if ((rsa = RSA_new()) == NULL) {
|
||||||
|
error("RSA_new failed");
|
||||||
|
} else {
|
||||||
|
rsa->n = BN_bin2bn(attribs[1].pValue,
|
||||||
|
attribs[1].ulValueLen, NULL);
|
||||||
|
rsa->e = BN_bin2bn(attribs[2].pValue,
|
||||||
|
attribs[2].ulValueLen, NULL);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rsa->n = BN_bin2bn(attribs[1].pValue,
|
cp = attribs[2].pValue;
|
||||||
attribs[1].ulValueLen, NULL);
|
if ((x509 = X509_new()) == NULL) {
|
||||||
rsa->e = BN_bin2bn(attribs[2].pValue,
|
error("X509_new failed");
|
||||||
attribs[2].ulValueLen, NULL);
|
} else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen)
|
||||||
if (rsa->n && rsa->e &&
|
== NULL) {
|
||||||
pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
|
error("d2i_X509 failed");
|
||||||
key = key_new(KEY_UNSPEC);
|
} else if ((evp = X509_get_pubkey(x509)) == NULL ||
|
||||||
key->rsa = rsa;
|
evp->type != EVP_PKEY_RSA ||
|
||||||
key->type = KEY_RSA;
|
evp->pkey.rsa == NULL) {
|
||||||
key->flags |= KEY_FLAG_EXT;
|
debug("X509_get_pubkey failed or no rsa");
|
||||||
|
} else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa))
|
||||||
|
== NULL) {
|
||||||
|
error("RSAPublicKey_dup");
|
||||||
|
}
|
||||||
|
if (x509)
|
||||||
|
X509_free(x509);
|
||||||
|
}
|
||||||
|
if (rsa && rsa->n && rsa->e &&
|
||||||
|
pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
|
||||||
|
key = key_new(KEY_UNSPEC);
|
||||||
|
key->rsa = rsa;
|
||||||
|
key->type = KEY_RSA;
|
||||||
|
key->flags |= KEY_FLAG_EXT;
|
||||||
|
if (pkcs11_key_included(keysp, nkeys, key)) {
|
||||||
|
key_free(key);
|
||||||
|
} else {
|
||||||
/* expand key array and add key */
|
/* expand key array and add key */
|
||||||
*keysp = xrealloc(*keysp, *nkeys + 1,
|
*keysp = xrealloc(*keysp, *nkeys + 1,
|
||||||
sizeof(Key *));
|
sizeof(Key *));
|
||||||
(*keysp)[*nkeys] = key;
|
(*keysp)[*nkeys] = key;
|
||||||
*nkeys = *nkeys + 1;
|
*nkeys = *nkeys + 1;
|
||||||
debug("have %d keys", *nkeys);
|
debug("have %d keys", *nkeys);
|
||||||
} else {
|
|
||||||
RSA_free(rsa);
|
|
||||||
}
|
}
|
||||||
|
} else if (rsa) {
|
||||||
|
RSA_free(rsa);
|
||||||
}
|
}
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
free(attribs[i].pValue);
|
free(attribs[i].pValue);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user