From 0380142482c9a4dd77c2c3d1c5c5216b65b8d912 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 18 Mar 2020 20:21:06 -0500 Subject: [PATCH] Fix obtaining key_length i.e. field_length pkcs15-openpgp card-opennpgp.c and pkcs15-openpgp.c have a strang way of using sc_object_id_t to store what they call a binary_oid or oid_binary. It is used to convert the EC curve asn1 returned in the cxdata. This code uses asn1_decode_object_id to use sc_object_id_t as used in the rest of the code. The code and ec_curve tabes in card-openpgp.c where not changed. pkcs15-openpgp.c was channge si to can use: algorithm_info = sc_card_find_ec_alg(card, 0, &oid); to retried the key_length to add to the pubkey and prkey entries. The EC and EDDSA needs (i.e. field_length) to run. On branch eddsa Your branch is up to date with 'Jakuje/eddsa'. Changes to be committed: modified: card.c modified: pkcs15-openpgp.c --- src/libopensc/card.c | 8 +-- src/libopensc/pkcs15-openpgp.c | 106 +++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 1f20a230..cb7c8622 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1154,13 +1154,13 @@ sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, if (info->algorithm != algorithm) continue; - if (info->key_length != key_length) - continue; if (param) { if (info->algorithm == SC_ALGORITHM_EC || info->algorithm == SC_ALGORITHM_EDDSA) - if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) - continue; + if(sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) + return info; } + if (info->key_length != key_length) + continue; return info; } return NULL; diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 6206b709..dd0399e5 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -70,7 +70,7 @@ static const pgp_pin_cfg_t pin_cfg_v2[3] = { { "Admin PIN", 0x03, PGP_ADMIN_PIN_FLAGS, 8, 2 } }; -struct sc_object_id curve25519_binary_oid = {{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, -1}}; +static struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}; #define PGP_SIG_PRKEY_USAGE (SC_PKCS15_PRKEY_USAGE_SIGN \ | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER \ @@ -259,7 +259,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) if ((r = read_file(card, "006E:0073:00C5", c5data, sizeof(c5data))) < 0) goto failed; if (r < 60) { - sc_log(ctx, + sc_log(ctx, "finger print bytes have unexpected length (expected 60, got %d)\n", r); return SC_ERROR_OBJECT_NOT_VALID; } @@ -291,8 +291,9 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) /* only add valid keys, i.e. those with a legal algorithm identifier & finger print */ if (j >= 0 && cxdata[0] != 0) { struct sc_object_id oid; - int k; + struct sc_algorithm_info * algorithm_info; /* no need to free */ + algorithm_info = NULL; prkey_info.id.len = 1; prkey_info.id.value[0] = i + 1; prkey_info.usage = key_cfg[i].prkey_usage; @@ -304,11 +305,32 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = key_cfg[i].prkey_pin; + /* need to get size from algorithms using oid */ + r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid); + + switch (cxdata[0]) { + case SC_OPENPGP_KEYALGO_ECDSA: + case SC_OPENPGP_KEYALGO_ECDH: + if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid))) + prkey_info.field_length = algorithm_info->key_length; + else { + sc_log(ctx, "algorithim not found"); + goto failed; + } + break; + case SC_OPENPGP_KEYALGO_EDDSA: + if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid))) + prkey_info.field_length = algorithm_info->key_length; + else { + sc_log(ctx, "algorithim not found"); + goto failed; + } + break; + } + switch (cxdata[0]) { case SC_OPENPGP_KEYALGO_EDDSA: - /* TODO Store the OID from cxdata + 1 ?? */ /* assuming Ed25519 as it is the only supported now */ - prkey_info.field_length = 255; /* Filter out invalid usage: ED does not support anything but sign */ prkey_info.usage &= PGP_SIG_PRKEY_USAGE; r = sc_pkcs15emu_add_eddsa_prkey(p15card, &prkey_obj, &prkey_info); @@ -316,28 +338,22 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) case SC_OPENPGP_KEYALGO_ECDH: /* This can result in either ECDSA key or EC_MONTGOMERY * so we need to check OID */ - sc_init_oid(&oid); - /* Create copy of oid */ - for (k = 0; k < (cxdata_len-1) && k < SC_MAX_OBJECT_ID_OCTETS; k++) { - oid.value[k] = cxdata[k+1]; /* ignore first byte of blob (algo ID) */ - } - if (sc_compare_oid(&oid, &curve25519_binary_oid)) { + if (sc_compare_oid(&oid, &curve25519_oid)) { /* This can do only DERIVE */ prkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE; - prkey_info.field_length = 255; r = sc_pkcs15emu_add_xeddsa_prkey(p15card, &prkey_obj, &prkey_info); break; } - /* fall through */ - case SC_OPENPGP_KEYALGO_ECDSA: - /* TODO Store the OID from cxdata + 1 ?? */ - /* EC keys can do derive, but not really encrypt */ prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; prkey_info.usage &= ~PGP_ENC_PRKEY_USAGE; r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); break; + case SC_OPENPGP_KEYALGO_ECDSA: + prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN; + r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); + break; case SC_OPENPGP_KEYALGO_RSA: - if (r >= 3) { + if (cxdata_len >= 3) { prkey_info.modulus_length = bebytes2ushort(cxdata + 1); r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); break; @@ -380,8 +396,9 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) /* only add valid keys, i.e. those with a legal algorithm identifier & finger print */ if (j >= 0 && cxdata[0] != 0) { struct sc_object_id oid; - int k; + struct sc_algorithm_info * algorithm_info; /* no need to free */ + algorithm_info = NULL; pubkey_info.id.len = 1; pubkey_info.id.value[0] = i + 1; pubkey_info.usage = key_cfg[i].pubkey_usage; @@ -390,11 +407,31 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) strlcpy(pubkey_obj.label, key_cfg[i].label, sizeof(pubkey_obj.label)); pubkey_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; + r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid); + + switch (cxdata[0]) { + case SC_OPENPGP_KEYALGO_ECDSA: + case SC_OPENPGP_KEYALGO_ECDH: + if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid))) + pubkey_info.field_length = algorithm_info->key_length; + else { + sc_log(ctx, "algorithim not found"); + goto failed; + } + break; + case SC_OPENPGP_KEYALGO_EDDSA: + if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid))) + pubkey_info.field_length = algorithm_info->key_length; + else { + sc_log(ctx, "algorithim not found"); + goto failed; + } + break; + } + switch (cxdata[0]) { case SC_OPENPGP_KEYALGO_EDDSA: - /* TODO Store the OID from cxdata + 1 ?? */ /* assuming Ed25519 as it is the only supported now */ - pubkey_info.field_length = 255; /* Filter out invalid usage: ED does not support anything but sign */ pubkey_info.usage &= PGP_SIG_PUBKEY_USAGE; r = sc_pkcs15emu_add_eddsa_pubkey(p15card, &pubkey_obj, &pubkey_info); @@ -402,32 +439,23 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) case SC_OPENPGP_KEYALGO_ECDH: /* This can result in either ECDSA key or EC_MONTGOMERY * so we need to check OID */ - sc_init_oid(&oid); - /* Create copy of oid */ - for (k = 0; k < (cxdata_len-1) && k < SC_MAX_OBJECT_ID_OCTETS; k++) { - oid.value[k] = cxdata[k+1]; /* ignore first byte of blob (algo ID) */ - } - if (sc_compare_oid(&oid, &curve25519_binary_oid)) { + if (sc_compare_oid(&oid, &curve25519_oid)) { /* XXX What can this key do? */ - pubkey_info.usage = 0; - pubkey_info.field_length = 255; + pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE; r = sc_pkcs15emu_add_xeddsa_pubkey(p15card, &pubkey_obj, &pubkey_info); break; } - /* fall through */ + pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE; + r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); + break; case SC_OPENPGP_KEYALGO_ECDSA: - /* TODO Store the OID from cxdata + 1 ?? */ - /* EC keys can not do encrypt */ - pubkey_info.usage &= ~PGP_ENC_PUBKEY_USAGE; + pubkey_info.usage = PGP_SIG_PUBKEY_USAGE; r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); break; case SC_OPENPGP_KEYALGO_RSA: - if (r >= 3) { - pubkey_info.modulus_length = bebytes2ushort(cxdata + 1); - r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); - break; - } - /* Fallthrough */ + pubkey_info.modulus_length = bebytes2ushort(cxdata + 1); + r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); + break; default: sc_log(ctx, "Invalid algorithm identifier %x (length = %d)", cxdata[0], r); @@ -473,7 +501,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) failed: if (r < 0) { - sc_log(card->ctx, + sc_log(card->ctx, "Failed to initialize OpenPGP emulation: %s\n", sc_strerror(r)); }