- pkcs15-init does not require openssl anymore

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@523 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2002-04-15 13:42:10 +00:00
parent 1ec7a85e51
commit 596220e821
18 changed files with 722 additions and 509 deletions

View File

@ -97,12 +97,12 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen,
cert->version++;
pklen >>= 3; /* convert number of bits to bytes */
key->data = pk;
key->data_len = pklen;
key->data.value = pk;
key->data.len = pklen;
/* FIXME: ignore the object id for now, and presume it's RSA */
r = sc_pkcs15_parse_pubkey_rsa(ctx, key);
if (r) {
free(key->data);
free(key->data.value);
return SC_ERROR_INVALID_ASN1_OBJECT;
}
@ -269,8 +269,8 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
{
assert(cert != NULL);
free(cert->key.data);
free(cert->key.modulus);
free(cert->key.data.value);
free(cert->key.modulus.data);
free(cert->subject);
free(cert->issuer);
free(cert->serial);

View File

@ -153,30 +153,120 @@ int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx,
return r;
}
static struct sc_asn1_entry c_asn1_public_key[2] = {
{ "publicKeyCoefficients", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, },
{ NULL }
};
static struct sc_asn1_entry c_asn1_rsa_pub_coefficients[3] = {
{ "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ "exponent", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ NULL }
};
static struct sc_asn1_entry c_asn1_dsa_pub_coefficients[5] = {
{ "publicKey",SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ "paramP", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ "paramQ", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ "paramG", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, },
{ NULL },
};
int
sc_pkcs15_parse_pubkey_rsa(struct sc_context *ctx, struct sc_pkcs15_pubkey_rsa *key)
{
struct sc_asn1_entry asn1_pubkey_rsa[] = {
{ "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, &key->modulus, &key->modulus_len },
{ "publicExponent", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &key->exponent },
{ NULL }
};
const u8 *obj;
size_t objlen;
struct sc_asn1_entry asn1_public_key[2];
struct sc_asn1_entry asn1_rsa_coeff[3];
int r;
obj = sc_asn1_verify_tag(ctx, key->data, key->data_len, ASN1_SEQUENCE | SC_ASN1_CONS,
&objlen);
if (obj == NULL) {
error(ctx, "RSA public key not found\n");
return SC_ERROR_INVALID_ASN1_OBJECT;
}
r = sc_asn1_decode(ctx, asn1_pubkey_rsa, obj, objlen, NULL, NULL);
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_coeff, NULL, 0);
sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_coeff);
sc_format_asn1_entry(asn1_rsa_coeff + 0,
&key->modulus.data, &key->modulus.len, 0);
sc_format_asn1_entry(asn1_rsa_coeff + 1,
&key->exponent.data, &key->exponent.len, 0);
r = sc_asn1_decode(ctx, asn1_public_key,
key->data.value, key->data.len, NULL, NULL);
SC_TEST_RET(ctx, r, "ASN.1 parsing failed");
return 0;
}
int
sc_pkcs15_encode_pubkey_rsa(struct sc_context *ctx,
struct sc_pkcs15_pubkey_rsa *key,
u8 **buf, size_t *buflen)
{
struct sc_asn1_entry asn1_public_key[2];
struct sc_asn1_entry asn1_rsa_pub_coeff[3];
int r;
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coeff, NULL, 1);
sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_pub_coeff);
sc_format_asn1_entry(asn1_rsa_pub_coeff + 0,
key->modulus.data, &key->modulus.len, 1);
sc_format_asn1_entry(asn1_rsa_pub_coeff + 1,
key->exponent.data, &key->exponent.len, 1);
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
SC_TEST_RET(ctx, r, "ASN.1 encoding failed");
return 0;
}
int
sc_pkcs15_encode_pubkey_dsa(struct sc_context *ctx,
struct sc_pkcs15_pubkey_dsa *key,
u8 **buf, size_t *buflen)
{
struct sc_asn1_entry asn1_public_key[2];
struct sc_asn1_entry asn1_dsa_pub_coeff[3];
int r;
sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key);
sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coeff);
sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coeff, NULL, 1);
sc_format_asn1_entry(asn1_dsa_pub_coeff + 0,
key->pub.data, &key->pub.len, 1);
sc_format_asn1_entry(asn1_dsa_pub_coeff + 1,
key->g.data, &key->g.len, 1);
sc_format_asn1_entry(asn1_dsa_pub_coeff + 2,
key->p.data, &key->p.len, 1);
sc_format_asn1_entry(asn1_dsa_pub_coeff + 3,
key->q.data, &key->q.len, 1);
r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen);
SC_TEST_RET(ctx, r, "ASN.1 encoding failed");
return 0;
}
int
sc_pkcs15_encode_pubkey(struct sc_context *ctx,
struct sc_pkcs15_pubkey *key,
u8 **buf, size_t *len)
{
if (key->algorithm == SC_ALGORITHM_RSA)
return sc_pkcs15_encode_pubkey_rsa(ctx, &key->u.rsa, buf, len);
if (key->algorithm == SC_ALGORITHM_DSA)
return sc_pkcs15_encode_pubkey_dsa(ctx, &key->u.dsa, buf, len);
error(ctx, "Encoding of public key type %u not supported\n",
key->algorithm);
return SC_ERROR_NOT_SUPPORTED;
}
/*
* Read public key.
* XXX: we should change this function to take an additional
* algorithm parameter, and a sc_pkcs15_pubkey rather than
* a sc_pkcs15_pubkey_rsa
*/
int
sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_pubkey_info *info,
@ -221,8 +311,8 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
return SC_ERROR_OUT_OF_MEMORY;
}
memset(pubkey, 0, sizeof(struct sc_pkcs15_pubkey_rsa));
pubkey->data = data;
pubkey->data_len = len;
pubkey->data.value = data;
pubkey->data.len = len;
if (sc_pkcs15_parse_pubkey_rsa(p15card->card->ctx, pubkey)) {
free(data);
free(pubkey);
@ -235,7 +325,7 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card,
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey_rsa *key)
{
assert(key != NULL);
free(key->modulus);
free(key->data);
free(key->modulus.data);
free(key->data.value);
free(key);
}

View File

@ -92,14 +92,81 @@ struct sc_pkcs15_algorithm_info {
int algorithm, supported_operations;
};
struct sc_pkcs15_pubkey_rsa {
u8 *modulus;
int modulus_len;
unsigned int exponent;
u8 *data; /* DER encoded raw key */
int data_len;
/* A large integer, big endian notation */
struct sc_pkcs15_bignum {
u8 * data;
size_t len;
};
typedef struct sc_pkcs15_bignum sc_pkcs15_bignum_t;
struct sc_pkcs15_der {
u8 * value;
size_t len;
};
typedef struct sc_pkcs15_der sc_pkcs15_der_t;
struct sc_pkcs15_pubkey_rsa {
sc_pkcs15_bignum_t modulus;
sc_pkcs15_bignum_t exponent;
/* DER encoded raw key */
sc_pkcs15_der_t data;
};
struct sc_pkcs15_prkey_rsa {
/* public components */
sc_pkcs15_bignum_t modulus;
sc_pkcs15_bignum_t exponent;
/* private components */
sc_pkcs15_bignum_t d;
sc_pkcs15_bignum_t p;
sc_pkcs15_bignum_t q;
/* optional CRT elements */
sc_pkcs15_bignum_t iqmp;
sc_pkcs15_bignum_t dmp1;
sc_pkcs15_bignum_t dmq1;
};
struct sc_pkcs15_pubkey_dsa {
sc_pkcs15_bignum_t pub;
sc_pkcs15_bignum_t p;
sc_pkcs15_bignum_t q;
sc_pkcs15_bignum_t g;
/* DER encoded raw key */
sc_pkcs15_der_t data;
};
struct sc_pkcs15_prkey_dsa {
/* public components */
sc_pkcs15_bignum_t pub;
sc_pkcs15_bignum_t p;
sc_pkcs15_bignum_t q;
sc_pkcs15_bignum_t g;
/* private key */
sc_pkcs15_bignum_t priv;
};
struct sc_pkcs15_pubkey {
int algorithm;
union {
struct sc_pkcs15_pubkey_rsa rsa;
struct sc_pkcs15_pubkey_dsa dsa;
} u;
};
typedef struct sc_pkcs15_pubkey sc_pkcs15_pubkey_t;
struct sc_pkcs15_prkey {
int algorithm;
union {
struct sc_pkcs15_prkey_rsa rsa;
struct sc_pkcs15_prkey_dsa dsa;
} u;
};
typedef struct sc_pkcs15_prkey sc_pkcs15_prkey_t;
struct sc_pkcs15_cert {
int version;
@ -277,6 +344,10 @@ int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *card,
struct sc_pkcs15_pubkey_rsa **out);
int sc_pkcs15_parse_pubkey_rsa(struct sc_context *ctx,
struct sc_pkcs15_pubkey_rsa *pubkey);
int sc_pkcs15_encode_pubkey_rsa(struct sc_context *,
struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *);
int sc_pkcs15_encode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, u8 **, size_t *);
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey_rsa *pubkey);
void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert);

View File

@ -6,18 +6,12 @@ MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = . rsaref
if HAVE_SSL
SSL_SRC = framework-pkcs15init.c
SSL_LIBS = ../pkcs15init/libpkcs15init.la
SSL_INCLUDES = -I../pkcs15init
endif
INCLUDES = @CFLAGS_OPENSC@ -I../pkcs15init
INCLUDES = @CFLAGS_OPENSC@ $(SSL_INCLUDES)
LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ $(SSL_LIBS)
LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ ../pkcs15init/libpkcs15init.la
SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
secretkey.c framework-pkcs15.c $(SSL_SRC)
secretkey.c framework-pkcs15.c framework-pkcs15init.c
INC = sc-pkcs11.h
lib_LTLIBRARIES = opensc-pkcs11.la

View File

@ -22,9 +22,7 @@
#include <malloc.h>
#include <string.h>
#include "sc-pkcs11.h"
#ifdef HAVE_OPENSSL
#include "opensc/pkcs15-init.h"
#endif
#define MAX_CACHE_PIN 32
struct pkcs15_slot_data {
@ -534,7 +532,6 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
return sc_to_cryptoki_error(rc, p11card->reader);
}
#ifdef HAVE_OPENSSL
static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
struct sc_pkcs11_slot *slot,
CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
@ -579,11 +576,11 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
CK_OBJECT_HANDLE_PTR phObject)
{
struct sc_pkcs15_card *card;
struct sc_pkcs15init_keyargs args;
struct sc_pkcs15init_prkeyargs args;
struct sc_pkcs15_object *key_obj;
struct sc_pkcs15_pin_info *pin;
CK_KEY_TYPE key_type;
RSA *rsa;
struct sc_pkcs15_prkey_rsa *rsa;
int rc, rv;
memset(&args, 0, sizeof(args));
@ -599,13 +596,13 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
return rv;
if (key_type != CKK_RSA)
return CKR_FUNCTION_NOT_SUPPORTED; /* XXX correct code? */
args.pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(args.pkey, rsa = RSA_new());
args.key.algorithm = SC_ALGORITHM_RSA;
rsa = &args.key.u.rsa;
rv = CKR_OK;
while (ulCount--) {
CK_ATTRIBUTE_PTR attr = pTemplate++;
BIGNUM *bn = NULL;
sc_pkcs15_bignum_t *bn = NULL;
switch (attr->type) {
/* Skip attrs we already know or don't care for */
@ -624,15 +621,15 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
goto out;
break;
case CKA_MODULUS:
bn = rsa->n = BN_new(); break;
bn = &rsa->modulus; break;
case CKA_PUBLIC_EXPONENT:
bn = rsa->e = BN_new(); break;
bn = &rsa->exponent; break;
case CKA_PRIVATE_EXPONENT:
bn = rsa->d = BN_new(); break;
bn = &rsa->d; break;
case CKA_PRIME_1:
bn = rsa->p = BN_new(); break;
bn = &rsa->p; break;
case CKA_PRIME_2:
bn = rsa->q = BN_new(); break;
bn = &rsa->q; break;
default:
/* ignore unknown attrs, or flag error? */
continue;
@ -641,48 +638,17 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
if (bn) {
if (attr->ulValueLen > 1024)
return CKR_ATTRIBUTE_VALUE_INVALID;
BN_bin2bn((unsigned char *) attr->pValue,
attr->ulValueLen, bn);
bn->len = attr->ulValueLen;
bn->data = attr->pValue;
}
}
if (!rsa->n || !rsa->e || !rsa->d || !rsa->p || !rsa->q) {
if (!rsa->modulus.len || !rsa->exponent.len || !rsa->d.len
|| !rsa->p.len || !rsa->q.len) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto out;
}
/* Generate additional parameters.
* At least the GPK seems to need the full set of CRT
* parameters; storing just the private exponent produces
* invalid signatures.
*/
if (!rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
BIGNUM *aux = BN_new();
BN_CTX *ctx = BN_CTX_new();
if (!rsa->dmp1)
rsa->dmp1 = BN_new();
if (!rsa->dmq1)
rsa->dmq1 = BN_new();
if (!rsa->iqmp)
rsa->iqmp = BN_new();
aux = BN_new();
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
}
card = (struct sc_pkcs15_card*) p11card->fw_data;
rc = sc_pkcs15init_store_private_key(card, profile, &args, &key_obj);
if (rc < 0) {
@ -696,11 +662,7 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
rv = CKR_OK;
out: if (args.pkey) {
EVP_PKEY_free(args.pkey);
RSA_free(rsa);
}
return rv;
out: return rv;
}
static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
@ -710,11 +672,11 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
CK_OBJECT_HANDLE_PTR phObject)
{
struct sc_pkcs15_card *card;
struct sc_pkcs15init_keyargs args;
struct sc_pkcs15init_pubkeyargs args;
struct sc_pkcs15_object *key_obj;
struct sc_pkcs15_pin_info *pin;
CK_KEY_TYPE key_type;
RSA *rsa;
struct sc_pkcs15_pubkey_rsa *rsa;
int rc, rv;
memset(&args, 0, sizeof(args));
@ -730,13 +692,13 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
return rv;
if (key_type != CKK_RSA)
return CKR_FUNCTION_NOT_SUPPORTED; /* XXX correct code? */
args.pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(args.pkey, rsa = RSA_new());
args.key.algorithm = SC_ALGORITHM_RSA;
rsa = &args.key.u.rsa;
rv = CKR_OK;
while (ulCount--) {
CK_ATTRIBUTE_PTR attr = pTemplate++;
BIGNUM *bn = NULL;
sc_pkcs15_bignum_t *bn = NULL;
switch (attr->type) {
/* Skip attrs we already know or don't care for */
@ -755,9 +717,9 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
goto out;
break;
case CKA_MODULUS:
bn = rsa->n = BN_new(); break;
bn = &rsa->modulus; break;
case CKA_PUBLIC_EXPONENT:
bn = rsa->e = BN_new(); break;
bn = &rsa->exponent; break;
default:
/* ignore unknown attrs, or flag error? */
continue;
@ -766,12 +728,12 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
if (bn) {
if (attr->ulValueLen > 1024)
return CKR_ATTRIBUTE_VALUE_INVALID;
BN_bin2bn((unsigned char *) attr->pValue,
attr->ulValueLen, bn);
bn->len = attr->ulValueLen;
bn->data = attr->pValue;
}
}
if (!rsa->n || !rsa->e) {
if (!rsa->modulus.len || !rsa->exponent.len) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto out;
}
@ -788,11 +750,7 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
rv = CKR_OK;
out: if (args.pkey) {
EVP_PKEY_free(args.pkey);
RSA_free(rsa);
}
return rv;
out: return rv;
}
static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
@ -806,8 +764,6 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
struct sc_pkcs15_object *key_obj;
CK_CERTIFICATE_TYPE cert_type;
CK_BBOOL bValue;
X509 *x509 = NULL;
unsigned char *ptr;
int rc, rv;
memset(&args, 0, sizeof(args));
@ -845,16 +801,8 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
goto out;
break;
case CKA_VALUE:
if (x509) {
rv = CKR_TEMPLATE_INCONSISTENT;
goto out;
}
ptr = attr->pValue;
x509 = d2i_X509(NULL, &ptr, attr->ulValueLen);
if (x509 == NULL) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto out;
}
args.der_encoded.len = attr->ulValueLen;
args.der_encoded.value = attr->pValue;
break;
default:
/* ignore unknown attrs, or flag error? */
@ -862,7 +810,7 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
}
}
if (!x509) {
if (args.der_encoded.len == 0) {
rv = CKR_TEMPLATE_INCOMPLETE;
goto out;
}
@ -879,9 +827,7 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
rv = CKR_OK;
out: if (x509)
X509_free(x509);
return rv;
out: return rv;
}
static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card,
@ -935,7 +881,6 @@ static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card,
sc_pkcs15init_unbind(profile);
return rv;
}
#endif
struct sc_pkcs11_framework_ops framework_pkcs15 = {
pkcs15_bind,
@ -948,13 +893,8 @@ struct sc_pkcs11_framework_ops framework_pkcs15 = {
pkcs15_logout,
pkcs15_change_pin,
NULL, /* init_token */
#ifdef HAVE_OPENSSL
pkcs15_init_pin,
pkcs15_create_object
#else
NULL, /* init_pin */
NULL, /* create_object */
#endif
};
/*
@ -1421,8 +1361,8 @@ get_modulus(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr)
{
if (key == NULL)
return CKR_ATTRIBUTE_TYPE_INVALID;
check_attribute_buffer(attr, key->modulus_len);
memcpy(attr->pValue, key->modulus, key->modulus_len);
check_attribute_buffer(attr, key->modulus.len);
memcpy(attr->pValue, key->modulus.data, key->modulus.len);
return CKR_OK;
}
@ -1433,9 +1373,9 @@ get_modulus_bits(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr)
if (key == NULL)
return CKR_ATTRIBUTE_TYPE_INVALID;
bits = key->modulus_len * 8;
bits = key->modulus.len * 8;
for (mask = 0x80; mask; mask >>= 1, bits--) {
if (key->modulus[0] & mask)
if (key->modulus.data[0] & mask)
break;
}
check_attribute_buffer(attr, sizeof(bits));
@ -1446,21 +1386,10 @@ get_modulus_bits(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr)
static int
get_public_exponent(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr)
{
CK_ULONG word;
unsigned int j, n;
CK_BYTE exponent[4];
if (key == NULL)
return CKR_ATTRIBUTE_TYPE_INVALID;
word = key->exponent;
for (j = 0, n = 4; j < n; word <<= 8) {
if ((word & 0xFF000000) || j)
exponent[j++] = word >> 24;
else
n--;
}
check_attribute_buffer(attr, n);
memcpy(attr->pValue, exponent, n);
check_attribute_buffer(attr, key->exponent.len);
memcpy(attr->pValue, key->exponent.data, key->exponent.len);
return CKR_OK;
}

View File

@ -22,9 +22,7 @@
#include <malloc.h>
#include <string.h>
#include "sc-pkcs11.h"
#ifdef HAVE_OPENSSL
#include "pkcs15-init.h"
#endif
/*
* Deal with uninitialized cards

View File

@ -200,9 +200,7 @@ extern struct sc_pkcs11_card card_table[SC_PKCS11_MAX_READERS];
/* Framework definitions */
extern struct sc_pkcs11_framework_ops framework_pkcs15;
#ifdef HAVE_OPENSSL
extern struct sc_pkcs11_framework_ops framework_pkcs15init;
#endif
void strcpy_bp(u8 *dst, const char *src, int dstsize);
CK_RV sc_to_cryptoki_error(int rc, int reader);

View File

@ -26,9 +26,7 @@ static struct sc_pkcs11_framework_ops *frameworks[] = {
/* This should be the last framework, because it
* will assume the card is blank and try to initialize it */
#ifdef HAVE_OPENSSL
&framework_pkcs15init,
#endif
NULL
};

View File

@ -5,13 +5,11 @@ includedir = ${prefix}/include/opensc
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = @CFLAGS_OPENSC@ -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
LDFLAGS = @LDFLAGS@ @LIBOPENSC@ @LIBCRYPTO@
LDFLAGS = @LDFLAGS@ @LIBOPENSC@
EXTRA_DIST = flex.profile gpk.profile miocos.profile pkcs15.profile
if HAVE_SSL
lib_LTLIBRARIES = libpkcs15init.la
endif
libpkcs15init_la_SOURCES = \
pkcs15-lib.c profile.c \

View File

@ -23,7 +23,6 @@
#endif
#include <string.h>
#include <sys/types.h>
#include <openssl/bn.h>
#include <opensc/opensc.h>
#include "pkcs15-init.h"
#include "profile.h"
@ -177,17 +176,10 @@ static void invert_buf(u8 *dest, const u8 *src, size_t c)
dest[i] = src[c-1-i];
}
static int bn2cf(const BIGNUM *num, u8 *buf)
static int bn2cf(sc_pkcs15_bignum_t *num, u8 *buf)
{
u8 tmp[512];
int r;
r = BN_bn2bin(num, tmp);
if (r <= 0)
return r;
invert_buf(buf, tmp, r);
return r;
invert_buf(buf, num->data, num->len);
return num->len;
}
#if 0
@ -216,24 +208,24 @@ static int gen_d(RSA *rsa)
}
#endif
static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_num)
static int cflex_encode_private_key(struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize, int key_num)
{
u8 buf[512], *p = buf;
u8 bnbuf[256];
int base = 0;
int r;
switch (BN_num_bits(rsa->n)) {
case 512:
switch (rsa->modulus.len) {
case 512 / 8:
base = 32;
break;
case 768:
case 768 / 8:
base = 48;
break;
case 1024:
case 1024 / 8:
base = 64;
break;
case 2048:
case 2048 / 8:
base = 128;
break;
}
@ -244,7 +236,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
*p++ = (5 * base + 3) >> 8;
*p++ = (5 * base + 3) & 0xFF;
*p++ = key_num;
r = bn2cf(rsa->p, bnbuf);
r = bn2cf(&rsa->p, bnbuf);
if (r != base) {
fprintf(stderr, "Invalid private key.\n");
return 2;
@ -252,7 +244,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
memcpy(p, bnbuf, base);
p += base;
r = bn2cf(rsa->q, bnbuf);
r = bn2cf(&rsa->q, bnbuf);
if (r != base) {
fprintf(stderr, "Invalid private key.\n");
return 2;
@ -260,7 +252,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
memcpy(p, bnbuf, base);
p += base;
r = bn2cf(rsa->iqmp, bnbuf);
r = bn2cf(&rsa->iqmp, bnbuf);
if (r != base) {
fprintf(stderr, "Invalid private key.\n");
return 2;
@ -268,7 +260,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
memcpy(p, bnbuf, base);
p += base;
r = bn2cf(rsa->dmp1, bnbuf);
r = bn2cf(&rsa->dmp1, bnbuf);
if (r != base) {
fprintf(stderr, "Invalid private key.\n");
return 2;
@ -276,7 +268,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
memcpy(p, bnbuf, base);
p += base;
r = bn2cf(rsa->dmq1, bnbuf);
r = bn2cf(&rsa->dmq1, bnbuf);
if (r != base) {
fprintf(stderr, "Invalid private key.\n");
return 2;
@ -293,24 +285,24 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_
return 0;
}
static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_num)
static int cflex_encode_public_key(struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize, int key_num)
{
u8 buf[512], *p = buf;
u8 bnbuf[256];
int base = 0;
int r;
switch (BN_num_bits(rsa->n)) {
case 512:
switch (rsa->modulus.len) {
case 512 / 8:
base = 32;
break;
case 768:
case 768 / 8:
base = 48;
break;
case 1024:
case 1024 / 8:
base = 64;
break;
case 2048:
case 2048 / 8:
base = 128;
break;
}
@ -321,7 +313,7 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n
*p++ = (5 * base + 7) >> 8;
*p++ = (5 * base + 7) & 0xFF;
*p++ = key_num;
r = bn2cf(rsa->n, bnbuf);
r = bn2cf(&rsa->modulus, bnbuf);
if (r != 2*base) {
fprintf(stderr, "Invalid public key.\n");
return 2;
@ -335,8 +327,8 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n
memset(bnbuf, 0, 2*base);
memcpy(p, bnbuf, 2*base);
p += 2*base;
r = bn2cf(rsa->e, bnbuf);
memcpy(p, bnbuf, 4);
r = bn2cf(&rsa->exponent, bnbuf);
memcpy(p, bnbuf, 4);
p += 4;
*p++ = 0;
*p++ = 0;
@ -353,20 +345,20 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n
*/
static int
cflex_new_key(struct sc_profile *profile, struct sc_card *card,
EVP_PKEY *key, unsigned int index,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
{
u8 prv[1024], pub[1024];
size_t prvsize, pubsize;
struct sc_file *keyfile = NULL, *tmpfile = NULL;
RSA *rsa = NULL;
struct sc_pkcs15_prkey_rsa *rsa = NULL;
int r;
if (key->type != EVP_PKEY_RSA) {
if (key->algorithm != SC_ALGORITHM_RSA) {
profile->cbs->error("Cryptoflex supports only RSA keys.");
return SC_ERROR_NOT_SUPPORTED;
}
rsa = EVP_PKEY_get1_RSA(key);
rsa = &key->u.rsa;
r = cflex_encode_private_key(rsa, prv, &prvsize, 1);
if (r)
goto err;
@ -383,7 +375,7 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card,
if (r < 0)
goto err;
info->path = keyfile->path;
info->modulus_length = RSA_size(rsa)*8;
info->modulus_length = rsa->modulus.len << 3;
sc_file_dup(&tmpfile, keyfile);
sc_file_clear_acl_entries(tmpfile, SC_AC_OP_READ);
sc_file_add_acl_entry(tmpfile, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE);
@ -394,8 +386,6 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card,
printf("Updating RSA public key...\n");
r = sc_pkcs15init_update_file(profile, card, tmpfile, pub, pubsize);
err:
if (rsa)
RSA_free(rsa);
if (tmpfile)
sc_file_free(tmpfile);
return r;

View File

@ -25,7 +25,6 @@
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <openssl/bn.h>
#include <opensc/opensc.h>
#include <opensc/cardctl.h>
#include "pkcs15-init.h"
@ -65,10 +64,10 @@ static int gpk_new_file(struct sc_profile *, struct sc_card *,
unsigned int, unsigned int,
struct sc_file **);
static int gpk_encode_rsa_key(struct sc_profile *,
RSA *, struct pkdata *,
struct sc_pkcs15_prkey_rsa *, struct pkdata *,
struct sc_pkcs15_prkey_info *);
static int gpk_encode_dsa_key(struct sc_profile *,
DSA *, struct pkdata *,
struct sc_pkcs15_prkey_dsa *, struct pkdata *,
struct sc_pkcs15_prkey_info *);
static int gpk_store_pk(struct sc_profile *, struct sc_card *,
struct sc_file *, struct pkdata *);
@ -297,38 +296,30 @@ gpk_new_pin(struct sc_profile *profile, struct sc_card *card,
*/
static int
gpk_new_key(struct sc_profile *profile, struct sc_card *card,
EVP_PKEY *key, unsigned int index,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
{
struct sc_file *keyfile;
struct pkdata data;
int r;
RSA *rsa;
DSA *dsa;
switch (key->type) {
case EVP_PKEY_RSA:
switch (key->algorithm) {
case SC_ALGORITHM_RSA:
r = gpk_new_file(profile, card,
SC_PKCS15_TYPE_PRKEY_RSA, index,
&keyfile);
if (r >= 0) {
rsa = EVP_PKEY_get1_RSA(key);
r = gpk_encode_rsa_key(profile, rsa, &data, info);
info->modulus_length = 8 * RSA_size(rsa);
RSA_free(rsa);
}
if (r >= 0)
r = gpk_encode_rsa_key(profile, &key->u.rsa,
&data, info);
break;
case EVP_PKEY_DSA:
case SC_ALGORITHM_DSA:
r = gpk_new_file(profile, card,
SC_PKCS15_TYPE_PRKEY_DSA, index,
&keyfile);
if (r >= 0) {
dsa = EVP_PKEY_get1_DSA(key);
r = gpk_encode_dsa_key(profile, dsa, &data, info);
info->modulus_length = 8 * DSA_size(dsa);
DSA_free(dsa);
}
if (r >= 0)
r = gpk_encode_dsa_key(profile, &key->u.dsa,
&data, info);
break;
default:
return SC_ERROR_NOT_SUPPORTED;
@ -723,35 +714,32 @@ gpk_compute_privlen(struct pkpart *part)
/*
* Convert BIGNUM to GPK representation, optionally zero padding to size.
* Note OpenSSL stores BIGNUMs big endian while the GPK wants them
* little endian
* Note that the bignum's we're given are big-endian, while the GPK
* wants them little-endian.
*/
static void
gpk_bn2bin(const BIGNUM *bn, unsigned char *dest, unsigned int size)
gpk_bn2bin(unsigned char *dest, sc_pkcs15_bignum_t *bn, unsigned int size)
{
u8 temp[256], *src;
unsigned int n, len;
u8 *src;
unsigned int n;
assert(BN_num_bytes(bn) <= sizeof(temp));
len = BN_bn2bin(bn, temp);
assert(len <= size);
for (n = 0, src = temp + len - 1; n < len; n++)
dest[n] = *src--;
for (; n < size; n++)
dest[n] = '\0';
assert(bn->len <= size);
memset(dest, 0, size);
for (n = bn->len, src = bn->data; n--; src++)
dest[n] = *src;
}
/*
* Add a BIGNUM component, optionally padding out the number to size bytes
*/
static void
gpk_add_bignum(struct pkpart *part, unsigned int tag, BIGNUM *bn, size_t size)
gpk_add_bignum(struct pkpart *part, unsigned int tag,
sc_pkcs15_bignum_t *bn, size_t size)
{
struct pkcomp *comp;
if (size == 0)
size = BN_num_bytes(bn);
size = bn->len;
comp = &part->components[part->count++];
memset(comp, 0, sizeof(*comp));
@ -763,24 +751,25 @@ gpk_add_bignum(struct pkpart *part, unsigned int tag, BIGNUM *bn, size_t size)
comp->data[0] = tag;
/* Add the BIGNUM */
gpk_bn2bin(bn, comp->data + 1, size);
gpk_bn2bin(comp->data + 1, bn, size);
/* printf("TAG 0x%02x, len=%u\n", tag, comp->size); */
}
int
gpk_encode_rsa_key(struct sc_profile *profile,
RSA *rsa, struct pkdata *p,
struct sc_pkcs15_prkey_rsa *rsa, struct pkdata *p,
struct sc_pkcs15_prkey_info *info)
{
if (!rsa->n || !rsa->e) {
if (!rsa->modulus.len || !rsa->exponent.len) {
error(profile, "incomplete RSA public key");
return SC_ERROR_INVALID_ARGUMENTS;
}
/* Make sure the exponent is 0x10001 because that's
* the only exponent supported by GPK4000 and GPK8000 */
if (!BN_is_word(rsa->e, RSA_F4)) {
if (rsa->exponent.len != 3
|| memcmp(rsa->exponent.data, "\001\000\001", 3)) {
error(profile, "unsupported RSA exponent");
return SC_ERROR_INVALID_ARGUMENTS;
}
@ -788,21 +777,21 @@ gpk_encode_rsa_key(struct sc_profile *profile,
memset(p, 0, sizeof(*p));
p->algo = SC_ALGORITHM_RSA;
p->usage = info->usage;
p->bits = BN_num_bits(rsa->n);
p->bytes = BN_num_bytes(rsa->n);
p->bytes = rsa->modulus.len;
p->bits = p->bytes << 3;
/* Set up the list of public elements */
gpk_add_bignum(&p->public, 0x01, rsa->n, 0);
gpk_add_bignum(&p->public, 0x07, rsa->e, 0);
gpk_add_bignum(&p->public, 0x01, &rsa->modulus, 0);
gpk_add_bignum(&p->public, 0x07, &rsa->exponent, 0);
/* Set up the list of private elements */
if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
if (!rsa->p.len || !rsa->q.len || !rsa->dmp1.len || !rsa->dmq1.len || !rsa->iqmp.len) {
/* No or incomplete CRT information */
if (!rsa->d) {
if (!rsa->d.len) {
error(profile, "incomplete RSA private key");
return SC_ERROR_INVALID_ARGUMENTS;
}
gpk_add_bignum(&p->private, 0x04, rsa->d, 0);
gpk_add_bignum(&p->private, 0x04, &rsa->d, 0);
} else if (5 * (p->bytes / 2) < 256) {
/* All CRT elements are stored in one record */
struct pkcomp *comp;
@ -812,11 +801,11 @@ gpk_encode_rsa_key(struct sc_profile *profile,
crtbuf = malloc(5 * K + 1);
crtbuf[0] = 0x05;
gpk_bn2bin(rsa->p, crtbuf + 1, K);
gpk_bn2bin(rsa->q, crtbuf + 1 + 1 * K, K);
gpk_bn2bin(rsa->iqmp, crtbuf + 1 + 2 * K, K);
gpk_bn2bin(rsa->dmp1, crtbuf + 1 + 3 * K, K);
gpk_bn2bin(rsa->dmq1, crtbuf + 1 + 4 * K, K);
gpk_bn2bin(crtbuf + 1 + 0 * K, &rsa->p, K);
gpk_bn2bin(crtbuf + 1 + 1 * K, &rsa->q, K);
gpk_bn2bin(crtbuf + 1 + 2 * K, &rsa->iqmp, K);
gpk_bn2bin(crtbuf + 1 + 3 * K, &rsa->dmp1, K);
gpk_bn2bin(crtbuf + 1 + 4 * K, &rsa->dmq1, K);
comp = &p->private.components[p->private.count++];
comp->tag = 0x05;
@ -826,11 +815,11 @@ gpk_encode_rsa_key(struct sc_profile *profile,
/* CRT elements stored in individual records.
* Make sure they're all fixed length even if they're
* shorter */
gpk_add_bignum(&p->private, 0x51, rsa->p, p->bytes/2);
gpk_add_bignum(&p->private, 0x52, rsa->q, p->bytes/2);
gpk_add_bignum(&p->private, 0x53, rsa->iqmp, p->bytes/2);
gpk_add_bignum(&p->private, 0x54, rsa->dmp1, p->bytes/2);
gpk_add_bignum(&p->private, 0x55, rsa->dmq1, p->bytes/2);
gpk_add_bignum(&p->private, 0x51, &rsa->p, p->bytes/2);
gpk_add_bignum(&p->private, 0x52, &rsa->q, p->bytes/2);
gpk_add_bignum(&p->private, 0x53, &rsa->iqmp, p->bytes/2);
gpk_add_bignum(&p->private, 0x54, &rsa->dmp1, p->bytes/2);
gpk_add_bignum(&p->private, 0x55, &rsa->dmq1, p->bytes/2);
}
return 0;
@ -844,10 +833,11 @@ gpk_encode_rsa_key(struct sc_profile *profile,
*/
int
gpk_encode_dsa_key(struct sc_profile *profile,
DSA *dsa, struct pkdata *p,
struct sc_pkcs15_prkey_dsa *dsa, struct pkdata *p,
struct sc_pkcs15_prkey_info *info)
{
if (!dsa->p || !dsa->q || !dsa->g || !dsa->pub_key || !dsa->priv_key) {
if (!dsa->p.len || !dsa->q.len || !dsa->g.len
|| !dsa->pub.len || !dsa->priv.len) {
error(profile, "incomplete DSA public key");
return SC_ERROR_INVALID_ARGUMENTS;
}
@ -855,8 +845,8 @@ gpk_encode_dsa_key(struct sc_profile *profile,
memset(p, 0, sizeof(*p));
p->algo = SC_ALGORITHM_RSA;
p->usage = info->usage;
p->bits = BN_num_bits(dsa->p);
p->bytes = BN_num_bytes(dsa->p);
p->bytes = dsa->q.len;
p->bits = dsa->q.len << 3;
/* Make sure the key is either 512 or 1024 bits */
if (p->bytes <= 64) {
@ -871,13 +861,13 @@ gpk_encode_dsa_key(struct sc_profile *profile,
}
/* Set up the list of public elements */
gpk_add_bignum(&p->public, 0x09, dsa->p, 0);
gpk_add_bignum(&p->public, 0x0a, dsa->q, 0);
gpk_add_bignum(&p->public, 0x0b, dsa->g, 0);
gpk_add_bignum(&p->public, 0x0c, dsa->pub_key, 0);
gpk_add_bignum(&p->public, 0x09, &dsa->p, 0);
gpk_add_bignum(&p->public, 0x0a, &dsa->q, 0);
gpk_add_bignum(&p->public, 0x0b, &dsa->g, 0);
gpk_add_bignum(&p->public, 0x0c, &dsa->pub, 0);
/* Set up the list of private elements */
gpk_add_bignum(&p->private, 0x0d, dsa->priv_key, 0);
gpk_add_bignum(&p->private, 0x0d, &dsa->priv, 0);
return 0;
}

View File

@ -7,8 +7,6 @@
#ifndef PKCS15_INIT_H
#define PKCS15_INIT_H
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <opensc/pkcs15.h>
struct sc_profile; /* opaque type */
@ -44,7 +42,7 @@ struct sc_pkcs15init_operations {
* Store a key on the card
*/
int (*new_key)(struct sc_profile *, struct sc_card *,
EVP_PKEY *key, unsigned int index,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *);
/*
@ -94,28 +92,32 @@ struct sc_pkcs15init_pinargs {
size_t puk_len;
};
struct sc_pkcs15init_keyargs {
struct sc_pkcs15init_prkeyargs {
struct sc_pkcs15_id id;
struct sc_pkcs15_id auth_id;
const char * label;
const char * template_name;
unsigned long usage;
unsigned long x509_usage;
/* For key generation */
unsigned char onboard_keygen;
unsigned int algorithm;
unsigned int keybits;
sc_pkcs15_prkey_t key;
};
EVP_PKEY * pkey;
X509 * cert;
struct sc_pkcs15init_pubkeyargs {
struct sc_pkcs15_id id;
struct sc_pkcs15_id auth_id;
const char * label;
unsigned long usage;
unsigned long x509_usage;
sc_pkcs15_pubkey_t key;
};
struct sc_pkcs15init_certargs {
struct sc_pkcs15_id id;
const char * label;
const char * template_name;
X509 * cert;
unsigned long x509_usage;
sc_pkcs15_der_t der_encoded;
};
extern void sc_pkcs15init_set_callbacks(struct sc_pkcs15init_callbacks *);
@ -132,15 +134,16 @@ extern int sc_pkcs15init_store_pin(struct sc_pkcs15_card *,
struct sc_pkcs15init_pinargs *);
extern int sc_pkcs15init_generate_key(struct sc_pkcs15_card *,
struct sc_profile *,
struct sc_pkcs15init_keyargs *,
struct sc_pkcs15init_prkeyargs *,
unsigned int keybits,
struct sc_pkcs15_object **);
extern int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *,
struct sc_profile *,
struct sc_pkcs15init_keyargs *,
struct sc_pkcs15init_prkeyargs *,
struct sc_pkcs15_object **);
extern int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *,
struct sc_profile *,
struct sc_pkcs15init_keyargs *,
struct sc_pkcs15init_pubkeyargs *,
struct sc_pkcs15_object **);
extern int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *,
struct sc_profile *,

View File

@ -57,16 +57,10 @@
typedef int (*pkcs15_encoder)(struct sc_context *,
struct sc_pkcs15_card *, u8 **, size_t *);
static int sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *,
struct sc_profile *, struct sc_pkcs15init_keyargs *,
struct sc_pkcs15_object **);
static int sc_pkcs15init_store_data(struct sc_pkcs15_card *,
struct sc_profile *, unsigned int, void *,
int (*)(void *, u8 **, size_t *),
struct sc_path *);
static int encode_pubkey(void *, u8 **, size_t *);
static int encode_cert(void *, u8 **, size_t *);
struct sc_profile *, unsigned int,
sc_pkcs15_der_t *, struct sc_path *);
static size_t sc_pkcs15init_keybits(sc_pkcs15_bignum_t *);
static int sc_pkcs15init_update_dir(struct sc_pkcs15_card *,
struct sc_profile *profile,
@ -78,13 +72,15 @@ static int sc_pkcs15init_update_odf(struct sc_pkcs15_card *,
static int sc_pkcs15init_update_df(struct sc_pkcs15_card *,
struct sc_profile *profile,
unsigned int df_type);
static int sc_pkcs15init_x509_key_usage(X509 *, int);
static int sc_pkcs15init_map_usage(unsigned long, int);
static int set_so_pin_from_card(struct sc_pkcs15_card *,
struct sc_profile *);
static int do_select_parent(struct sc_profile *, struct sc_card *,
struct sc_file *, struct sc_file **);
static int aodf_add_pin(struct sc_pkcs15_card *, struct sc_profile *,
const struct sc_pkcs15_pin_info *, const char *);
static int fixup_rsa_key(struct sc_pkcs15_prkey_rsa *);
static int fixup_dsa_key(struct sc_pkcs15_prkey_dsa *);
static void default_error_handler(const char *fmt, ...);
static void default_debug_handler(const char *fmt, ...);
@ -290,6 +286,17 @@ sc_pkcs15init_store_pin(struct sc_pkcs15_card *p15card,
p15init_error("No auth_id specified for new PIN");
return SC_ERROR_INVALID_ARGUMENTS;
}
} else {
struct sc_pkcs15_object *dummy;
/* Make sure we don't get duplicate PIN IDs */
card->ctx->log_errors = 0;
r = sc_pkcs15_find_pin_by_auth_id(p15card,
&args->auth_id, &dummy);
if (r != SC_ERROR_OBJECT_NOT_FOUND) {
p15init_error("There already is a PIN with this ID.");
return SC_ERROR_INVALID_ARGUMENTS;
}
}
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info);
@ -353,68 +360,14 @@ aodf_add_pin(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
int
sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_pkcs15init_prkeyargs *keyargs,
unsigned int keybits,
struct sc_pkcs15_object **res_obj)
{
if (keyargs->onboard_keygen)
return SC_ERROR_NOT_SUPPORTED;
/* Fall back to software generated keys */
return sc_pkcs15init_generate_key_soft(p15card, profile,
keyargs, res_obj);
/* Currently, we do not support on-board key generation */
return SC_ERROR_NOT_SUPPORTED;
}
static int
sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_pkcs15_object **res_obj)
{
int r;
keyargs->pkey = EVP_PKEY_new();
switch (keyargs->algorithm) {
case SC_ALGORITHM_RSA: {
RSA *rsa;
BIO *err;
err = BIO_new(BIO_s_mem());
rsa = RSA_generate_key(keyargs->keybits,
0x10001, NULL, err);
BIO_free(err);
if (rsa == 0) {
p15init_error("RSA key generation error");
return -1;
}
EVP_PKEY_assign_RSA(keyargs->pkey, rsa);
break;
}
case SC_ALGORITHM_DSA: {
DSA *dsa;
int r = 0;
dsa = DSA_generate_parameters(keyargs->keybits,
NULL, 0, NULL,
NULL, NULL, NULL);
if (dsa)
r = DSA_generate_key(dsa);
if (r == 0 || dsa == 0) {
p15init_error("DSA key generation error");
return -1;
}
EVP_PKEY_assign_DSA(keyargs->pkey, dsa);
break;
}
default:
return SC_ERROR_NOT_SUPPORTED;
}
r = sc_pkcs15init_store_private_key(p15card, profile, keyargs, res_obj);
if (r < 0)
return r;
return 0;
}
/*
* Store private key
@ -422,22 +375,32 @@ sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *p15card,
int
sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_pkcs15init_prkeyargs *keyargs,
struct sc_pkcs15_object **res_obj)
{
struct sc_pkcs15_pin_info *pin_info = NULL;
struct sc_pkcs15_object *object;
struct sc_pkcs15_prkey_info *key_info;
sc_pkcs15_prkey_t key;
const char *label;
unsigned int type, index, usage;
int r;
unsigned int keybits, type, index, usage;
int r = 0;
switch (keyargs->algorithm) {
/* Create a copy of the key first */
key = keyargs->key;
switch (key.algorithm) {
case SC_ALGORITHM_RSA:
type = SC_PKCS15_TYPE_PRKEY_RSA; break;
keybits = sc_pkcs15init_keybits(&key.u.rsa.modulus);
type = SC_PKCS15_TYPE_PRKEY_RSA;
r = fixup_rsa_key(&key.u.rsa);
break;
#ifdef SC_PKCS15_TYPE_PRKEY_DSA
case SC_ALGORITHM_DSA:
type = SC_PKCS15_TYPE_PRKEY_DSA; break;
keybits = sc_pkcs15init_keybits(&key.u.dsa.q);
type = SC_PKCS15_TYPE_PRKEY_DSA;
r = fixup_dsa_key(&key.u.dsa);
break;
#endif
default:
p15init_error("Unsupported key algorithm.\n");
@ -459,10 +422,9 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
if (keyargs->id.len == 0)
sc_pkcs15_format_id(DEFAULT_ID, &keyargs->id);
if ((usage = keyargs->usage) == 0) {
if (keyargs->cert)
usage = sc_pkcs15init_x509_key_usage(keyargs->cert, 1);
else
usage = SC_PKCS15_PRKEY_USAGE_SIGN;
usage = SC_PKCS15_PRKEY_USAGE_SIGN;
if (keyargs->x509_usage)
usage = sc_pkcs15init_map_usage(keyargs->x509_usage, 1);
}
if ((label = keyargs->label) == NULL)
label = "Private Key";
@ -472,7 +434,8 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
key_info->usage = usage;
key_info->native = 1;
key_info->key_reference = 0;
/* modulus_length and path set by card driver */
key_info->modulus_length = keybits;
/* path set by card driver */
object = calloc(1, sizeof(*object));
object->type = type;
@ -489,7 +452,7 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
return r;
r = profile->ops->new_key(profile, p15card->card,
keyargs->pkey, index, key_info);
&key, index, key_info);
if (r == SC_ERROR_NOT_SUPPORTED) {
/* XXX: handle extractable keys here.
* Store the private key, encrypted.
@ -518,20 +481,27 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card,
int
sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_pkcs15init_pubkeyargs *keyargs,
struct sc_pkcs15_object **res_obj)
{
struct sc_pkcs15_object *object;
struct sc_pkcs15_pubkey_info *key_info;
sc_pkcs15_pubkey_t key;
sc_pkcs15_der_t der_encoded;
const char *label;
unsigned int type, usage;
unsigned int keybits, type, usage;
int r;
switch (keyargs->algorithm) {
/* Create a copy of the key first */
key = keyargs->key;
switch (key.algorithm) {
case SC_ALGORITHM_RSA:
keybits = sc_pkcs15init_keybits(&key.u.rsa.modulus);
type = SC_PKCS15_TYPE_PUBKEY_RSA; break;
#ifdef SC_PKCS15_TYPE_PUBKEY_DSA
case SC_ALGORITHM_DSA:
keybits = sc_pkcs15init_keybits(&key.u.dsa.q);
type = SC_PKCS15_TYPE_PUBKEY_DSA; break;
#endif
default:
@ -542,10 +512,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
if (keyargs->id.len == 0)
sc_pkcs15_format_id(DEFAULT_ID, &keyargs->id);
if ((usage = keyargs->usage) == 0) {
if (keyargs->cert)
usage = sc_pkcs15init_x509_key_usage(keyargs->cert, 0);
else
usage = SC_PKCS15_PRKEY_USAGE_SIGN;
usage = SC_PKCS15_PRKEY_USAGE_SIGN;
if (keyargs->x509_usage)
usage = sc_pkcs15init_map_usage(keyargs->x509_usage, 0);
}
if ((label = keyargs->label) == NULL)
label = "Public Key";
@ -553,7 +522,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
key_info = calloc(1, sizeof(*key_info));
key_info->id = keyargs->id;
key_info->usage = usage;
key_info->modulus_length = 8 * EVP_PKEY_size(keyargs->pkey);
key_info->modulus_length = keybits;
object = calloc(1, sizeof(*object));
object->type = type;
@ -561,10 +530,15 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
object->flags = DEFAULT_PUBKEY_FLAGS;
strncpy(object->label, label, sizeof(object->label));
/* DER encode public key components */
r = sc_pkcs15_encode_pubkey(p15card->card->ctx, &key,
&der_encoded.value, &der_encoded.len);
if (r < 0)
return r;
/* Now create key file and store key */
r = sc_pkcs15init_store_data(p15card, profile,
type, keyargs->pkey,
encode_pubkey, &key_info->path);
type, &der_encoded, &key_info->path);
/* Update the PuKDF */
if (r >= 0)
@ -593,7 +567,9 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
const char *label;
int r;
usage = sc_pkcs15init_x509_key_usage(args->cert, 0);
usage = SC_PKCS15_PRKEY_USAGE_SIGN;
if (args->x509_usage)
usage = sc_pkcs15init_map_usage(args->x509_usage, 0);
if ((label = args->label) == NULL)
label = "Certificate";
if (args->id.len == 0)
@ -633,8 +609,8 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
strncpy(object->label, label, sizeof(object->label));
r = sc_pkcs15init_store_data(p15card, profile,
SC_PKCS15_TYPE_CERT_X509, args->cert,
encode_cert, &cert_info->path);
SC_PKCS15_TYPE_CERT_X509, &args->der_encoded,
&cert_info->path);
/* Now update the CDF */
if (r >= 0)
@ -651,22 +627,14 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
static int
sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
unsigned int type, void *ptr,
int (*encode)(void *, u8 **, size_t *),
unsigned int type, sc_pkcs15_der_t *data,
struct sc_path *path)
{
struct sc_file *file = NULL;
unsigned char *data = NULL;
unsigned int index;
size_t size;
int r;
/* Encode the object */
r = encode(ptr, &data, &size);
if (r < 0)
return r;
/* Get the number of private keys already on this card */
/* Get the number of objects of this type already on this card */
index = sc_pkcs15_get_objects(p15card,
type & SC_PKCS15_TYPE_CLASS_MASK, NULL, 0);
@ -682,63 +650,14 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
}
r = sc_pkcs15init_update_file(profile, p15card->card,
file, data, size);
file, data->value, data->len);
*path = file->path;
done: if (file)
sc_file_free(file);
if (data)
free(data);
return r;
}
/*
* Encoder functions
*/
static int
encode_pubkey(void *ptr, u8 **data, size_t *sizep)
{
EVP_PKEY *pk = (EVP_PKEY *) ptr;
RSA *rsa;
DSA *dsa;
u8 *p;
switch (pk->type) {
case EVP_PKEY_RSA:
rsa = EVP_PKEY_get1_RSA(pk);
*sizep = i2d_RSAPublicKey(rsa, NULL);
*data = p = malloc(*sizep);
i2d_RSAPublicKey(rsa, &p);
RSA_free(rsa);
break;
case EVP_PKEY_DSA:
dsa = EVP_PKEY_get1_DSA(pk);
*sizep = i2d_DSAPublicKey(dsa, NULL);
*data = p = malloc(*sizep);
i2d_DSAPublicKey(dsa, &p);
DSA_free(dsa);
break;
default:
p15init_error("Unsupported key algorithm.\n");
return SC_ERROR_NOT_SUPPORTED;
}
return 0;
}
static int
encode_cert(void *ptr, u8 **data, size_t *sizep)
{
X509 *cert = (X509 *) ptr;
u8 *p;
*sizep = i2d_X509(cert, NULL);
*data = p = malloc(*sizep);
i2d_X509(cert, &p);
return 0;
}
/*
* Map X509 keyUsage extension bits to PKCS#15 keyUsage bits
*/
@ -769,9 +688,8 @@ static unsigned int x509_to_pkcs15_public_key_usage[16] = {
};
static int
sc_pkcs15init_x509_key_usage(X509 *cert, int private)
sc_pkcs15init_map_usage(unsigned long x509_usage, int private)
{
unsigned int x509_usage = cert->ex_kusage;
unsigned int p15_usage, n, *bits;
bits = private? x509_to_pkcs15_private_key_usage
@ -783,6 +701,101 @@ sc_pkcs15init_x509_key_usage(X509 *cert, int private)
return p15_usage;
}
/*
* Compute modulus length
*/
size_t
sc_pkcs15init_keybits(sc_pkcs15_bignum_t *bn)
{
unsigned int mask, bits;
bits = bn->len << 3;
for (mask = 0x80; !(bn->data[0] & mask); mask >>= 1)
bits--;
return bits;
}
/*
* Check RSA key for consistency, and compute missing
* CRT elements
*/
int
fixup_rsa_key(struct sc_pkcs15_prkey_rsa *key)
{
if (!key->modulus.len || !key->exponent.len
|| !key->d.len || !key->p.len || !key->q.len) {
p15init_error("Missing private RSA coefficient");
return SC_ERROR_INVALID_ARGUMENTS;
}
#ifdef HAVE_OPENSSL
#define GETBN(dst, src, mem) \
do { dst.len = BN_num_bytes(src); \
assert(dst.len <= sizeof(mem)); \
BN_bn2bin(src, dst.data = mem); \
} while (0)
/* Generate additional parameters.
* At least the GPK seems to need the full set of CRT
* parameters; storing just the private exponent produces
* invalid signatures.
* The cryptoflex does not seem to be able to do any sort
* of RSA without the full set of CRT coefficients either
*/
if (!key->dmp1.len || !key->dmq1.len || !key->iqmp.len) {
static u8 dmp1[256], dmq1[256], iqmp[256];
RSA *rsa;
BIGNUM *aux = BN_new();
BN_CTX *ctx = BN_CTX_new();
rsa = RSA_new();
rsa->n = BN_bin2bn(key->modulus.data, key->modulus.len, 0);
rsa->e = BN_bin2bn(key->exponent.data, key->exponent.len, 0);
rsa->d = BN_bin2bn(key->d.data, key->d.len, 0);
rsa->p = BN_bin2bn(key->p.data, key->p.len, 0);
rsa->q = BN_bin2bn(key->q.data, key->q.len, 0);
if (!rsa->dmp1)
rsa->dmp1 = BN_new();
if (!rsa->dmq1)
rsa->dmq1 = BN_new();
if (!rsa->iqmp)
rsa->iqmp = BN_new();
aux = BN_new();
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
/* Not thread safe, but much better than a memory leak */
GETBN(key->dmp1, rsa->dmp1, dmp1);
GETBN(key->dmq1, rsa->dmq1, dmq1);
GETBN(key->iqmp, rsa->iqmp, iqmp);
RSA_free(rsa);
}
#undef GETBN
#endif
return 0;
}
static int
fixup_dsa_key(struct sc_pkcs15_prkey_dsa *key)
{
/* for now */
return 0;
}
/*
* Update EF(DIR)
*/
static int
sc_pkcs15init_update_dir(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,

View File

@ -23,7 +23,6 @@
#endif
#include <string.h>
#include <sys/types.h>
#include <openssl/bn.h>
#include <opensc/opensc.h>
#include <opensc/cardctl.h>
#include "pkcs15-init.h"
@ -153,37 +152,17 @@ miocos_new_file(struct sc_profile *profile, struct sc_card *card,
return 0;
}
static int bn2bin(const BIGNUM *num, u8 *buf)
{
int r;
r = BN_bn2bin(num, buf);
if (r <= 0)
return r;
return 0;
}
static int
miocos_update_private_key(struct sc_profile *profile, struct sc_card *card,
RSA *rsa)
struct sc_pkcs15_prkey_rsa *rsa)
{
int r;
u8 modulus[128];
u8 priv_exp[128];
u8 buf[266];
if (bn2bin(rsa->d, priv_exp) != 0) {
profile->cbs->error("Unable to convert private exponent.");
return -1;
}
if (bn2bin(rsa->n, modulus) != 0) {
profile->cbs->error("Unable to convert modulus.");
return -1;
}
memcpy(buf, "\x30\x82\x01\x06\x80\x81\x80", 7);
memcpy(buf + 7, modulus, 128);
memcpy(buf + 7, rsa->modulus.data, 128);
memcpy(buf + 7 + 128, "\x82\x81\x80", 3);
memcpy(buf + 10 + 128, priv_exp, 128);
memcpy(buf + 10 + 128, rsa->d.data, 128);
r = sc_update_binary(card, 0, buf, sizeof(buf), 0);
return r;
@ -194,39 +173,34 @@ miocos_update_private_key(struct sc_profile *profile, struct sc_card *card,
*/
static int
miocos_new_key(struct sc_profile *profile, struct sc_card *card,
EVP_PKEY *key, unsigned int index,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
{
sc_file_t *keyfile;
RSA *rsa;
struct sc_pkcs15_prkey_rsa *rsa;
int r;
if (key->type != EVP_PKEY_RSA) {
if (key->algorithm != SC_ALGORITHM_RSA) {
profile->cbs->error("MioCOS supports only 1024-bit RSA keys.");
return SC_ERROR_NOT_SUPPORTED;
}
rsa = EVP_PKEY_get1_RSA(key);
if (RSA_size(rsa) != 128) {
RSA_free(rsa);
rsa = &key->u.rsa;
if (rsa->modulus.len != 128) {
profile->cbs->error("MioCOS supports only 1024-bit RSA keys.");
return SC_ERROR_NOT_SUPPORTED;
}
r = miocos_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index,
&keyfile);
if (r < 0) {
RSA_free(rsa);
if (r < 0)
return r;
}
info->modulus_length = 1024;
info->path = keyfile->path;
r = sc_pkcs15init_create_file(profile, card, keyfile);
sc_file_free(keyfile);
if (r < 0) {
RSA_free(rsa);
if (r < 0)
return r;
}
r = miocos_update_private_key(profile, card, rsa);
RSA_free(rsa);
return r;
}

View File

@ -27,6 +27,7 @@
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <opensc/scconf.h>
#include "pkcs15-init.h"
#include "profile.h"

View File

@ -7,8 +7,6 @@
#ifndef _OPENSC_PROFILE_H
#define _OPENSC_PROFILE_H
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <opensc/pkcs15.h>
#ifndef SC_PKCS15_PROFILE_DIRECTORY

View File

@ -41,6 +41,8 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/bn.h>
#include <openssl/pkcs12.h>
#include <opensc/pkcs15.h>
#include <opensc/pkcs15-init.h>
@ -57,9 +59,12 @@ static int connect(int);
static int do_init_app(struct sc_profile *);
static int do_store_pin(struct sc_profile *);
static int do_generate_key(struct sc_profile *, const char *);
static int do_store_private_key(struct sc_profile *profile);
static int do_store_public_key(struct sc_profile *profile);
static int do_store_certificate(struct sc_profile *profile);
static int do_store_private_key(struct sc_profile *);
static int do_store_public_key(struct sc_profile *, EVP_PKEY *);
static int do_store_certificate(struct sc_profile *);
static int do_convert_private_key(struct sc_pkcs15_prkey *, EVP_PKEY *);
static int do_convert_public_key(struct sc_pkcs15_pubkey *, EVP_PKEY *);
static int do_convert_cert(sc_pkcs15_der_t *, X509 *);
static int read_one_pin(struct sc_profile *, const char *,
@ -68,10 +73,10 @@ static int get_pin_callback(struct sc_profile *profile,
int id, const struct sc_pkcs15_pin_info *info,
u8 *pinbuf, size_t *pinsize);
static int do_generate_key_soft(int, unsigned int, EVP_PKEY **);
static int do_read_private_key(const char *, const char *,
EVP_PKEY **, X509 **);
static int do_read_public_key(const char *, const char *, EVP_PKEY **);
static int do_write_public_key(const char *, const char *, EVP_PKEY *);
static int do_read_certificate(const char *, const char *, X509 **);
static void parse_commandline(int argc, char **argv);
static void read_options_file(const char *);
@ -250,7 +255,7 @@ main(int argc, char **argv)
else if (opt_action == ACTION_STORE_PRIVKEY)
r = do_store_private_key(profile);
else if (opt_action == ACTION_STORE_PUBKEY)
r = do_store_public_key(profile);
r = do_store_public_key(profile, NULL);
else if (opt_action == ACTION_STORE_CERT)
r = do_store_certificate(profile);
else if (opt_action == ACTION_GENERATE_KEY)
@ -395,7 +400,9 @@ do_store_pin(struct sc_profile *profile)
static int
do_store_private_key(struct sc_profile *profile)
{
struct sc_pkcs15init_keyargs args;
struct sc_pkcs15init_prkeyargs args;
EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
int r;
memset(&args, 0, sizeof(args));
@ -410,10 +417,15 @@ do_store_private_key(struct sc_profile *profile)
}
args.label = opt_objectlabel;
r = do_read_private_key(opt_infile, opt_format, &args.pkey, &args.cert);
r = do_read_private_key(opt_infile, opt_format, &pkey, &cert);
if (r < 0)
return r;
if ((r = do_convert_private_key(&args.key, pkey)) < 0)
return r;
if (cert)
args.x509_usage = cert->ex_kusage;
r = sc_pkcs15init_store_private_key(p15card, profile, &args, NULL);
if (r < 0)
return r;
@ -422,17 +434,19 @@ do_store_private_key(struct sc_profile *profile)
* private key from a PKCS #12 file) store it, too.
* Otherwise store the public key.
*/
if (args.cert) {
if (cert) {
struct sc_pkcs15init_certargs cargs;
memset(&cargs, 0, sizeof(cargs));
cargs.id = args.id;
cargs.cert = args.cert;
r = sc_pkcs15init_store_certificate(p15card, profile,
cargs.x509_usage = cert->ex_kusage;
r = do_convert_cert(&cargs.der_encoded, cert);
if (r >= 0)
r = sc_pkcs15init_store_certificate(p15card, profile,
&cargs, NULL);
free(cargs.der_encoded.value);
} else {
r = sc_pkcs15init_store_public_key(p15card, profile,
&args, NULL);
r = do_store_public_key(profile, pkey);
}
return r;
@ -442,10 +456,10 @@ do_store_private_key(struct sc_profile *profile)
* Store a public key
*/
static int
do_store_public_key(struct sc_profile *profile)
do_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey)
{
struct sc_pkcs15init_keyargs args;
int r;
struct sc_pkcs15init_pubkeyargs args;
int r = 0;
memset(&args, 0, sizeof(args));
if (opt_objectid)
@ -453,12 +467,15 @@ do_store_public_key(struct sc_profile *profile)
if (opt_objectlabel)
args.label = opt_objectlabel;
r = do_read_public_key(opt_infile, opt_format, &args.pkey);
if (pkey == NULL)
r = do_read_public_key(opt_infile, opt_format, &pkey);
if (r >= 0)
r = do_convert_public_key(&args.key, pkey);
if (r >= 0)
r = sc_pkcs15init_store_public_key(p15card, profile,
&args, NULL);
return -1;
return r;
}
/*
@ -468,6 +485,7 @@ static int
do_store_certificate(struct sc_profile *profile)
{
struct sc_pkcs15init_certargs args;
X509 *cert;
int r;
memset(&args, 0, sizeof(args));
@ -476,7 +494,9 @@ do_store_certificate(struct sc_profile *profile)
sc_pkcs15_format_id(opt_objectid, &args.id);
args.label = opt_objectlabel;
r = do_read_certificate(opt_infile, opt_format, &args.cert);
r = do_read_certificate(opt_infile, opt_format, &cert);
if (r >= 0)
r = do_convert_cert(&args.der_encoded, cert);
if (r >= 0)
r = sc_pkcs15init_store_certificate(p15card, profile,
&args, NULL);
@ -490,16 +510,19 @@ do_store_certificate(struct sc_profile *profile)
static int
do_generate_key(struct sc_profile *profile, const char *spec)
{
struct sc_pkcs15init_keyargs args;
struct sc_pkcs15init_prkeyargs args;
unsigned int evp_algo, keybits = 1024;
int r;
/* Parse the key spec given on the command line */
memset(&args, 0, sizeof(args));
if (!strncasecmp(spec, "rsa", 3)) {
args.algorithm = SC_ALGORITHM_RSA;
args.key.algorithm = SC_ALGORITHM_RSA;
evp_algo = EVP_PKEY_RSA;
spec += 3;
} else if (!strncasecmp(spec, "dsa", 3)) {
args.algorithm = SC_ALGORITHM_DSA;
args.key.algorithm = SC_ALGORITHM_DSA;
evp_algo = EVP_PKEY_DSA;
spec += 3;
} else {
error("Unknown algorithm \"%s\"", spec);
@ -511,7 +534,7 @@ do_generate_key(struct sc_profile *profile, const char *spec)
if (*spec) {
char *end;
args.keybits = strtoul(spec, &end, 10);
keybits = strtoul(spec, &end, 10);
if (*end) {
error("Invalid number of key bits \"%s\"", spec);
return SC_ERROR_INVALID_ARGUMENTS;
@ -529,26 +552,35 @@ do_generate_key(struct sc_profile *profile, const char *spec)
}
args.label = opt_objectlabel;
while (1) {
r = sc_pkcs15init_generate_key(p15card, profile, &args, NULL);
if (r != SC_ERROR_NOT_SUPPORTED || !args.onboard_keygen)
break;
r = sc_pkcs15init_generate_key(p15card, profile, &args, keybits, NULL);
if (r < 0) {
EVP_PKEY *pkey;
if (r != SC_ERROR_NOT_SUPPORTED)
return r;
if (!opt_quiet)
printf("Warning: card doesn't support on-board "
"key generation; using software generation\n");
args.onboard_keygen = 0;
}
if (r < 0)
return r;
/* Store public key portion on card */
r = sc_pkcs15init_store_public_key(p15card, profile, &args, NULL);
/* Generate the key ourselves */
r = do_generate_key_soft(evp_algo, keybits, &pkey);
if (r >= 0) {
r = do_convert_private_key(&args.key, pkey);
}
if (r >= 0 && opt_outkey) {
if (!opt_quiet)
printf("Writing public key to %s\n", opt_outkey);
r = do_write_public_key(opt_outkey, opt_format, args.pkey);
if (r >= 0)
r = sc_pkcs15init_store_private_key(p15card, profile,
&args, NULL);
/* Store public key portion on card */
if (r >= 0)
r = do_store_public_key(profile, pkey);
EVP_PKEY_free(pkey);
if (r < 0)
return r;
}
return r;
}
@ -627,6 +659,46 @@ get_pin_callback(struct sc_profile *profile,
return 0;
}
/*
* Generate a private key
*/
int
do_generate_key_soft(int algorithm, unsigned int bits, EVP_PKEY **res)
{
*res = EVP_PKEY_new();
switch (algorithm) {
case EVP_PKEY_RSA: {
RSA *rsa;
BIO *err;
err = BIO_new(BIO_s_mem());
rsa = RSA_generate_key(bits, 0x10001, NULL, err);
BIO_free(err);
if (rsa == 0)
fatal("RSA key generation error");
EVP_PKEY_assign_RSA(*res, rsa);
break;
}
case EVP_PKEY_DSA: {
DSA *dsa;
int r = 0;
dsa = DSA_generate_parameters(bits,
NULL, 0, NULL,
NULL, NULL, NULL);
if (dsa)
r = DSA_generate_key(dsa);
if (r == 0 || dsa == 0)
fatal("DSA key generation error");
EVP_PKEY_assign_DSA(*res, dsa);
break;
}
default:
fatal("Unable to generate key: unsupported algorithm");
}
return 0;
}
/*
* Read a private key
*/
@ -762,6 +834,7 @@ do_read_public_key(const char *name, const char *format, EVP_PKEY **out)
return 0;
}
#if 0
/*
* Write a PEM encoded public key
*/
@ -798,6 +871,7 @@ do_write_public_key(const char *filename, const char *format, EVP_PKEY *pk)
}
return r;
}
#endif
/*
* Read a certificate
@ -852,6 +926,100 @@ do_read_certificate(const char *name, const char *format, X509 **out)
return 0;
}
static int
do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src)
{
if (src == 0)
return 0;
dst->len = BN_num_bytes(src);
dst->data = malloc(dst->len);
BN_bn2bin(src, dst->data);
return 1;
}
int
do_convert_private_key(struct sc_pkcs15_prkey *key, EVP_PKEY *pk)
{
switch (pk->type) {
case EVP_PKEY_RSA: {
struct sc_pkcs15_prkey_rsa *dst = &key->u.rsa;
RSA *src = EVP_PKEY_get1_RSA(pk);
key->algorithm = SC_ALGORITHM_RSA;
if (!do_convert_bignum(&dst->modulus, src->n)
|| !do_convert_bignum(&dst->exponent, src->e)
|| !do_convert_bignum(&dst->d, src->d)
|| !do_convert_bignum(&dst->p, src->p)
|| !do_convert_bignum(&dst->q, src->q))
fatal("Invalid/incomplete RSA key.\n");
if (src->iqmp && src->dmp1 && src->dmq1) {
do_convert_bignum(&dst->iqmp, src->iqmp);
do_convert_bignum(&dst->dmp1, src->dmp1);
do_convert_bignum(&dst->dmq1, src->dmq1);
}
RSA_free(src);
break;
}
case EVP_PKEY_DSA: {
struct sc_pkcs15_prkey_dsa *dst = &key->u.dsa;
DSA *src = EVP_PKEY_get1_DSA(pk);
key->algorithm = SC_ALGORITHM_DSA;
do_convert_bignum(&dst->pub, src->pub_key);
do_convert_bignum(&dst->p, src->p);
do_convert_bignum(&dst->q, src->q);
do_convert_bignum(&dst->g, src->g);
do_convert_bignum(&dst->priv, src->priv_key);
DSA_free(src);
}
default:
fatal("Unsupported key algorithm\n");
}
return 0;
}
int
do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk)
{
switch (pk->type) {
case EVP_PKEY_RSA: {
struct sc_pkcs15_pubkey_rsa *dst = &key->u.rsa;
RSA *src = EVP_PKEY_get1_RSA(pk);
key->algorithm = SC_ALGORITHM_RSA;
if (!do_convert_bignum(&dst->modulus, src->n)
|| !do_convert_bignum(&dst->exponent, src->e))
fatal("Invalid/incomplete RSA key.\n");
RSA_free(src);
break;
}
case EVP_PKEY_DSA: {
struct sc_pkcs15_pubkey_dsa *dst = &key->u.dsa;
DSA *src = EVP_PKEY_get1_DSA(pk);
key->algorithm = SC_ALGORITHM_DSA;
do_convert_bignum(&dst->pub, src->pub_key);
DSA_free(src);
}
default:
fatal("Unsupported key algorithm\n");
}
return 0;
}
int
do_convert_cert(sc_pkcs15_der_t *der, X509 *cert)
{
unsigned char *p;
der->len = i2d_X509(cert, NULL);
der->value = p = malloc(der->len);
i2d_X509(cert, &p);
return 0;
}
/*
* Handle one option
*/

View File

@ -354,12 +354,12 @@ int read_public_key(void)
return 1;
}
memcpy(buffer, PEM_RSA_KEY_PREFIX, PEM_RSA_KEY_PREFIX_SIZE);
buffer[1] += key->data_len;
buffer[PEM_RSA_KEY_PREFIX_SIZE-2] = key->data_len + 1;
buffer[1] += key->data.len;
buffer[PEM_RSA_KEY_PREFIX_SIZE-2] = key->data.len + 1;
memcpy(buffer + PEM_RSA_KEY_PREFIX_SIZE,
key->data, key->data_len);
key->data.value, key->data.len);
r = print_pem_object("PUBLIC KEY", buffer,
PEM_RSA_KEY_PREFIX_SIZE + key->data_len);
PEM_RSA_KEY_PREFIX_SIZE + key->data.len);
sc_pkcs15_free_pubkey(key);
return r;
}