diff --git a/.travis.yml b/.travis.yml
index 46c471b94b..54a754d026 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,13 +9,22 @@ env:
matrix:
include:
- compiler: clang
+ os: osx
- compiler: gcc
+ os: osx
+ - compiler: clang
+ os: linux
+ env: ENABLE_DOC=--enable-doc
+ - compiler: gcc
+ os: linux
+ env: ENABLE_DOC=--enable-doc
- compiler: gcc
+ os: linux
env: HOST=i686-w64-mingw32
before_install:
- if [ $TRAVIS_OS_NAME == linux ]; then
- sudo apt-get update;
+ sudo apt-get update || true;
fi
install:
@@ -30,11 +39,11 @@ install:
before_script:
- ./bootstrap
- if [ -z "$HOST" ]; then
- ./configure --enable-pedantic --disable-strict --enable-doc --enable-dnie-ui;
+ ./configure $ENABLE_DOC --enable-dnie-ui;
else
unset CC;
unset CXX;
- ./configure --enable-pedantic --disable-strict --host=$HOST --disable-openssl;
+ ./configure --host=$HOST --disable-openssl;
fi
addons:
@@ -48,9 +57,13 @@ addons:
script:
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then
- make;
+ if [ $TRAVIS_OS_NAME == osx ]; then
+ ./MacOSX/build;
+ else
+ make;
+ fi;
fi
- - if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 ]; then
+ - if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 -a "$TRAVIS_OS_NAME" != "osx" ]; then
make check;
make dist;
fi
diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in
index 4f671c4553..c0db7daf98 100755
--- a/MacOSX/build-package.in
+++ b/MacOSX/build-package.in
@@ -70,7 +70,7 @@ fi
test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src
# Build and copy OpenSC.tokend
-xcodebuild -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj
+xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj
# Prepare target root
# Copy Tokend
diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml
index 9c5887266a..82ad7b91b7 100644
--- a/doc/tools/pkcs15-tool.1.xml
+++ b/doc/tools/pkcs15-tool.1.xml
@@ -185,7 +185,21 @@
Reads the public key with id id,
writing the output in format suitable for
- $HOME/.ssh/authorized_keys.
+ $HOME/.ssh/authorized_keys.
+
+ The key label, if any will be shown in the 'Comment' field.
+
+
+
+
+
+
+ When used in conjunction with option the
+ output format of the public key follows rfc4716.
+
+
+ The default output format is a single line (openssh).
+
diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c
index c9d2518cda..abe8245168 100644
--- a/src/libopensc/card-iasecc.c
+++ b/src/libopensc/card-iasecc.c
@@ -1801,12 +1801,14 @@ iasecc_chv_verify_pinpad(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd,
LOG_FUNC_RETURN(ctx, SC_ERROR_READER);
}
- if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) {
- sc_log(ctx, "Different values for PIN min and max lengths is not actually compatible with PinPAD.");
- LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,
- "Different values for PIN min and max lengths is not actually compatible with PinPAD.");
+ sc_log(ctx, "reader %s", card->reader->name);
+ if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) {
+ sc_log(ctx, "reader %s", card->reader->name);
+ if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) {
+ sc_log(ctx, "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths.");
+ LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
+ }
}
-
pin_cmd->pin1.len = pin_cmd->pin1.min_length;
memset(buffer, 0xFF, sizeof(buffer));
@@ -2037,8 +2039,10 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le
rv = iasecc_pin_get_policy(card, &pin_cmd);
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");
- if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
- LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD.");
+ if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name)
+ if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
+ LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,
+ "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths.");
if (pin_cmd.pin1.min_length < 4)
pin_cmd.pin1.min_length = 4;
@@ -2083,8 +2087,10 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference)
rv = iasecc_pin_get_policy(card, &pin_cmd);
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");
- if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
- LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD.");
+ if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name)
+ if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length)
+ LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,
+ "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths.");
if (pin_cmd.pin1.min_length < 4)
pin_cmd.pin1.min_length = 4;
@@ -3385,7 +3391,7 @@ iasecc_read_public_key(struct sc_card *card, unsigned type,
iasecc_sdo_free_fields(card, &sdo);
- SC_FUNC_RETURN(ctx, SC_SUCCESS, rv);
+ LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c
index e8c28ec95a..6a9fd7520d 100644
--- a/src/libopensc/card-myeid.c
+++ b/src/libopensc/card-myeid.c
@@ -344,17 +344,20 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
}
static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
- u8 *out, size_t *outlen)
+ u8 *buf, size_t *outlen)
{
const sc_acl_entry_t *read, *update, *delete, *generate;
- u8 buf[42];
size_t i;
LOG_FUNC_CALLED(card->ctx);
+
+ if (!buf || !outlen || *outlen < 45)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
+
/* PrivateKey
* 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984
* 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */
- memset(buf, 0x0, sizeof(buf));
+ memset(buf, 0x0, *outlen);
buf[0] = 0x62;
buf[1] = 0x17;
@@ -453,9 +456,9 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
buf[26] = (u8)file->namelen;
for(i=0;i < file->namelen;i++)
- buf[i + 26] = file->name[i];
+ buf[i + 27] = file->name[i];
- buf[1] = 0x19 + file->namelen + 2;
+ buf[1] = 27 + file->namelen;
}
break;
default:
@@ -464,16 +467,15 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
}
*outlen = buf[1]+2;
- memcpy(out, buf, *outlen);
- LOG_FUNC_RETURN(card->ctx, 0);
+ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
static int myeid_create_file(struct sc_card *card, struct sc_file *file)
{
sc_apdu_t apdu;
- u8 sbuf[32];
- size_t buflen;
+ u8 sbuf[45];
+ size_t buflen = sizeof sbuf;
int r;
LOG_FUNC_CALLED(card->ctx);
@@ -808,7 +810,7 @@ static int
myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char *data, size_t datalen)
{
unsigned char *buf;
- size_t i, buflen;
+ size_t buflen;
int r;
assert(data && datalen);
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 5ae66f6740..6c63a5e81f 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -305,7 +305,7 @@ pgp_init(sc_card_t *card)
sc_file_t *file = NULL;
struct do_info *info;
int r;
- struct blob *child = NULL;
+ struct blob *child = NULL;
priv = calloc (1, sizeof *priv);
if (!priv)
@@ -330,8 +330,14 @@ pgp_init(sc_card_t *card)
return r;
}
+ /* defensive programming check */
+ if (!file) {
+ pgp_finish(card);
+ return SC_ERROR_OBJECT_NOT_FOUND;
+ }
+
/* read information from AID */
- if (file && file->namelen == 16) {
+ if (file->namelen == 16) {
/* OpenPGP card spec 1.1 & 2.0, section 4.2.1 & 4.1.2.1 */
priv->bcd_version = bebytes2ushort(file->name + 6);
/* kludge: get card's serial number from manufacturer ID + serial number */
@@ -2166,7 +2172,9 @@ static int pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *ke
/* ABI: card ctl: perform special card-specific operations */
static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
{
+#ifdef ENABLE_OPENSSL
int r;
+#endif /* ENABLE_OPENSSL */
LOG_FUNC_CALLED(card->ctx);
diff --git a/src/libopensc/ctbcs.c b/src/libopensc/ctbcs.c
index 16c4336978..ad51cac8c8 100644
--- a/src/libopensc/ctbcs.c
+++ b/src/libopensc/ctbcs.c
@@ -58,7 +58,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d
prompt = data->pin1.prompt;
if (prompt && *prompt) {
len = strlen(prompt);
- if (count + len + 2 > buflen || len > 254)
+ if (len + 2 > buflen)
return SC_ERROR_BUFFER_TOO_SMALL;
buf[count++] = CTBCS_TAG_PROMPT;
buf[count++] = len;
@@ -126,7 +126,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da
prompt = data->pin1.prompt;
if (prompt && *prompt) {
len = strlen(prompt);
- if (count + len + 2 > buflen || len > 254)
+ if (len + 2 > buflen)
return SC_ERROR_BUFFER_TOO_SMALL;
buf[count++] = CTBCS_TAG_PROMPT;
buf[count++] = len;
diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c
index c37bbf0449..37abd1772e 100644
--- a/src/libopensc/iso7816.c
+++ b/src/libopensc/iso7816.c
@@ -430,6 +430,10 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
if (tag != NULL && taglen)
sc_file_set_sec_attr(file, tag, taglen);
+ tag = sc_asn1_find_tag(ctx, p, len, 0x88, &taglen);
+ if (tag != NULL && taglen == 1)
+ file->sid = *tag;
+
tag = sc_asn1_find_tag(ctx, p, len, 0x8A, &taglen);
if (tag != NULL && taglen==1) {
if (tag[0] == 0x01)
@@ -1012,8 +1016,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
* but expect the new one to be entered on the keypad.
*/
if (data->pin1.len && data->pin2.len == 0) {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Special case - initial pin provided - but new pin asked on keypad");
+ sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad");
data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
};
len += r;
diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports
index 23f6c05ac4..7c64d9aa3b 100644
--- a/src/libopensc/libopensc.exports
+++ b/src/libopensc/libopensc.exports
@@ -317,6 +317,7 @@ sc_pkcs15_convert_pubkey
sc_sm_parse_answer
sc_sm_update_apdu_response
sc_sm_single_transmit
+sc_sm_stop
iasecc_sm_create_file
iasecc_sm_delete_file
iasecc_sm_external_authentication
diff --git a/src/libopensc/log.c b/src/libopensc/log.c
index 32f396d8e6..9d98413b49 100644
--- a/src/libopensc/log.c
+++ b/src/libopensc/log.c
@@ -73,9 +73,7 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin
FILE *outf = NULL;
int n;
- assert(ctx != NULL);
-
- if (ctx->debug < level)
+ if (!ctx || ctx->debug < level)
return;
p = buf;
@@ -167,9 +165,7 @@ void sc_hex_dump(struct sc_context *ctx, int level, const u8 * in, size_t count,
char *p = buf;
int lines = 0;
- assert(ctx != NULL);
-
- if (ctx->debug < level)
+ if (!ctx || ctx->debug < level)
return;
assert(buf != NULL && (in != NULL || count == 0));
diff --git a/src/libopensc/muscle-filesystem.c b/src/libopensc/muscle-filesystem.c
index f54d263fef..dc618a6733 100644
--- a/src/libopensc/muscle-filesystem.c
+++ b/src/libopensc/muscle-filesystem.c
@@ -42,6 +42,8 @@ static const u8* ignoredFiles[] = {
mscfs_t *mscfs_new(void) {
mscfs_t *fs = malloc(sizeof(mscfs_t));
+ if (!fs)
+ return NULL;
memset(fs, 0, sizeof(mscfs_t));
memcpy(fs->currentPath, "\x3F\x00", 2);
return fs;
diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c
index aa928421f1..c1191eefda 100644
--- a/src/libopensc/pkcs15-gemsafeV1.c
+++ b/src/libopensc/pkcs15-gemsafeV1.c
@@ -183,11 +183,9 @@ static int gemsafe_get_cert_len(sc_card_t *card)
* (allocated EF space is much greater!)
*/
objlen = (((size_t) ibuf[0]) << 8) | ibuf[1];
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Stored object is of size: %d\n", objlen);
+ sc_log(card->ctx, "Stored object is of size: %d", objlen);
if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Invalid object size: %d\n", objlen);
+ sc_log(card->ctx, "Invalid object size: %d", objlen);
return SC_ERROR_INTERNAL;
}
@@ -209,15 +207,14 @@ static int gemsafe_get_cert_len(sc_card_t *card)
while (ibuf[ind] == 0x01) {
if (ibuf[ind+1] == 0xFE) {
gemsafe_prkeys[i].ref = ibuf[ind+4];
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Key container %d is allocated and uses key_ref %d\n", i+1,
- gemsafe_prkeys[i].ref);
+ sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
+ i+1, gemsafe_prkeys[i].ref);
ind += 9;
- } else {
+ }
+ else {
gemsafe_prkeys[i].label = NULL;
gemsafe_cert[i].label = NULL;
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Key container %d is unallocated\n", i+1);
+ sc_log(card->ctx, "Key container %d is unallocated", i+1);
ind += 8;
}
i++;
@@ -239,8 +236,7 @@ static int gemsafe_get_cert_len(sc_card_t *card)
r = sc_read_binary(card, iptr - ibuf, iptr,
MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
if (r < 0) {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Could not read cert object\n");
+ sc_log(card->ctx, "Could not read cert object");
return SC_ERROR_INTERNAL;
}
iptr += GEMSAFE_READ_QUANTUM;
@@ -254,15 +250,12 @@ static int gemsafe_get_cert_len(sc_card_t *card)
while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL)
i++;
if (i == gemsafe_cert_max) {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Warning: Found orphaned certificate at offset %d\n", ind);
+ sc_log(card->ctx, "Warning: Found orphaned certificate at offset %d", ind);
return SC_SUCCESS;
}
/* DER cert len is encoded this way */
certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4;
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Found certificate of key container %d at offset %d, len %d\n",
- i+1, ind, certlen);
+ sc_log(card->ctx, "Found certificate of key container %d at offset %d, len %d", i+1, ind, certlen);
gemsafe_cert[i].index = ind;
gemsafe_cert[i].count = certlen;
ind += certlen;
@@ -276,8 +269,7 @@ static int gemsafe_get_cert_len(sc_card_t *card)
*/
for (; i < gemsafe_cert_max; i++) {
if (gemsafe_cert[i].label) {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Warning: Certificate of key container %d is missing\n", i+1);
+ sc_log(card->ctx, "Warning: Certificate of key container %d is missing", i+1);
gemsafe_prkeys[i].label = NULL;
gemsafe_cert[i].label = NULL;
}
@@ -304,7 +296,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n");
+ sc_log(p15card->card->ctx, "Setting pkcs15 parameters");
if (p15card->tokeninfo->label)
free(p15card->tokeninfo->label);
@@ -330,7 +322,8 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
apdu.lc = 0;
apdu.datalen = 0;
r = sc_transmit_apdu(card, &apdu);
- SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
+ LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
+
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
return SC_ERROR_INTERNAL;
if (r != SC_SUCCESS)
@@ -350,7 +343,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
return SC_ERROR_INTERNAL;
/* set certs */
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n");
+ sc_log(p15card->card->ctx, "Setting certificates");
for (i = 0; i < gemsafe_cert_max; i++) {
struct sc_pkcs15_id p15Id;
struct sc_path path;
@@ -367,7 +360,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
}
/* set gemsafe_pin */
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n");
+ sc_log(p15card->card->ctx, "Setting PIN");
for (i=0; i < gemsafe_pin_max; i++) {
struct sc_pkcs15_id p15Id;
struct sc_path path;
@@ -388,11 +381,11 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
};
/* set private keys */
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n");
+ sc_log(p15card->card->ctx, "Setting private keys");
for (i = 0; i < gemsafe_cert_max; i++) {
struct sc_pkcs15_id p15Id, authId, *pauthId;
struct sc_path path;
- int key_ref = 0x03;
+ int key_ref = 0x03;
if (gemsafe_prkeys[i].label == NULL)
continue;
@@ -403,7 +396,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
} else
pauthId = NULL;
sc_format_path(gemsafe_prkeys[i].path, &path);
- /*
+ /*
* The key ref may be different for different sites;
* by adding flags=n where the low order 4 bits can be
* the key ref we can force it.
@@ -423,7 +416,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
}
/* select the application DF */
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n");
+ sc_log(p15card->card->ctx, "Selecting application DF");
sc_format_path(GEMSAFE_APP_PATH, &path);
r = sc_select_file(card, &path, &file);
if (r != SC_SUCCESS || !file)
@@ -511,8 +504,7 @@ sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
df_type = SC_PKCS15_CDF;
break;
default:
- sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
- "Unknown PKCS15 object type %d\n", type);
+ sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type);
free(obj);
return SC_ERROR_INVALID_ARGUMENTS;
}
@@ -534,6 +526,9 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
sc_pkcs15_auth_info_t *info;
info = calloc(1, sizeof(*info));
+ if (!info)
+ LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
+
info->auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
info->auth_method = SC_AC_CHV;
info->auth_id = *id;
@@ -549,9 +544,7 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
if (path)
info->path = *path;
- return sc_pkcs15emu_add_object(p15card,
- SC_PKCS15_TYPE_AUTH_PIN,
- label, info, NULL, obj_flags);
+ return sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info, NULL, obj_flags);
}
static int
@@ -563,6 +556,10 @@ sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card,
{
sc_pkcs15_cert_info_t *info;
info = calloc(1, sizeof(*info));
+ if (!info)
+ {
+ LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
+ }
info->id = *id;
info->authority = authority;
if (path)
@@ -582,6 +579,10 @@ sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
sc_pkcs15_prkey_info_t *info;
info = calloc(1, sizeof(*info));
+ if (!info)
+ {
+ LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
+ }
info->id = *id;
info->modulus_length = modulus_length;
info->usage = usage;
diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c
index 189e413ee2..9cf75e350f 100644
--- a/src/libopensc/pkcs15-pubkey.c
+++ b/src/libopensc/pkcs15-pubkey.c
@@ -1019,6 +1019,8 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv
break;
case SC_ALGORITHM_EC:
pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len);
+ if (!pubkey->u.ec.ecpointQ.value)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len);
pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len;
break;
@@ -1583,6 +1585,8 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
/* copy the public key */
if (buflen > 0) {
dst->ecpointQ.value = malloc(buflen);
+ if (!dst->ecpointQ.value)
+ return SC_ERROR_OUT_OF_MEMORY;
memcpy(dst->ecpointQ.value, buf, buflen);
dst->ecpointQ.len = buflen;
/* calculate the field length */
diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c
index 5f4bd899e6..4705ba626e 100644
--- a/src/libopensc/sm.c
+++ b/src/libopensc/sm.c
@@ -140,6 +140,9 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
* Send plain APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, apdu);
LOG_FUNC_RETURN(ctx, rv);
+ } else {
+ if (rv < 0)
+ sc_sm_stop(card);
}
LOG_TEST_RET(ctx, rv, "get SM APDU error");
@@ -147,34 +150,66 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
rv = sc_check_apdu(card, sm_apdu);
if (rv < 0) {
card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
+ sc_sm_stop(card);
LOG_TEST_RET(ctx, rv, "cannot validate SM encoded APDU");
}
/* send APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, sm_apdu);
- LOG_TEST_RET(ctx, rv, "unable to transmit APDU");
+ if (rv < 0) {
+ card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
+ sc_sm_stop(card);
+ LOG_TEST_RET(ctx, rv, "unable to transmit APDU");
+ }
/* decode SM answer and free temporary SM related data */
rv = card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
+ if (rv < 0)
+ sc_sm_stop(card);
LOG_FUNC_RETURN(ctx, rv);
}
+
+int
+sc_sm_stop(struct sc_card *card)
+{
+ int r = SC_SUCCESS;
+
+ if (card) {
+ if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
+ && card->sm_ctx.ops.close)
+ r = card->sm_ctx.ops.close(card);
+ card->sm_ctx.sm_mode = SM_MODE_NONE;
+ }
+
+ return r;
+}
+
#else
+
int
sc_sm_parse_answer(struct sc_card *card, unsigned char *resp_data, size_t resp_len,
struct sm_card_response *out)
{
return SC_ERROR_NOT_SUPPORTED;
}
+
int
sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_t resp_len,
int ref_rv, struct sc_apdu *apdu)
{
return SC_ERROR_NOT_SUPPORTED;
}
+
int
sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
return SC_ERROR_NOT_SUPPORTED;
}
+
+int
+sc_sm_stop(struct sc_card *card)
+{
+ return SC_ERROR_NOT_SUPPORTED;
+}
#endif
diff --git a/src/libopensc/sm.h b/src/libopensc/sm.h
index 8ff19887ef..e27725f45b 100644
--- a/src/libopensc/sm.h
+++ b/src/libopensc/sm.h
@@ -353,6 +353,18 @@ int sc_sm_parse_answer(struct sc_card *, unsigned char *, size_t, struct sm_card
int sc_sm_update_apdu_response(struct sc_card *, unsigned char *, size_t, int, struct sc_apdu *);
int sc_sm_single_transmit(struct sc_card *, struct sc_apdu *);
+/**
+ * @brief Stops SM and frees allocated ressources.
+ *
+ * Calls \a card->sm_ctx.ops.close() if available and \c card->sm_ctx.sm_mode
+ * is \c SM_MODE_TRANSMIT
+ *
+ * @param[in] card
+ *
+ * @return \c SC_SUCCESS or error code if an error occurred
+ */
+int sc_sm_stop(struct sc_card *card);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/libopensc/types.h b/src/libopensc/types.h
index 0bf0c29bfb..38f4c4bf00 100644
--- a/src/libopensc/types.h
+++ b/src/libopensc/types.h
@@ -225,7 +225,8 @@ typedef struct sc_file {
unsigned int type, ef_structure, status; /* See constant values defined above */
unsigned int shareable; /* true(1), false(0) according to ISO 7816-4:2005 Table 14 */
size_t size; /* Size of file (in bytes) */
- int id; /* Short file id (2 bytes) */
+ int id; /* file identifier (2 bytes) */
+ int sid; /* short EF identifier (1 byte) */
struct sc_acl_entry *acl[SC_MAX_AC_OPS]; /* Access Control List */
int record_length; /* In case of fixed-length or cyclic EF */
diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c
index 63506382f4..fec1123a14 100644
--- a/src/pkcs11/mechanism.c
+++ b/src/pkcs11/mechanism.c
@@ -990,6 +990,9 @@ sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *p11card,
mech_info.flags &= (CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER);
info = calloc(1, sizeof(*info));
+ if (!info)
+ LOG_FUNC_RETURN(p11card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
+
info->mech = mech;
info->sign_type = sign_type;
info->hash_type = hash_type;
diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c
index 99e7046812..5f9e8955c5 100644
--- a/src/pkcs15init/pkcs15-iasecc.c
+++ b/src/pkcs15init/pkcs15-iasecc.c
@@ -950,9 +950,7 @@ iasecc_pkcs15_fix_private_key_attributes(struct sc_profile *profile, struct sc_p
IASECC_ALGORITHM_RSA_PKCS | IASECC_ALGORITHM_SHA2);
LOG_TEST_RET(ctx, rv, "Cannot add RSA_PKCS SHA2 supported mechanism");
- key_info->usage |= SC_PKCS15_PRKEY_USAGE_SIGN;
if (sdo_prvkey->docp.non_repudiation.value && sdo_prvkey->docp.non_repudiation.value[0]) {
- key_info->usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
object->user_consent = 1;
}
}
@@ -960,14 +958,12 @@ iasecc_pkcs15_fix_private_key_attributes(struct sc_profile *profile, struct sc_p
rv = iasecc_pkcs15_add_algorithm_reference(p15card, key_info, IASECC_ALGORITHM_RSA_PKCS);
LOG_TEST_RET(ctx, rv, "Cannot add RSA_PKCS supported mechanism");
- key_info->usage |= SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
}
else if (ii == IASECC_ACLS_RSAKEY_PSO_DECIPHER) {
rv = iasecc_pkcs15_add_algorithm_reference(p15card, key_info,
IASECC_ALGORITHM_RSA_PKCS_DECRYPT | IASECC_ALGORITHM_SHA1);
LOG_TEST_RET(ctx, rv, "Cannot add decipher RSA_PKCS supported mechanism");
- key_info->usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP;
}
}
diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c
index cefc3e16c2..fa2581bb78 100644
--- a/src/tools/opensc-explorer.c
+++ b/src/tools/opensc-explorer.c
@@ -786,8 +786,10 @@ static int do_info(int argc, char **argv)
st = "Unknown File";
break;
}
- printf("\n%s ID %04X\n\n", st, file->id);
- printf("%-15s%s\n", "File path:", path_to_filename(&path, '/'));
+ printf("\n%s ID %04X", st, file->id);
+ if (file->sid)
+ printf(", SFI %02X", file->sid);
+ printf("\n\n%-15s%s\n", "File path:", path_to_filename(&path, '/'));
printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size);
if (file->type == SC_FILE_TYPE_DF) {
diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c
index f5eb7f63c1..b79beeec58 100644
--- a/src/tools/pkcs11-tool.c
+++ b/src/tools/pkcs11-tool.c
@@ -166,6 +166,7 @@ static const struct option options[] = {
{ "attr-from", 1, NULL, OPT_ATTR_FROM },
{ "input-file", 1, NULL, 'i' },
{ "output-file", 1, NULL, 'o' },
+ { "signature-format", 1, NULL, 'f' },
{ "test", 0, NULL, 't' },
{ "test-hotplug", 0, NULL, OPT_TEST_HOTPLUG },
@@ -223,6 +224,7 @@ static const char *option_help[] = {
"Use to create some attributes when writing an object",
"Specify the input file",
"Specify the output file",
+ "Format for ECDSA signature : 'rs' (default), 'sequence', 'openssl'",
"Test (best used with the --login or --pin option)",
"Test hotplug capabilities (C_GetSlotList + C_WaitForSlotEvent)",
@@ -262,6 +264,7 @@ static char * opt_application_id = NULL;
static char * opt_issuer = NULL;
static char * opt_subject = NULL;
static char * opt_key_type = NULL;
+static char * opt_sig_format = NULL;
static int opt_is_private = 0;
static int opt_test_hotplug = 0;
static int opt_login_type = -1;
@@ -420,7 +423,7 @@ int main(int argc, char * argv[])
CRYPTO_malloc_init();
#endif
while (1) {
- c = getopt_long(argc, argv, "ILMOTa:bd:e:hi:klm:o:p:scvty:w:z:r",
+ c = getopt_long(argc, argv, "ILMOTa:bd:e:hi:klm:o:p:scvf:ty:w:z:r",
options, &long_optind);
if (c == -1)
break;
@@ -543,6 +546,9 @@ int main(int argc, char * argv[])
do_sign = 1;
action_count++;
break;
+ case 'f':
+ opt_sig_format = optarg;
+ break;
case 't':
need_session |= NEED_SESSION_RO;
do_test = 1;
@@ -1424,33 +1430,23 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
util_fatal("failed to open %s: %m", opt_output);
}
-#if defined(ENABLE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_ECDSA)
-/*
- * PKCS11 implies the ECDSA sig is 2nLen,
- * OpenSSL expects sequence of {integer, integer}
- * so we will write it for OpenSSL if built with OpenSSL
- */
- if (opt_mechanism == CKM_ECDSA) {
- int nLen;
- ECDSA_SIG * ecsig = NULL;
- unsigned char *p = NULL;
- int der_len;
-
- nLen = sig_len/2;
+ if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1) {
+ if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) {
+ unsigned char *seq;
+ size_t seqlen;
- ecsig = ECDSA_SIG_new();
- ecsig->r = BN_bin2bn(sig_buffer, nLen, ecsig->r);
- ecsig->s = BN_bin2bn(sig_buffer + nLen, nLen, ecsig->s);
+ if (sc_asn1_sig_value_rs_to_sequence(NULL, sig_buffer, sig_len, &seq, &seqlen)) {
+ util_fatal("Failed to convert signature to ASN.1 sequence format.");
+ }
- der_len = i2d_ECDSA_SIG(ecsig, &p);
- printf("Writing OpenSSL ECDSA_SIG\n");
- r = write(fd, p, der_len);
- free(p);
- ECDSA_SIG_free(ecsig);
+ memcpy(sig_buffer, seq, seqlen);
+ sig_len = seqlen;
- } else
-#endif /* ENABLE_OPENSSL && !OPENSSL_NO_EC && !OPENSSL_NO_ECDSA */
+ free(seq);
+ }
+ }
r = write(fd, sig_buffer, sig_len);
+
if (r < 0)
util_fatal("Failed to write to %s: %m", opt_output);
if (fd != 1)
diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c
index 409d9847db..abc64f4354 100644
--- a/src/tools/pkcs15-tool.c
+++ b/src/tools/pkcs15-tool.c
@@ -57,6 +57,9 @@ static const char * opt_pin = NULL;
static const char * opt_puk = NULL;
static int verbose = 0;
static int opt_no_prompt = 0;
+#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
+static int opt_rfc4716 = 0;
+#endif
enum {
OPT_CHANGE_PIN = 0x100,
@@ -68,6 +71,7 @@ enum {
OPT_READ_PUB,
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
OPT_READ_SSH,
+ OPT_RFC4716,
#endif
OPT_PIN,
OPT_NEWPIN,
@@ -76,7 +80,7 @@ enum {
OPT_BIND_TO_AID,
OPT_LIST_APPLICATIONS,
OPT_LIST_SKEYS,
- OPT_NO_PROMPT
+ OPT_NO_PROMPT,
};
#define NELEMENTS(x) (sizeof(x)/sizeof((x)[0]))
@@ -100,6 +104,7 @@ static const struct option options[] = {
{ "read-public-key", required_argument, NULL, OPT_READ_PUB },
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
{ "read-ssh-key", required_argument, NULL, OPT_READ_SSH },
+ { "rfc4716", no_argument, NULL, OPT_RFC4716 },
#endif
{ "test-update", no_argument, NULL, 'T' },
{ "update", no_argument, NULL, 'U' },
@@ -786,6 +791,36 @@ static int list_skeys(void)
#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
+
+static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object *obj, unsigned char * buf, uint32_t len) {
+ unsigned char *uu;
+ int r;
+
+ uu = malloc(len*2); // Way over - even if we have extra LFs; as each 6 bits take one byte.
+
+ if (opt_rfc4716) {
+ r = sc_base64_encode(buf, len, uu, 2*len, 64);
+
+ fprintf(outf,"---- BEGIN SSH2 PUBLIC KEY ----\n");
+
+ if (obj->label && strlen(obj->label))
+ fprintf(outf,"Comment: \"%s\"\n", obj->label);
+
+ fprintf(outf,"%s", uu);
+ fprintf(outf,"---- END SSH2 PUBLIC KEY ----\n");
+ } else {
+ // Old style openssh - [ [ anything else]
+ //
+ r = sc_base64_encode(buf, len, uu, 2*len, 0);
+ if (obj->label && strlen(obj->label))
+ fprintf(outf,"ssh-%s %s %s\n", alg, uu, obj->label);
+ else
+ fprintf(outf,"ssh-%s %s\n", alg, uu);
+ }
+ free(uu);
+ return;
+}
+
static int read_ssh_key(void)
{
int r;
@@ -844,7 +879,6 @@ static int read_ssh_key(void)
if (pubkey->algorithm == SC_ALGORITHM_RSA) {
unsigned char buf[2048];
- unsigned char *uu;
uint32_t len, n;
if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.modulus.len ||
@@ -895,16 +929,11 @@ static int read_ssh_key(void)
memcpy(buf+len,pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len);
len += pubkey->u.rsa.modulus.len;
- uu = malloc(len*2);
- r = sc_base64_encode(buf, len, uu, 2*len, 2*len);
-
- fprintf(outf,"ssh-rsa %s", uu);
- free(uu);
+ print_ssh_key(outf, "rsa", obj, buf, len);
}
if (pubkey->algorithm == SC_ALGORITHM_DSA) {
unsigned char buf[2048];
- unsigned char *uu;
uint32_t len;
uint32_t n;
@@ -991,11 +1020,7 @@ static int read_ssh_key(void)
memcpy(buf+len,pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len);
len += pubkey->u.dsa.pub.len;
- uu = malloc(len*2);
- r = sc_base64_encode(buf, len, uu, 2*len, 2*len);
-
- fprintf(outf,"ssh-dss %s", uu);
- free(uu);
+ print_ssh_key(outf, "dss", obj, buf, len);
}
if (outf != stdout)
@@ -1016,6 +1041,7 @@ static int read_ssh_key(void)
sc_pkcs15_free_pubkey(pubkey);
return SC_ERROR_OUT_OF_MEMORY;
}
+
#endif
static sc_pkcs15_object_t *
@@ -1900,6 +1926,9 @@ int main(int argc, char * const argv[])
do_read_sshkey = 1;
action_count++;
break;
+ case OPT_RFC4716:
+ opt_rfc4716 = 1;
+ break;
#endif
case 'L':
do_learn_card = 1;