- 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:
parent
1ec7a85e51
commit
596220e821
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 *,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue