- First shot at pkcs15 data objects from Danny De Cock

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@788 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2002-12-18 10:17:01 +00:00
parent ca82169e63
commit b86d2e994b
13 changed files with 621 additions and 7 deletions

View File

@ -23,7 +23,7 @@ bin_SCRIPTS = opensc-config
lib_LTLIBRARIES = libopensc.la
libopensc_la_SOURCES = sc.c ctx.c module.c asn1.c log.c base64.c \
errors.c sec.c card.c iso7816.c dir.c \
pkcs15.c pkcs15-cert.c pkcs15-pin.c \
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
pkcs15-wrap.c pkcs15-algo.c \
pkcs15-cache.c $(PCSC_SRC) reader-ctapi.c \

View File

@ -11,7 +11,7 @@ HEADERSDIR = $(TOPDIR)\src\include\opensc
OBJECTS = sc.obj ctx.obj module.obj asn1.obj log.obj base64.obj \
errors.obj sec.obj card.obj iso7816.obj dir.obj \
pkcs15.obj pkcs15-cert.obj pkcs15-pin.obj \
pkcs15.obj pkcs15-cert.obj pkcs15-data.obj pkcs15-pin.obj \
pkcs15-prkey.obj pkcs15-pubkey.obj pkcs15-sec.obj \
pkcs15-wrap.obj pkcs15-algo.obj \
pkcs15-cache.obj reader-pcsc.obj \

216
src/libopensc/pkcs15-data.c Normal file
View File

@ -0,0 +1,216 @@
/*
* pkcs15-data.c: PKCS #15 data object functions
*
* Copyright (C) 2002 Danny De Cock <daniel.decock@postbox.be>
*
* This source file was inspired by pkcs15-cert.c.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "internal.h"
#include "pkcs15.h"
#include "log.h"
#include "asn1.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <assert.h>
static const struct sc_asn1_entry c_asn1_data_object[] = {
{ "dataObject", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0 },
{ NULL }
};
int
asn1_decode_data_object(struct sc_context *ctx, u8 **dataobj, size_t *datalen,
const u8 *buf, size_t buflen, int depth)
{
struct sc_asn1_entry asn1_data_obj[2];
u8 *data;
int r;
int data_len;
data=malloc(buflen+64);
if (data == NULL) {
return SC_ERROR_OUT_OF_MEMORY;
}
sc_copy_asn1_entry(c_asn1_data_object, asn1_data_obj);
sc_format_asn1_entry(asn1_data_obj + 0, data, &data_len, 0);
r = _sc_asn1_decode(ctx, asn1_data_obj, buf, buflen, NULL, NULL, 0, depth + 1);
*datalen=data_len;
if (r < 0) {
free(data);
return r;
}
*dataobj = malloc(*datalen);
memcpy(*dataobj, data, *datalen);
free(data);
return 0;
}
int
asn1_encode_data_object(struct sc_context *ctx, u8 *dataobj,size_t datalen,
u8 **buf, size_t *buflen, int depth)
{
int r;
struct sc_asn1_entry asn1_data_obj[2];
sc_copy_asn1_entry(c_asn1_data_object, asn1_data_obj);
sc_format_asn1_entry(asn1_data_obj + 0, dataobj, &datalen, 1);
r= _sc_asn1_encode(ctx, asn1_data_obj, buf, buflen, depth + 1);
return r;
}
int sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_data_info *info,
struct sc_pkcs15_data **data_object_out)
{
int r;
struct sc_pkcs15_data *data_object;
u8 *data = NULL;
size_t len;
assert(p15card != NULL && info != NULL && data_object_out != NULL);
SC_FUNC_CALLED(p15card->card->ctx, 1);
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len, NULL);
if (r)
return r;
data_object = (struct sc_pkcs15_data *) malloc(sizeof(struct sc_pkcs15_data));
if (data_object == NULL) {
free(data);
return SC_ERROR_OUT_OF_MEMORY;
}
memset(data_object, 0, sizeof(struct sc_pkcs15_data));
if ((r=asn1_decode_data_object(p15card->card->ctx, &data_object->data, &data_object->data_len, data, len, 0)) < 0) {
return SC_ERROR_INVALID_ASN1_OBJECT;
}
*data_object_out = data_object;
return 0;
}
static const struct sc_asn1_entry c_asn1_cred_ident[] = {
{ "idType", SC_ASN1_INTEGER, ASN1_INTEGER, 0, NULL },
{ "idValue", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0, NULL },
{ NULL }
};
static const struct sc_asn1_entry c_asn1_com_data_attr[] = {
{ "dataID", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL },
{ NULL }
};
static const struct sc_asn1_entry c_asn1_type_data_attr[] = {
{ "dataType", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
{ NULL }
};
static const struct sc_asn1_entry c_asn1_data[] = {
{ "data", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
{ NULL }
};
static const struct sc_asn1_entry c_asn1_x509_data_attr[] = {
{ "dataValue", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL },
{ NULL }
};
static const struct sc_asn1_entry c_asn1_datalen_object[] = {
{ "dataLen", SC_ASN1_OCTET_STRING, ASN1_OCTET_STRING, 0 },
{ NULL }
};
int sc_pkcs15_decode_dodf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 ** buf, size_t *buflen)
{
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_data_info info;
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_data_attr[4],
asn1_x509_data_attr[2], asn1_type_data_attr[2],
asn1_data[2],asn1_datalen[2];
struct sc_asn1_pkcs15_object data_obj = { obj, asn1_com_data_attr, NULL,
asn1_type_data_attr };
u8 id_value[128];
int id_type;
size_t id_value_len = sizeof(id_value);
int r;
sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
sc_copy_asn1_entry(c_asn1_com_data_attr, asn1_com_data_attr);
sc_copy_asn1_entry(c_asn1_x509_data_attr, asn1_x509_data_attr);
sc_copy_asn1_entry(c_asn1_datalen_object , asn1_datalen);
sc_copy_asn1_entry(c_asn1_type_data_attr, asn1_type_data_attr);
sc_copy_asn1_entry(c_asn1_data, asn1_data);
sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0);
sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0);
sc_format_asn1_entry(asn1_com_data_attr + 0, &info.id, NULL, 0);
sc_format_asn1_entry(asn1_com_data_attr + 1, asn1_cred_ident, NULL, 0);
sc_format_asn1_entry(asn1_x509_data_attr + 0, &info.path, NULL, 0);
sc_format_asn1_entry(asn1_type_data_attr + 0, asn1_x509_data_attr, NULL, 0);
sc_format_asn1_entry(asn1_data + 0, &data_obj, NULL, 0);
/* Fill in defaults */
memset(&info, 0, sizeof(info));
r = sc_asn1_decode(ctx, asn1_data, *buf, *buflen, buf, buflen);
if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
return r;
SC_TEST_RET(ctx, r, "ASN.1 decoding failed");
obj->type = SC_PKCS15_TYPE_DATA_OBJECT;
obj->data = malloc(sizeof(info));
if (obj->data == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
memcpy(obj->data, &info, sizeof(info));
return 0;
}
int sc_pkcs15_encode_dodf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj,
u8 **buf, size_t *bufsize)
{
struct sc_asn1_entry asn1_cred_ident[3], asn1_com_data_attr[4],
asn1_x509_data_attr[2], asn1_type_data_attr[2],
asn1_data[2],asn1_datalen[2];
struct sc_pkcs15_data_info *infop =
(struct sc_pkcs15_data_info *) obj->data;
struct sc_asn1_pkcs15_object data_obj = { (struct sc_pkcs15_object *) obj,
asn1_com_data_attr, NULL,
asn1_type_data_attr };
int r;
sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
sc_copy_asn1_entry(c_asn1_com_data_attr, asn1_com_data_attr);
sc_copy_asn1_entry(c_asn1_x509_data_attr, asn1_x509_data_attr);
sc_copy_asn1_entry(c_asn1_datalen_object, asn1_datalen);
sc_copy_asn1_entry(c_asn1_type_data_attr, asn1_type_data_attr);
sc_copy_asn1_entry(c_asn1_data, asn1_data);
sc_format_asn1_entry(asn1_com_data_attr + 0, (void *) &infop->id, NULL, 1);
sc_format_asn1_entry(asn1_x509_data_attr + 0, (void *) &infop->path, NULL, 1);
sc_format_asn1_entry(asn1_type_data_attr + 0, (void *) asn1_x509_data_attr, NULL, 1);
sc_format_asn1_entry(asn1_data + 0, (void *) &data_obj, NULL, 1);
r = sc_asn1_encode(ctx, asn1_data, buf, bufsize);
return r;
}
void sc_pkcs15_free_data_object(struct sc_pkcs15_data *data_object)
{
assert(data_object != NULL);
free(data_object->data);
free(data_object);
}

View File

@ -587,6 +587,7 @@ int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *p15card, int type,
const int prkey_df[] = { SC_PKCS15_PRKDF, -1 };
const int pubkey_df[] = { SC_PKCS15_PUKDF, SC_PKCS15_PUKDF_TRUSTED, -1 };
const int cert_df[] = { SC_PKCS15_CDF, SC_PKCS15_CDF_TRUSTED, SC_PKCS15_CDF_USEFUL, -1 };
const int data_df[] = { SC_PKCS15_DODF, -1 };
const int auth_df[] = { SC_PKCS15_AODF, -1 };
const int *dfs;
sc_pkcs15_object_t *obj;
@ -602,6 +603,9 @@ int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *p15card, int type,
case SC_PKCS15_TYPE_CERT:
dfs = cert_df;
break;
case SC_PKCS15_TYPE_DATA_OBJECT:
dfs = data_df;
break;
case SC_PKCS15_TYPE_AUTH:
dfs = auth_df;
break;
@ -664,6 +668,8 @@ static int compare_obj_id(struct sc_pkcs15_object *obj, void *arg)
return sc_pkcs15_compare_id(&((struct sc_pkcs15_pubkey_info *) data)->id, id);
case SC_PKCS15_TYPE_AUTH_PIN:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_pin_info *) data)->auth_id, id);
case SC_PKCS15_TYPE_DATA_OBJECT:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_data_info *) data)->id, id);
}
return 0;
}
@ -710,6 +716,13 @@ int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *p15card,
return find_by_id(p15card, SC_PKCS15_TYPE_AUTH_PIN, id, out);
}
int sc_pkcs15_find_data_object_by_id(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_id *id,
struct sc_pkcs15_object **out)
{
return find_by_id(p15card, SC_PKCS15_TYPE_DATA_OBJECT, id, out);
}
static int compare_flags(struct sc_pkcs15_object *obj, void *arg)
{
struct sc_pkcs15_pin_info *pin;
@ -841,6 +854,9 @@ int sc_pkcs15_encode_df(struct sc_context *ctx,
case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_encode_cdf_entry;
break;
case SC_PKCS15_DODF:
func = sc_pkcs15_encode_dodf_entry;
break;
case SC_PKCS15_AODF:
func = sc_pkcs15_encode_aodf_entry;
break;
@ -894,6 +910,9 @@ int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card,
case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_decode_cdf_entry;
break;
case SC_PKCS15_DODF:
func = sc_pkcs15_decode_dodf_entry;
break;
case SC_PKCS15_AODF:
func = sc_pkcs15_decode_aodf_entry;
break;

View File

@ -205,6 +205,19 @@ struct sc_pkcs15_cert_info {
};
typedef struct sc_pkcs15_cert_info sc_pkcs15_cert_info_t;
struct sc_pkcs15_data {
u8 *data; /* DER encoded raw data object */
size_t data_len;
};
typedef struct sc_pkcs15_data sc_pkcs15_data_t;
struct sc_pkcs15_data_info {
struct sc_pkcs15_id id; /* correlates to data object id */
/* identifiers [2] SEQUENCE OF CredentialIdentifier{{KeyIdentifiers}} */
struct sc_path path;
};
typedef struct sc_pkcs15_data_info sc_pkcs15_data_info_t;
#define SC_PKCS15_PRKEY_USAGE_ENCRYPT 0x01
#define SC_PKCS15_PRKEY_USAGE_DECRYPT 0x02
#define SC_PKCS15_PRKEY_USAGE_SIGN 0x04
@ -396,6 +409,14 @@ int sc_pkcs15_encode_prkey(struct sc_context *,
void sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *prkey);
void sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *prkey);
int sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_data_info *info,
struct sc_pkcs15_data **data_object_out);
int sc_pkcs15_find_data_object_by_id(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_id *id,
struct sc_pkcs15_object **out);
void sc_pkcs15_free_data_object(struct sc_pkcs15_data *data_object);
int sc_pkcs15_read_certificate(struct sc_pkcs15_card *card,
const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert);
@ -453,6 +474,9 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx,
int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_encode_dodf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize);
@ -464,6 +488,9 @@ int sc_pkcs15_read_df(struct sc_pkcs15_card *p15card,
int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 **buf, size_t *bufsize);
int sc_pkcs15_decode_dodf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 **buf, size_t *bufsize);
int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj,
const u8 **buf, size_t *bufsize);

View File

@ -62,6 +62,16 @@ filesystem {
WRITE=$PIN;
}
# data objects are stored in transparent EFs.
EF template-data {
file-id = 5000;
structure = transparent;
ACL = *=NEVER,
READ=NONE,
UPDATE=$PIN,
WRITE=$PIN;
}
EF template-public-key {
file-id = 8000;
structure = transparent;

View File

@ -138,6 +138,13 @@ struct sc_pkcs15init_pubkeyargs {
sc_pkcs15_pubkey_t key;
};
struct sc_pkcs15init_dataargs {
struct sc_pkcs15_id id;
const char * label;
sc_pkcs15_der_t der_encoded;
};
struct sc_pkcs15init_certargs {
struct sc_pkcs15_id id;
const char * label;
@ -176,6 +183,10 @@ extern int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *,
struct sc_profile *,
struct sc_pkcs15init_certargs *,
struct sc_pkcs15_object **);
extern int sc_pkcs15init_store_data_object(struct sc_pkcs15_card *,
struct sc_profile *,
struct sc_pkcs15init_dataargs *,
struct sc_pkcs15_object **);
extern int sc_pkcs15init_create_file(struct sc_profile *,
struct sc_card *, struct sc_file *);

View File

@ -58,6 +58,7 @@
#define DEFAULT_PRKEY_FLAGS 0x1d
#define DEFAULT_PUBKEY_FLAGS 0x02
#define DEFAULT_CERT_FLAGS 0x02
#define DEFAULT_DATA_FLAGS 0x03
/* Handle encoding of PKCS15 on the card */
typedef int (*pkcs15_encoder)(struct sc_context *,
@ -845,6 +846,10 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id)) < 0)
return r;
/* If there is a private key corresponding to the ID given
* by the user, make sure $PIN references the pin protecting
* this key
*/
if (args->id.len != 0) {
sc_pkcs15_object_t *objp;
struct sc_pkcs15_pin_info *pin_info;
@ -894,6 +899,77 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
return r;
}
/*
* Store a data object
*/
int
sc_pkcs15init_store_data_object(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
struct sc_pkcs15init_dataargs *args,
struct sc_pkcs15_object **res_obj)
{
struct sc_pkcs15_data_info *data_object_info;
struct sc_pkcs15_object *object;
const char *label;
int r;
if ((label = args->label) == NULL)
label = "Data Object";
/* Select an ID if the user didn't specify one, otherwise
* make sure it's unique */
if ((r = select_id(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &args->id)) < 0)
return r;
#ifdef notused
if (args->id.len != 0) {
sc_pkcs15_object_t *objp;
struct sc_pkcs15_pin_info *pin_info;
r = sc_pkcs15_find_prkey_by_id(p15card,
&args->id, &objp);
if (r == 0) {
r = sc_pkcs15_find_pin_by_auth_id(p15card,
&objp->auth_id, &objp);
}
if (r < 0) {
/* XXX: Fallback to the first PIN object */
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN,
&objp, 1);
if (r != 1)
r = SC_ERROR_OBJECT_NOT_FOUND;
}
if (r >= 0) {
pin_info = (struct sc_pkcs15_pin_info *) objp->data;
sc_profile_set_pin_info(profile,
SC_PKCS15INIT_SO_PIN, pin_info);
}
}
#endif
data_object_info = (struct sc_pkcs15_data_info *) calloc(1, sizeof(*data_object_info));
data_object_info->id = args->id;
object = (struct sc_pkcs15_object *) calloc(1, sizeof(*object));
object->type = SC_PKCS15_TYPE_DATA_OBJECT;
object->data = data_object_info;
object->flags = DEFAULT_DATA_FLAGS;
strncpy(object->label, label, sizeof(object->label));
r = sc_pkcs15init_store_data(p15card, profile,
SC_PKCS15_TYPE_DATA_OBJECT, &args->der_encoded,
&data_object_info->path);
/* Now update the DDF */
if (r >= 0)
r = sc_pkcs15init_add_object(p15card, profile,
SC_PKCS15_DODF, object);
if (r >= 0 && res_obj)
*res_obj = object;
return r;
}
static int
sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
struct sc_profile *profile,
@ -907,7 +983,6 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
/* 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);
/* Set the SO PIN reference from card */
if ((r = set_so_pin_from_card(p15card, profile)) < 0)
return r;
@ -918,7 +993,6 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
p15init_error("Unable to allocate file");
goto done;
}
r = sc_pkcs15init_update_file(profile, p15card->card,
file, data->value, data->len);
*path = file->path;
@ -1193,6 +1267,9 @@ select_id(struct sc_pkcs15_card *p15card, int type, struct sc_pkcs15_id *id)
case SC_PKCS15_TYPE_CERT:
func = sc_pkcs15_find_cert_by_id;
break;
case SC_PKCS15_TYPE_DATA_OBJECT:
func = sc_pkcs15_find_data_object_by_id;
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}

View File

@ -86,6 +86,13 @@ filesystem {
size = 128;
acl = *=$SOPIN, READ=NONE;
}
EF PKCS15-DODF {
file-id = 4405;
size = 128;
ACL = *=NONE;
}
}
}
}

View File

@ -75,6 +75,7 @@ int main(int argc, char *argv[])
dump_objects("Private keys", SC_PKCS15_TYPE_PRKEY);
dump_objects("Public keys", SC_PKCS15_TYPE_PUBKEY);
dump_objects("X.509 certificates", SC_PKCS15_TYPE_CERT_X509);
dump_objects("data objects", SC_PKCS15_TYPE_DATA_OBJECT);
sc_pkcs15_unbind(p15card);
sc_test_cleanup();

View File

@ -161,6 +161,24 @@ static void print_cert_x509(const struct sc_pkcs15_object *obj)
* and dump the label */
}
static void print_data_object_summary(const struct sc_pkcs15_object *obj)
{
struct sc_pkcs15_data_info *data_object;
int i;
data_object = (struct sc_pkcs15_data_info *) obj->data;
printf("\tPath : ");
for (i = 0; i < data_object->path.len; i++)
printf("%02X", data_object->path.value[i]);
printf("\n");
printf("\tID : ");
sc_pkcs15_print_id(&data_object->id);
printf("\n");
/* XXX original p15dump code would read the data object
* and dump the label */
}
void sc_test_print_object(const struct sc_pkcs15_object *obj)
{
const char *kind;
@ -191,6 +209,10 @@ void sc_test_print_object(const struct sc_pkcs15_object *obj)
printer = print_cert_x509;
kind = "X.509 Certificate";
break;
case SC_PKCS15_TYPE_DATA_OBJECT:
printer = print_data_object_summary;
kind = "Data Object";
break;
default:
printer = NULL;
kind = "Something";

View File

@ -72,6 +72,11 @@ 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 do_read_data_object(const char *name, u8 **out, size_t *outlen);
static int do_convert_data_object(struct sc_context *ctx, sc_pkcs15_der_t *der, u8 *data,size_t datalen);
static int do_store_data_object(struct sc_profile *profile);
extern int asn1_encode_data_object(struct sc_context *ctx, u8 *dataobj,size_t datalen,
u8 **buf, size_t *buflen, int depth);
static int init_keyargs(struct sc_pkcs15init_prkeyargs *);
static int read_one_pin(struct sc_profile *, const char *,
@ -129,6 +134,7 @@ const struct option options[] = {
{ "format", required_argument, 0, 'f' },
{ "passphrase", required_argument, 0, OPT_PASSPHRASE },
{ "store-certificate", required_argument, 0, 'X' },
{ "store-data", required_argument, 0, 'W' },
{ "authority", no_argument, 0, OPT_AUTHORITY },
{ "key-usage", required_argument, 0, 'u' },
@ -163,6 +169,7 @@ const char * option_help[] = {
"Specify key file format (default PEM)",
"Specify passphrase for unlocking secret key",
"Store an X.509 certificate",
"Store a data object",
"Mark certificate as a CA certificate",
"Specify X.509 key usage (use \"--key-usage help\" for more information)",
@ -183,7 +190,8 @@ enum {
ACTION_GENERATE_KEY,
ACTION_STORE_PRIVKEY,
ACTION_STORE_PUBKEY,
ACTION_STORE_CERT
ACTION_STORE_CERT,
ACTION_STORE_DATA
};
static char * action_names[] = {
"do nothing",
@ -192,7 +200,8 @@ static char * action_names[] = {
"generate key",
"store private key",
"store public key",
"store certificate"
"store certificate",
"store data object"
};
/* Flags for read_one_pin */
@ -299,6 +308,8 @@ main(int argc, char **argv)
r = do_store_public_key(profile, NULL);
else if (opt_action == ACTION_STORE_CERT)
r = do_store_certificate(profile);
else if (opt_action == ACTION_STORE_DATA)
r = do_store_data_object(profile);
else if (opt_action == ACTION_GENERATE_KEY)
r = do_generate_key(profile, opt_newkey);
else
@ -574,6 +585,33 @@ do_store_certificate(struct sc_profile *profile)
return r;
}
/*
* Download data object to card
*/
static int
do_store_data_object(struct sc_profile *profile)
{
struct sc_pkcs15init_dataargs args;
u8 *data;
size_t datalen;
int r=0;
memset(&args, 0, sizeof(args));
if (opt_objectid)
sc_pkcs15_format_id(opt_objectid, &args.id);
args.label = opt_label;
r = do_read_data_object(opt_infile, &data, &datalen);
if (r >= 0)
r = do_convert_data_object(p15card->card->ctx, &args.der_encoded, data, datalen);
if (r >= 0)
r = sc_pkcs15init_store_data_object(p15card, profile,
&args, NULL);
return r;
}
/*
* Generate a new private key
*/
@ -1113,6 +1151,47 @@ do_read_certificate(const char *name, const char *format, X509 **out)
return 0;
}
static int determine_filesize(const char *filename) {
FILE *fp;
size_t size;
if ((fp = fopen(filename,"r")) == NULL) {
fatal("Unable to open %s: %m", filename);
}
fseek(fp,0L,SEEK_END);
size = ftell(fp);
fclose(fp);
return size;
}
static int
do_read_data_object(const char *name, u8 **out, size_t *outlen)
{
FILE *inf;
size_t filesize = determine_filesize(name);
int c;
*out = malloc(filesize);
if (*out == NULL) {
return SC_ERROR_OUT_OF_MEMORY;
}
inf = fopen(name, "r");
if (inf == NULL) {
fprintf(stderr, "Unable to open '%s' for reading.\n", name);
return -1;
}
c = fread(*out, 1, filesize, inf);
fclose(inf);
if (c < 0) {
perror("read");
return -1;
}
*outlen = filesize;
return 0;
}
static int
do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src)
{
@ -1201,6 +1280,13 @@ do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk)
return 0;
}
int
do_convert_data_object(struct sc_context *ctx, sc_pkcs15_der_t *der,
u8 *data,size_t datalen)
{
return asn1_encode_data_object(ctx, data, datalen, &der->value, &der->len, 0);
}
int
do_convert_cert(sc_pkcs15_der_t *der, X509 *cert)
{
@ -1316,6 +1402,10 @@ handle_option(int c)
opt_action = ACTION_STORE_CERT;
opt_infile = optarg;
break;
case 'W':
opt_action = ACTION_STORE_DATA;
opt_infile = optarg;
break;
case 'd':
opt_debug++;
break;

View File

@ -57,6 +57,8 @@ const struct option options[] = {
{ "learn-card", 0, 0, 'L' },
{ "read-certificate", 1, 0, 'r' },
{ "list-certificates", 0, 0, 'c' },
{ "read-data-object", 1, 0, 'R' },
{ "list-data-objects", 0, 0, 'C' },
{ "list-pins", 0, 0, OPT_LIST_PINS },
{ "change-pin", 0, 0, OPT_CHANGE_PIN },
{ "list-keys", 0, 0, 'k' },
@ -75,6 +77,8 @@ const char *option_help[] = {
"Stores card info to cache",
"Reads certificate with ID <arg>",
"Lists certificates",
"Reads data object with ID <arg>",
"Lists data objects",
"Lists PIN codes",
"Changes the PIN code",
"Lists private keys",
@ -160,6 +164,49 @@ print_pem_object(const char *kind, const u8*data, size_t data_len)
return 0;
}
int
list_data_object(const char *kind, const u8*data, size_t data_len)
{
int i;
printf("%s (%i bytes): <", kind, data_len);
for (i = 0; i < data_len; i++)
printf(" %02X", data[i]);
printf(" >\n");
return 0;
}
int
print_data_object(const char *kind, const u8*data, size_t data_len)
{
int i;
if (opt_outfile != NULL) {
FILE *outf;
outf = fopen(opt_outfile, "w");
if (outf == NULL) {
fprintf(stderr, "Error opening file '%s': %s\n",
opt_outfile, strerror(errno));
return 2;
}
for (i=0; i < data_len; i++)
fprintf(outf, "%c", data[i]);
printf("Dumping (%i bytes) to file <%s>: <", data_len, opt_outfile);
for (i=0; i < data_len; i++)
printf(" %02X", data[i]);
printf(" >\n");
fclose(outf);
} else {
printf("%s (%i bytes): <", kind, data_len);
for (i=0; i < data_len; i++)
printf(" %02X", data[i]);
printf(" >\n");
}
printf(" >\n");
return 0;
}
int read_certificate(void)
{
int r, i, count;
@ -197,6 +244,72 @@ int read_certificate(void)
return 2;
}
int read_data_object(void)
{
int r, i, count;
struct sc_pkcs15_id id;
struct sc_pkcs15_object *objs[32];
id.len = SC_PKCS15_MAX_ID_SIZE;
sc_pkcs15_hex_string_to_id(opt_cert, &id);
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32);
if (r < 0) {
fprintf(stderr, "Data object enumeration failed: %s\n", sc_strerror(r));
return 1;
}
count = r;
for (i = 0; i < count; i++) {
struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data;
struct sc_pkcs15_data *data_object;
if (sc_pkcs15_compare_id(&id, &cinfo->id) != 1)
continue;
if (!quiet)
printf("Reading data object with ID '%s'\n", opt_cert);
r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object);
if (r) {
fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r));
return 1;
}
r = print_data_object("Data Object", data_object->data, data_object->data_len);
sc_pkcs15_free_data_object(data_object);
return r;
}
fprintf(stderr, "Data object with ID '%s' not found.\n", opt_cert);
return 2;
}
int list_data_objects(void)
{
int r, i, count;
struct sc_pkcs15_id id;
struct sc_pkcs15_object *objs[32];
id.len = SC_PKCS15_MAX_ID_SIZE;
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32);
if (r < 0) {
fprintf(stderr, "Data object enumeration failed: %s\n", sc_strerror(r));
return 1;
}
count = r;
for (i = 0; i < count; i++) {
struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data;
struct sc_pkcs15_data *data_object;
printf("Reading data object <%i> ---------------------------\n", i);
r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object);
if (r) {
fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r));
return 1;
}
r = list_data_object("Data Object", data_object->data, data_object->data_len);
sc_pkcs15_free_data_object(data_object);
}
return 0;
}
void print_prkey_info(const struct sc_pkcs15_object *obj)
{
unsigned int i;
@ -641,6 +754,8 @@ int main(int argc, char * const argv[])
int err = 0, r, c, long_optind = 0;
int do_read_cert = 0;
int do_list_certs = 0;
int do_read_data_object = 0;
int do_list_data_objects = 0;
int do_list_pins = 0;
int do_list_prkeys = 0;
int do_list_pubkeys = 0;
@ -650,7 +765,7 @@ int main(int argc, char * const argv[])
int action_count = 0;
while (1) {
c = getopt_long(argc, argv, "r:cko:qdp:L", options, &long_optind);
c = getopt_long(argc, argv, "r:cko:qdp:LR:C", options, &long_optind);
if (c == -1)
break;
if (c == '?')
@ -665,6 +780,15 @@ int main(int argc, char * const argv[])
do_list_certs = 1;
action_count++;
break;
case 'R':
opt_cert = optarg;
do_read_data_object = 1;
action_count++;
break;
case 'C':
do_list_data_objects = 1;
action_count++;
break;
case OPT_CHANGE_PIN:
do_change_pin = 1;
action_count++;
@ -776,6 +900,16 @@ int main(int argc, char * const argv[])
goto end;
action_count--;
}
if (do_list_data_objects) {
if ((err = list_data_objects()))
goto end;
action_count--;
}
if (do_read_data_object) {
if ((err = read_data_object()))
goto end;
action_count--;
}
if (do_list_prkeys) {
if ((err = list_private_keys()))
goto end;