opensc/src/libopensc/card-openpgp.c

3489 lines
108 KiB
C
Raw Normal View History

/*
* card-openpgp.c: Support for OpenPGP card
*
* 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
*/
/*
* Specifications:
* (all available from: https://gnupg.org/ftp/specs/)
* https://gnupg.org/ftp/specs/openpgp-card-1.0.pdf (obsolete)
* https://gnupg.org/ftp/specs/openpgp-card-1.1.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-2.0.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-2.1.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-2.2.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.0.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.1.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.2.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.3.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.3.0.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.3.1.pdf
* https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf
*/
2015-04-22 21:55:33 +00:00
#if HAVE_CONFIG_H
#include "config.h"
2015-04-22 21:55:33 +00:00
#endif
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "internal.h"
#include "asn1.h"
#include "cardctl.h"
#include "errors.h"
#ifdef ENABLE_OPENSSL
#include <openssl/sha.h>
#endif /* ENABLE_OPENSSL */
#include "card-openpgp.h"
static const char default_cardname[] = "OpenPGP card";
static const char default_cardname_v1[] = "OpenPGP card v1.x";
static const char default_cardname_v2[] = "OpenPGP card v2.x";
static const char default_cardname_v3[] = "OpenPGP card v3.x";
static const struct sc_atr_table pgp_atrs[] = {
{ "3b:fa:13:00:ff:81:31:80:45:00:31:c1:73:c0:01:00:00:90:00:b1", NULL, default_cardname_v1, SC_CARD_TYPE_OPENPGP_V1, 0, NULL },
{ "3b:da:18:ff:81:b1:fe:75:1f:03:00:31:c5:73:c0:01:40:00:90:00:0c", NULL, default_cardname_v2, SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
{
"3b:da:11:ff:81:b1:fe:55:1f:03:00:31:84:73:80:01:80:00:90:00:e4",
"ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff",
"Gnuk v1.x.x (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_GNUK, 0, NULL
},
{ "3b:fc:13:00:00:81:31:fe:15:59:75:62:69:6b:65:79:4e:45:4f:72:33:e1", NULL, "Yubikey NEO (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
{ "3b:f8:13:00:00:81:31:fe:15:59:75:62:69:6b:65:79:34:d4", NULL, "Yubikey 4 (OpenPGP v2.1)", SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
2019-12-25 15:30:17 +00:00
{ "3b:fd:13:00:00:81:31:fe:15:80:73:c0:21:c0:57:59:75:62:69:4b:65:79:40", NULL, "Yubikey 5 (OpenPGP v3.4)", SC_CARD_TYPE_OPENPGP_V3, 0, NULL },
{ "3b:da:18:ff:81:b1:fe:75:1f:03:00:31:f5:73:c0:01:60:00:90:00:1c", NULL, default_cardname_v3, SC_CARD_TYPE_OPENPGP_V3, 0, NULL },
{ NULL, NULL, NULL, 0, 0, NULL }
};
static struct sc_card_operations *iso_ops;
static struct sc_card_operations pgp_ops;
static struct sc_card_driver pgp_drv = {
"OpenPGP card",
"openpgp",
&pgp_ops,
NULL, 0, NULL
};
static pgp_ec_curves_t ec_curves[] = {
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
{{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */
{{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */
{{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256}, /* brainpoolP256r1 */
{{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384}, /* brainpoolP384r1 */
{{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512}, /* brainpoolP512r1 */
{{{-1}}, 0} /* This entry must not be touched. */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
};
static pgp_ec_curves_t ec_curves_gnuk[] = {
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
{{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */
/*{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, //cv25519
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, // ed25519 */
{{{-1}}, 0} /* This entry must not be touched. */
};
/*
* The OpenPGP card doesn't have a file system, instead everything
* is stored in data objects that are accessed through GET/PUT.
*
* However, much inside OpenSC's pkcs15 implementation is based on
* the assumption that we have a file system. So we fake one here.
*
* Selecting the MF causes us to select the OpenPGP AID.
*
* Everything else is mapped to "file" IDs.
*/
static int pgp_get_card_features(sc_card_t *card);
static int pgp_finish(sc_card_t *card);
static void pgp_iterate_blobs(pgp_blob_t *, int, void (*func)());
static int pgp_get_blob(sc_card_t *card, pgp_blob_t *blob,
unsigned int id, pgp_blob_t **ret);
static pgp_blob_t *pgp_new_blob(sc_card_t *, pgp_blob_t *, unsigned int, sc_file_t *);
static void pgp_free_blob(pgp_blob_t *);
static int pgp_get_pubkey(sc_card_t *, unsigned int, u8 *, size_t);
static int pgp_get_pubkey_pem(sc_card_t *, unsigned int, u8 *, size_t);
static pgp_do_info_t pgp1x_objects[] = { /* OpenPGP card spec 1.1 */
{ 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0065, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x006e, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x0073, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x007a, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x0081, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x0082, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x0093, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c0, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c1, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c2, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c3, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c4, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c5, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c6, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c7, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c8, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c9, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00ca, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cb, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cc, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cd, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00ce, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cf, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d0, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00e0, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00e1, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00e2, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x0101, SIMPLE, READ_ALWAYS | WRITE_PIN2, sc_get_data, sc_put_data },
{ 0x0102, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0103, SIMPLE, READ_PIN2 | WRITE_PIN2, sc_get_data, sc_put_data },
{ 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f50, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x7f49, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
2014-11-09 08:58:40 +00:00
{ DO_AUTH, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
{ DO_AUTH_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ DO_SIGN, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
{ DO_SIGN_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ DO_ENCR, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
{ DO_ENCR_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ 0, 0, 0, NULL, NULL },
};
static pgp_do_info_t pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/
{ 0x00d9, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00da, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00db, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00dc, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00de, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00de, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
/* DO FA is CONSTRUCTED in spec; we treat it as SIMPLE for the time being */
{ 0x00fa, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
/* DO FB is CONSTRUCTED in spec; we treat it as SIMPLE for the time being */
{ 0x00fb, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
/* DO FC is CONSTRUCTED in spec; we treat it as SIMPLE for the time being */
{ 0x00fc, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
/**** OpenPGP card spec 3.3 ****/
{ 0x00f9, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
/**** OpenPGP card spec 3.0 - 3.2 ****/
{ 0x00d6, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d7, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d8, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
/* DO 7F66 is CONSTRUCTED in spec; we treat it as SIMPLE: no need to parse TLV */
{ 0x7f66, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, sc_put_data },
/* DO 7F74 is CONSTRUCTED in spec; we treat it as SIMPLE for the time being */
{ 0x7f74, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, sc_put_data },
/**** OpenPGP card spec 2.1 & 2.2 ****/
{ 0x00d5, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
/**** OpenPGP card spec 2.0 ****/
{ 0x004d, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0065, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x006e, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x0073, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x007a, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
{ 0x0081, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x0082, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x0093, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c0, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x00c1, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c2, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c3, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c4, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x00c5, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c6, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c7, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c8, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00c9, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00ca, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cb, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cc, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cd, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x00ce, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00cf, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d0, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d1, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d2, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00d3, SIMPLE, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x00f4, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x0101, SIMPLE, READ_ALWAYS | WRITE_PIN2, sc_get_data, sc_put_data },
{ 0x0102, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x0103, SIMPLE, READ_PIN2 | WRITE_PIN2, sc_get_data, sc_put_data },
{ 0x0104, SIMPLE, READ_PIN3 | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x3f00, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
{ 0x5f2d, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f35, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f48, CONSTRUCTED, READ_NEVER | WRITE_PIN3, NULL, sc_put_data },
{ 0x5f50, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x5f52, SIMPLE, READ_ALWAYS | WRITE_NEVER, sc_get_data, NULL },
2018-06-10 18:11:34 +00:00
/* DO 7F21 is CONSTRUCTED in spec; we treat it as SIMPLE: no need to parse TLV */
2014-11-09 08:58:40 +00:00
{ DO_CERT, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
{ 0x7f48, CONSTRUCTED, READ_NEVER | WRITE_NEVER, NULL, NULL },
{ 0x7f49, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
2014-11-09 08:58:40 +00:00
{ DO_AUTH, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
2018-06-10 18:11:34 +00:00
/* The DOs 0xA401, 0xB601, 0xB801 are virtual DOs, they do not represent any real DO.
* However, their R/W access condition may block the process of importing key in pkcs15init.
* So we set their accesses condition as WRITE_PIN3 (writable). */
2014-11-09 08:58:40 +00:00
{ DO_AUTH_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ DO_SIGN, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
{ DO_SIGN_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ DO_ENCR, CONSTRUCTED, READ_ALWAYS | WRITE_NEVER, pgp_get_pubkey, NULL },
{ DO_ENCR_SYM, SIMPLE, READ_ALWAYS | WRITE_PIN3, pgp_get_pubkey_pem, NULL },
{ 0, 0, 0, NULL, NULL },
};
static pgp_do_info_t *pgp33_objects = pgp34_objects + 9;
static pgp_do_info_t *pgp30_objects = pgp34_objects + 10;
static pgp_do_info_t *pgp21_objects = pgp34_objects + 15;
static pgp_do_info_t *pgp20_objects = pgp34_objects + 16;
/**
* Internal: get OpenPGP application identifier from AID DO 004F
*/
static int
get_full_pgp_aid(sc_card_t *card, sc_file_t *file)
{
int r = SC_ERROR_INVALID_ARGUMENTS;
if (file != NULL) {
/* explicitly get the full aid */
r = sc_get_data(card, 0x004F, file->name, sizeof file->name);
file->namelen = MAX(r, 0);
}
return r;
}
/**
* ABI: check if card's ATR matches one of driver's
* or if the OpenPGP application is present on the card.
*/
static int
pgp_match_card(sc_card_t *card)
{
int i;
LOG_FUNC_CALLED(card->ctx);
i = _sc_match_atr(card, pgp_atrs, &card->type);
if (i >= 0) {
card->name = pgp_atrs[i].name;
LOG_FUNC_RETURN(card->ctx, 1);
}
else {
sc_path_t partial_aid;
sc_file_t *file = NULL;
/* select application "OpenPGP" */
sc_format_path("D276:0001:2401", &partial_aid);
partial_aid.type = SC_PATH_TYPE_DF_NAME;
/* OpenPGP card only supports selection *with* requested FCI */
i = iso_ops->select_file(card, &partial_aid, &file);
if (SC_SUCCESS == i) {
card->type = SC_CARD_TYPE_OPENPGP_BASE;
card->name = default_cardname;
if (file->namelen != 16)
(void) get_full_pgp_aid(card, file);
if (file->namelen == 16) {
unsigned char major = BCD2UCHAR(file->name[6]);
switch (major) {
case 1:
card->type = SC_CARD_TYPE_OPENPGP_V1;
card->name = default_cardname_v1;
break;
case 2:
card->type = SC_CARD_TYPE_OPENPGP_V2;
card->name = default_cardname_v2;
break;
case 3:
card->type = SC_CARD_TYPE_OPENPGP_V3;
card->name = default_cardname_v3;
break;
default:
break;
}
}
sc_file_free(file);
LOG_FUNC_RETURN(card->ctx, 1);
}
}
LOG_FUNC_RETURN(card->ctx, 0);
}
/**
* ABI: initialize driver & allocate private data.
*/
static int
pgp_init(sc_card_t *card)
{
2012-06-14 02:17:28 +00:00
struct pgp_priv_data *priv;
sc_path_t path;
sc_file_t *file = NULL;
pgp_do_info_t *info;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
int r, i;
LOG_FUNC_CALLED(card->ctx);
Do not cast the return value of malloc(3) and calloc(3) From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety " Casting and type safety malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. One may "cast" (see type conversion) this pointer to a specific type, as in int *ptr = (int*)malloc(10 * sizeof (int)); When using C, this is considered bad practice; it is redundant under the C standard. Moreover, putting in a cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the C compiler will assume that malloc returns an int, and will issue a warning in a context such as the above, provided the error is not masked by a cast. On certain architectures and data models (such as LP64 on 64 bit systems, where long and pointers are 64 bit and int is 32 bit), this error can actually result in undefined behavior, as the implicitly declared malloc returns a 32 bit value whereas the actually defined function returns a 64 bit value. Depending on calling conventions and memory layout, this may result in stack smashing. The returned pointer need not be explicitly cast to a more specific pointer type, since ANSI C defines an implicit conversion between the void pointer type and other pointers to objects. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in standard C code.[4][5] Omitting the cast, however, creates an incompatibility with C++, which does require it. The lack of a specific pointer type returned from malloc is type-unsafe behaviour: malloc allocates based on byte count but not on type. This distinguishes it from the C++ new operator that returns a pointer whose type relies on the operand. (see C Type Safety). " See also http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
priv = calloc (1, sizeof *priv);
if (!priv)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
card->drv_data = priv;
card->cla = 0x00;
/* select application "OpenPGP" */
sc_format_path("D276:0001:2401", &path);
path.type = SC_PATH_TYPE_DF_NAME;
if ((r = iso_ops->select_file(card, &path, &file)) < 0) {
2019-09-02 07:39:11 +00:00
sc_file_free(file);
pgp_finish(card);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
}
/* defensive programming check */
if (!file) {
pgp_finish(card);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
}
if (file->namelen != 16) {
/* explicitly get the full aid */
r = get_full_pgp_aid(card, file);
if (r < 0) {
sc_file_free(file);
pgp_finish(card);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
}
}
/* read information from AID */
if (file->namelen == 16) {
static char card_name[SC_MAX_APDU_BUFFER_SIZE] = "OpenPGP card";
/* OpenPGP card spec 1.1, 2.x & 3.x, section 4.2.1 & 4.1.2.1 */
priv->bcd_version = bebytes2ushort(file->name + 6);
card->version.fw_major = card->version.hw_major = BCD2UCHAR(file->name[6]);
card->version.fw_minor = card->version.hw_minor = BCD2UCHAR(file->name[7]);
/* for "standard" cards, include detailed card version & serial no. in card name */
if (card->name == default_cardname_v1 ||
card->name == default_cardname_v2 ||
card->name == default_cardname_v3) {
snprintf(card_name, sizeof(card_name),
"OpenPGP card v%u.%u (%04X %08lX)",
card->version.hw_major, card->version.hw_minor,
bebytes2ushort(file->name + 8),
bebytes2ulong(file->name + 10));
}
else if (card->name != NULL) {
/* for other cards, append serial number to the card name */
snprintf(card_name, sizeof(card_name),
"%s (%04X %08lX)",
card->name,
bebytes2ushort(file->name + 8),
bebytes2ulong(file->name + 10));
}
card->name = card_name;
/* GPG compatibility: set card's serial number to manufacturer ID + serial number */
memcpy(card->serialnr.value, file->name + 8, 6);
card->serialnr.len = 6;
} else {
/* set detailed card version */
switch (card->type) {
case SC_CARD_TYPE_OPENPGP_V3:
priv->bcd_version = OPENPGP_CARD_3_0;
break;
case SC_CARD_TYPE_OPENPGP_GNUK:
case SC_CARD_TYPE_OPENPGP_V2:
priv->bcd_version = OPENPGP_CARD_2_0;
break;
default:
priv->bcd_version = OPENPGP_CARD_1_1;
break;
}
}
/* set pointer to correct list of card objects */
priv->pgp_objects = (priv->bcd_version < OPENPGP_CARD_2_0) ? pgp1x_objects
: (priv->bcd_version < OPENPGP_CARD_2_1) ? pgp20_objects
: (priv->bcd_version < OPENPGP_CARD_3_0) ? pgp21_objects
: (priv->bcd_version < OPENPGP_CARD_3_3) ? pgp30_objects
: (priv->bcd_version < OPENPGP_CARD_3_4) ? pgp33_objects
: pgp34_objects;
/* change file path to MF for re-use in MF */
sc_format_path("3f00", &file->path);
/* set up the root of our fake file tree */
/* Transfers ownership of the file to the priv->mf structure */
priv->mf = pgp_new_blob(card, NULL, 0x3f00, file);
if (!priv->mf) {
sc_file_free(file);
pgp_finish(card);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
/* select MF */
priv->current = priv->mf;
/* populate MF - add matching blobs listed in the pgp_objects table */
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) {
2018-06-16 14:03:41 +00:00
if (((info->access & READ_MASK) != READ_NEVER) && (info->get_fn != NULL)) {
pgp_blob_t *child = NULL;
child = pgp_new_blob(card, priv->mf, info->id, sc_file_new());
/* catch out of memory condition */
if (child == NULL) {
pgp_finish(card);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
}
}
/* get card_features from ATR & DOs */
pgp_get_card_features(card);
/* if algorithm attributes can be changed,
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
* add supported algorithms based on specification for pkcs15-init */
if ((priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) &&
(strcmp(card->ctx->app_name, "pkcs15-init") == 0)) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
unsigned long flags_rsa, flags_ecc, ext_flags;
/* OpenPGP card spec 1.1 & 2.x, section 7.2.9 & 7.2.10 / v3.x section 7.2.11 & 7.2.12 */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
flags_rsa = SC_ALGORITHM_RSA_PAD_PKCS1|
SC_ALGORITHM_RSA_HASH_NONE|
SC_ALGORITHM_ONBOARD_KEY_GEN;
flags_ecc = SC_ALGORITHM_ECDSA_RAW|
SC_ALGORITHM_ECDH_CDH_RAW|
SC_ALGORITHM_ECDSA_HASH_NONE|
SC_ALGORITHM_ONBOARD_KEY_GEN;
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE;
switch (card->type) {
case SC_CARD_TYPE_OPENPGP_V3:
/* RSA 1024 was removed for v3+ */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 4096, flags_rsa, 0);
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
for (i=0; ec_curves[i].oid.value[0] >= 0; i++)
{
_sc_card_add_ec_alg(card, ec_curves[i].size, flags_ecc, ext_flags, &ec_curves[i].oid);
}
break;
case SC_CARD_TYPE_OPENPGP_GNUK:
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
/* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */
for (i=0; ec_curves_gnuk[i].oid.value[0] >= 0; i++)
{
_sc_card_add_ec_alg(card, ec_curves_gnuk[i].size,
flags_ecc, ext_flags, &ec_curves_gnuk[i].oid);
}
break;
case SC_CARD_TYPE_OPENPGP_V2:
default:
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
_sc_card_add_rsa_alg(card, 1024, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
_sc_card_add_rsa_alg(card, 4096, flags_rsa, 0);
break;
}
}
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/**
* Internal: parse historic bytes to get card capabilities.
*/
static void
pgp_parse_hist_bytes(sc_card_t *card, u8 *ctlv, size_t ctlv_len)
{
struct pgp_priv_data *priv = DRVDATA(card);
const u8 *ptr;
/* IS07816-4 hist bytes: 3rd function table */
if ((ptr = sc_compacttlv_find_tag(ctlv, ctlv_len, 0x73, NULL)) != NULL) {
/* bit 0x40 in byte 3 of TL 0x73 means "extended Le/Lc" */
if (ptr[2] & 0x40) {
card->caps |= SC_CARD_CAP_APDU_EXT;
priv->ext_caps |= EXT_CAP_APDU_EXT;
}
/* bit 0x80 in byte 3 of TL 0x73 means "Command chaining" */
if (ptr[2] & 0x80) {
priv->ext_caps |= EXT_CAP_CHAINING;
}
}
if ((priv->bcd_version >= OPENPGP_CARD_3_0) &&
((ptr = sc_compacttlv_find_tag(ctlv, ctlv_len, 0x31, NULL)) != NULL)) {
// ToDo ...
}
}
/**
* Internal: parse an algorithm attributes DO
**/
static int
pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_t *key_info)
{
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
struct sc_object_id oid;
unsigned int j, r;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (blob == NULL || blob->data == NULL || blob->len == 0 ||
blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL)
return SC_ERROR_INCORRECT_PARAMETERS;
key_info->key_id = blob->id - 0x00c0; /* attribute algorithm blobs are C1 - C3 */
switch (blob->data[0]) {
case SC_OPENPGP_KEYALGO_RSA:
if (blob->len < 5)
return SC_ERROR_INCORRECT_PARAMETERS;
key_info->algorithm = SC_OPENPGP_KEYALGO_RSA;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
key_info->u.rsa.modulus_len = bebytes2ushort(blob->data + 1);
key_info->u.rsa.exponent_len = bebytes2ushort(blob->data + 3);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
key_info->u.rsa.keyformat = (blob->len > 5)
? blob->data[5]
: SC_OPENPGP_KEYFORMAT_RSA_STD;
break;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
case SC_OPENPGP_KEYALGO_ECDH:
case SC_OPENPGP_KEYALGO_ECDSA:
/* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA */
key_info->algorithm = blob->data[0];
/* last byte is only set if pubkey import is supported, empty otherwise*/
2020-03-19 12:31:31 +00:00
if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){
if (blob->len < 3)
return SC_ERROR_INCORRECT_PARAMETERS;
key_info->u.ec.oid_len = blob->len - 2;
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STDPUB;
}
else {
2020-03-19 12:31:31 +00:00
if (blob->len < 2)
return SC_ERROR_INCORRECT_PARAMETERS;
key_info->u.ec.oid_len = blob->len - 1;
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STD;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
/* Create copy of oid from blob */
2020-03-19 12:31:31 +00:00
sc_init_oid(&oid);
r = sc_asn1_decode_object_id(&blob->data[1], key_info->u.ec.oid_len, &oid);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* decoding failed, return sc_asn1_decode_object_id error code */
if (r > 0){
return r;
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* compare with list of supported ec_curves */
for (j=0; ec_curves[j].oid.value[0] >= 0; j++){
if (sc_compare_oid(&ec_curves[j].oid, &oid)){
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
key_info->u.ec.oid = ec_curves[j].oid;
key_info->u.ec.key_length = ec_curves[j].size;
break;
}
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
break;
default:
return SC_ERROR_NOT_IMPLEMENTED;
}
return SC_SUCCESS;
}
/**
* Internal: get features of the card: capabilities, ...
*/
static int
pgp_get_card_features(sc_card_t *card)
{
struct pgp_priv_data *priv = DRVDATA(card);
u8 *hist_bytes = card->reader->atr_info.hist_bytes;
size_t hist_bytes_len = card->reader->atr_info.hist_bytes_len;
size_t i;
pgp_blob_t *blob, *blob6e, *blob73;
/* parse card capabilities from historical bytes in ATR */
if (hist_bytes_len > 0) {
/* category indicator 0x00, 0x10 or 0x80 => compact TLV (ISO) */
switch (hist_bytes[0]) {
case 0x00:
2018-07-03 07:36:21 +00:00
if (hist_bytes_len > 4) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-4);
}
break;
case 0x80:
2018-07-03 07:36:21 +00:00
if (hist_bytes_len > 1) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-1);
}
break;
case 0x10:
2018-07-03 07:36:21 +00:00
if (hist_bytes_len > 2) {
pgp_parse_hist_bytes(card, hist_bytes+2, hist_bytes_len-2);
}
break;
}
}
/* v1.1 does not support lifecycle via ACTIVATE & TERMINATE: set default */
priv->ext_caps &= ~EXT_CAP_LCS;
if (priv->bcd_version >= OPENPGP_CARD_2_0) {
/* get card capabilities from "historical bytes" DO */
if ((pgp_get_blob(card, priv->mf, 0x5f52, &blob) >= 0) &&
(blob->data != NULL) && (blob->data[0] == 0x00)) {
if (blob->len > 4) {
pgp_parse_hist_bytes(card, blob->data+1, blob->len-4);
2018-07-03 07:36:21 +00:00
}
/* get card status from historical bytes status indicator */
if ((blob->data[0] == 0x00) && (blob->len >= 4)) {
priv->state = blob->data[blob->len-3];
/* state not CARD_STATE_UNKNOWN => LCS supported */
if (priv->state != CARD_STATE_UNKNOWN)
priv->ext_caps |= EXT_CAP_LCS;
}
}
}
if (priv->bcd_version >= OPENPGP_CARD_3_1) {
card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
}
/* v1.1 & v2.x: special DOs are limited to 254 bytes */
priv->max_specialDO_size = 254;
if ((pgp_get_blob(card, priv->mf, 0x006e, &blob6e) >= 0) &&
(pgp_get_blob(card, blob6e, 0x0073, &blob73) >= 0)) {
/* get "extended capabilities" DO */
if ((pgp_get_blob(card, blob73, 0x00c0, &blob) >= 0) &&
(blob->data != NULL) && (blob->len > 0)) {
/* v2.0+: bit 0x04 in first byte means "algorithm attributes changeable" */
if ((blob->data[0] & 0x04) &&
(priv->bcd_version >= OPENPGP_CARD_2_0))
priv->ext_caps |= EXT_CAP_ALG_ATTR_CHANGEABLE;
/* bit 0x08 in first byte means "support for private use DOs" */
if (blob->data[0] & 0x08)
priv->ext_caps |= EXT_CAP_PRIVATE_DO;
/* bit 0x10 in first byte means "support for CHV status byte changeable" */
if (blob->data[0] & 0x10)
priv->ext_caps |= EXT_CAP_C4_CHANGEABLE;
/* bit 0x20 in first byte means "support for Key Import" */
if (blob->data[0] & 0x20)
priv->ext_caps |= EXT_CAP_KEY_IMPORT;
/* bit 0x40 in first byte means "support for Get Challenge" */
if (blob->data[0] & 0x40) {
card->caps |= SC_CARD_CAP_RNG;
priv->ext_caps |= EXT_CAP_GET_CHALLENGE;
}
/* v2.0+: bit 0x80 in first byte means "support Secure Messaging" */
if ((blob->data[0] & 0x80) &&
(priv->bcd_version >= OPENPGP_CARD_2_0))
priv->ext_caps |= EXT_CAP_SM;
if ((priv->bcd_version >= OPENPGP_CARD_2_0) && (blob->len >= 10)) {
/* v2.0+: max. challenge size is at bytes 3-4 */
priv->max_challenge_size = bebytes2ushort(blob->data + 2);
/* v2.0+: max. cert size it at bytes 5-6 */
priv->max_cert_size = bebytes2ushort(blob->data + 4);
if (priv->bcd_version < OPENPGP_CARD_3_0) {
/* v2.x: SM algorithm is at byte 2: 0 == 3DES */
priv->sm_algo = blob->data[1];
if ((priv->sm_algo == SM_ALGO_NONE) && (priv->ext_caps & EXT_CAP_SM))
priv->sm_algo = SM_ALGO_3DES;
/* v2.x: max. send/receive sizes are at bytes 7-8 resp. 9-10 */
card->max_send_size = bebytes2ushort(blob->data + 6);
card->max_recv_size = bebytes2ushort(blob->data + 8);
}
else {
/* v3.0+: SM algorithm is at byte 2: 0 == UNKNOWN */
priv->sm_algo = blob->data[1];
if ((priv->sm_algo == SM_ALGO_NONE) && (priv->ext_caps & EXT_CAP_SM))
priv->sm_algo = SM_ALGO_UNKNOWN;
/* v3.0+: max. size of special DOs is at bytes 7-8 */
priv->max_specialDO_size = bebytes2ushort(blob->data + 6);
}
if (priv->bcd_version >= OPENPGP_CARD_3_3 && (blob->len >= 10)) {
/* v3.3+: MSE for key numbers 2(DEC) and 3(AUT) supported */
if (blob->data[9])
priv->ext_caps |= EXT_CAP_MSE;
}
}
}
/* get max. PIN length from "CHV status bytes" DO */
if ((pgp_get_blob(card, blob73, 0x00c4, &blob) >= 0) &&
2015-07-03 16:21:38 +00:00
(blob->data != NULL) && (blob->len > 1)) {
/* 2nd byte in "CHV status bytes" DO means "max. PIN length" */
card->max_pin_len = blob->data[1];
}
/* get _current_ algorithms & key lengths from "algorithm attributes" DOs
*
* All available algorithms should be already provided by pgp_init. However, if another
* algorithm is found in the "algorithm attributes" DOs, it is supported by the card as
* well and therefore added
* see OpenPGP card spec 1.1 & 2.x section 4.3.3.6 / v3.x section 4.4.3.7 */
for (i = 0x00c1; i <= 0x00c3; i++) {
sc_cardctl_openpgp_keygen_info_t key_info;
/* OpenPGP card spec 1.1 & 2.x section 4.3.3.6 / v3.x section 4.4.3.7 */
if ((pgp_get_blob(card, blob73, i, &blob) >= 0) &&
(pgp_parse_algo_attr_blob(blob, &key_info) >= 0)) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA [RFC 4880] */
if (key_info.algorithm == SC_OPENPGP_KEYALGO_RSA){
/* OpenPGP card spec 1.1 & 2.x, section 7.2.9 & 7.2.10 /
* v3.x section 7.2.11 & 7.2.12 */
unsigned long flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
SC_ALGORITHM_RSA_HASH_NONE |
SC_ALGORITHM_ONBOARD_KEY_GEN; /* key gen on card */
_sc_card_add_rsa_alg(card, key_info.u.rsa.modulus_len, flags, 0);
}
/* v3.0+: ECC [RFC 4880 & 6637] */
else if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info.algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
unsigned long flags, ext_flags;
if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH)
flags = SC_ALGORITHM_ECDH_CDH_RAW;
if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDSA)
flags = SC_ALGORITHM_ECDSA_RAW;
flags |= SC_ALGORITHM_ECDSA_HASH_NONE;
flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE;
_sc_card_add_ec_alg(card, key_info.u.ec.key_length, flags, ext_flags,
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
&key_info.u.ec.oid);
}
}
}
if (priv->bcd_version >= OPENPGP_CARD_3_0) {
/* v3.0+: get length info from "extended length information" DO */
if ((pgp_get_blob(card, blob6e, 0x7f66, &blob) >= 0) &&
(blob->data != NULL) && (blob->len >= 8)) {
/* kludge: treat as SIMPLE DO and use appropriate offsets */
card->max_send_size = bebytes2ushort(blob->data + 2);
card->max_recv_size = bebytes2ushort(blob->data + 6);
}
}
}
return SC_SUCCESS;
}
/**
* ABI: terminate driver & free private data.
*/
static int
pgp_finish(sc_card_t *card)
{
if (card != NULL) {
struct pgp_priv_data *priv = DRVDATA(card);
if (priv != NULL) {
/* delete fake file hierarchy */
pgp_iterate_blobs(priv->mf, 99, pgp_free_blob);
/* delete private data */
free(priv);
}
card->drv_data = NULL;
}
return SC_SUCCESS;
}
/**
* Internal: fill a blob's data.
*/
static int
pgp_set_blob(pgp_blob_t *blob, const u8 *data, size_t len)
{
if (blob->data)
free(blob->data);
blob->data = NULL;
blob->len = 0;
blob->status = 0;
if (len > 0) {
void *tmp = calloc(len, 1);
if (tmp == NULL)
return SC_ERROR_OUT_OF_MEMORY;
blob->data = tmp;
blob->len = (unsigned int)len;
if (data != NULL)
memcpy(blob->data, data, len);
}
if (blob->file)
blob->file->size = len;
return SC_SUCCESS;
}
/**
* Internal: implement Access Control List for emulated file.
* The Access Control is derived from the DO access permission.
**/
static void
pgp_attach_acl(sc_card_t *card, sc_file_t *file, pgp_do_info_t *info)
{
unsigned int method = SC_AC_NONE;
unsigned long key_ref = SC_AC_KEY_REF_NONE;
/* Write access */
switch (info->access & WRITE_MASK) {
case WRITE_NEVER:
method = SC_AC_NEVER;
break;
case WRITE_PIN1:
method = SC_AC_CHV;
key_ref = 0x01;
break;
case WRITE_PIN2:
method = SC_AC_CHV;
key_ref = 0x02;
break;
case WRITE_PIN3:
method = SC_AC_CHV;
key_ref = 0x03;
break;
}
if (method != SC_AC_NONE || key_ref != SC_AC_KEY_REF_NONE) {
sc_file_add_acl_entry(file, SC_AC_OP_WRITE, method, key_ref);
sc_file_add_acl_entry(file, SC_AC_OP_UPDATE, method, key_ref);
sc_file_add_acl_entry(file, SC_AC_OP_DELETE, method, key_ref);
sc_file_add_acl_entry(file, SC_AC_OP_CREATE, method, key_ref);
}
else {
/* When SC_AC_OP_DELETE is absent, we need to provide
* SC_AC_OP_DELETE_SELF for sc_pkcs15init_delete_by_path() */
sc_file_add_acl_entry(file, SC_AC_OP_DELETE_SELF, method, key_ref);
}
method = SC_AC_NONE;
key_ref = SC_AC_KEY_REF_NONE;
/* Read access */
switch (info->access & READ_MASK) {
case READ_NEVER:
method = SC_AC_NEVER;
break;
case READ_PIN1:
method = SC_AC_CHV;
key_ref = 0x01;
break;
case READ_PIN2:
method = SC_AC_CHV;
key_ref = 0x02;
break;
case READ_PIN3:
method = SC_AC_CHV;
key_ref = 0x03;
break;
}
if (method != SC_AC_NONE || key_ref != SC_AC_KEY_REF_NONE) {
sc_file_add_acl_entry(file, SC_AC_OP_READ, method, key_ref);
}
}
/**
* Internal: append a blob to the list of children of a given parent blob.
*/
static pgp_blob_t *
pgp_new_blob(sc_card_t *card, pgp_blob_t *parent, unsigned int file_id,
sc_file_t *file)
{
pgp_blob_t *blob = NULL;
if (file == NULL)
return NULL;
if ((blob = calloc(1, sizeof(pgp_blob_t))) != NULL) {
struct pgp_priv_data *priv = DRVDATA(card);
pgp_do_info_t *info;
blob->file = file;
blob->file->type = SC_FILE_TYPE_WORKING_EF; /* default */
blob->file->ef_structure = SC_FILE_EF_TRANSPARENT;
blob->file->id = file_id;
blob->id = file_id;
blob->parent = parent;
if (parent != NULL) {
pgp_blob_t **p;
/* set file's path = parent's path + file's id */
blob->file->path = parent->file->path;
sc_append_file_id(&blob->file->path, file_id);
/* append blob to list of parent's children */
for (p = &parent->files; *p != NULL; p = &(*p)->next)
;
*p = blob;
}
else {
char path[10] = "0000"; /* long enough */
/* no parent: set file's path = file's id */
if (4 != snprintf(path, sizeof(path), "%04X", file_id & 0xFFFF)) {
free(blob);
return NULL;
}
sc_format_path(path, &blob->file->path);
}
/* find matching DO info: set file type depending on it */
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) {
if (info->id == file_id) {
blob->info = info;
blob->file->type = blob->info->type;
pgp_attach_acl(card, blob->file, info);
break;
}
}
}
return blob;
}
/**
* Internal: free a blob including its content.
*/
static void
pgp_free_blob(pgp_blob_t *blob)
{
if (blob) {
if (blob->parent) {
pgp_blob_t **p;
/* remove blob from list of parent's children */
for (p = &blob->parent->files; *p != NULL && *p != blob; p = &(*p)->next)
;
if (*p == blob)
*p = blob->next;
}
sc_file_free(blob->file);
if (blob->data)
free(blob->data);
free(blob);
}
}
/**
* Internal: iterate through the blob tree, calling a function for each blob.
*/
static void
pgp_iterate_blobs(pgp_blob_t *blob, int level, void (*func)())
{
if (blob) {
if (level > 0) {
pgp_blob_t *child = blob->files;
while (child != NULL) {
pgp_blob_t *next = child->next;
pgp_iterate_blobs(child, level-1, func);
child = next;
}
}
func(blob);
}
}
/**
* Internal: read a blob's contents from card.
*/
static int
pgp_read_blob(sc_card_t *card, pgp_blob_t *blob)
{
struct pgp_priv_data *priv = DRVDATA(card);
if (blob->data != NULL)
return SC_SUCCESS;
if (blob->info == NULL)
return blob->status;
if (blob->info->get_fn) { /* readable, top-level DO */
u8 buffer[MAX_OPENPGP_DO_SIZE];
size_t buf_len = sizeof(buffer);
2013-05-08 09:51:21 +00:00
int r = SC_SUCCESS;
/* buffer length for certificate */
if (blob->id == DO_CERT && priv->max_cert_size > 0) {
buf_len = MIN(priv->max_cert_size, sizeof(buffer));
}
/* buffer length for Gnuk pubkey */
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
(blob->id == DO_AUTH ||
blob->id == DO_SIGN ||
blob->id == DO_ENCR ||
blob->id == DO_AUTH_SYM ||
blob->id == DO_SIGN_SYM ||
blob->id == DO_ENCR_SYM)) {
buf_len = MIN(MAXLEN_RESP_PUBKEY_GNUK, sizeof(buffer));
}
2013-05-08 09:51:21 +00:00
r = blob->info->get_fn(card, blob->id, buffer, buf_len);
if (r < 0) { /* an error occurred */
blob->status = r;
return r;
}
return pgp_set_blob(blob, buffer, r);
}
else { /* un-readable DO or part of a constructed DO */
return SC_SUCCESS;
}
}
/**
* Internal: enumerate contents of a data blob.
* The OpenPGP card has a TLV encoding according ASN.1 BER-encoding rules.
*/
static int
pgp_enumerate_blob(sc_card_t *card, pgp_blob_t *blob)
{
const u8 *in;
int r;
if (blob->files != NULL)
return SC_SUCCESS;
if ((r = pgp_read_blob(card, blob)) < 0)
return r;
in = blob->data;
while ((int) blob->len > (in - blob->data)) {
unsigned int cla, tag, tmptag;
size_t len;
const u8 *data = in;
pgp_blob_t *new;
if (!in)
return SC_ERROR_OBJECT_NOT_VALID;
r = sc_asn1_read_tag(&data, blob->len - (in - blob->data),
&cla, &tag, &len);
if (r < 0 || data == NULL) {
sc_log(card->ctx,
"Unexpected end of contents\n");
return SC_ERROR_OBJECT_NOT_VALID;
}
if (data + len > blob->data + blob->len)
return SC_ERROR_OBJECT_NOT_VALID;
/* undo ASN1's split of tag & class */
for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
cla <<= 8;
}
tag |= cla;
/* Awful hack for composite DOs that have
* a TLV with the DO's id encompassing the
* entire blob. Example: Yubikey Neo */
if (tag == blob->id) {
in = data;
continue;
}
/* create fake file system hierarchy by
* using constructed DOs as DF */
if ((new = pgp_new_blob(card, blob, tag, sc_file_new())) == NULL)
return SC_ERROR_OUT_OF_MEMORY;
pgp_set_blob(new, data, len);
in = data + len;
}
return SC_SUCCESS;
}
/**
* Internal: find a blob by ID below a given parent, filling its contents when necessary.
*/
static int
pgp_get_blob(sc_card_t *card, pgp_blob_t *blob, unsigned int id,
pgp_blob_t **ret)
{
pgp_blob_t *child;
int r;
if ((r = pgp_enumerate_blob(card, blob)) < 0)
return r;
for (child = blob->files; child; child = child->next) {
if (child->id == id) {
(void) pgp_read_blob(card, child);
*ret = child;
return SC_SUCCESS;
}
}
/* This part is for "NOT FOUND" cases */
/* Special case:
* Gnuk does not have default value for children of DO 65 (DOs 5B, 5F2D, 5F35)
* So, if these blob was not found, we create it. */
2014-11-11 15:16:15 +00:00
if (blob->id == DO_CARDHOLDER && (id == DO_NAME || id == DO_LANG_PREF || id == DO_SEX)) {
sc_log(card->ctx, "Create blob %X under %X", id, blob->id);
child = pgp_new_blob(card, blob, id, sc_file_new());
if (child) {
pgp_set_blob(child, NULL, 0);
*ret = child;
return SC_SUCCESS;
}
else
sc_log(card->ctx,
"Not enough memory to create blob for DO %X",
id);
}
return SC_ERROR_FILE_NOT_FOUND;
}
/**
* Internal: search recursively for a blob by ID below a given root.
*/
2012-06-01 15:45:12 +00:00
static int
pgp_seek_blob(sc_card_t *card, pgp_blob_t *root, unsigned int id,
pgp_blob_t **ret)
2012-06-01 15:45:12 +00:00
{
pgp_blob_t *child;
2012-06-01 15:45:12 +00:00
int r;
if ((r = pgp_get_blob(card, root, id, ret)) == 0)
/* the sought blob is right under root */
2012-06-01 15:45:12 +00:00
return r;
/* not found, seek deeper */
2012-06-01 15:45:12 +00:00
for (child = root->files; child; child = child->next) {
/* The DO of SIMPLE type or the DO holding certificate
* does not contain children */
if ((child->info && child->info->type == SIMPLE) || child->id == DO_CERT)
2012-06-01 15:45:12 +00:00
continue;
r = pgp_seek_blob(card, child, id, ret);
if (r == 0)
return r;
}
return SC_ERROR_FILE_NOT_FOUND;
}
/**
* Internal: find a blob by tag - pgp_seek_blob with optimizations.
*/
static pgp_blob_t *
pgp_find_blob(sc_card_t *card, unsigned int tag)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob = NULL;
int r;
/* check if current selected blob is which we want to test */
if (priv->current->id == tag) {
return priv->current;
}
/* look for the blob representing the DO */
r = pgp_seek_blob(card, priv->mf, tag, &blob);
if (r < 0) {
sc_log(card->ctx, "Failed to seek the blob representing the tag %04X. Error %d.", tag, r);
return NULL;
}
return blob;
}
/**
* Internal: get info for a specific tag.
*/
static pgp_do_info_t *
pgp_get_info_by_tag(sc_card_t *card, unsigned int tag)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_do_info_t *info;
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++)
if (tag == info->id)
return info;
return NULL;
}
/**
* Internal: strip out the parts of PKCS15 file layout in the path.
* Get the reduced version which is understood by the OpenPGP card driver.
* Return the index whose preceding part will be ignored.
**/
static unsigned int
pgp_strip_path(sc_card_t *card, const sc_path_t *path)
{
unsigned int start_point = 0;
/* start_point will move through the path string */
2015-01-28 06:39:35 +00:00
if (path->len == 0)
return 0;
/* ignore 3F00 (MF) at the beginning */
start_point = (memcmp(path->value, "\x3f\x00", 2) == 0) ? 2 : 0;
/* strip path of PKCS15-App DF (5015) */
start_point += (memcmp(path->value + start_point, "\x50\x15", 2) == 0) ? 2 : 0;
return start_point;
}
/**
* ABI: ISO 7816-4 SELECT FILE - search given file & make it the currently selected one.
*/
static int
pgp_select_file(sc_card_t *card, const sc_path_t *path, sc_file_t **ret)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob;
unsigned int path_start = 0;
unsigned int n;
sc_path_t dummy_path;
LOG_FUNC_CALLED(card->ctx);
if (path->type == SC_PATH_TYPE_DF_NAME)
LOG_FUNC_RETURN(card->ctx, iso_ops->select_file(card, path, ret));
if (path->len < 2 || (path->len & 1))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid path length");
if (path->type == SC_PATH_TYPE_FILE_ID && path->len != 2)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid path type");
/* Due to pkcs15init implementation, sometimes a file at path "11001101"
* need to be written (one use case is when importing key&cert from p12 file).
* This file does not exist in OpenPGP but pkcs15 requires that
* writing this file must be successful.
* So, we pretend that selecting & writing this file is successful.
* The "11001101"is defined in sc_pkcs15emu_get_df() function, pkcs15-sync.c file. */
sc_format_path("11001101", &dummy_path);
if (sc_compare_path(path, &dummy_path)) {
if (ret != NULL) {
*ret = sc_file_new();
/* One use case of this dummy file is after writing certificate in pkcs15init.
* So we set its size to be the same as max certificate size the card supports. */
(*ret)->size = priv->max_cert_size;
}
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/* ignore explicitly mentioned MF at the path's beginning */
path_start = pgp_strip_path(card, path);
/* starting with the MF ... */
blob = priv->mf;
/* ... recurse through the tree following the path */
for (n = path_start; n < path->len; n += 2) {
unsigned int id = bebytes2ushort(path->value + n);
int r = pgp_get_blob(card, blob, id, &blob);
/* This file ID is referred when importing key&certificate via pkcs15init, like above.
* We pretend to successfully find this inexistent file. */
if (id == 0x4402 || id == 0x5f48) {
if (ret == NULL)
/* No need to return file */
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
/* Else, need to return file */
*ret = sc_file_new();
(*ret)->size = priv->max_cert_size;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
if (r < 0) { /* failure */
LOG_FUNC_RETURN(card->ctx, r);
}
}
/* success: select file = set "current" pointer to blob found */
priv->current = blob;
if (ret)
sc_file_dup(ret, blob->file);
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/**
* ABI: ISO 7816-4 LIST FILES - enumerate all files in current DF.
*/
static int
pgp_list_files(sc_card_t *card, u8 *buf, size_t buflen)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob;
unsigned int k;
int r;
LOG_FUNC_CALLED(card->ctx);
/* jump to selected file */
blob = priv->current;
if (blob->file->type != SC_FILE_TYPE_DF)
LOG_TEST_RET(card->ctx, SC_ERROR_OBJECT_NOT_VALID,
"invalid file type");
if ((r = pgp_enumerate_blob(card, blob)) < 0)
LOG_FUNC_RETURN(card->ctx, r);
for (k = 0, blob = blob->files; blob != NULL; blob = blob->next) {
if (blob->info != NULL && (blob->info->access & READ_MASK) != READ_NEVER) {
if (k + 2 > buflen)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);
ushort2bebytes(buf + k, blob->id);
k += 2;
}
}
LOG_FUNC_RETURN(card->ctx, k);
}
/**
* ABI: ISO 7816-4 GET CHALLENGE - generate random byte sequence.
*/
2018-01-18 11:33:34 +00:00
static int
pgp_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
{
struct pgp_priv_data *priv;
2018-01-18 11:33:34 +00:00
LOG_FUNC_CALLED(card->ctx);
priv = DRVDATA(card);
2018-01-18 11:33:34 +00:00
if (0 == (priv->ext_caps & EXT_CAP_GET_CHALLENGE)) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
if (priv->max_challenge_size > 0 && len > priv->max_challenge_size) {
len = priv->max_challenge_size;
2018-01-18 11:33:34 +00:00
}
LOG_FUNC_RETURN(card->ctx, iso_ops->get_challenge(card, rnd, len));
}
/**
* ABI: ISO 7816-4 READ BINARY - read data from currently selected EF.
*/
static int
pgp_read_binary(sc_card_t *card, unsigned int idx,
u8 *buf, size_t count, unsigned long flags)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob;
int r;
LOG_FUNC_CALLED(card->ctx);
/* jump to selected file */
blob = priv->current;
if (blob == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND);
if (blob->file->type != SC_FILE_TYPE_WORKING_EF)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND);
if ((r = pgp_read_blob(card, blob)) < 0)
LOG_FUNC_RETURN(card->ctx, r);
if (idx > blob->len)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
if (idx + count > blob->len)
count = blob->len - idx;
memcpy(buf, blob->data + idx, count);
LOG_FUNC_RETURN(card->ctx, (int)count);
}
/**
* Internal: get public key from card - as DF + sub-wEFs.
*/
static int
pgp_get_pubkey(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
{
sc_apdu_t apdu;
u8 apdu_case = (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_4;
u8 idbuf[2];
int r;
sc_log(card->ctx, "called, tag=%04x\n", tag);
sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x81, 0);
apdu.lc = 2;
apdu.data = ushort2bebytes(idbuf, tag);
apdu.datalen = 2;
apdu.le = ((buf_len >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : buf_len;
apdu.resp = buf;
apdu.resplen = buf_len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
}
/**
* Internal: get public key from card - as one wEF.
*/
static int
pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob, *mod_blob, *exp_blob, *pubkey_blob, *blob6e, *blob73, *aa_blob;
sc_pkcs15_pubkey_t p15pubkey;
sc_cardctl_openpgp_keygen_info_t key_info;
unsigned int aa_tag = 0;
u8 *data = NULL;
size_t len = 0;
int r;
sc_log(card->ctx, "called, tag=%04x\n", tag);
memset(&p15pubkey, 0, sizeof(p15pubkey));
if ((r = pgp_get_blob(card, priv->mf, tag & 0xFFFE, &blob)) < 0
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
|| (r = pgp_get_blob(card, blob, 0x7F49, &blob)) < 0)
LOG_TEST_RET(card->ctx, r, "error getting elements");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA */
if ((r = pgp_get_blob(card, blob, 0x0081, &mod_blob)) >= 0
&& (r = pgp_get_blob(card, blob, 0x0082, &exp_blob)) >= 0
&& (r = pgp_read_blob(card, mod_blob)) >= 0
&& (r = pgp_read_blob(card, exp_blob)) >= 0) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
p15pubkey.algorithm = SC_ALGORITHM_RSA;
p15pubkey.u.rsa.modulus.data = mod_blob->data;
p15pubkey.u.rsa.modulus.len = mod_blob->len;
p15pubkey.u.rsa.exponent.data = exp_blob->data;
p15pubkey.u.rsa.exponent.len = exp_blob->len;
r = sc_pkcs15_encode_pubkey(card->ctx, &p15pubkey, &data, &len);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
/* ECC */
else if ((r = pgp_get_blob(card, blob, 0x0086, &pubkey_blob)) >= 0
&& (r = pgp_read_blob(card, pubkey_blob)) >= 0) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
p15pubkey.algorithm = SC_ALGORITHM_EC;
p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data;
p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len;
switch(tag & 0xFFFE) {
case DO_SIGN: aa_tag = 0x00C1; break;
case DO_ENCR: aa_tag = 0x00C2; break;
case DO_AUTH: aa_tag = 0x00C3; break;
default: r = SC_ERROR_INCORRECT_PARAMETERS;
}
/* Get EC parameters from Algorithm Attribute if present */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (aa_tag && ((r = pgp_get_blob(card, priv->mf, 0x006e, &blob6e)) >= 0) &&
((r = pgp_get_blob(card, blob6e, 0x0073, &blob73)) >= 0) &&
((r = pgp_get_blob(card, blob73, aa_tag, &aa_blob)) >= 0) &&
((r = pgp_parse_algo_attr_blob(aa_blob, &key_info)) >= 0)) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid,
&p15pubkey.u.ec.params.der.value,
&p15pubkey.u.ec.params.der.len)) == 0) {
p15pubkey.u.ec.params.type = 1;
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
}
} else
sc_log(card->ctx, "Unable to find Algorithm Attribute for EC curve OID");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
else
LOG_TEST_RET(card->ctx, r, "error getting elements");
/* clean up anything we may have set in p15pubkey that can not be freed */
if (p15pubkey.algorithm == SC_ALGORITHM_RSA) {
p15pubkey.u.rsa.modulus.data = NULL;
p15pubkey.u.rsa.modulus.len = 0;
p15pubkey.u.rsa.exponent.data = NULL;
p15pubkey.u.rsa.exponent.len = 0;
} else
if (p15pubkey.algorithm == SC_ALGORITHM_EC) {
p15pubkey.u.ec.ecpointQ.value = NULL;
p15pubkey.u.ec.ecpointQ.len = 0;
/* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */
}
sc_pkcs15_erase_pubkey(&p15pubkey);
LOG_TEST_RET(card->ctx, r, "public key encoding failed");
if (len > buf_len)
len = buf_len;
memcpy(buf, data, len);
free(data);
LOG_FUNC_RETURN(card->ctx, (int)len);
}
/**
* ABI: ISO 7816-4 GET DATA - get contents of a DO.
*/
static int
pgp_get_data(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
{
sc_apdu_t apdu;
int r;
LOG_FUNC_CALLED(card->ctx);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xCA, tag >> 8, tag);
apdu.le = ((buf_len >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : buf_len;
apdu.resp = buf;
apdu.resplen = buf_len;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
/* Gnuk returns an error instead of empty data if there is no certificate or private DO.
* So, for this case, we ignore error and consider success */
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
(tag == DO_CERT ||
tag == DO_PRIV1 ||
tag == DO_PRIV2 ||
tag == DO_PRIV3 ||
tag == DO_PRIV4)) {
if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) {
r = SC_SUCCESS;
apdu.resplen = 0;
}
}
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
}
/**
* Internal: write certificate for Gnuk.
*/
static int
gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
{
size_t i = 0;
2012-06-01 15:40:39 +00:00
sc_apdu_t apdu;
int r = SC_SUCCESS;
LOG_FUNC_CALLED(card->ctx);
/* If null data is passed, delete certificate */
if (buf == NULL || length == 0) {
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xD6, 0x85, 0);
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check response */
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
/* Ref: gnuk_put_binary_libusb.py and gnuk_token.py in Gnuk source tree */
/* Split data to segments of 256 bytes. Send each segment via command chaining,
* with particular P1 byte for each segment */
for (i = 0; i*256 < length; i++) {
u8 *part = (u8 *)buf + i*256;
size_t plen = MIN(length - i*256, 256);
u8 roundbuf[256]; /* space to build APDU data with even length for Gnuk */
sc_log(card->ctx,
"Write part %"SC_FORMAT_LEN_SIZE_T"u from offset 0x%"SC_FORMAT_LEN_SIZE_T"X, len %"SC_FORMAT_LEN_SIZE_T"u",
i+1, i*256, plen);
/* 1st chunk: P1 = 0x85, further chunks: P1 = chunk no */
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, (i == 0) ? 0x85 : i, 0);
apdu.flags |= SC_APDU_FLAGS_CHAINING;
apdu.data = part;
apdu.datalen = apdu.lc = plen;
/* If the last part has odd length, we add zero padding to make it even.
* Gnuk does not allow data with odd length */
if (plen < 256 && (plen % 2) != 0) {
memcpy(roundbuf, part, plen);
roundbuf[plen++] = 0;
apdu.data = roundbuf;
apdu.datalen = apdu.lc = plen;
}
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check response */
2013-04-16 09:02:17 +00:00
LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "UPDATE BINARY returned error");
}
LOG_FUNC_RETURN(card->ctx, (int)length);
}
/**
* Internal: use PUT DATA command to write.
*/
static int
pgp_put_data_plain(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
{
2012-06-01 15:40:39 +00:00
struct pgp_priv_data *priv = DRVDATA(card);
sc_apdu_t apdu;
u8 ins = 0xDA;
u8 p1 = tag >> 8;
u8 p2 = tag & 0xFF;
u8 apdu_case = (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
? SC_APDU_CASE_3_SHORT : SC_APDU_CASE_3;
2012-06-01 15:40:39 +00:00
int r;
LOG_FUNC_CALLED(card->ctx);
/* Extended Header list (DO 004D) needs a variant of PUT DATA command */
if (tag == 0x004D) {
ins = 0xDB;
p1 = 0x3F;
p2 = 0xFF;
}
/* build APDU */
if (buf != NULL && buf_len > 0) {
sc_format_apdu(card, &apdu, apdu_case, ins, p1, p2);
/* if card/reader does not support extended APDUs, but chaining, then set it */
if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
apdu.flags |= SC_APDU_FLAGS_CHAINING;
apdu.data = (u8 *)buf;
apdu.datalen = buf_len;
apdu.lc = buf_len;
2012-06-01 15:40:39 +00:00
}
else {
/* This case is to empty DO */
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, ins, p1, p2);
}
/* send APDU to card */
2012-06-01 15:40:39 +00:00
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* check response */
2012-06-01 15:40:39 +00:00
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, (int)buf_len);
}
/**
* ABI: ISO 7816-4 PUT DATA - write contents of a DO.
*/
static int
pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *affected_blob = NULL;
pgp_do_info_t *dinfo = NULL;
int r;
LOG_FUNC_CALLED(card->ctx);
/* check if the tag is writable */
if (priv->current->id != tag)
affected_blob = pgp_find_blob(card, tag);
/* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
if (affected_blob == NULL)
dinfo = pgp_get_info_by_tag(card, tag);
else
dinfo = affected_blob->info;
if (dinfo == NULL) {
sc_log(card->ctx, "The DO %04X does not exist.", tag);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
else if ((dinfo->access & WRITE_MASK) == WRITE_NEVER) {
sc_log(card->ctx, "DO %04X is not writable.", tag);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED);
}
/* Check data size.
* We won't check other DOs than 7F21 (certificate), because their capacity
* is hard-coded and may change in various version of the card.
* If we check here, the driver may be stuck to a limit version number of card.
* 7F21 size is soft-coded, so we can check it. */
if (tag == DO_CERT && buf_len > priv->max_cert_size) {
sc_log(card->ctx,
"Data size %"SC_FORMAT_LEN_SIZE_T"u exceeds DO size limit %"SC_FORMAT_LEN_SIZE_T"u.",
buf_len, priv->max_cert_size);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
}
if (tag == DO_CERT && card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
/* Gnuk need a special way to write certificate. */
r = gnuk_write_certificate(card, buf, buf_len);
}
else {
r = pgp_put_data_plain(card, tag, buf, buf_len);
}
/* instruct more in case of error */
2012-06-01 15:40:39 +00:00
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Please verify PIN first.");
}
LOG_TEST_RET(card->ctx, r, "PUT DATA returned error");
2012-06-01 15:40:39 +00:00
if (affected_blob) {
/* update the corresponding file */
sc_log(card->ctx, "Updating the corresponding blob data");
r = pgp_set_blob(affected_blob, buf, buf_len);
if (r < 0)
sc_log(card->ctx, "Failed to update blob %04X. Error %d.", affected_blob->id, r);
/* pgp_set_blob()'s failures do not impact pgp_put_data()'s result */
}
2012-06-01 15:40:39 +00:00
LOG_FUNC_RETURN(card->ctx, (int)buf_len);
}
/**
* ABI: ISO 7816-9 PIN CMD - verify/change/unblock a PIN.
*/
static int
pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
{
struct pgp_priv_data *priv = DRVDATA(card);
LOG_FUNC_CALLED(card->ctx);
if (data->pin_type != SC_AC_CHV)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid PIN type");
/* In general, the PIN Reference is extracted from the key-id,
* for example, CHV0 -> Ref=0, CHV1 -> Ref=1.
2012-06-01 15:41:17 +00:00
* However, in the case of OpenGPG, the PIN Ref to compose APDU
* must be 81, 82, 83.
* So, if we receive Ref=1, Ref=2, we must convert to 81, 82...
* In OpenPGP v1, the PINs are named CHV1, CHV2, CHV3.
* In v2, they are named PW1, PW3 (PW1 operates in 2 modes).
*
* The PIN references (P2 in APDU) for "VERIFY" are the same in both versions:
* 81 (CHV1 or PW1), 82 (CHV2 or PW1-mode 2), 83 (CHV3 or PW3),
* On the other hand from version 2.0 "CHANGE REFERENCE DATA" and
* "RESET RETRY COUNTER" don't support PW1-mode 2 (82) and need this
* value changed to PW1 (81).
* Both of these commands also differ between card versions in that
* v1 cards can use only implicit old PIN or CHV3 test for both commands
* whereas v2 can use both implicit (for PW3) and explicit
* (for special "Resetting Code") PIN test for "RESET RETRY COUNTER"
* and only explicit test for "CHANGE REFERENCE DATA".
2012-06-01 15:41:17 +00:00
*
* Note that if this function is called from sc_pkcs15_verify_pin() in pkcs15-pin.c,
* the Ref is already 81, 82, 83.
*/
/* convert the PIN Reference if needed */
2012-06-01 15:41:17 +00:00
data->pin_reference |= 0x80;
/* check version-dependent constraints */
if (data->cmd == SC_PIN_CMD_CHANGE || data->cmd == SC_PIN_CMD_UNBLOCK) {
if (priv->bcd_version >= OPENPGP_CARD_2_0) {
if (data->pin_reference == 0x82)
data->pin_reference = 0x81;
if (data->cmd == SC_PIN_CMD_CHANGE) {
if (data->pin1.len == 0 &&
!(data->flags & SC_PIN_CMD_USE_PINPAD))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"v2 cards don't support implicit old PIN for PIN change");
data->flags &= ~SC_PIN_CMD_IMPLICIT_CHANGE;
}
} else {
if (data->pin1.len != 0) {
sc_log(card->ctx,
"v1 cards don't support explicit old or CHV3 PIN, PIN ignored.");
sc_log(card->ctx,
"please make sure that you have verified the relevant PIN first.");
data->pin1.len = 0;
}
data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
}
}
if (data->cmd == SC_PIN_CMD_UNBLOCK && data->pin2.len == 0 &&
!(data->flags & SC_PIN_CMD_USE_PINPAD))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"new PIN must be provided for unblock operation");
/* ensure pin_reference is 81, 82, 83 */
if (data->pin_reference < 0x81 || data->pin_reference > 0x83)
2012-06-01 15:41:17 +00:00
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
/* emulate SC_PIN_CMD_GET_INFO command for cards not supporting it */
if (data->cmd == SC_PIN_CMD_GET_INFO && (card->caps & SC_CARD_CAP_ISO7816_PIN_INFO) == 0) {
u8 c4data[10];
int r;
r = sc_get_data(card, 0x00c4, c4data, sizeof(c4data));
LOG_TEST_RET(card->ctx, r, "reading CHV status bytes failed");
if (r != 7)
LOG_TEST_RET(card->ctx, SC_ERROR_OBJECT_NOT_VALID,
"CHV status bytes have unexpected length");
data->pin1.tries_left = c4data[4 + (data->pin_reference & 0x0F)];
data->pin1.max_tries = 3;
data->pin1.logged_in = SC_PIN_STATE_UNKNOWN;
if (tries_left != NULL)
*tries_left = data->pin1.tries_left;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
LOG_FUNC_RETURN(card->ctx, iso_ops->pin_cmd(card, data, tries_left));
}
/**
* ABI: ISO 7816-8 LOGOUT - reset all access rights gained.
*/
int pgp_logout(struct sc_card *card)
{
int r = SC_SUCCESS;
struct pgp_priv_data *priv = DRVDATA(card);
LOG_FUNC_CALLED(card->ctx);
if (priv->bcd_version >= OPENPGP_CARD_3_1) {
unsigned char pin_reference;
for (pin_reference = 0x81; pin_reference <= 0x83; pin_reference++) {
int tmp = iso7816_logout(card, pin_reference);
if (r == SC_SUCCESS) {
r = tmp;
}
}
} else {
sc_path_t path;
sc_file_t *file = NULL;
/* select application "OpenPGP" */
sc_format_path("D276:0001:2401", &path);
path.type = SC_PATH_TYPE_DF_NAME;
r = iso_ops->select_file(card, &path, &file);
sc_file_free(file);
}
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* ABI: ISO 7816-8 SET SECURITY ENVIRONMENT.
*/
static int
pgp_set_security_env(sc_card_t *card,
const sc_security_env_t *env, int se_num)
{
struct pgp_priv_data *priv = DRVDATA(card);
LOG_FUNC_CALLED(card->ctx);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if ((env->flags & SC_SEC_ENV_ALG_PRESENT)
&& (env->algorithm != SC_ALGORITHM_RSA)
&& (priv->bcd_version < OPENPGP_CARD_3_0))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"only RSA algorithm supported");
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || (env->key_ref_len != 1))
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"exactly one key reference required");
if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"passing file references not supported");
sc_log(card->ctx, "Key ref %d", env->key_ref[0]);
switch (env->operation) {
case SC_SEC_OPERATION_SIGN:
sc_log(card->ctx, "Operation: Sign.");
if (env->key_ref[0] != 0x00 && env->key_ref[0] != 0x02) {
LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED,
"Key reference not compatible with "
"requested usage");
}
break;
case SC_SEC_OPERATION_DECIPHER:
sc_log(card->ctx, "Operation: Decipher.");
/* we allow key ref 2 (auth key) to be used for deciphering */
if (env->key_ref[0] != 0x01 && env->key_ref[0] != 0x02) {
LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED,
"Key reference not compatible with "
"requested usage");
}
break;
default:
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
}
priv->sec_env = *env;
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/**
* set MANAGE SECURITY ENVIRONMENT as documented in 7.2.18 since OpenPGP Card v3.3
*
* "This optional command (announced in Extended Capabilities) assigns a specific key to a
* command. The DEC-key (Key-Ref 2) can be assigned to the command INTERNAL AUTHENTICATE
* and the AUT-Key (Key.Ref 3) can be linked to the command PSO:DECIPHER also."
*
* key: Key-Ref to change (2 for DEC-Key or 3 for AUT-Key)
* p2: Usage to set (0xb8 for PSO:DECIPHER or 0xa4 for INTERNAL AUTHENTICATE)
**/
static int
pgp_set_MSE(sc_card_t *card, int key, u8 p2)
{
struct pgp_priv_data *priv = DRVDATA(card);
sc_apdu_t apdu;
u8 apdu_case = SC_APDU_CASE_3;
u8 apdu_data[3];
int r;
LOG_FUNC_CALLED(card->ctx);
// check if MSE is supported
if (!(priv->ext_caps & EXT_CAP_MSE))
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
// create apdu
sc_format_apdu(card, &apdu, apdu_case, 0x22, 0x41, p2);
apdu.lc = 3;
apdu_data[0] = 0x83;
apdu_data[1] = 0x01;
apdu_data[2] = key;
apdu.data = apdu_data;
apdu.datalen = 3;
// transmit apdu
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/**
* ABI: ISO 7816-8 COMPUTE DIGITAL SIGNATURE.
*/
static int
pgp_compute_signature(sc_card_t *card, const u8 *data,
size_t data_len, u8 * out, size_t outlen)
{
struct pgp_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
sc_apdu_t apdu;
u8 apdu_case = (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_4;
int r;
LOG_FUNC_CALLED(card->ctx);
if (env->operation != SC_SEC_OPERATION_SIGN)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
switch (env->key_ref[0]) {
case 0x00: /* signature key */
/* PSO SIGNATURE */
sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x9E, 0x9A);
break;
case 0x02: /* authentication key */
/* INTERNAL AUTHENTICATE */
sc_format_apdu(card, &apdu, apdu_case, 0x88, 0, 0);
break;
case 0x01:
default:
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid key reference");
}
/* if card/reader does not support extended APDUs, but chaining, then set it */
if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
apdu.flags |= SC_APDU_FLAGS_CHAINING;
apdu.lc = data_len;
apdu.data = (u8 *)data;
apdu.datalen = data_len;
apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
apdu.resp = out;
apdu.resplen = outlen;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
}
/**
* ABI: ISO 7816-8 DECIPHER - perform deciphering operation.
*/
static int
pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
u8 *out, size_t outlen)
{
struct pgp_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
sc_apdu_t apdu;
u8 apdu_case = SC_APDU_CASE_4;
u8 *temp = NULL;
int r;
LOG_FUNC_CALLED(card->ctx);
/* padding according to OpenPGP card spec 1.1 & 2.x section 7.2.9 / 3.x section 7.2.11 */
Do not cast the return value of malloc(3) and calloc(3) From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety " Casting and type safety malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. One may "cast" (see type conversion) this pointer to a specific type, as in int *ptr = (int*)malloc(10 * sizeof (int)); When using C, this is considered bad practice; it is redundant under the C standard. Moreover, putting in a cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the C compiler will assume that malloc returns an int, and will issue a warning in a context such as the above, provided the error is not masked by a cast. On certain architectures and data models (such as LP64 on 64 bit systems, where long and pointers are 64 bit and int is 32 bit), this error can actually result in undefined behavior, as the implicitly declared malloc returns a 32 bit value whereas the actually defined function returns a 64 bit value. Depending on calling conventions and memory layout, this may result in stack smashing. The returned pointer need not be explicitly cast to a more specific pointer type, since ANSI C defines an implicit conversion between the void pointer type and other pointers to objects. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in standard C code.[4][5] Omitting the cast, however, creates an incompatibility with C++, which does require it. The lack of a specific pointer type returned from malloc is type-unsafe behaviour: malloc allocates based on byte count but not on type. This distinguishes it from the C++ new operator that returns a pointer whose type relies on the operand. (see C Type Safety). " See also http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
if (!(temp = malloc(inlen + 1)))
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* padding byte: 0xa6 = ECC; 0x00 = RSA; 0x02 = AES */
(env->algorithm == SC_ALGORITHM_EC) ? (temp[0] = 0xa6) : (temp[0] = 0x00);
memcpy(temp + 1, in, inlen);
in = temp;
inlen += 1;
if (env->operation != SC_SEC_OPERATION_DECIPHER) {
free(temp);
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
}
switch (env->key_ref[0]) {
case 0x01: /* Decryption key */
case 0x02: /* authentication key */
/* PSO DECIPHER */
sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x80, 0x86);
break;
case 0x00: /* signature key */
default:
free(temp);
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid key reference");
}
/* Gnuk only supports short APDU, so we need to use command chaining */
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
apdu.flags |= SC_APDU_FLAGS_CHAINING;
}
/* if card/reader does not support extended APDUs, but chaining, then set it */
if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
apdu.flags |= SC_APDU_FLAGS_CHAINING;
apdu.lc = inlen;
apdu.data = (u8 *)in;
apdu.datalen = inlen;
apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
apdu.resp = out;
apdu.resplen = outlen;
/* For OpenPGP Card >=v3.3, key slot 3 instead of 2 can be used for deciphering,
* but this has to be set via MSE beforehand on every usage (slot 2 is used by default)
* see section 7.2.18 of the specification of OpenPGP Card v3.3 */
if (priv->bcd_version >= OPENPGP_CARD_3_3 && env->key_ref[0] == 0x02){
pgp_set_MSE(card, 3, 0xb8);
}
r = sc_transmit_apdu(card, &apdu);
free(temp);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
/* For OpenPGP Card >=v3.3, use key slot 2 for deciphering again (set to default) */
if (priv->bcd_version >= OPENPGP_CARD_3_3 && env->key_ref[0] == 0x02){
pgp_set_MSE(card, 2, 0xb8);
}
LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
}
#ifdef ENABLE_OPENSSL
/**
* Internal: update algorithm attribute for new key size (before generating key).
**/
static int
pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *algo_blob;
const unsigned int tag = 0x00C0 | key_info->key_id;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
u8 *data;
int data_len;
int r = SC_SUCCESS;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
unsigned int i;
LOG_FUNC_CALLED(card->ctx);
r = pgp_seek_blob(card, priv->mf, tag, &algo_blob);
LOG_TEST_RET(card->ctx, r, "Cannot get old algorithm attributes");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) {
/* ECDSA and ECDH */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
data_len = key_info->u.ec.oid_len+1;
data = malloc(data_len);
if (!data)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
data[0] = key_info->algorithm;
/* oid.value is type int, therefore we need to loop over the values */
for (i=0; i < key_info->u.ec.oid_len; i++){
data[i+1] = key_info->u.ec.oid.value[i];
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
/* RSA */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){
/* We can not rely on previous key attributes anymore, as it might be ECC */
if (key_info->u.rsa.exponent_len == 0 || key_info->u.rsa.modulus_len == 0)
LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS);
data_len = 6;
data = malloc(data_len);
if (!data)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
data[0] = key_info->algorithm;
ushort2bebytes(data+1, key_info->u.rsa.modulus_len);
2020-08-29 21:22:34 +00:00
/* OpenPGP Card only accepts 32bit as exponent length field,
* although you can import keys with smaller exponent;
* thus we don't change rsa.exponent_len, but ignore it here */
ushort2bebytes(data+3, SC_OPENPGP_MAX_EXP_BITS);
/* Import-Format of private key (e,p,q) */
data[5] = SC_OPENPGP_KEYFORMAT_RSA_STD;
}
else {
sc_log(card->ctx, "Unknown algorithm id");
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
pgp_set_blob(algo_blob, data, data_len);
free(data);
r = pgp_put_data(card, tag, algo_blob->data, data_len);
/* Note: Don't use pgp_set_blob to set data, because it won't touch the real DO */
LOG_TEST_RET(card->ctx, r, "Cannot set new algorithm attributes");
} else {
sc_cardctl_openpgp_keygen_info_t old_key_info;
if (pgp_parse_algo_attr_blob(algo_blob, &old_key_info) != SC_SUCCESS
|| old_key_info.algorithm != key_info->algorithm)
LOG_TEST_RET(card->ctx, SC_ERROR_NO_CARD_SUPPORT,
"Requested algorithm not supported");
/* FIXME check whether the static parameters match the requested ones. */
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Internal: store creation time of key.
* Pass non-zero outtime to use predefined time.
* Pass zero/null outtime to calculate current time. outtime then will be output.
* Pass null outtime to not receive output.
**/
static int
pgp_store_creationtime(sc_card_t *card, u8 key_id, time_t *outtime)
{
int r;
time_t createtime = 0;
const size_t timestrlen = 64;
char timestring[65];
u8 buf[4];
struct tm tm;
LOG_FUNC_CALLED(card->ctx);
if (key_id < 1 || key_id > 3)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
if (outtime != NULL && *outtime != 0)
createtime = *outtime;
else if (outtime != NULL)
/* set output */
*outtime = createtime = time(NULL);
#ifdef _WIN32
if (0 != gmtime_s(&tm, &createtime))
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
#else
if (NULL == gmtime_r(&createtime, &tm))
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
#endif
strftime(timestring, timestrlen, "%c %Z", &tm);
sc_log(card->ctx, "Creation time %s.", timestring);
/* Code borrowed from GnuPG */
ulong2bebytes(buf, (unsigned long)createtime);
r = pgp_put_data(card, 0x00CD + key_id, buf, 4);
LOG_TEST_RET(card->ctx, r, "Cannot write to DO");
LOG_FUNC_RETURN(card->ctx, r);
}
/**
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
* Internal: calculate and store PGP fingerprints.
* Reference: GnuPG, app-openpgp.c.
**/
static int
pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime,
sc_cardctl_openpgp_keygen_info_t *key_info)
{
u8 fingerprint[SHA_DIGEST_LENGTH];
u8 *fp_buffer = NULL; /* fingerprint buffer, not hashed */
size_t fp_buffer_len;
u8 *p; /* use this pointer to set fp_buffer content */
size_t pk_packet_len;
unsigned int tag = 0x00C6 + key_info->key_id;
pgp_blob_t *fpseq_blob = NULL;
u8 *newdata = NULL;
int r;
LOG_FUNC_CALLED(card->ctx);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* constructing public-key packet length */
/* RSA */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA) {
if (key_info->u.rsa.modulus == NULL
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
|| key_info->u.rsa.exponent == NULL
|| (key_info->u.rsa.modulus_len) == 0
|| (key_info->u.rsa.exponent_len) == 0) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
sc_log(card->ctx, "Null data (modulus or exponent)");
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* https://tools.ietf.org/html/rfc4880 page 41, 72 */
pk_packet_len = 1 /* version number */
+ 4 /* creation time */
+ 1 /* algorithm */
+ 2 /* algorithm-specific fields: RSA modulus+exponent */
+ (BYTES4BITS(key_info->u.rsa.modulus_len))
+ 2
+ (BYTES4BITS(key_info->u.rsa.exponent_len));
}
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
if (key_info->u.ec.ecpoint == NULL || (key_info->u.ec.ecpoint_len) == 0) {
sc_log(card->ctx, "Error: ecpoint required!");
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* https://tools.ietf.org/html/rfc4880 page 41, 72
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
* and https://tools.ietf.org/html/rfc6637 section 9 (page 8 and 9) */
pk_packet_len = 1 /* version number */
+ 4 /* creation time */
+ 1 /* algorithm */
+ 1 /* oid len */
+ (key_info->u.ec.oid_len) /* oid */
+ (key_info->u.ec.ecpoint_len); /* ecpoint */
/* KDF parameters for ECDH */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH) {
/* https://tools.ietf.org/html/rfc6637#section-8 */
pk_packet_len += 1 /* number of bytes */
+ 1 /* version number */
+ 1 /* KDF algo */
+ 1; /* KEK algo */
}
}
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
sc_log(card->ctx, "pk_packet_len is %"SC_FORMAT_LEN_SIZE_T"u", pk_packet_len);
fp_buffer_len = 3 + pk_packet_len;
p = fp_buffer = calloc(fp_buffer_len, 1);
if (p == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* constructing public-key packet */
p[0] = 0x99; /* http://tools.ietf.org/html/rfc4880 page 71 */
ushort2bebytes(++p, (unsigned short)pk_packet_len);
/* start pk_packet */
p += 2;
*p = 4; /* Version 4 key */
ulong2bebytes(++p, (unsigned long)ctime); /* Creation time */
p += 4;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA) {
*p = 1; /* Algorithm ID, RSA */
p += 1;
ushort2bebytes(p, (unsigned short)key_info->u.rsa.modulus_len);
p += 2;
memcpy(p, key_info->u.rsa.modulus, (BYTES4BITS(key_info->u.rsa.modulus_len)));
p += (key_info->u.rsa.modulus_len >> 3);
ushort2bebytes(++p, (unsigned short)key_info->u.rsa.exponent_len);
p += 2;
memcpy(p, key_info->u.rsa.exponent, (BYTES4BITS(key_info->u.rsa.exponent_len)));
}
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
/* Algorithm ID, see https://tools.ietf.org/html/rfc6637#section-5 */
*p = key_info->algorithm + 6;
p += 1;
*p = key_info->u.ec.oid_len;
p += 1;
memcpy(p, key_info->u.ec.oid.value, key_info->u.ec.oid_len);
p += key_info->u.ec.oid_len;
memcpy(p, key_info->u.ec.ecpoint, key_info->u.ec.ecpoint_len);
/* KDF parameters for ECDH */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH) {
/* https://tools.ietf.org/html/rfc6637#section-8
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
* This is copied from GnuPG's ecdh_params() function in app-openpgp.c */
p += key_info->u.ec.ecpoint_len;
*p = 0x03; /* number of bytes following */
p += 1;
*p = 0x01; /* version of this format */
p += 1;
if (key_info->u.ec.ecpoint_len <= 256){ /* ec bit size <= 256 */
*p = 0x08; /* KDF algo */
*(p+1) = 0x07; /* KEK algo */
}
else if (key_info->u.ec.ecpoint_len <= 384) { /* ec bit size <= 384 */
*p = 0x09; /* KDF algo */
*(p+1) = 0x08; /* KEK algo */
}
else { /* ec bit size = 512 or 521*/
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
*p = 0x0a; /* KDF algo */
*(p+1) = 0x09; /* KEK algo */
}
}
}
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
p = NULL;
/* hash with SHA-1 */
SHA1(fp_buffer, fp_buffer_len, fingerprint);
free(fp_buffer);
/* store to DO */
sc_log(card->ctx, "Writing to DO %04X.", tag);
r = pgp_put_data(card, tag, fingerprint, SHA_DIGEST_LENGTH);
LOG_TEST_RET(card->ctx, r, "Cannot write to DO");
/* update the blob containing fingerprints (00C5) */
sc_log(card->ctx, "Updating fingerprint blob 00C5.");
fpseq_blob = pgp_find_blob(card, 0x00C5);
if (fpseq_blob == NULL)
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot find blob 00C5");
/* save the fingerprints sequence */
newdata = malloc(fpseq_blob->len);
if (newdata == NULL)
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY,
"Not enough memory to update fingerprint blob 00C5");
memcpy(newdata, fpseq_blob->data, fpseq_blob->len);
/* move p to the portion holding the fingerprint of the current key */
p = newdata + 20 * (key_info->key_id - 1);
/* copy new fingerprint value */
memcpy(p, fingerprint, 20);
/* set blob's data */
pgp_set_blob(fpseq_blob, newdata, fpseq_blob->len);
free(newdata);
err:
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Internal: update pubkey blob.
* Note that modulus_len, exponent_len is measured in bit.
**/
static int
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *pk_blob;
unsigned int blob_id = 0;
sc_pkcs15_pubkey_t p15pubkey;
u8 *data = NULL;
size_t len;
int r;
LOG_FUNC_CALLED(card->ctx);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (key_info->key_id == SC_OPENPGP_KEY_SIGN)
2014-11-09 08:58:40 +00:00
blob_id = DO_SIGN_SYM;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
else if (key_info->key_id == SC_OPENPGP_KEY_ENCR)
2014-11-09 08:58:40 +00:00
blob_id = DO_ENCR_SYM;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
else if (key_info->key_id == SC_OPENPGP_KEY_AUTH)
2014-11-09 08:58:40 +00:00
blob_id = DO_AUTH_SYM;
else {
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
}
sc_log(card->ctx, "Retrieving blob %04X.", blob_id);
r = pgp_get_blob(card, priv->mf, blob_id, &pk_blob);
LOG_TEST_RET(card->ctx, r, "Cannot get the blob");
/* encode pubkey */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){
memset(&p15pubkey, 0, sizeof(p15pubkey));
p15pubkey.algorithm = SC_ALGORITHM_RSA;
p15pubkey.u.rsa.modulus.data = key_info->u.rsa.modulus;
p15pubkey.u.rsa.modulus.len = BYTES4BITS(key_info->u.rsa.modulus_len);
p15pubkey.u.rsa.exponent.data = key_info->u.rsa.exponent;
p15pubkey.u.rsa.exponent.len = BYTES4BITS(key_info->u.rsa.exponent_len);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
memset(&p15pubkey, 0, sizeof(p15pubkey));
p15pubkey.algorithm = SC_ALGORITHM_EC;
p15pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint;
p15pubkey.u.ec.ecpointQ.len = key_info->u.ec.ecpoint_len;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
r = sc_pkcs15_encode_pubkey(card->ctx, &p15pubkey, &data, &len);
LOG_TEST_RET(card->ctx, r, "Cannot encode pubkey");
sc_log(card->ctx, "Updating blob %04X's content.", blob_id);
r = pgp_set_blob(pk_blob, data, len);
LOG_TEST_RET(card->ctx, r, "Cannot update blob content");
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Internal: parse response data and set output
**/
static int
pgp_parse_and_set_pubkey_output(sc_card_t *card, u8* data, size_t data_len,
sc_cardctl_openpgp_keygen_info_t *key_info)
{
time_t ctime = 0;
u8 *in = data;
int r;
LOG_FUNC_CALLED(card->ctx);
/* store creation time */
r = pgp_store_creationtime(card, key_info->key_id, &ctime);
LOG_TEST_RET(card->ctx, r, "Cannot store creation time");
/* parse response. Ref: pgp_enumerate_blob() */
while (data_len > (size_t) (in - data)) {
unsigned int cla, tag, tmptag;
size_t len;
u8 *part = in;
/* parse TLV structure */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
r = sc_asn1_read_tag((const u8**)&part, data_len - (in - data), &cla, &tag, &len);
if (part == NULL)
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
LOG_TEST_RET(card->ctx, r, "Unexpected end of contents");
/* undo ASN1's split of tag & class */
for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
cla <<= 8;
}
tag |= cla;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA modulus */
if (tag == 0x0081) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if ((BYTES4BITS(key_info->u.rsa.modulus_len) < len) /* modulus_len is in bits */
|| key_info->u.rsa.modulus == NULL) {
free(key_info->u.rsa.modulus);
key_info->u.rsa.modulus = malloc(len);
if (key_info->u.rsa.modulus == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* set values */
memcpy(key_info->u.rsa.modulus, part, len);
key_info->u.rsa.modulus_len = len * 8; /* store length in bits */
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA public exponent */
else if (tag == 0x0082) {
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if ((BYTES4BITS(key_info->u.rsa.exponent_len) < len) /* exponent_len is in bits */
|| key_info->u.rsa.exponent == NULL) {
free(key_info->u.rsa.exponent);
key_info->u.rsa.exponent = malloc(len);
if (key_info->u.rsa.exponent == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
}
/* set values */
memcpy(key_info->u.rsa.exponent, part, len);
key_info->u.rsa.exponent_len = len * 8; /* store length in bits */
}
/* ECC public key */
else if (tag == 0x0086) {
/* set the output data */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* len is ecpoint length + format byte
* see section 7.2.14 of 3.3.1 specs */
if ((key_info->u.ec.ecpoint_len) != (len - 1)
|| key_info->u.ec.ecpoint == NULL) {
free(key_info->u.ec.ecpoint);
key_info->u.ec.ecpoint = malloc(len);
if (key_info->u.ec.ecpoint == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
memcpy(key_info->u.ec.ecpoint, part + 1, len - 1);
}
/* go to next part to parse */
/* This will be different from pgp_enumerate_blob() a bit */
in = part + ((tag != 0x7F49) ? len : 0);
}
/* calculate and store fingerprint */
sc_log(card->ctx, "Calculate and store fingerprint");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
r = pgp_calculate_and_store_fingerprint(card, ctime, key_info);
LOG_TEST_RET(card->ctx, r, "Cannot store fingerprint");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* update pubkey blobs (B601, B801, A401) */
sc_log(card->ctx, "Update blobs holding pubkey info.");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
r = pgp_update_pubkey_blob(card, key_info);
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Internal: update card->algorithms
*/
static int
pgp_update_card_algorithms(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
{
sc_algorithm_info_t *algo;
u8 id = key_info->key_id;
LOG_FUNC_CALLED(card->ctx);
/* protect incompatible cards against non-RSA */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA
&& card->type < SC_CARD_TYPE_OPENPGP_V3
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
if (id > card->algorithm_count) {
sc_log(card->ctx,
"This key ID %u is out of the card's algorithm list.",
(unsigned int)id);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* get the algorithm corresponding to the key ID */
algo = card->algorithms + (id - 1);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* update new key attribute */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA) {
algo->algorithm = SC_ALGORITHM_RSA;
algo->key_length = (unsigned int)key_info->u.rsa.modulus_len;
}
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
algo->algorithm = SC_ALGORITHM_EC;
algo->key_length = (unsigned int)((key_info->u.ec.ecpoint_len));
}
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/**
* ABI (card ctl): GENERATE ASYMMETRIC KEY PAIR
**/
static int
pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
{
sc_apdu_t apdu;
/* temporary variables to hold APDU params */
u8 apdu_case;
u8 apdu_data[2] = { 0x00, 0x00 };
size_t apdu_le;
size_t resplen = 0;
int r = SC_SUCCESS;
LOG_FUNC_CALLED(card->ctx);
/* protect incompatible cards against non-RSA */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA
&& card->type < SC_CARD_TYPE_OPENPGP_V3
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
/* set Control Reference Template for key */
if (key_info->key_id == SC_OPENPGP_KEY_SIGN)
ushort2bebytes(apdu_data, DO_SIGN);
else if (key_info->key_id == SC_OPENPGP_KEY_ENCR)
ushort2bebytes(apdu_data, DO_ENCR);
else if (key_info->key_id == SC_OPENPGP_KEY_AUTH)
ushort2bebytes(apdu_data, DO_AUTH);
else {
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
}
/* set attributes for new-generated key */
r = pgp_update_new_algo_attr(card, key_info);
LOG_TEST_RET(card->ctx, r, "Cannot set attributes for new-generated key");
/* Test whether we will need extended APDU. 1900 is an
2012-06-14 02:17:28 +00:00
* arbitrary modulus length which for sure fits into a short APDU.
* This idea is borrowed from GnuPG code. */
if (card->caps & SC_CARD_CAP_APDU_EXT
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
&& key_info->u.rsa.modulus_len > 1900
2015-07-03 16:21:38 +00:00
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
/* We won't store to apdu variable yet, because it will be reset in
* sc_format_apdu() */
apdu_le = card->max_recv_size;
apdu_case = SC_APDU_CASE_4_EXT;
}
else {
apdu_case = SC_APDU_CASE_4_SHORT;
apdu_le = 256;
resplen = MAXLEN_RESP_PUBKEY;
}
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
resplen = MAXLEN_RESP_PUBKEY_GNUK;
}
/* prepare APDU */
sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0);
apdu.data = apdu_data;
apdu.datalen = sizeof(apdu_data);
apdu.lc = sizeof(apdu_data);
apdu.le = apdu_le;
/* buffer to receive response */
apdu.resplen = (resplen > 0) ? resplen : apdu_le;
apdu.resp = calloc(apdu.resplen, 1);
if (apdu.resp == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
}
/* send */
sc_log(card->ctx, "Waiting for the card to generate key...");
r = sc_transmit_apdu(card, &apdu);
sc_log(card->ctx, "Card has done key generation.");
LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed");
/* check response */
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
/* instruct more in case of error */
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Please verify PIN first.");
goto err;
}
LOG_TEST_GOTO_ERR(card->ctx, r, "Card returned error");
/* parse response data and set output */
pgp_parse_and_set_pubkey_output(card, apdu.resp, apdu.resplen, key_info);
pgp_update_card_algorithms(card, key_info);
err:
free(apdu.resp);
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Internal: build TLV.
*
* FIXME use `sc_asn1_put_tag` or similar instead
*
* @param[in] data The data ("value") part to build TLV.
* @param[in] len Data length
* @param[out] out The buffer of overall TLV. This buffer should be freed later.
* @param[out] outlen The length of buffer out.
**/
static int
pgp_build_tlv(sc_context_t *ctx, unsigned int tag, u8 *data, size_t len, u8 **out, size_t *outlen)
{
u8 highest_order = 0;
int r;
r = sc_asn1_write_element(ctx, tag, data, len, out, outlen);
LOG_TEST_RET(ctx, r, "Failed to write ASN.1 element");
/* Restore class bits stripped by sc_asn1_write_element */
/* determine the leftmost byte of tag, which contains class bits */
while ((tag >> 8*highest_order) != 0) {
highest_order++;
}
highest_order--;
/* restore class bits in output */
if (highest_order < 4)
*out[0] |= (tag >> 8*highest_order);
return SC_SUCCESS;
}
/**
* Internal: set Tag & Length components for TLV, store them in buffer.
*
* FIXME use `sc_asn1_put_tag` or similar instead
*
* Return the total length of Tag + Length.
* Note that the Value components is not counted.
* Ref: add_tlv() of GnuPG code.
**/
static size_t
set_taglength_tlv(u8 *buffer, unsigned int tag, size_t length)
{
u8 *p = buffer;
assert(tag <= 0xffff);
if (tag > 0xff)
*p++ = (tag >> 8) & 0xFF;
*p++ = tag;
if (length < 128)
*p++ = (u8)length;
else if (length < 256) {
*p++ = 0x81;
*p++ = (u8)length;
}
else {
if (length > 0xffff)
length = 0xffff;
*p++ = 0x82;
*p++ = (length >> 8) & 0xFF;
*p++ = length & 0xFF;
}
return p - buffer;
}
/**
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
* Internal: build Extended Header list (sec 4.3.3.9 - OpenPGP card spec v.3)
**/
static int
pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info,
u8 **result, size_t *resultlen)
{
sc_context_t *ctx = card->ctx;
/* Cardholder private key template (7F48) part */
const size_t max_prtem_len = 7*(1 + 3); /* 7 components */
/* 1 for tag name (91, 92... 97)
* 3 for storing length */
u8 pritemplate[7*(1 + 3)];
size_t tpl_len = 0; /* Actual size of pritemplate */
/* Concatenation of key data */
u8 kdata[3 + 256 + 256 + 512]; /* Exponent is stored in 3 bytes
* With maximum 4096-bit key,
* p and q can be stored in 256 bytes (2048 bits).
* Maximum 4096-bit modulus is stored in 512 bytes */
size_t kdata_len = 0; /* Actual size of kdata */
u8 *tlvblock = NULL;
size_t tlvlen = 0;
u8 *tlv_5f48 = NULL;
size_t tlvlen_5f48 = 0;
u8 *tlv_7f48 = NULL;
size_t tlvlen_7f48 = 0;
u8 *data = NULL;
size_t len = 0;
u8 *p = NULL;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
u8 *components[4];
size_t componentlens[4];
unsigned int componenttags[4];
char *componentnames[4];
size_t comp_to_add;
u8 i;
int r;
LOG_FUNC_CALLED(ctx);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){
components[0] = key_info->u.rsa.e;
components[1] = key_info->u.rsa.p;
components[2] = key_info->u.rsa.q;
componentlens[0] = key_info->u.rsa.e_len;
componentlens[1] = key_info->u.rsa.p_len;
componentlens[2] = key_info->u.rsa.q_len;
componenttags[0] = 0x91;
componenttags[1] = 0x92;
componenttags[2] = 0x93;
componentnames[0] = "public exponent";
componentnames[1] = "prime p";
componentnames[2] = "prime q";
comp_to_add = 3;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* The maximum exponent length is 32 bit, as set on card
* we use this variable to check against actual exponent_len */
size_t max_e_len_bytes = BYTES4BITS(SC_OPENPGP_MAX_EXP_BITS);
size_t e_len_bytes = BYTES4BITS(key_info->u.rsa.e_len);
if (key_info->u.rsa.keyformat == SC_OPENPGP_KEYFORMAT_RSA_STDN
|| key_info->u.rsa.keyformat == SC_OPENPGP_KEYFORMAT_RSA_CRTN){
components[3] = key_info->u.rsa.n;
componentlens[3] = key_info->u.rsa.n_len;
componenttags[3] = 0x97;
componentnames[3] = "modulus";
comp_to_add = 4;
}
/* validate */
if (comp_to_add == 4 && (key_info->u.rsa.n == NULL || key_info->u.rsa.n_len == 0)){
sc_log(ctx, "Error: Modulus required!");
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* Cardholder private key template's data part */
memset(pritemplate, 0, max_prtem_len);
/* maximum 32 bit exponent length allowed on OpenPGP Card */
assert(key_info->u.rsa.e_len <= SC_OPENPGP_MAX_EXP_BITS);
/* We need to right justify the exponent with allowed exponent length,
* e.g. from '01 00 01' to '00 01 00 01' */
if (key_info->u.rsa.e_len < SC_OPENPGP_MAX_EXP_BITS) {
/* create new buffer */
p = calloc(max_e_len_bytes, 1);
if (!p)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
memcpy(p + (max_e_len_bytes - e_len_bytes), key_info->u.rsa.e, e_len_bytes);
/* set key_info->u.rsa.e to new buffer */
free(key_info->u.rsa.e);
key_info->u.rsa.e = p;
components[0] = p;
key_info->u.rsa.e_len = SC_OPENPGP_MAX_EXP_BITS; /* we store info in bits */
componentlens[0] = max_e_len_bytes; /* ... but in bytes for header list */
}
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
components[0] = key_info->u.ec.privateD;
componentlens[0] = key_info->u.ec.privateD_len;
componenttags[0] = 0x92;
componentnames[0] = "private key";
comp_to_add = 1;
/* import public key as well */
if (key_info->u.ec.keyformat == SC_OPENPGP_KEYFORMAT_EC_STDPUB){
components[1] = key_info->u.ec.ecpointQ;
componentlens[1] = key_info->u.ec.ecpointQ_len;
componenttags[1] = 0x99;
componentnames[1] = "public key";
comp_to_add = 2;
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* validate */
if ((key_info->u.ec.ecpointQ == NULL || key_info->u.ec.ecpointQ_len == 0)){
sc_log(ctx, "Error: ecpointQ required!");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* Cardholder private key template's data part */
memset(pritemplate, 0, max_prtem_len);
}
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
/* start from beginning of pritemplate */
p = pritemplate;
for (i = 0; i < comp_to_add; i++) {
sc_log(ctx, "Set Tag+Length for %s (%X).", componentnames[i], componenttags[i]);
len = set_taglength_tlv(p, componenttags[i], componentlens[i]);
tpl_len += len;
/*
* <-- kdata_len --><-- Copy here -->
* kdata |===============|___________________
*/
memcpy(kdata + kdata_len, components[i], componentlens[i]);
kdata_len += componentlens[i];
/* Move p to next part and build */
p += len;
}
/* TODO: Components for CRT format */
/* TLV block for 7F48 */
r = pgp_build_tlv(ctx, 0x7F48, pritemplate, tpl_len, &tlv_7f48, &tlvlen_7f48);
LOG_TEST_RET(ctx, r, "Failed to build TLV for 7F48");
tlv_7f48[0] |= 0x7F;
r = pgp_build_tlv(ctx, 0x5f48, kdata, kdata_len, &tlv_5f48, &tlvlen_5f48);
LOG_TEST_GOTO_ERR(ctx, r, "Failed to build TLV for 5F48");
/* data part's length for Extended Header list */
len = 2 + tlvlen_7f48 + tlvlen_5f48;
/* set data part content */
data = calloc(len, 1);
if (data == NULL)
LOG_TEST_GOTO_ERR(ctx, SC_ERROR_NOT_ENOUGH_MEMORY, "Not enough memory");
switch (key_info->key_id) {
case SC_OPENPGP_KEY_SIGN:
ushort2bebytes(data, DO_SIGN);
break;
case SC_OPENPGP_KEY_ENCR:
ushort2bebytes(data, DO_ENCR);
break;
case SC_OPENPGP_KEY_AUTH:
ushort2bebytes(data, DO_AUTH);
break;
default:
LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
memcpy(data + 2, tlv_7f48, tlvlen_7f48);
memcpy(data + 2 + tlvlen_7f48, tlv_5f48, tlvlen_5f48);
r = pgp_build_tlv(ctx, 0x4D, data, len, &tlvblock, &tlvlen);
LOG_TEST_GOTO_ERR(ctx, r, "Cannot build TLV for Extended Header list");
/* set output */
if (result != NULL) {
*result = tlvblock;
*resultlen = tlvlen;
} else {
free(tlvblock);
}
err:
free(data);
free(tlv_5f48);
free(tlv_7f48);
LOG_FUNC_RETURN(ctx, r);
}
/**
* ABI (card ctl): store key
**/
static int
pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info)
{
sc_cardctl_openpgp_keygen_info_t pubkey;
u8 *data = NULL;
size_t len = 0;
int r;
LOG_FUNC_CALLED(card->ctx);
/* protect incompatible cards against non-RSA */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA
&& card->type < SC_CARD_TYPE_OPENPGP_V3
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
/* Validate */
if (key_info->key_id < 1 || key_info->key_id > 3)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
/* set algorithm attributes */
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* RSA */
if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){
/* we just support standard key format */
switch (key_info->u.rsa.keyformat) {
case SC_OPENPGP_KEYFORMAT_RSA_STD:
case SC_OPENPGP_KEYFORMAT_RSA_STDN:
break;
case SC_OPENPGP_KEYFORMAT_RSA_CRT:
case SC_OPENPGP_KEYFORMAT_RSA_CRTN:
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
default:
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
/* we only support exponent of maximum 32 bits */
if (key_info->u.rsa.e_len > SC_OPENPGP_MAX_EXP_BITS) {
sc_log(card->ctx,
"Exponent %"SC_FORMAT_LEN_SIZE_T"u-bit (>32) is not supported.",
key_info->u.rsa.e_len);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
memset(&pubkey, 0, sizeof(pubkey));
pubkey.key_id = key_info->key_id;
pubkey.algorithm = key_info->algorithm;
if (key_info->u.rsa.n && key_info->u.rsa.n_len
&& key_info->u.rsa.e && key_info->u.rsa.e_len) {
pubkey.u.rsa.modulus = key_info->u.rsa.n;
pubkey.u.rsa.modulus_len = key_info->u.rsa.n_len;
pubkey.u.rsa.exponent = key_info->u.rsa.e;
pubkey.u.rsa.exponent_len = key_info->u.rsa.e_len;
}
else
LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
/* ECC */
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
memset(&pubkey, 0, sizeof(pubkey));
pubkey.key_id = key_info->key_id;
pubkey.algorithm = key_info->algorithm;
if (key_info->u.ec.ecpointQ && key_info->u.ec.ecpointQ_len){
pubkey.u.ec.ecpoint = key_info->u.ec.ecpointQ;
pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpointQ_len;
pubkey.u.ec.oid = key_info->u.ec.oid;
pubkey.u.ec.oid_len = key_info->u.ec.oid_len;
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
}
else
LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS);
}
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
else
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
r = pgp_update_new_algo_attr(card, &pubkey);
LOG_TEST_RET(card->ctx, r, "Failed to update new algorithm attributes");
/* build Extended Header list */
r = pgp_build_extended_header_list(card, key_info, &data, &len);
LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to build Extended Header list");
/* write to DO */
r = pgp_put_data(card, 0x4D, data, len);
LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to write to DO 004D");
/* store creation time */
r = pgp_store_creationtime(card, key_info->key_id, &key_info->creationtime);
LOG_TEST_RET(card->ctx, r, "Cannot store creation time");
/* calculate and store fingerprint */
sc_log(card->ctx, "Calculate and store fingerprint");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
r = pgp_calculate_and_store_fingerprint(card, key_info->creationtime, &pubkey);
LOG_TEST_RET(card->ctx, r, "Cannot store fingerprint");
/* update pubkey blobs (B601,B801, A401) */
sc_log(card->ctx, "Update blobs holding pubkey info.");
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
r = pgp_update_pubkey_blob(card, &pubkey);
OpenPGP Card v3 ECC support (#1506) * pgp: initialize ecc keys for OPC3 * Add supported ECC algorithms by card version * Add tasks identified so far * pgp: Recognize ECC set on card * pgp: get_pubkey_pem read ECC pubkey from card * pgp: minor code changes for ECC compatibility * pgp: expand sc_cardctl_openpgp_keygen_info to hold ec info * Fix segfault problem in pkcs15-pubkey.c * pgp: enable key generation with pkcs15-init and ECC * pgp: adapt calculate_and_store_fingerprint to accept ECC * pgp: adapt rest of pgp_gen_key and subfunctions to accept ECC * pgp: add kdf parameters for ECDH fingerprint calculation * pgp: enable key import with pkcs15-init and ECC * pkcs15-pubkey: fix_ec_parameters onlz accpets explicit data or named_curve * Fix some mistakes during merge * More clean up for PR * Fix some ugly alignments * Improve code readability * Prevent unitialized variable by using FUNC_RETURN * OpenPGP: add length check * pgp: save exponent length in bits for sc_cardctl_openpgp_keystore_info_t * pgp: length checks and reallocations * pgp: oid init added * OpenPGP: slightly re-factor pgp_update_new_algo_attr() * replace loop copy with memcpy() * use ushort2bebytes() to set RSA modulus & exponent * use symbolic name SC_OPENPGP_KEYFORMAT_RSA_STD for the key import format * OpenPGP: slighly re-factor pgp_parse_and_set_pubkey_output() * check for RSA modulus & exponent lengths not being a multiple of 8 * make sure RSA modulus & exponent lengths are always set * remove a left-over RSA setting from the EC code * pgp: adding BYTES4BITS * pgp: initialization of values in pgp_build_extended_header_list based on key type * pgp: add BYTES4BITS and remove unnecessary tests * Fix broken pgp_update_new_algo_attr * pgp: fix the ecpoint_len variable
2019-01-30 21:00:36 +00:00
sc_log(card->ctx, "Update card algorithms");
pgp_update_card_algorithms(card, &pubkey);
err:
free(data);
LOG_FUNC_RETURN(card->ctx, r);
}
#endif /* ENABLE_OPENSSL */
/**
* ABI (card ctl): erase card
**/
static int
pgp_erase_card(sc_card_t *card)
{
/* Special series of commands to erase OpenPGP card,
* according to https://www.crypto-stick.com/en/faq
* (How to reset a Crypto Stick? question).
* Gnuk is known not to support this feature. */
const char *apdu_hex[] = {
/* block PIN1 */
"00:20:00:81:08:40:40:40:40:40:40:40:40",
"00:20:00:81:08:40:40:40:40:40:40:40:40",
"00:20:00:81:08:40:40:40:40:40:40:40:40",
"00:20:00:81:08:40:40:40:40:40:40:40:40",
/* block PIN3 */
"00:20:00:83:08:40:40:40:40:40:40:40:40",
"00:20:00:83:08:40:40:40:40:40:40:40:40",
"00:20:00:83:08:40:40:40:40:40:40:40:40",
"00:20:00:83:08:40:40:40:40:40:40:40:40",
/* TERMINATE */
"00:e6:00:00",
NULL
};
sc_apdu_t apdu;
int i;
int r = SC_SUCCESS;
struct pgp_priv_data *priv = DRVDATA(card);
LOG_FUNC_CALLED(card->ctx);
if ((priv->ext_caps & EXT_CAP_LCS) == 0) {
LOG_TEST_RET(card->ctx, SC_ERROR_NO_CARD_SUPPORT,
"Card does not offer life cycle management");
}
switch (priv->state) {
case CARD_STATE_ACTIVATED:
/* iterate over the commands above */
for (i = 0; apdu_hex[i] != NULL; i++) {
u8 apdu_bin[25]; /* large enough to convert apdu_hex */
size_t apdu_bin_len = sizeof(apdu_bin);
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
/* convert hex array to bin array */
r = sc_hex_to_bin(apdu_hex[i], apdu_bin, &apdu_bin_len);
LOG_TEST_RET(card->ctx, r, "Failed to convert APDU bytes");
/* build APDU from binary array */
r = sc_bytes2apdu(card->ctx, apdu_bin, apdu_bin_len, &apdu);
if (r)
LOG_TEST_RET(card->ctx, SC_ERROR_INTERNAL,
"Failed to build APDU");
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
/* send APDU to card */
sc_log(card->ctx, "Sending APDU%d %s", i, apdu_hex[i]);
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "Transmitting APDU failed");
}
/* fall through */
case CARD_STATE_INITIALIZATION:
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x44, 0, 0);
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "Transmitting APDU failed");
break;
default:
LOG_TEST_RET(card->ctx, SC_ERROR_NO_CARD_SUPPORT,
"Card does not offer life cycle management");
}
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* ABI: ISO 7816-9 CARD CTL - perform special card-specific operations.
*/
static int
pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
{
int r;
LOG_FUNC_CALLED(card->ctx);
switch(cmd) {
case SC_CARDCTL_GET_SERIALNR:
memmove((sc_serial_number_t *) ptr, &card->serialnr, sizeof(card->serialnr));
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
break;
#ifdef ENABLE_OPENSSL
case SC_CARDCTL_OPENPGP_GENERATE_KEY:
r = pgp_gen_key(card, (sc_cardctl_openpgp_keygen_info_t *) ptr);
LOG_FUNC_RETURN(card->ctx, r);
break;
case SC_CARDCTL_OPENPGP_STORE_KEY:
r = pgp_store_key(card, (sc_cardctl_openpgp_keystore_info_t *) ptr);
LOG_FUNC_RETURN(card->ctx, r);
break;
#endif /* ENABLE_OPENSSL */
case SC_CARDCTL_ERASE_CARD:
r = pgp_erase_card(card);
LOG_FUNC_RETURN(card->ctx, r);
break;
}
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
2013-04-12 08:33:31 +00:00
/**
* Internal: delete key (GnuK only).
*/
2013-04-12 08:33:31 +00:00
static int
gnuk_delete_key(sc_card_t *card, u8 key_id)
{
sc_context_t *ctx = card->ctx;
int r = SC_SUCCESS;
u8 data[4] = { 0x4D, 0x02, 0x00, 0x00 };
2013-04-12 08:33:31 +00:00
LOG_FUNC_CALLED(ctx);
if (key_id < 1 || key_id > 3)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS,
"Invalid key ID; must be 1, 2, or 3");
2013-04-16 03:19:34 +00:00
/* delete fingerprint */
2013-04-12 08:33:31 +00:00
sc_log(ctx, "Delete fingerprints");
r = pgp_put_data(card, 0xC6 + key_id, NULL, 0);
LOG_TEST_RET(ctx, r, "Failed to delete fingerprints");
/* delete creation time */
2013-04-12 08:33:31 +00:00
sc_log(ctx, "Delete creation time");
r = pgp_put_data(card, 0xCD + key_id, NULL, 0);
LOG_TEST_RET(ctx, r, "Failed to delete creation time");
/* rewrite Extended Header List */
2013-04-12 08:33:31 +00:00
sc_log(ctx, "Rewrite Extended Header List");
if (key_id == SC_OPENPGP_KEY_SIGN)
ushort2bebytes(data+2, DO_SIGN);
else if (key_id == SC_OPENPGP_KEY_ENCR)
ushort2bebytes(data+2, DO_ENCR);
else if (key_id == SC_OPENPGP_KEY_AUTH)
ushort2bebytes(data+2, DO_AUTH);
2013-04-12 08:33:31 +00:00
r = pgp_put_data(card, 0x4D, data, sizeof(data));
2013-04-12 08:33:31 +00:00
LOG_FUNC_RETURN(ctx, r);
}
/**
* ABI: ISO 7816-9 DELETE FILE - delete EF or DF given.
*/
static int
pgp_delete_file(sc_card_t *card, const sc_path_t *path)
2012-06-01 15:59:20 +00:00
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob;
2012-06-01 15:59:20 +00:00
sc_file_t *file;
int r;
LOG_FUNC_CALLED(card->ctx);
/* sc_pkcs15init_delete_by_path() sets the path type to SC_PATH_TYPE_FILE_ID */
2012-06-01 15:59:20 +00:00
r = pgp_select_file(card, path, &file);
LOG_TEST_RET(card->ctx, r, "Cannot select file");
2012-06-01 15:59:20 +00:00
/* save "current" blob */
blob = priv->current;
2012-06-01 15:59:20 +00:00
/* don't try to delete MF */
if (blob == priv->mf)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
2013-04-12 08:33:31 +00:00
if (card->type != SC_CARD_TYPE_OPENPGP_GNUK &&
2015-07-03 16:21:38 +00:00
(file->id == DO_SIGN_SYM || file->id == DO_ENCR_SYM || file->id == DO_AUTH_SYM)) {
/* These tags are just symbolic. We don't really delete them. */
r = SC_SUCCESS;
}
2014-11-09 08:58:40 +00:00
else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == DO_SIGN_SYM) {
2013-04-12 08:33:31 +00:00
r = gnuk_delete_key(card, 1);
}
2014-11-09 08:58:40 +00:00
else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == DO_ENCR_SYM) {
2013-04-12 08:33:31 +00:00
r = gnuk_delete_key(card, 2);
}
2014-11-09 08:58:40 +00:00
else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == DO_AUTH_SYM) {
2013-04-12 08:33:31 +00:00
r = gnuk_delete_key(card, 3);
}
else {
/* call pgp_put_data() with zero-sized NULL-buffer to zap the DO contents */
r = pgp_put_data(card, file->id, NULL, 0);
}
/* set "current" blob to parent */
priv->current = blob->parent;
LOG_FUNC_RETURN(card->ctx, r);
2012-06-01 15:59:20 +00:00
}
/**
* ABI: ISO 7816-4 UPDATE BINARY - update data in current EF.
*/
static int
pgp_update_binary(sc_card_t *card, unsigned int idx,
const u8 *buf, size_t count, unsigned long flags)
{
struct pgp_priv_data *priv = DRVDATA(card);
pgp_blob_t *blob = priv->current;
int r = SC_SUCCESS;
LOG_FUNC_CALLED(card->ctx);
/* We will use PUT DATA to write to DO.
* As PUT DATA does not support idx, we don't either */
if (idx > 0)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
/* When a dummy file, e.g "11001101", is selected, the current blob
* is set to NULL. We don't really put data to dummy file. */
if (blob != NULL) {
r = pgp_put_data(card, blob->id, buf, count);
}
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* ABI: card reader lock obtained - re-select card applet if necessary.
*/
static int pgp_card_reader_lock_obtained(sc_card_t *card, int was_reset)
{
struct pgp_priv_data *priv = DRVDATA(card); /* may be null during initialization */
int r = SC_SUCCESS;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
if (card->flags & SC_CARD_FLAG_KEEP_ALIVE
&& was_reset <= 0
&& priv != NULL && priv->mf && priv->mf->file) {
/* check whether applet is still selected */
unsigned char aid[16];
r = sc_get_data(card, 0x004F, aid, sizeof aid);
if ((size_t) r != priv->mf->file->namelen
|| 0 != memcmp(aid, priv->mf->file->name, r)) {
/* reselect is required */
was_reset = 1;
}
r = SC_SUCCESS;
}
if (was_reset > 0) {
sc_file_t *file = NULL;
sc_path_t path;
/* select application "OpenPGP" */
sc_format_path("D276:0001:2401", &path);
path.type = SC_PATH_TYPE_DF_NAME;
r = iso_ops->select_file(card, &path, &file);
sc_file_free(file);
}
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* API: integrate OpenPGP driver into OpenSC's driver list.
*/
struct sc_card_driver *
sc_get_openpgp_driver(void)
{
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
iso_ops = iso_drv->ops;
pgp_ops = *iso_ops;
pgp_ops.match_card = pgp_match_card;
pgp_ops.init = pgp_init;
pgp_ops.finish = pgp_finish;
pgp_ops.select_file = pgp_select_file;
pgp_ops.list_files = pgp_list_files;
2018-01-18 11:33:34 +00:00
pgp_ops.get_challenge = pgp_get_challenge;
pgp_ops.read_binary = pgp_read_binary;
pgp_ops.write_binary = NULL;
pgp_ops.pin_cmd = pgp_pin_cmd;
pgp_ops.logout = pgp_logout;
pgp_ops.get_data = pgp_get_data;
pgp_ops.put_data = pgp_put_data;
pgp_ops.set_security_env= pgp_set_security_env;
pgp_ops.compute_signature= pgp_compute_signature;
pgp_ops.decipher = pgp_decipher;
pgp_ops.card_ctl = pgp_card_ctl;
2012-06-01 15:59:20 +00:00
pgp_ops.delete_file = pgp_delete_file;
pgp_ops.update_binary = pgp_update_binary;
pgp_ops.card_reader_lock_obtained = pgp_card_reader_lock_obtained;
return &pgp_drv;
}