- Implemented download of public keys and X509 certificates

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@294 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2002-03-12 10:08:18 +00:00
parent f7ce196a66
commit 2c7a0ac27b
7 changed files with 403 additions and 19 deletions

View File

@ -44,6 +44,13 @@ EF template-public-key
Structure transparent
ACL *=NONE
# Certificate template
EF template-certificate
Parent PKCS15-AppDF
FileID 9000
Structure transparent
ACL *=NONE
# CVH1. 7 attempts for the PIN, and 3 for the PUK
# Reference 0x8 means "PIN0 in the local EFsc" in GPK parlance
PIN CHV1

View File

@ -276,18 +276,18 @@ gpk_allocate_file(struct sc_profile *profile, struct sc_card *card,
tag = "public-key";
break;
#ifdef SC_PKCS15_TYPE_PRKEY_DSA
case SC_PKCS15_TYPE_PRKEY_RSA:
desc = "RSA private key";
case SC_PKCS15_TYPE_PRKEY_DSA:
desc = "DSA private key";
tag = "data";
break;
case SC_PKCS15_TYPE_PUBKEY_RSA:
desc = "RSA public key";
case SC_PKCS15_TYPE_PUBKEY_DSA:
desc = "DSA public key";
tag = "data";
break;
#endif
case SC_PKCS15_TYPE_CERT:
desc = "certificate";
tag = "data";
tag = "certificate";
break;
case SC_PKCS15_TYPE_DATA_OBJECT:
desc = "data object";

View File

@ -55,6 +55,7 @@ static void bind_operations(struct pkcs15_init_operations *, const char *);
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 sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *,
struct sc_profile *, struct sc_pkcs15init_keyargs *);
@ -62,20 +63,27 @@ struct sc_pkcs15_object *
sc_pkcs15init_find_key(struct sc_pkcs15_card *p15card,
unsigned int type,
struct sc_pkcs15_id *id);
int sc_pkcs15init_new_private_key(struct sc_profile *profile,
static int sc_pkcs15init_new_private_key(struct sc_profile *profile,
unsigned int type,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_key_template *out);
int sc_pkcs15init_new_public_key(struct sc_profile *profile,
static int sc_pkcs15init_new_public_key(struct sc_profile *profile,
unsigned int type,
struct sc_pkcs15init_keyargs *keyargs,
struct sc_key_template *out);
static int sc_pkcs15init_new_cert(struct sc_profile *profile,
unsigned int type,
struct sc_pkcs15init_certargs *certargs,
struct sc_cert_template *out);
static int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *,
struct sc_profile *, struct sc_pkcs15init_keyargs *);
static int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_keyargs *keyargs);
static int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_certargs *certargs);
static int sc_pkcs15init_update_dir(struct sc_card *card,
struct sc_profile *profile,
struct sc_app_info *app);
@ -90,8 +98,11 @@ static int do_select_parent(struct sc_profile *, struct sc_file *,
struct sc_file **);
static int do_read_pins(struct sc_profile *);
static int set_pins_from_args(struct sc_profile *);
static int do_read_private_key(const char *, const char *, EVP_PKEY **);
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 *);
static void ossl_print_errors(void);
@ -117,10 +128,12 @@ const struct option options[] = {
{ "puk2", required_argument, 0, OPT_PUK2 },
{ "id", required_argument, 0, 'i' },
{ "generate-key", required_argument, 0, 'G' },
{ "pubkey-file", required_argument, 0, 'o' },
{ "store-key", required_argument, 0, 'S' },
{ "key-format", required_argument, 0, 'f' },
{ "output-file", required_argument, 0, 'o' },
{ "store-private-key", required_argument, 0, 'S' },
{ "store-public-key", required_argument, 0, 'P' },
{ "format", required_argument, 0, 'f' },
{ "passphrase", required_argument, 0, OPT_PASSPHRASE },
{ "store-certificate", required_argument, 0, 'X' },
{ "profile", required_argument, 0, 'p' },
{ "options-file", required_argument, 0, OPT_OPTIONS },
@ -138,8 +151,10 @@ const char * option_help[] = {
"Generate a new key and store it on the card",
"Output public portion of generated key to file",
"Store private key",
"Store public key",
"Specify key file format (default PEM)",
"Specify passphrase for unlocking secret key",
"Store an X.509 certificate",
"Specify the profile to use",
"Read additional command line options from file",
@ -164,7 +179,7 @@ static int opt_debug = 0,
opt_erase = 0;
static char * opt_driver = 0;
static char * opt_profile = "pkcs15";
static char * opt_keyfile = 0;
static char * opt_infile = 0;
static char * opt_format = 0;
static char * opt_objectid = 0;
static char * opt_objectlabel = 0;
@ -250,6 +265,8 @@ main(int argc, char **argv)
r = do_store_private_key(&profile);
else if (opt_action == ACTION_STORE_PUBKEY)
r = do_store_public_key(&profile);
else if (opt_action == ACTION_STORE_CERT)
r = do_store_certificate(&profile);
else if (opt_action == ACTION_GENERATE_KEY)
r = do_generate_key(&profile, opt_newkey);
else
@ -339,7 +356,7 @@ do_store_private_key(struct sc_profile *profile)
if (opt_objectlabel)
args.label = opt_objectlabel;
r = do_read_private_key(opt_keyfile, opt_format, &args.pkey);
r = do_read_private_key(opt_infile, opt_format, &args.pkey);
if (r < 0)
return -1;
@ -374,11 +391,9 @@ do_store_public_key(struct sc_profile *profile)
if (opt_objectlabel)
args.label = opt_objectlabel;
#ifdef notyet
r = do_read_public_key(opt_keyfile, opt_format, &args.pkey);
r = do_read_public_key(opt_infile, opt_format, &args.pkey);
if (r < 0)
return r;
#endif
r = sc_pkcs15init_store_public_key(p15card, profile, &args);
if (r < 0)
@ -390,6 +405,28 @@ failed: error("Failed to store public key: %s\n", sc_strerror(r));
return -1;
}
/*
* Download certificate to card
*/
static int
do_store_certificate(struct sc_profile *profile)
{
struct sc_pkcs15init_certargs args;
int r;
memset(&args, 0, sizeof(args));
if (opt_objectid)
sc_pkcs15_format_id(opt_objectid, &args.id);
args.label = opt_objectlabel;
r = do_read_certificate(opt_infile, opt_format, &args.cert);
if (r < 0)
return r;
return sc_pkcs15init_store_certificate(p15card, profile, &args);
}
/*
* Generate a new private key
*/
@ -829,6 +866,105 @@ sc_pkcs15init_new_public_key(struct sc_profile *profile,
return 0;
}
/*
* See if there's a CDF entry matching this certinfo.
* If not, allocate a file and create a corresponding DF entry.
*/
static int
sc_pkcs15init_setup_cert(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_certargs *certargs,
struct sc_cert_template *out)
{
struct sc_pkcs15_object *found = NULL;
int r;
memset(out, 0, sizeof(*out));
/* If a key ID has been given, try to locate the key. */
r = sc_pkcs15_find_cert_by_id(p15card, &certargs->id, &found);
if (found) {
/* XXX: TBD set up out */
r = SC_ERROR_NOT_SUPPORTED; /* we don't support updates yet */
} else {
/* If there's no such key on the card yet, allocate an ID,
* and a file.
*/
r = sc_pkcs15init_new_cert(profile,
SC_PKCS15_TYPE_CERT_X509,
certargs, out);
}
return r;
}
int
sc_pkcs15init_new_cert(struct sc_profile *profile,
unsigned int type,
struct sc_pkcs15init_certargs *certargs,
struct sc_cert_template *out)
{
struct sc_cert_template *template;
int index, r;
index = sc_pkcs15_get_objects(p15card, type, NULL, 0);
if (certargs->template_name)
template = sc_profile_find_cert(profile,
certargs->template_name);
else
template = profile->cert_list;
if (template == NULL)
return SC_ERROR_OBJECT_NOT_FOUND;
out->file = template->file;
if (certargs->label)
strcpy(out->pkcs15_obj.label, certargs->label);
else if (!out->pkcs15_obj.label[0])
strcpy(out->pkcs15_obj.label, "Certificate");
if (certargs->id.len)
out->pkcs15.id = certargs->id;
else {
struct sc_pkcs15_id *ip = &out->pkcs15.id;
if (!ip->len)
sc_pkcs15_format_id("45", ip);
ip->value[ip->len-1] += index;
}
/* Sanity checks */
if (!out->pkcs15.id.len) {
/* error("No ID set for certificate object"); */
return SC_ERROR_INVALID_ARGUMENTS;
}
/* Now allocate a file */
r = profile->ops->allocate_file(profile,
p15card->card, type, index,
&out->file);
if (r < 0) {
/* error("Unable to allocate certificate file"); */
return r;
}
out->pkcs15.path = out->file->path;
out->pkcs15_obj.data = &out->pkcs15;
out->pkcs15_obj.type = type;
r = sc_pkcs15_add_object(p15card, &p15card->df[SC_PKCS15_CDF],
0, &out->pkcs15_obj);
if (r) {
/* error("failed to add object to CDF"); */
return r;
}
/* Return the ID we selected, for reference */
certargs->id = out->pkcs15.id;
return 0;
}
/*
* Find a key given its ID
*/
@ -946,6 +1082,34 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card,
return sc_pkcs15init_update_df(p15card, profile, SC_PKCS15_PUKDF);
}
static int
sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_certargs *args)
{
struct sc_cert_template info;
unsigned char *data, *p;
size_t size;
int r;
r = sc_pkcs15init_setup_cert(p15card, profile, args, &info);
if (r < 0)
return r;
size = i2d_X509(args->cert, NULL);
data = p = malloc(size);
i2d_X509(args->cert, NULL);
r = sc_pkcs15init_update_file(profile, info.file, data, size);
free(data);
if (r < 0)
return r;
/* Now update the CDF */
return sc_pkcs15init_update_df(p15card, profile, SC_PKCS15_CDF);
}
static int
sc_pkcs15init_update_dir(struct sc_card *card,
struct sc_profile *profile,
@ -1275,7 +1439,7 @@ sc_pkcs15init_update_file(struct sc_profile *profile,
{
int r;
if ((r = sc_select_file(card, &file->path, NULL)) < 0) {
if ((r = sc_select_file(card, &file->path, &file)) < 0) {
/* Create file if it doesn't exist */
if (file->size < datalen)
file->size = datalen;
@ -1344,7 +1508,60 @@ do_read_private_key(const char *filename, const char *format, EVP_PKEY **pk)
}
/*
* Write a PEM encoded publci key
* Read a public key
*/
static EVP_PKEY *
do_read_pem_public_key(const char *filename)
{
BIO *bio;
EVP_PKEY *pk;
bio = BIO_new(BIO_s_file());
if (BIO_read_filename(bio, filename) < 0)
fatal("Unable to open %s: %m", filename);
pk = PEM_read_bio_PUBKEY(bio, 0, 0, NULL);
BIO_free(bio);
if (pk == NULL)
ossl_print_errors();
return pk;
}
static EVP_PKEY *
do_read_der_public_key(const char *filename)
{
BIO *bio;
EVP_PKEY *pk;
bio = BIO_new(BIO_s_file());
if (BIO_read_filename(bio, filename) < 0)
fatal("Unable to open %s: %m", filename);
pk = d2i_PUBKEY_bio(bio, NULL);
BIO_free(bio);
if (pk == NULL)
ossl_print_errors();
return pk;
}
static int
do_read_public_key(const char *name, const char *format, EVP_PKEY **out)
{
if (!format || !strcasecmp(format, "pem")) {
*out = do_read_pem_public_key(name);
} else if (!strcasecmp(format, "der")) {
*out = do_read_der_public_key(name);
} else {
fatal("Error when reading public key. "
"File format \"%s\" not supported.\n",
format);
}
if (!*out)
fatal("Unable to read public key from %s\n", name);
return 0;
}
/*
* Write a PEM encoded public key
*/
static int
do_write_pem_public_key(const char *filename, EVP_PKEY *pk)
@ -1380,6 +1597,59 @@ do_write_public_key(const char *filename, const char *format, EVP_PKEY *pk)
return r;
}
/*
* Read a certificate
*/
static X509 *
do_read_pem_certificate(const char *filename)
{
BIO *bio;
X509 *xp;
bio = BIO_new(BIO_s_file());
if (BIO_read_filename(bio, filename) < 0)
fatal("Unable to open %s: %m", filename);
xp = PEM_read_bio_X509(bio, 0, 0, 0);
BIO_free(bio);
if (xp == NULL)
ossl_print_errors();
return xp;
}
static X509 *
do_read_der_certificate(const char *filename)
{
BIO *bio;
X509 *xp;
bio = BIO_new(BIO_s_file());
if (BIO_read_filename(bio, filename) < 0)
fatal("Unable to open %s: %m", filename);
xp = d2i_X509_bio(bio, NULL);
BIO_free(bio);
if (xp == NULL)
ossl_print_errors();
return xp;
}
static int
do_read_certificate(const char *name, const char *format, X509 **out)
{
if (!format || !strcasecmp(format, "pem")) {
*out = do_read_pem_certificate(name);
} else if (!strcasecmp(format, "der")) {
*out = do_read_der_certificate(name);
} else {
fatal("Error when reading certificate. "
"File format \"%s\" not supported.\n",
format);
}
if (!*out)
fatal("Unable to read certificate from %s\n", name);
return 0;
}
/*
* Handle one option
*/
@ -1399,7 +1669,15 @@ handle_option(int c)
break;
case 'S':
opt_action = ACTION_STORE_PRIVKEY;
opt_keyfile = optarg;
opt_infile = optarg;
break;
case 'P':
opt_action = ACTION_STORE_PUBKEY;
opt_infile = optarg;
break;
case 'X':
opt_action = ACTION_STORE_CERT;
opt_infile = optarg;
break;
case 'd':
opt_debug++;

View File

@ -8,6 +8,7 @@
#define PKCS15_INIT_H
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "profile.h"
struct pkcs15_init_operations {
@ -34,6 +35,14 @@ struct sc_pkcs15init_keyargs {
EVP_PKEY * pkey;
};
struct sc_pkcs15init_certargs {
struct sc_pkcs15_id id;
const char * label;
const char * template_name;
X509 * cert;
};
extern int sc_pkcs15init_add_app(struct sc_card *,
struct sc_profile *);
extern int sc_pkcs15init_generate_key(struct sc_pkcs15_card *,

View File

@ -80,3 +80,12 @@ PublicKey SignKey
Label "Non-repudiation Key"
ID 46
KeyUsage NonRepudiation
Certificate AuthCertificate
Label "Authentication Certificate"
ID 45
Certificate SignCertificate
Label "Non-repudiation Certificate"
ID 46

View File

@ -44,7 +44,8 @@ enum {
PARSE_CARDINFO,
PARSE_PIN,
PARSE_PRKEY,
PARSE_PUBKEY
PARSE_PUBKEY,
PARSE_CERT
};
static struct parser_info {
@ -58,6 +59,7 @@ static struct file_info * cur_file;
static struct sc_file * cur_parent;
static struct pin_info * cur_pin;
static struct sc_key_template * cur_key;
static struct sc_cert_template *cur_cert;
struct map {
const char * name;
@ -1181,6 +1183,58 @@ do_pubkey_reference(int argc, char **argv)
return get_uint(argv[0], (unsigned int *) &ki->key_reference);
}
static int
do_cert(int argc, char **argv)
{
struct sc_profile *pro = parser.profile;
struct sc_cert_template *ci, **tail;
if ((ci = sc_profile_find_cert(pro, argv[0])) != NULL)
goto out;
ci = calloc(1, sizeof(*ci));
ci->ident = strdup(argv[0]);
ci->pkcs15_obj.type = SC_PKCS15_TYPE_CERT_X509;
ci->pkcs15_obj.data = &ci->pkcs15;
for (tail = &pro->cert_list; *tail; tail = &(*tail)->next)
;
*tail = ci;
out: parser.section = PARSE_CERT;
cur_cert = ci;
return 0;
}
static int
do_cert_file(int argc, char **argv)
{
struct file_info *fi;
const char *name = argv[0];
if (!(fi = sc_profile_find_file(parser.profile, name))) {
parse_error("unknown certificate file \"%s\"\n", name);
return 1;
}
cur_cert->file = fi->file;
return 0;
}
static int
do_cert_label(int argc, char **argv)
{
strcpy(cur_cert->pkcs15_obj.label, argv[0]);
return 0;
}
static int
do_cert_id(int argc, char **argv)
{
sc_pkcs15_format_id(argv[0], &cur_cert->pkcs15.id);
return 0;
}
static struct command commands[] = {
{ "CardInfo", -1, 0, 0, do_cardinfo },
{ "Driver", PARSE_CARDINFO, 1, 1, do_card_driver },
@ -1231,6 +1285,10 @@ static struct command commands[] = {
{ "KeyUsage", PARSE_PUBKEY, 1, 1, do_pubkey_usage },
{ "AccessFlags", PARSE_PUBKEY, 1, -1, do_pubkey_access_flags },
{ "Reference", PARSE_PUBKEY, 1, 1, do_pubkey_reference },
{ "Certificate", -1, 1, 1, do_cert },
{ "Label", PARSE_CERT, 1, 1, do_cert_label },
{ "File", PARSE_CERT, 1, 1, do_cert_file },
{ "ID", PARSE_CERT, 1, 1, do_cert_id },
#if 0
#endif
@ -1354,6 +1412,18 @@ sc_profile_find_public_key(struct sc_profile *pro, const char *ident)
return NULL;
}
struct sc_cert_template *
sc_profile_find_cert(struct sc_profile *profile, const char *ident)
{
struct sc_cert_template *ci;
for (ci = profile->cert_list; ci; ci = ci->next) {
if (!strcasecmp(ci->ident, ident))
return ci;
}
return NULL;
}
char *
next_word(char **cp)
{

View File

@ -73,6 +73,14 @@ struct sc_key_template {
} pkcs15;
};
struct sc_cert_template {
char * ident;
struct sc_cert_template *next;
struct sc_file * file;
struct sc_pkcs15_object pkcs15_obj;
struct sc_pkcs15_cert_info pkcs15;
};
struct sc_profile {
char * driver;
struct pkcs15_init_operations *ops;
@ -86,6 +94,7 @@ struct sc_profile {
struct auth_info * auth_list;
struct sc_key_template *prkey_list;
struct sc_key_template *pubkey_list;
struct sc_cert_template *cert_list;
unsigned int pin_maxlen;
unsigned int pin_minlen;
@ -114,5 +123,7 @@ struct sc_key_template *sc_profile_find_private_key(struct sc_profile *,
struct sc_key_template *sc_profile_find_public_key(struct sc_profile *, const char *);
struct auth_info *sc_profile_find_key(struct sc_profile *,
unsigned int, unsigned int);
struct sc_cert_template *sc_profile_find_cert(struct sc_profile *,
const char *);
#endif /* _OPENSC_PROFILE_H */