- 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:
parent
ca82169e63
commit
b86d2e994b
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,13 @@ filesystem {
|
|||
size = 128;
|
||||
acl = *=$SOPIN, READ=NONE;
|
||||
}
|
||||
|
||||
EF PKCS15-DODF {
|
||||
file-id = 4405;
|
||||
size = 128;
|
||||
ACL = *=NONE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue