- 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
|
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 \
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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 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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue