2010-03-09 17:40:22 +00:00
|
|
|
/*
|
|
|
|
* PKCS15 emulation layer for Oberthur card.
|
|
|
|
*
|
2010-03-13 19:48:09 +00:00
|
|
|
* Copyright (C) 2010, Viktor Tarasov <vtarasov@opentrust.com>
|
2010-03-09 17:40:22 +00:00
|
|
|
* Copyright (C) 2005, Andrea Frigido <andrea@frisoft.it>
|
|
|
|
* Copyright (C) 2005, Sirio Capizzi <graaf@virgilio.it>
|
|
|
|
* Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
|
|
|
|
* Copyright (C) 2003, Olaf Kirch <okir@suse.de>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2018-05-18 16:54:56 +00:00
|
|
|
#include "../common/compat_strlcpy.h"
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
#include "pkcs15.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "asn1.h"
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
#include <openssl/bio.h>
|
|
|
|
#include <openssl/crypto.h>
|
|
|
|
#include <openssl/x509.h>
|
|
|
|
#include <openssl/x509v3.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define OBERTHUR_ATTR_MODIFIABLE 0x0001
|
|
|
|
#define OBERTHUR_ATTR_TRUSTED 0x0002
|
|
|
|
#define OBERTHUR_ATTR_LOCAL 0x0004
|
|
|
|
#define OBERTHUR_ATTR_ENCRYPT 0x0008
|
|
|
|
#define OBERTHUR_ATTR_DECRYPT 0x0010
|
|
|
|
#define OBERTHUR_ATTR_SIGN 0x0020
|
|
|
|
#define OBERTHUR_ATTR_VERIFY 0x0040
|
|
|
|
#define OBERTHUR_ATTR_RSIGN 0x0080
|
|
|
|
#define OBERTHUR_ATTR_RVERIFY 0x0100
|
|
|
|
#define OBERTHUR_ATTR_WRAP 0x0200
|
|
|
|
#define OBERTHUR_ATTR_UNWRAP 0x0400
|
|
|
|
#define OBERTHUR_ATTR_DERIVE 0x0800
|
|
|
|
|
|
|
|
#define USAGE_PRV_ENC (SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT |\
|
|
|
|
SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_UNWRAP)
|
|
|
|
#define USAGE_PRV_AUT SC_PKCS15_PRKEY_USAGE_SIGN
|
|
|
|
#define USAGE_PRV_SIGN (SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)
|
|
|
|
#define USAGE_PUB_ENC (SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP)
|
|
|
|
#define USAGE_PUB_AUT SC_PKCS15_PRKEY_USAGE_VERIFY
|
|
|
|
#define USAGE_PUB_SIGN (SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER)
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
#define PIN_DOMAIN_LABEL "SCM"
|
2010-03-13 19:48:09 +00:00
|
|
|
const unsigned char PinDomainID[3] = {0x53, 0x43, 0x4D};
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
#define AWP_PIN_DF "3F005011"
|
|
|
|
#define AWP_TOKEN_INFO "3F0050111000"
|
|
|
|
#define AWP_PUK_FILE "3F0050112000"
|
|
|
|
#define AWP_CONTAINERS_MS "3F0050113000"
|
|
|
|
#define AWP_OBJECTS_LIST_PUB "3F0050114000"
|
|
|
|
#define AWP_OBJECTS_LIST_PRV "3F0050115000"
|
|
|
|
#define AWP_OBJECTS_DF_PUB "3F0050119001"
|
|
|
|
#define AWP_OBJECTS_DF_PRV "3F0050119002"
|
|
|
|
#define AWP_BASE_RSA_PRV "3F00501190023000"
|
|
|
|
#define AWP_BASE_RSA_PUB "3F00501190011000"
|
|
|
|
#define AWP_BASE_CERTIFICATE "3F00501190012000"
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
#define BASE_ID_PUB_RSA 0x10
|
|
|
|
#define BASE_ID_CERT 0x20
|
|
|
|
#define BASE_ID_PRV_RSA 0x30
|
|
|
|
#define BASE_ID_PRV_DES 0x40
|
|
|
|
#define BASE_ID_PUB_DATA 0x50
|
|
|
|
#define BASE_ID_PRV_DATA 0x60
|
|
|
|
#define BASE_ID_PUB_DES 0x70
|
|
|
|
|
|
|
|
static int sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *, unsigned, unsigned);
|
|
|
|
static int sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *, unsigned, unsigned);
|
|
|
|
static int sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *, unsigned);
|
|
|
|
static int sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *, unsigned, unsigned, int);
|
|
|
|
|
|
|
|
static int sc_oberthur_parse_tokeninfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
|
|
|
|
static int sc_oberthur_parse_containers (struct sc_pkcs15_card *, unsigned char *, size_t, int);
|
|
|
|
static int sc_oberthur_parse_publicinfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
|
|
|
|
static int sc_oberthur_parse_privateinfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
|
|
|
|
|
2010-03-13 19:48:09 +00:00
|
|
|
static int sc_awp_parse_df(struct sc_pkcs15_card *, struct sc_pkcs15_df *);
|
2010-04-18 16:38:49 +00:00
|
|
|
static void sc_awp_clear(struct sc_pkcs15_card *);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
struct crypto_container {
|
2010-03-18 12:30:39 +00:00
|
|
|
unsigned id_pub;
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned id_prv;
|
|
|
|
unsigned id_cert;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct container {
|
|
|
|
char uuid[37];
|
|
|
|
struct crypto_container exchange;
|
|
|
|
struct crypto_container sign;
|
|
|
|
|
|
|
|
struct container *next;
|
|
|
|
struct container *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct container *Containers = NULL;
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
const char *path;
|
|
|
|
unsigned char *content;
|
|
|
|
size_t len;
|
|
|
|
int (*parser)(struct sc_pkcs15_card *, unsigned char *, size_t, int);
|
|
|
|
int postpone_allowed;
|
|
|
|
} oberthur_infos[] = {
|
2010-03-13 19:48:09 +00:00
|
|
|
/* Never change the following order */
|
2010-03-11 13:29:10 +00:00
|
|
|
{ "Token info", AWP_TOKEN_INFO, NULL, 0, sc_oberthur_parse_tokeninfo, 0},
|
|
|
|
{ "Containers MS", AWP_CONTAINERS_MS, NULL, 0, sc_oberthur_parse_containers, 0},
|
|
|
|
{ "Public objects list", AWP_OBJECTS_LIST_PUB, NULL, 0, sc_oberthur_parse_publicinfo, 0},
|
|
|
|
{ "Private objects list", AWP_OBJECTS_LIST_PRV, NULL, 0, sc_oberthur_parse_privateinfo, 1},
|
2010-03-09 17:40:22 +00:00
|
|
|
{ NULL, NULL, NULL, 0, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
sc_oberthur_decode_usage(unsigned flags)
|
|
|
|
{
|
|
|
|
unsigned ret = 0;
|
|
|
|
|
|
|
|
if (flags & OBERTHUR_ATTR_ENCRYPT)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
|
|
|
|
if (flags & OBERTHUR_ATTR_DECRYPT)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
|
|
|
|
if (flags & OBERTHUR_ATTR_SIGN)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_SIGN;
|
|
|
|
if (flags & OBERTHUR_ATTR_RSIGN)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
|
|
|
|
if (flags & OBERTHUR_ATTR_WRAP)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_WRAP;
|
|
|
|
if (flags & OBERTHUR_ATTR_UNWRAP)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_UNWRAP;
|
|
|
|
if (flags & OBERTHUR_ATTR_VERIFY)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_VERIFY;
|
|
|
|
if (flags & OBERTHUR_ATTR_RVERIFY)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
|
|
|
|
if (flags & OBERTHUR_ATTR_DERIVE)
|
|
|
|
ret |= SC_PKCS15_PRKEY_USAGE_DERIVE;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_oberthur_get_friends (unsigned int id, struct crypto_container *ccont)
|
|
|
|
{
|
|
|
|
struct container *cont;
|
|
|
|
|
|
|
|
for (cont = Containers; cont; cont = cont->next) {
|
|
|
|
if (cont->exchange.id_pub == id || cont->exchange.id_prv == id || cont->exchange.id_cert == id) {
|
|
|
|
if (ccont)
|
|
|
|
memcpy(ccont, &cont->exchange, sizeof(struct crypto_container));
|
|
|
|
break;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
if (cont->sign.id_pub == id || cont->sign.id_prv == id || cont->sign.id_cert == id) {
|
|
|
|
if (ccont)
|
|
|
|
memcpy(ccont, &cont->sign, sizeof(struct crypto_container));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
return cont ? 0 : SC_ERROR_TEMPLATE_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
sc_oberthur_get_certificate_authority(struct sc_pkcs15_der *der, int *out_authority)
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
X509 *x;
|
|
|
|
BUF_MEM buf_mem;
|
2016-04-05 17:44:37 +00:00
|
|
|
BIO *bio = NULL;
|
2010-03-09 17:40:22 +00:00
|
|
|
BASIC_CONSTRAINTS *bs = NULL;
|
|
|
|
|
|
|
|
if (!der)
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
buf_mem.data = malloc(der->len);
|
|
|
|
if (!buf_mem.data)
|
2013-03-02 18:29:14 +00:00
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
memcpy(buf_mem.data, der->value, der->len);
|
|
|
|
buf_mem.max = buf_mem.length = der->len;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
bio = BIO_new(BIO_s_mem());
|
2018-09-27 13:13:25 +00:00
|
|
|
if (!bio) {
|
|
|
|
free(buf_mem.data);
|
2013-03-02 18:29:14 +00:00
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
2018-09-27 13:13:25 +00:00
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE);
|
|
|
|
x = d2i_X509_bio(bio, 0);
|
2021-03-17 19:17:34 +00:00
|
|
|
free(buf_mem.data);
|
2010-03-09 17:40:22 +00:00
|
|
|
BIO_free(bio);
|
|
|
|
if (!x)
|
|
|
|
return SC_ERROR_INVALID_DATA;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
bs = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL);
|
|
|
|
if (out_authority)
|
|
|
|
*out_authority = (bs && bs->ca);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
X509_free(x);
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
#else
|
|
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned char **out, size_t *out_len,
|
|
|
|
int verify_pin)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
struct sc_card *card = p15card->card;
|
|
|
|
struct sc_file *file = NULL;
|
|
|
|
struct sc_path path;
|
|
|
|
size_t sz;
|
|
|
|
int rv;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (!in_path || !out || !out_len)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file");
|
|
|
|
|
|
|
|
sc_log(ctx, "read file '%s'; verify_pin:%i", in_path, verify_pin);
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
*out = NULL;
|
|
|
|
*out_len = 0;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path(in_path, &path);
|
|
|
|
rv = sc_select_file(card, &path, &file);
|
2020-06-08 12:52:30 +00:00
|
|
|
if (rv != SC_SUCCESS) {
|
|
|
|
sc_file_free(file);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot select oberthur file to read");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
|
|
|
|
sz = file->size;
|
|
|
|
else
|
|
|
|
sz = (file->record_length + 2) * file->record_count;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
*out = calloc(sz, 1);
|
2020-06-08 12:52:30 +00:00
|
|
|
if (*out == NULL) {
|
|
|
|
sc_file_free(file);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot read oberthur file");
|
2020-06-08 12:52:30 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
|
|
|
|
rv = sc_read_binary(card, 0, *out, sz, 0);
|
|
|
|
}
|
|
|
|
else {
|
2020-07-30 00:21:17 +00:00
|
|
|
size_t rec;
|
|
|
|
size_t offs = 0;
|
|
|
|
size_t rec_len = file->record_length;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
for (rec = 1; ; rec++) {
|
2020-07-30 00:21:17 +00:00
|
|
|
if (rec > file->record_count) {
|
|
|
|
rv = 0;
|
|
|
|
break;
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR);
|
|
|
|
if (rv == SC_ERROR_RECORD_NOT_FOUND) {
|
|
|
|
rv = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (rv < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
rec_len = rv;
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
*(*out + offs) = 'R';
|
|
|
|
*(*out + offs + 1) = rv;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
offs += rv + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
sz = offs;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "read oberthur file result %i", rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
|
|
struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
|
|
|
|
const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
|
2021-01-07 13:20:31 +00:00
|
|
|
int ii, nobjs;
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2020-11-16 12:55:04 +00:00
|
|
|
if (acl == NULL) {
|
|
|
|
sc_file_free(file);
|
|
|
|
free(*out);
|
|
|
|
*out = NULL;
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
|
2021-01-07 13:20:31 +00:00
|
|
|
nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
|
|
|
|
if (nobjs < 1) {
|
2020-06-08 12:52:30 +00:00
|
|
|
sc_file_free(file);
|
2020-08-12 09:04:13 +00:00
|
|
|
free(*out);
|
|
|
|
*out = NULL;
|
2021-01-07 13:20:31 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND,
|
|
|
|
"Cannot read oberthur file: get AUTH objects error");
|
2020-06-08 12:52:30 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2021-01-07 13:20:31 +00:00
|
|
|
for (ii = 0; ii < nobjs; ii++) {
|
2011-06-05 15:46:25 +00:00
|
|
|
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
|
2021-01-07 13:20:31 +00:00
|
|
|
auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
|
2011-06-05 15:46:25 +00:00
|
|
|
if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) {
|
2010-03-09 17:40:22 +00:00
|
|
|
pin_obj = objs[ii];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pin_obj || !pin_obj->content.value) {
|
|
|
|
rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
|
|
|
|
}
|
|
|
|
else {
|
2010-03-10 09:23:01 +00:00
|
|
|
rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (!rv)
|
|
|
|
rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0);
|
|
|
|
}
|
2020-10-15 06:27:31 +00:00
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_file_free(file);
|
|
|
|
|
|
|
|
if (rv < 0) {
|
|
|
|
free(*out);
|
|
|
|
*out = NULL;
|
|
|
|
*out_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_len = sz;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_oberthur_parse_tokeninfo (struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned char *buff, size_t len, int postpone_allowed)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
char label[0x21];
|
|
|
|
unsigned flags;
|
|
|
|
int ii;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (!buff || len < 0x24)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot parse token info");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
memset(label, 0, sizeof(label));
|
|
|
|
|
|
|
|
memcpy(label, buff, 0x20);
|
|
|
|
ii = 0x20;
|
|
|
|
while (*(label + --ii)==' ' && ii)
|
|
|
|
;
|
|
|
|
*(label + ii + 1) = '\0';
|
|
|
|
|
|
|
|
flags = *(buff + 0x22) * 0x100 + *(buff + 0x23);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2020-06-04 10:21:47 +00:00
|
|
|
set_string(&p15card->tokeninfo->label, label);
|
|
|
|
set_string(&p15card->tokeninfo->manufacturer_id, "Oberthur/OpenSC");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (flags & 0x01)
|
2010-10-05 15:44:58 +00:00
|
|
|
p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION;
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "label %s", p15card->tokeninfo->label);
|
|
|
|
sc_log(ctx, "manufacturer_id %s", p15card->tokeninfo->manufacturer_id);
|
|
|
|
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_oberthur_parse_containers (struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned char *buff, size_t len, int postpone_allowed)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
size_t offs;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
while (Containers) {
|
|
|
|
struct container *next = Containers->next;
|
|
|
|
|
|
|
|
free (Containers);
|
|
|
|
Containers = next;
|
|
|
|
}
|
|
|
|
|
2020-09-30 21:37:09 +00:00
|
|
|
for (offs=0; offs + 2 + 2+2+2 + 2+2+2 + 2+36 <= len;) {
|
2010-03-09 17:40:22 +00:00
|
|
|
struct container *cont;
|
|
|
|
unsigned char *ptr = buff + offs + 2;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx,
|
|
|
|
"parse contaniers offs:%"SC_FORMAT_LEN_SIZE_T"u, len:%"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
offs, len);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (*(buff + offs) != 'R')
|
|
|
|
return SC_ERROR_INVALID_DATA;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
cont = (struct container *)calloc(sizeof(struct container), 1);
|
|
|
|
if (!cont)
|
2013-03-02 18:29:14 +00:00
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
cont->exchange.id_pub = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
|
|
|
cont->exchange.id_prv = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
|
|
|
cont->exchange.id_cert = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
cont->sign.id_pub = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
|
|
|
cont->sign.id_prv = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
|
|
|
cont->sign.id_cert = *ptr * 0x100 + *(ptr + 1); ptr += 2;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(cont->uuid, ptr + 2, 36);
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "UUID: %s; 0x%X, 0x%X, 0x%X", cont->uuid,
|
2010-03-09 17:40:22 +00:00
|
|
|
cont->exchange.id_pub, cont->exchange.id_prv, cont->exchange.id_cert);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
if (!Containers) {
|
|
|
|
Containers = cont;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cont->next = Containers;
|
|
|
|
Containers->prev = (void *)cont;
|
|
|
|
Containers = cont;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
offs += *(buff + offs + 1) + 2;
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_oberthur_parse_publicinfo (struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned char *buff, size_t len, int postpone_allowed)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
size_t ii;
|
|
|
|
int rv;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2020-09-30 21:37:09 +00:00
|
|
|
for (ii=0; ii+5<=len; ii+=5) {
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned int file_id, size;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
if(*(buff+ii) != 0xFF)
|
|
|
|
continue;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
file_id = 0x100 * *(buff+ii + 1) + *(buff+ii + 2);
|
|
|
|
size = 0x100 * *(buff+ii + 3) + *(buff+ii + 4);
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "add public object(file-id:%04X,size:%X)", file_id, size);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
switch (*(buff+ii + 1)) {
|
|
|
|
case BASE_ID_PUB_RSA :
|
|
|
|
rv = sc_pkcs15emu_oberthur_add_pubkey(p15card, file_id, size);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot parse public key info");
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
case BASE_ID_CERT :
|
|
|
|
rv = sc_pkcs15emu_oberthur_add_cert(p15card, file_id);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot parse certificate info");
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
case BASE_ID_PUB_DES :
|
|
|
|
break;
|
|
|
|
case BASE_ID_PUB_DATA :
|
|
|
|
rv = sc_pkcs15emu_oberthur_add_data(p15card, file_id, size, 0);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot parse data info");
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Public object parse error");
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_oberthur_parse_privateinfo (struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned char *buff, size_t len, int postpone_allowed)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
size_t ii;
|
|
|
|
int rv;
|
2010-04-18 14:51:44 +00:00
|
|
|
int no_more_private_keys = 0, no_more_private_data = 0;
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2020-10-05 06:49:27 +00:00
|
|
|
for (ii=0; ii+5<=len; ii+=5) {
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned int file_id, size;
|
|
|
|
|
|
|
|
if(*(buff+ii) != 0xFF)
|
|
|
|
continue;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
file_id = 0x100 * *(buff+ii + 1) + *(buff+ii + 2);
|
|
|
|
size = 0x100 * *(buff+ii + 3) + *(buff+ii + 4);
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "add private object (file-id:%04X, size:%X)", file_id, size);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
switch (*(buff+ii + 1)) {
|
|
|
|
case BASE_ID_PRV_RSA :
|
|
|
|
if (no_more_private_keys)
|
|
|
|
break;
|
2010-03-11 13:29:10 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_pkcs15emu_oberthur_add_prvkey(p15card, file_id, size);
|
|
|
|
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed) {
|
|
|
|
struct sc_path path;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "postpone adding of the private keys");
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path("5011A5A5", &path);
|
2011-04-10 04:09:33 +00:00
|
|
|
rv = sc_pkcs15_add_df(p15card, SC_PKCS15_PRKDF, &path);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Add PrkDF error");
|
2010-03-09 17:40:22 +00:00
|
|
|
no_more_private_keys = 1;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot parse private key info");
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
case BASE_ID_PRV_DES :
|
|
|
|
break;
|
|
|
|
case BASE_ID_PRV_DATA :
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "*(buff+ii + 1):%X", *(buff+ii + 1));
|
2010-04-18 14:51:44 +00:00
|
|
|
if (no_more_private_data)
|
|
|
|
break;
|
|
|
|
|
|
|
|
rv = sc_pkcs15emu_oberthur_add_data(p15card, file_id, size, 1);
|
|
|
|
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed) {
|
|
|
|
struct sc_path path;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "postpone adding of the private data");
|
2010-04-18 14:51:44 +00:00
|
|
|
sc_format_path("5011A6A6", &path);
|
2011-04-10 04:09:33 +00:00
|
|
|
rv = sc_pkcs15_add_df(p15card, SC_PKCS15_DODF, &path);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Add DODF error");
|
2010-04-18 14:51:44 +00:00
|
|
|
no_more_private_data = 1;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Cannot parse private data info");
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Private object parse error");
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Public key info:
|
2016-04-05 17:44:37 +00:00
|
|
|
* flags:2,
|
|
|
|
* CN(len:2,value:<variable length>),
|
|
|
|
* ID(len:2,value:(SHA1 value)),
|
2010-03-09 17:40:22 +00:00
|
|
|
* StartDate(Ascii:8)
|
|
|
|
* EndDate(Ascii:8)
|
2016-04-05 17:44:37 +00:00
|
|
|
* ??(0x00:2)
|
2010-03-09 17:40:22 +00:00
|
|
|
*/
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned int file_id, unsigned int size)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
struct sc_pkcs15_pubkey_info key_info;
|
|
|
|
struct sc_pkcs15_object key_obj;
|
|
|
|
char ch_tmp[0x100];
|
2021-02-03 20:27:21 +00:00
|
|
|
unsigned char *info_blob = NULL;
|
2011-02-05 22:14:19 +00:00
|
|
|
size_t len, info_len, offs;
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned flags;
|
|
|
|
int rv;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
sc_log(ctx, "public key(file-id:%04X,size:%X)", file_id, size);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
memset(&key_info, 0, sizeof(key_info));
|
|
|
|
memset(&key_obj, 0, sizeof(key_obj));
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100);
|
2016-04-05 17:44:37 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add public key: read oberthur file error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
/* Flags */
|
|
|
|
offs = 2;
|
2021-02-03 20:27:21 +00:00
|
|
|
if (offs > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'tag'");
|
2021-02-03 20:27:21 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
|
|
|
key_info.usage = sc_oberthur_decode_usage(flags);
|
|
|
|
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
|
|
|
key_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "Public key key-usage:%04X", key_info.usage);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
/* Label */
|
2021-02-03 20:27:21 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'Label'");
|
2021-02-03 20:27:21 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-18 18:48:33 +00:00
|
|
|
if (offs + 2 + len > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'Label' length");
|
|
|
|
} else if (len) {
|
2011-03-23 17:17:07 +00:00
|
|
|
if (len > sizeof(key_obj.label) - 1)
|
|
|
|
len = sizeof(key_obj.label) - 1;
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(key_obj.label, info_blob + offs + 2, len);
|
|
|
|
}
|
|
|
|
offs += 2 + len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* ID */
|
2021-03-17 17:16:34 +00:00
|
|
|
if (offs + 2 > info_len) {
|
2021-02-03 20:27:21 +00:00
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'ID'");
|
2021-02-03 20:27:21 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-17 17:16:34 +00:00
|
|
|
if (len == 0
|
|
|
|
|| len > sizeof(key_info.id.value)
|
|
|
|
|| offs + 2 + len > info_len) {
|
2021-02-03 20:27:21 +00:00
|
|
|
free(info_blob);
|
2018-04-14 17:38:34 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'ID' length");
|
2021-02-03 20:27:21 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(key_info.id.value, info_blob + offs + 2, len);
|
|
|
|
key_info.id.len = len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2021-02-03 20:27:21 +00:00
|
|
|
free(info_blob);
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* Ignore Start/End dates */
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path(ch_tmp, &key_info.path);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
key_info.native = 1;
|
|
|
|
key_info.key_reference = file_id & 0xFF;
|
|
|
|
key_info.modulus_length = size;
|
|
|
|
|
|
|
|
rv = sc_pkcs15emu_add_rsa_pubkey(p15card, &key_obj, &key_info);
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Certificate info:
|
2016-04-05 17:44:37 +00:00
|
|
|
* flags:2,
|
|
|
|
* Label(len:2,value:),
|
|
|
|
* ID(len:2,value:(SHA1 value)),
|
2010-03-09 17:40:22 +00:00
|
|
|
* Subject in ASN.1(len:2,value:)
|
|
|
|
* Issuer in ASN.1(len:2,value:)
|
|
|
|
* Serial encoded in LV or ASN.1 FIXME
|
|
|
|
*/
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file_id)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
struct sc_pkcs15_cert_info cinfo;
|
|
|
|
struct sc_pkcs15_object cobj;
|
2021-03-01 10:57:06 +00:00
|
|
|
unsigned char *info_blob = NULL, *cert_blob = NULL;
|
2011-02-05 22:14:19 +00:00
|
|
|
size_t info_len, cert_len, len, offs;
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned flags;
|
|
|
|
int rv;
|
|
|
|
char ch_tmp[0x20];
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
sc_log(ctx, "add certificate(file-id:%04X)", file_id);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
memset(&cinfo, 0, sizeof(cinfo));
|
|
|
|
memset(&cobj, 0, sizeof(cobj));
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100);
|
2016-04-05 17:44:37 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add certificate: read oberthur file error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2021-03-01 10:57:06 +00:00
|
|
|
if (info_len < 2) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
|
|
|
offs = 2;
|
|
|
|
|
|
|
|
/* Label */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'CN'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (len + offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
|
|
|
|
} else if (len) {
|
2011-03-23 17:17:07 +00:00
|
|
|
if (len > sizeof(cobj.label) - 1)
|
|
|
|
len = sizeof(cobj.label) - 1;
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(cobj.label, info_blob + offs + 2, len);
|
|
|
|
}
|
|
|
|
offs += 2 + len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* ID */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'ID'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (len + offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
|
|
|
|
} else if (len > sizeof(cinfo.id.value)) {
|
|
|
|
free(info_blob);
|
2018-04-14 17:38:34 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add certificate: invalid 'ID' length");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(cinfo.id.value, info_blob + offs + 2, len);
|
|
|
|
cinfo.id.len = len;
|
|
|
|
|
2021-03-01 10:57:06 +00:00
|
|
|
free(info_blob);
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* Ignore subject, issuer and serial */
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path(ch_tmp, &cinfo.path);
|
2016-04-05 17:44:37 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, ch_tmp, &cert_blob, &cert_len, 1);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add certificate: read certificate error");
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
cinfo.value.value = cert_blob;
|
|
|
|
cinfo.value.len = cert_len;
|
|
|
|
|
|
|
|
rv = sc_oberthur_get_certificate_authority(&cinfo.value, &cinfo.authority);
|
2021-03-17 19:17:34 +00:00
|
|
|
if (rv != SC_SUCCESS) {
|
|
|
|
free(cinfo.value.value);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
|
|
|
cobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
|
|
|
|
|
|
|
|
rv = sc_pkcs15emu_add_x509_cert(p15card, &cobj, &cinfo);
|
|
|
|
|
2018-11-22 22:10:49 +00:00
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Private key info:
|
2016-04-05 17:44:37 +00:00
|
|
|
* flags:2,
|
|
|
|
* CN(len:2,value:),
|
|
|
|
* ID(len:2,value:(SHA1 value)),
|
2010-03-09 17:40:22 +00:00
|
|
|
* StartDate(Ascii:8)
|
|
|
|
* EndDate(Ascii:8)
|
|
|
|
* Subject in ASN.1(len:2,value:)
|
|
|
|
* modulus(value:)
|
|
|
|
* exponent(length:1, value:3)
|
|
|
|
*/
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned int file_id, unsigned int size)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
struct sc_pkcs15_prkey_info kinfo;
|
|
|
|
struct sc_pkcs15_object kobj;
|
|
|
|
struct crypto_container ccont;
|
|
|
|
unsigned char *info_blob = NULL;
|
|
|
|
size_t info_len = 0;
|
|
|
|
unsigned flags;
|
|
|
|
size_t offs, len;
|
|
|
|
char ch_tmp[0x100];
|
|
|
|
int rv;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
sc_log(ctx, "add private key(file-id:%04X,size:%04X)", file_id, size);
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
memset(&kinfo, 0, sizeof(kinfo));
|
|
|
|
memset(&kobj, 0, sizeof(kobj));
|
|
|
|
memset(&ccont, 0, sizeof(ccont));
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_oberthur_get_friends (file_id, &ccont);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add private key: get friends error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (ccont.id_cert) {
|
|
|
|
struct sc_pkcs15_object *objs[32];
|
|
|
|
int ii;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
sc_log(ctx, "friend certificate %04X", ccont.id_cert);
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add private key: get certificates error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
for (ii=0; ii<rv; ii++) {
|
|
|
|
struct sc_pkcs15_cert_info *cert = (struct sc_pkcs15_cert_info *)objs[ii]->data;
|
|
|
|
struct sc_path path = cert->path;
|
|
|
|
unsigned int id = path.value[path.len - 2] * 0x100 + path.value[path.len - 1];
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
if (id == ccont.id_cert) {
|
2018-05-18 16:54:56 +00:00
|
|
|
strlcpy(kobj.label, objs[ii]->label, sizeof(kobj.label));
|
2010-03-09 17:40:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
if (ii == rv)
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "Failed to add private key: friend not found");
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id | 0x100);
|
2016-04-05 17:44:37 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add private key: read oberthur file error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2021-03-01 10:57:06 +00:00
|
|
|
if (info_len < 2) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'tag'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
|
|
|
offs = 2;
|
|
|
|
|
|
|
|
/* CN */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'CN'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (len + offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
if (len && !strlen(kobj.label)) {
|
2016-04-05 17:44:37 +00:00
|
|
|
if (len > sizeof(kobj.label) - 1)
|
2010-03-09 17:40:22 +00:00
|
|
|
len = sizeof(kobj.label) - 1;
|
|
|
|
strncpy(kobj.label, (char *)(info_blob + offs + 2), len);
|
|
|
|
}
|
|
|
|
offs += 2 + len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* ID */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'ID'");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (!len) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: zero length ID");
|
2021-03-01 10:57:06 +00:00
|
|
|
} else if (len + offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
|
|
|
|
} else if (len > sizeof(kinfo.id.value)) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add private key: invalid ID length");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(kinfo.id.value, info_blob + offs + 2, len);
|
|
|
|
kinfo.id.len = len;
|
|
|
|
offs += 2 + len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
/* Ignore Start/End dates */
|
2010-03-09 17:40:22 +00:00
|
|
|
offs += 16;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* Subject encoded in ASN1 */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'subject'");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (len + offs + 2 > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'subject' length");
|
|
|
|
} else if (len) {
|
2010-07-05 13:29:10 +00:00
|
|
|
kinfo.subject.value = malloc(len);
|
2021-03-01 10:57:06 +00:00
|
|
|
if (!kinfo.subject.value) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Failed to add private key: memory allocation error");
|
2021-03-01 10:57:06 +00:00
|
|
|
}
|
2010-07-05 13:29:10 +00:00
|
|
|
kinfo.subject.len = len;
|
|
|
|
memcpy(kinfo.subject.value, info_blob + offs + 2, len);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Modulus and exponent are ignored */
|
|
|
|
|
2021-03-01 10:57:06 +00:00
|
|
|
free(info_blob);
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id);
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path(ch_tmp, &kinfo.path);
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "Private key info path %s", ch_tmp);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
kinfo.modulus_length = size;
|
|
|
|
kinfo.native = 1;
|
|
|
|
kinfo.key_reference = file_id & 0xFF;
|
|
|
|
|
|
|
|
kinfo.usage = sc_oberthur_decode_usage(flags);
|
|
|
|
kobj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
|
|
|
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
|
|
|
kobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
kobj.auth_id.len = sizeof(PinDomainID) > sizeof(kobj.auth_id.value)
|
2010-03-09 17:40:22 +00:00
|
|
|
? sizeof(kobj.auth_id.value) : sizeof(PinDomainID);
|
|
|
|
memcpy(kobj.auth_id.value, PinDomainID, kobj.auth_id.len);
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "Parsed private key(reference:%i,usage:%X,flags:%X)", kinfo.key_reference, kinfo.usage, kobj.flags);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
rv = sc_pkcs15emu_add_rsa_prkey(p15card, &kobj, &kinfo);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
|
|
|
sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
|
2010-03-09 17:40:22 +00:00
|
|
|
unsigned int file_id, unsigned int size, int private)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
struct sc_pkcs15_data_info dinfo;
|
|
|
|
struct sc_pkcs15_object dobj;
|
|
|
|
unsigned flags;
|
|
|
|
unsigned char *info_blob = NULL, *label = NULL, *app = NULL, *oid = NULL;
|
2010-04-18 14:51:44 +00:00
|
|
|
size_t info_len, label_len, app_len, oid_len, offs;
|
2010-03-09 17:40:22 +00:00
|
|
|
char ch_tmp[0x100];
|
|
|
|
int rv;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "Add data(file-id:%04X,size:%i,is-private:%i)", file_id, size, private);
|
2010-03-09 17:40:22 +00:00
|
|
|
memset(&dinfo, 0, sizeof(dinfo));
|
|
|
|
memset(&dobj, 0, sizeof(dobj));
|
|
|
|
|
2010-04-18 14:51:44 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", private ? AWP_OBJECTS_DF_PRV : AWP_OBJECTS_DF_PUB, file_id | 0x100);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Failed to add data: read oberthur file error");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2021-02-03 20:34:52 +00:00
|
|
|
if (info_len < 2) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
|
2021-02-03 20:34:52 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
|
|
|
offs = 2;
|
|
|
|
|
|
|
|
/* Label */
|
2021-02-03 20:46:15 +00:00
|
|
|
if (offs + 2 > info_len) {
|
2021-02-03 20:34:52 +00:00
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'label'");
|
2021-02-03 20:34:52 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
label = info_blob + offs + 2;
|
|
|
|
label_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-02-03 20:46:15 +00:00
|
|
|
if (offs + 2 + label_len > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'label' received");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
if (label_len > sizeof(dobj.label) - 1)
|
|
|
|
label_len = sizeof(dobj.label) - 1;
|
|
|
|
offs += 2 + *(info_blob + offs + 1);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* Application */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
2021-02-03 20:34:52 +00:00
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'application'");
|
2021-02-03 20:34:52 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
app = info_blob + offs + 2;
|
|
|
|
app_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 + app_len > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'application' received");
|
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
if (app_len > sizeof(dinfo.app_label) - 1)
|
|
|
|
app_len = sizeof(dinfo.app_label) - 1;
|
|
|
|
offs += 2 + app_len;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
/* OID encode like DER(ASN.1(oid)) */
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 > info_len) {
|
2021-02-03 20:34:52 +00:00
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'OID'");
|
2021-02-03 20:34:52 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
oid_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
2021-03-01 10:57:06 +00:00
|
|
|
if (offs + 2 + oid_len > info_len) {
|
|
|
|
free(info_blob);
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'oid' received");
|
|
|
|
}
|
2021-04-06 10:45:24 +00:00
|
|
|
if (oid_len > 2) {
|
2010-03-09 17:40:22 +00:00
|
|
|
oid = info_blob + offs + 2;
|
2021-02-03 20:34:52 +00:00
|
|
|
if (*oid != 0x06 || (*(oid + 1) != oid_len - 2)) {
|
|
|
|
free(info_blob);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: invalid 'OID' format");
|
2021-02-03 20:34:52 +00:00
|
|
|
}
|
2010-03-09 17:40:22 +00:00
|
|
|
oid += 2;
|
|
|
|
oid_len -= 2;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-04-18 14:51:44 +00:00
|
|
|
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", private ? AWP_OBJECTS_DF_PRV : AWP_OBJECTS_DF_PUB, file_id);
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_format_path(ch_tmp, &dinfo.path);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
memcpy(dobj.label, label, label_len);
|
|
|
|
memcpy(dinfo.app_label, app, app_len);
|
|
|
|
if (oid_len)
|
|
|
|
sc_asn1_decode_object_id(oid, oid_len, &dinfo.app_oid);
|
|
|
|
|
|
|
|
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
|
|
|
dobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
|
|
|
|
|
2010-04-18 14:51:44 +00:00
|
|
|
if (private) {
|
|
|
|
dobj.auth_id.len = sizeof(PinDomainID) > sizeof(dobj.auth_id.value)
|
2016-04-05 17:44:37 +00:00
|
|
|
? sizeof(dobj.auth_id.value) : sizeof(PinDomainID);
|
2010-04-18 14:51:44 +00:00
|
|
|
memcpy(dobj.auth_id.value, PinDomainID, dobj.auth_id.len);
|
|
|
|
|
|
|
|
dobj.flags |= SC_PKCS15_CO_FLAG_PRIVATE;
|
|
|
|
}
|
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_pkcs15emu_add_data_object(p15card, &dobj, &dinfo);
|
|
|
|
|
2021-02-03 20:34:52 +00:00
|
|
|
free(info_blob);
|
2018-11-22 22:10:49 +00:00
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_pkcs15emu_oberthur_init(struct sc_pkcs15_card * p15card)
|
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
2011-06-05 15:46:25 +00:00
|
|
|
struct sc_pkcs15_auth_info auth_info;
|
2010-03-09 17:40:22 +00:00
|
|
|
struct sc_pkcs15_object obj;
|
|
|
|
struct sc_card *card = p15card->card;
|
|
|
|
struct sc_path path;
|
|
|
|
int rv, ii, tries_left;
|
|
|
|
char serial[0x10];
|
2010-03-11 13:29:10 +00:00
|
|
|
unsigned char sopin_reference = 0x04;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
2010-03-09 17:40:22 +00:00
|
|
|
sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial, sizeof(serial), 0);
|
2020-06-04 10:21:47 +00:00
|
|
|
set_string(&p15card->tokeninfo->serial_number, serial);
|
2010-03-13 19:48:09 +00:00
|
|
|
|
2010-04-18 16:38:49 +00:00
|
|
|
p15card->ops.parse_df = sc_awp_parse_df;
|
|
|
|
p15card->ops.clear = sc_awp_clear;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
sc_log(ctx, "Oberthur init: serial %s", p15card->tokeninfo->serial_number);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
sc_format_path(AWP_PIN_DF, &path);
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_select_file(card, &path, NULL);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot select PIN dir");
|
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
tries_left = -1;
|
|
|
|
rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
|
|
|
|
if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT) {
|
|
|
|
sopin_reference = 0x84;
|
|
|
|
rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
|
|
|
|
}
|
|
|
|
if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Invalid state of SO-PIN");
|
2010-03-11 13:29:10 +00:00
|
|
|
|
|
|
|
/* add PIN */
|
2011-06-05 15:46:25 +00:00
|
|
|
memset(&auth_info, 0, sizeof(auth_info));
|
2010-03-11 13:29:10 +00:00
|
|
|
memset(&obj, 0, sizeof(obj));
|
2011-06-05 15:46:25 +00:00
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
auth_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
|
2011-06-05 15:46:25 +00:00
|
|
|
auth_info.auth_method = SC_AC_CHV;
|
|
|
|
auth_info.auth_id.len = 1;
|
|
|
|
auth_info.auth_id.value[0] = 0xFF;
|
|
|
|
auth_info.attrs.pin.min_length = 4;
|
|
|
|
auth_info.attrs.pin.max_length = 64;
|
|
|
|
auth_info.attrs.pin.stored_length = 64;
|
|
|
|
auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
|
|
|
|
auth_info.attrs.pin.reference = sopin_reference;
|
|
|
|
auth_info.attrs.pin.pad_char = 0xFF;
|
2016-04-05 17:44:37 +00:00
|
|
|
auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
|
|
|
|
| SC_PKCS15_PIN_FLAG_INITIALIZED
|
2010-03-11 13:29:10 +00:00
|
|
|
| SC_PKCS15_PIN_FLAG_NEEDS_PADDING
|
|
|
|
| SC_PKCS15_PIN_FLAG_SO_PIN;
|
2011-06-05 15:46:25 +00:00
|
|
|
auth_info.tries_left = tries_left;
|
2016-08-11 16:26:01 +00:00
|
|
|
auth_info.logged_in = SC_PIN_STATE_UNKNOWN;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
strncpy(obj.label, "SO PIN", SC_PKCS15_MAX_LABEL_SIZE-1);
|
|
|
|
obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
|
2011-06-05 15:46:25 +00:00
|
|
|
sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
|
|
|
|
rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object");
|
2010-03-11 13:29:10 +00:00
|
|
|
|
2010-03-09 17:40:22 +00:00
|
|
|
tries_left = -1;
|
|
|
|
rv = sc_verify(card, SC_AC_CHV, 0x81, (unsigned char *)"", 0, &tries_left);
|
2010-03-11 13:29:10 +00:00
|
|
|
if (rv == SC_ERROR_PIN_CODE_INCORRECT) {
|
2010-03-09 17:40:22 +00:00
|
|
|
/* add PIN */
|
2011-06-05 15:46:25 +00:00
|
|
|
memset(&auth_info, 0, sizeof(auth_info));
|
2010-03-09 17:40:22 +00:00
|
|
|
memset(&obj, 0, sizeof(obj));
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
auth_info.auth_id.len = sizeof(PinDomainID) > sizeof(auth_info.auth_id.value)
|
2011-06-05 15:46:25 +00:00
|
|
|
? sizeof(auth_info.auth_id.value) : sizeof(PinDomainID);
|
|
|
|
memcpy(auth_info.auth_id.value, PinDomainID, auth_info.auth_id.len);
|
|
|
|
auth_info.auth_method = SC_AC_CHV;
|
|
|
|
|
|
|
|
auth_info.attrs.pin.min_length = 4;
|
|
|
|
auth_info.attrs.pin.max_length = 64;
|
|
|
|
auth_info.attrs.pin.stored_length = 64;
|
|
|
|
auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
|
|
|
|
auth_info.attrs.pin.reference = 0x81;
|
|
|
|
auth_info.attrs.pin.pad_char = 0xFF;
|
2016-04-05 17:44:37 +00:00
|
|
|
auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
|
|
|
|
| SC_PKCS15_PIN_FLAG_INITIALIZED
|
2010-03-11 13:29:10 +00:00
|
|
|
| SC_PKCS15_PIN_FLAG_NEEDS_PADDING
|
|
|
|
| SC_PKCS15_PIN_FLAG_LOCAL;
|
2011-06-05 15:46:25 +00:00
|
|
|
auth_info.tries_left = tries_left;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
strncpy(obj.label, PIN_DOMAIN_LABEL, SC_PKCS15_MAX_LABEL_SIZE-1);
|
|
|
|
obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
|
2016-08-13 22:55:13 +00:00
|
|
|
if (sopin_reference == 0x84) {
|
|
|
|
/*
|
|
|
|
* auth_pin_reset_oberthur_style() in card-oberthur.c
|
|
|
|
* always uses PUK with reference 0x84 for
|
|
|
|
* unblocking of User PIN
|
|
|
|
*/
|
|
|
|
obj.auth_id.len = 1;
|
|
|
|
obj.auth_id.value[0] = 0xFF;
|
|
|
|
}
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
sc_format_path(AWP_PIN_DF, &auth_info.path);
|
2011-06-05 15:46:25 +00:00
|
|
|
auth_info.path.type = SC_PATH_TYPE_PATH;
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
|
2011-06-05 15:46:25 +00:00
|
|
|
sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
|
|
|
|
rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object");
|
2010-03-11 13:29:10 +00:00
|
|
|
}
|
|
|
|
else if (rv != SC_ERROR_DATA_OBJECT_NOT_FOUND) {
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot verify PIN");
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (ii=0; oberthur_infos[ii].name; ii++) {
|
2016-04-05 17:44:37 +00:00
|
|
|
sc_log(ctx, "Oberthur init: read %s file", oberthur_infos[ii].name);
|
2020-09-17 10:37:08 +00:00
|
|
|
free(oberthur_infos[ii].content);
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, oberthur_infos[ii].path,
|
|
|
|
&oberthur_infos[ii].content, &oberthur_infos[ii].len, 1);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: read oberthur file error");
|
|
|
|
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx,
|
|
|
|
"Oberthur init: parse %s file, content length %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
oberthur_infos[ii].name, oberthur_infos[ii].len);
|
2016-04-05 17:44:37 +00:00
|
|
|
rv = oberthur_infos[ii].parser(p15card, oberthur_infos[ii].content, oberthur_infos[ii].len,
|
2010-03-09 17:40:22 +00:00
|
|
|
oberthur_infos[ii].postpone_allowed);
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Oberthur init failed: parse error");
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
2010-03-09 17:40:22 +00:00
|
|
|
oberthur_detect_card(struct sc_pkcs15_card * p15card)
|
|
|
|
{
|
|
|
|
struct sc_card *card = p15card->card;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
2010-03-09 17:40:22 +00:00
|
|
|
if (p15card->card->type != SC_CARD_TYPE_OBERTHUR_64K)
|
2018-11-22 22:10:49 +00:00
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_WRONG_CARD);
|
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
int
|
2019-03-26 14:14:25 +00:00
|
|
|
sc_pkcs15emu_oberthur_init_ex(struct sc_pkcs15_card * p15card, struct sc_aid *aid)
|
2010-03-09 17:40:22 +00:00
|
|
|
{
|
2016-04-05 17:44:37 +00:00
|
|
|
int rv;
|
|
|
|
|
|
|
|
LOG_FUNC_CALLED(p15card->card->ctx);
|
2019-03-26 14:14:25 +00:00
|
|
|
rv = oberthur_detect_card(p15card);
|
|
|
|
if (!rv)
|
2010-03-09 17:40:22 +00:00
|
|
|
rv = sc_pkcs15emu_oberthur_init(p15card);
|
2016-04-05 17:44:37 +00:00
|
|
|
|
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
static int
|
2010-03-13 19:48:09 +00:00
|
|
|
sc_awp_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
|
2010-03-09 17:40:22 +00:00
|
|
|
{
|
|
|
|
struct sc_context *ctx = p15card->card->ctx;
|
|
|
|
unsigned char *buf = NULL;
|
|
|
|
size_t buf_len;
|
|
|
|
int rv;
|
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2010-04-18 14:51:44 +00:00
|
|
|
if (df->type != SC_PKCS15_PRKDF && df->type != SC_PKCS15_DODF)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
if (df->enumerated)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2010-03-11 13:29:10 +00:00
|
|
|
rv = sc_oberthur_read_file(p15card, AWP_OBJECTS_LIST_PRV, &buf, &buf_len, 1);
|
2018-04-14 17:38:34 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Parse DF: read private objects info failed");
|
2010-03-09 17:40:22 +00:00
|
|
|
|
|
|
|
rv = sc_oberthur_parse_privateinfo(p15card, buf, buf_len, 0);
|
|
|
|
|
|
|
|
if (buf)
|
|
|
|
free(buf);
|
|
|
|
|
2010-03-13 19:48:09 +00:00
|
|
|
if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2010-03-13 19:48:09 +00:00
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_TEST_RET(ctx, rv, "Parse DF: private info parse error");
|
2010-03-13 19:48:09 +00:00
|
|
|
df->enumerated = 1;
|
2010-03-09 17:40:22 +00:00
|
|
|
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, rv);
|
2010-03-09 17:40:22 +00:00
|
|
|
}
|
2010-04-18 16:38:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
sc_awp_clear(struct sc_pkcs15_card *p15card)
|
|
|
|
{
|
2016-04-05 17:44:37 +00:00
|
|
|
LOG_FUNC_CALLED(p15card->card->ctx);
|
2010-04-18 16:38:49 +00:00
|
|
|
}
|