- 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 lib_LTLIBRARIES = libopensc.la
libopensc_la_SOURCES = sc.c ctx.c module.c asn1.c log.c base64.c \ 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 \ 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-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
pkcs15-wrap.c pkcs15-algo.c \ pkcs15-wrap.c pkcs15-algo.c \
pkcs15-cache.c $(PCSC_SRC) reader-ctapi.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 \ OBJECTS = sc.obj ctx.obj module.obj asn1.obj log.obj base64.obj \
errors.obj sec.obj card.obj iso7816.obj dir.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-prkey.obj pkcs15-pubkey.obj pkcs15-sec.obj \
pkcs15-wrap.obj pkcs15-algo.obj \ pkcs15-wrap.obj pkcs15-algo.obj \
pkcs15-cache.obj reader-pcsc.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 prkey_df[] = { SC_PKCS15_PRKDF, -1 };
const int pubkey_df[] = { SC_PKCS15_PUKDF, SC_PKCS15_PUKDF_TRUSTED, -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 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 auth_df[] = { SC_PKCS15_AODF, -1 };
const int *dfs; const int *dfs;
sc_pkcs15_object_t *obj; 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: case SC_PKCS15_TYPE_CERT:
dfs = cert_df; dfs = cert_df;
break; break;
case SC_PKCS15_TYPE_DATA_OBJECT:
dfs = data_df;
break;
case SC_PKCS15_TYPE_AUTH: case SC_PKCS15_TYPE_AUTH:
dfs = auth_df; dfs = auth_df;
break; 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); return sc_pkcs15_compare_id(&((struct sc_pkcs15_pubkey_info *) data)->id, id);
case SC_PKCS15_TYPE_AUTH_PIN: case SC_PKCS15_TYPE_AUTH_PIN:
return sc_pkcs15_compare_id(&((struct sc_pkcs15_pin_info *) data)->auth_id, id); 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; 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); 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) static int compare_flags(struct sc_pkcs15_object *obj, void *arg)
{ {
struct sc_pkcs15_pin_info *pin; struct sc_pkcs15_pin_info *pin;
@ -841,6 +854,9 @@ int sc_pkcs15_encode_df(struct sc_context *ctx,
case SC_PKCS15_CDF_USEFUL: case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_encode_cdf_entry; func = sc_pkcs15_encode_cdf_entry;
break; break;
case SC_PKCS15_DODF:
func = sc_pkcs15_encode_dodf_entry;
break;
case SC_PKCS15_AODF: case SC_PKCS15_AODF:
func = sc_pkcs15_encode_aodf_entry; func = sc_pkcs15_encode_aodf_entry;
break; break;
@ -894,6 +910,9 @@ int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card,
case SC_PKCS15_CDF_USEFUL: case SC_PKCS15_CDF_USEFUL:
func = sc_pkcs15_decode_cdf_entry; func = sc_pkcs15_decode_cdf_entry;
break; break;
case SC_PKCS15_DODF:
func = sc_pkcs15_decode_dodf_entry;
break;
case SC_PKCS15_AODF: case SC_PKCS15_AODF:
func = sc_pkcs15_decode_aodf_entry; func = sc_pkcs15_decode_aodf_entry;
break; break;

View File

@ -205,6 +205,19 @@ struct sc_pkcs15_cert_info {
}; };
typedef struct sc_pkcs15_cert_info sc_pkcs15_cert_info_t; 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_ENCRYPT 0x01
#define SC_PKCS15_PRKEY_USAGE_DECRYPT 0x02 #define SC_PKCS15_PRKEY_USAGE_DECRYPT 0x02
#define SC_PKCS15_PRKEY_USAGE_SIGN 0x04 #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_erase_prkey(struct sc_pkcs15_prkey *prkey);
void sc_pkcs15_free_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, int sc_pkcs15_read_certificate(struct sc_pkcs15_card *card,
const struct sc_pkcs15_cert_info *info, const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert); 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, int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf, const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize); 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, int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx,
const struct sc_pkcs15_object *obj, u8 **buf, const struct sc_pkcs15_object *obj, u8 **buf,
size_t *bufsize); 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, int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj, struct sc_pkcs15_object *obj,
const u8 **buf, size_t *bufsize); 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, int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *obj, struct sc_pkcs15_object *obj,
const u8 **buf, size_t *bufsize); const u8 **buf, size_t *bufsize);

View File

@ -62,6 +62,16 @@ filesystem {
WRITE=$PIN; 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 { EF template-public-key {
file-id = 8000; file-id = 8000;
structure = transparent; structure = transparent;

View File

@ -138,6 +138,13 @@ struct sc_pkcs15init_pubkeyargs {
sc_pkcs15_pubkey_t key; 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_pkcs15init_certargs {
struct sc_pkcs15_id id; struct sc_pkcs15_id id;
const char * label; const char * label;
@ -176,6 +183,10 @@ extern int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *,
struct sc_profile *, struct sc_profile *,
struct sc_pkcs15init_certargs *, struct sc_pkcs15init_certargs *,
struct sc_pkcs15_object **); 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 *, extern int sc_pkcs15init_create_file(struct sc_profile *,
struct sc_card *, struct sc_file *); struct sc_card *, struct sc_file *);

View File

@ -58,6 +58,7 @@
#define DEFAULT_PRKEY_FLAGS 0x1d #define DEFAULT_PRKEY_FLAGS 0x1d
#define DEFAULT_PUBKEY_FLAGS 0x02 #define DEFAULT_PUBKEY_FLAGS 0x02
#define DEFAULT_CERT_FLAGS 0x02 #define DEFAULT_CERT_FLAGS 0x02
#define DEFAULT_DATA_FLAGS 0x03
/* Handle encoding of PKCS15 on the card */ /* Handle encoding of PKCS15 on the card */
typedef int (*pkcs15_encoder)(struct sc_context *, 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) if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id)) < 0)
return r; 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) { if (args->id.len != 0) {
sc_pkcs15_object_t *objp; sc_pkcs15_object_t *objp;
struct sc_pkcs15_pin_info *pin_info; struct sc_pkcs15_pin_info *pin_info;
@ -894,6 +899,77 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card,
return r; 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 static int
sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
struct sc_profile *profile, 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 */ /* Get the number of objects of this type already on this card */
index = sc_pkcs15_get_objects(p15card, index = sc_pkcs15_get_objects(p15card,
type & SC_PKCS15_TYPE_CLASS_MASK, NULL, 0); type & SC_PKCS15_TYPE_CLASS_MASK, NULL, 0);
/* Set the SO PIN reference from card */ /* Set the SO PIN reference from card */
if ((r = set_so_pin_from_card(p15card, profile)) < 0) if ((r = set_so_pin_from_card(p15card, profile)) < 0)
return r; return r;
@ -918,7 +993,6 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card,
p15init_error("Unable to allocate file"); p15init_error("Unable to allocate file");
goto done; goto done;
} }
r = sc_pkcs15init_update_file(profile, p15card->card, r = sc_pkcs15init_update_file(profile, p15card->card,
file, data->value, data->len); file, data->value, data->len);
*path = file->path; *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: case SC_PKCS15_TYPE_CERT:
func = sc_pkcs15_find_cert_by_id; func = sc_pkcs15_find_cert_by_id;
break; break;
case SC_PKCS15_TYPE_DATA_OBJECT:
func = sc_pkcs15_find_data_object_by_id;
break;
default: default:
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
} }

View File

@ -86,6 +86,13 @@ filesystem {
size = 128; size = 128;
acl = *=$SOPIN, READ=NONE; 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("Private keys", SC_PKCS15_TYPE_PRKEY);
dump_objects("Public keys", SC_PKCS15_TYPE_PUBKEY); dump_objects("Public keys", SC_PKCS15_TYPE_PUBKEY);
dump_objects("X.509 certificates", SC_PKCS15_TYPE_CERT_X509); dump_objects("X.509 certificates", SC_PKCS15_TYPE_CERT_X509);
dump_objects("data objects", SC_PKCS15_TYPE_DATA_OBJECT);
sc_pkcs15_unbind(p15card); sc_pkcs15_unbind(p15card);
sc_test_cleanup(); sc_test_cleanup();

View File

@ -161,6 +161,24 @@ static void print_cert_x509(const struct sc_pkcs15_object *obj)
* and dump the label */ * 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) void sc_test_print_object(const struct sc_pkcs15_object *obj)
{ {
const char *kind; const char *kind;
@ -191,6 +209,10 @@ void sc_test_print_object(const struct sc_pkcs15_object *obj)
printer = print_cert_x509; printer = print_cert_x509;
kind = "X.509 Certificate"; kind = "X.509 Certificate";
break; break;
case SC_PKCS15_TYPE_DATA_OBJECT:
printer = print_data_object_summary;
kind = "Data Object";
break;
default: default:
printer = NULL; printer = NULL;
kind = "Something"; 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_public_key(struct sc_pkcs15_pubkey *, EVP_PKEY *);
static int do_convert_cert(sc_pkcs15_der_t *, X509 *); 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 init_keyargs(struct sc_pkcs15init_prkeyargs *);
static int read_one_pin(struct sc_profile *, const char *, static int read_one_pin(struct sc_profile *, const char *,
@ -129,6 +134,7 @@ const struct option options[] = {
{ "format", required_argument, 0, 'f' }, { "format", required_argument, 0, 'f' },
{ "passphrase", required_argument, 0, OPT_PASSPHRASE }, { "passphrase", required_argument, 0, OPT_PASSPHRASE },
{ "store-certificate", required_argument, 0, 'X' }, { "store-certificate", required_argument, 0, 'X' },
{ "store-data", required_argument, 0, 'W' },
{ "authority", no_argument, 0, OPT_AUTHORITY }, { "authority", no_argument, 0, OPT_AUTHORITY },
{ "key-usage", required_argument, 0, 'u' }, { "key-usage", required_argument, 0, 'u' },
@ -163,6 +169,7 @@ const char * option_help[] = {
"Specify key file format (default PEM)", "Specify key file format (default PEM)",
"Specify passphrase for unlocking secret key", "Specify passphrase for unlocking secret key",
"Store an X.509 certificate", "Store an X.509 certificate",
"Store a data object",
"Mark certificate as a CA certificate", "Mark certificate as a CA certificate",
"Specify X.509 key usage (use \"--key-usage help\" for more information)", "Specify X.509 key usage (use \"--key-usage help\" for more information)",
@ -183,7 +190,8 @@ enum {
ACTION_GENERATE_KEY, ACTION_GENERATE_KEY,
ACTION_STORE_PRIVKEY, ACTION_STORE_PRIVKEY,
ACTION_STORE_PUBKEY, ACTION_STORE_PUBKEY,
ACTION_STORE_CERT ACTION_STORE_CERT,
ACTION_STORE_DATA
}; };
static char * action_names[] = { static char * action_names[] = {
"do nothing", "do nothing",
@ -192,7 +200,8 @@ static char * action_names[] = {
"generate key", "generate key",
"store private key", "store private key",
"store public key", "store public key",
"store certificate" "store certificate",
"store data object"
}; };
/* Flags for read_one_pin */ /* Flags for read_one_pin */
@ -299,6 +308,8 @@ main(int argc, char **argv)
r = do_store_public_key(profile, NULL); r = do_store_public_key(profile, NULL);
else if (opt_action == ACTION_STORE_CERT) else if (opt_action == ACTION_STORE_CERT)
r = do_store_certificate(profile); 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) else if (opt_action == ACTION_GENERATE_KEY)
r = do_generate_key(profile, opt_newkey); r = do_generate_key(profile, opt_newkey);
else else
@ -574,6 +585,33 @@ do_store_certificate(struct sc_profile *profile)
return r; 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 * Generate a new private key
*/ */
@ -1113,6 +1151,47 @@ do_read_certificate(const char *name, const char *format, X509 **out)
return 0; 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 static int
do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src) 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; 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 int
do_convert_cert(sc_pkcs15_der_t *der, X509 *cert) do_convert_cert(sc_pkcs15_der_t *der, X509 *cert)
{ {
@ -1316,6 +1402,10 @@ handle_option(int c)
opt_action = ACTION_STORE_CERT; opt_action = ACTION_STORE_CERT;
opt_infile = optarg; opt_infile = optarg;
break; break;
case 'W':
opt_action = ACTION_STORE_DATA;
opt_infile = optarg;
break;
case 'd': case 'd':
opt_debug++; opt_debug++;
break; break;

View File

@ -57,6 +57,8 @@ const struct option options[] = {
{ "learn-card", 0, 0, 'L' }, { "learn-card", 0, 0, 'L' },
{ "read-certificate", 1, 0, 'r' }, { "read-certificate", 1, 0, 'r' },
{ "list-certificates", 0, 0, 'c' }, { "list-certificates", 0, 0, 'c' },
{ "read-data-object", 1, 0, 'R' },
{ "list-data-objects", 0, 0, 'C' },
{ "list-pins", 0, 0, OPT_LIST_PINS }, { "list-pins", 0, 0, OPT_LIST_PINS },
{ "change-pin", 0, 0, OPT_CHANGE_PIN }, { "change-pin", 0, 0, OPT_CHANGE_PIN },
{ "list-keys", 0, 0, 'k' }, { "list-keys", 0, 0, 'k' },
@ -75,6 +77,8 @@ const char *option_help[] = {
"Stores card info to cache", "Stores card info to cache",
"Reads certificate with ID <arg>", "Reads certificate with ID <arg>",
"Lists certificates", "Lists certificates",
"Reads data object with ID <arg>",
"Lists data objects",
"Lists PIN codes", "Lists PIN codes",
"Changes the PIN code", "Changes the PIN code",
"Lists private keys", "Lists private keys",
@ -160,6 +164,49 @@ print_pem_object(const char *kind, const u8*data, size_t data_len)
return 0; 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 read_certificate(void)
{ {
int r, i, count; int r, i, count;
@ -197,6 +244,72 @@ int read_certificate(void)
return 2; 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) void print_prkey_info(const struct sc_pkcs15_object *obj)
{ {
unsigned int i; unsigned int i;
@ -641,6 +754,8 @@ int main(int argc, char * const argv[])
int err = 0, r, c, long_optind = 0; int err = 0, r, c, long_optind = 0;
int do_read_cert = 0; int do_read_cert = 0;
int do_list_certs = 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_pins = 0;
int do_list_prkeys = 0; int do_list_prkeys = 0;
int do_list_pubkeys = 0; int do_list_pubkeys = 0;
@ -650,7 +765,7 @@ int main(int argc, char * const argv[])
int action_count = 0; int action_count = 0;
while (1) { 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) if (c == -1)
break; break;
if (c == '?') if (c == '?')
@ -665,6 +780,15 @@ int main(int argc, char * const argv[])
do_list_certs = 1; do_list_certs = 1;
action_count++; action_count++;
break; 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: case OPT_CHANGE_PIN:
do_change_pin = 1; do_change_pin = 1;
action_count++; action_count++;
@ -776,6 +900,16 @@ int main(int argc, char * const argv[])
goto end; goto end;
action_count--; 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 (do_list_prkeys) {
if ((err = list_private_keys())) if ((err = list_private_keys()))
goto end; goto end;