Merge branch 'master' into attestation2

This commit is contained in:
Klas Lindfors
2016-03-10 15:34:25 +01:00
32 changed files with 2405 additions and 689 deletions
+3 -6
View File
@@ -46,12 +46,9 @@
#define MAX_READERS 16
struct ykpiv_state {
SCARDCONTEXT context;
SCARDHANDLE card;
unsigned long n_readers;
char readers[MAX_READERS][READER_LEN];
unsigned long tot_readers_len;
int verbose;
SCARDCONTEXT context;
SCARDHANDLE card;
int verbose;
};
union u_APDU {
+188 -5
View File
@@ -5,15 +5,15 @@
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -258,7 +258,7 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
rc = SCardBeginTransaction(state->card);
if(rc != SCARD_S_SUCCESS) {
if(state->verbose) {
fprintf(stderr, "error: Failed to being pcsc transaction, rc=%08lx\n", rc);
fprintf(stderr, "error: Failed to begin pcsc transaction, rc=%08lx\n", rc);
}
return YKPIV_PCSC_ERROR;
}
@@ -716,6 +716,68 @@ ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
}
}
#define CHREF_ACT_CHANGE_PIN 0
#define CHREF_ACT_UNBLOCK_PIN 1
#define CHREF_ACT_CHANGE_PUK 2
static ykpiv_rc _change_pin_internal(ykpiv_state *state, int action, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
int sw;
unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
unsigned char indata[0x10];
unsigned char data[0xff];
unsigned long recv_len = sizeof(data);
ykpiv_rc res;
if (current_pin_len > 8) {
return YKPIV_SIZE_ERROR;
}
if (new_pin_len > 8) {
return YKPIV_SIZE_ERROR;
}
if(action == CHREF_ACT_UNBLOCK_PIN) {
templ[1] = YKPIV_INS_RESET_RETRY;
}
else if(action == CHREF_ACT_CHANGE_PUK) {
templ[3] = 0x81;
}
memcpy(indata, current_pin, current_pin_len);
if(current_pin_len < 8) {
memset(indata + current_pin_len, 0xff, 8 - current_pin_len);
}
memcpy(indata + 8, new_pin, new_pin_len);
if(new_pin_len < 8) {
memset(indata + 8 + new_pin_len, 0xff, 8 - new_pin_len);
}
res = ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw);
if(res != YKPIV_OK) {
return res;
} else if(sw != 0x9000) {
if((sw >> 8) == 0x63) {
*tries = sw & 0xf;
return YKPIV_WRONG_PIN;
} else if(sw == 0x6983) {
return YKPIV_PIN_LOCKED;
} else {
if(state->verbose) {
fprintf(stderr, "Failed changing pin, token response code: %x.\n", sw);
}
return YKPIV_GENERIC_ERROR;
}
}
return YKPIV_OK;
}
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PIN, current_pin, current_pin_len, new_pin, new_pin_len, tries);
}
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len, const char * new_puk, size_t new_puk_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, current_puk, current_puk_len, new_puk, new_puk_len, tries);
}
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len, const char * new_pin, size_t new_pin_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, puk, puk_len, new_pin, new_pin_len, tries);
}
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len) {
int sw;
@@ -751,7 +813,7 @@ ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len) {
unsigned char data[2048];
unsigned char data[3072];
unsigned char *dataptr = data;
unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff};
int sw;
@@ -781,3 +843,124 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
return YKPIV_GENERIC_ERROR;
}
}
ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *dp, size_t dp_len,
const unsigned char *dq, size_t dq_len,
const unsigned char *qinv, size_t qinv_len,
const unsigned char *ec_data, unsigned char ec_data_len,
const unsigned char pin_policy, const unsigned char touch_policy) {
unsigned char key_data[1024];
unsigned char *in_ptr = key_data;
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
unsigned char data[256];
unsigned long recv_len = sizeof(data);
unsigned elem_len;
int sw;
const unsigned char *params[5];
size_t lens[5];
size_t padding;
unsigned char n_params;
int i;
int param_tag;
if (state == NULL)
return YKPIV_GENERIC_ERROR;
if (key == YKPIV_KEY_CARDMGM ||
key < YKPIV_KEY_RETIRED1 ||
(key > YKPIV_KEY_RETIRED20 && key < YKPIV_KEY_AUTHENTICATION) ||
key > YKPIV_KEY_CARDAUTH) {
return YKPIV_KEY_ERROR;
}
if (pin_policy != YKPIV_PINPOLICY_DEFAULT &&
pin_policy != YKPIV_PINPOLICY_NEVER &&
pin_policy != YKPIV_PINPOLICY_ONCE &&
pin_policy != YKPIV_PINPOLICY_ALWAYS)
return YKPIV_GENERIC_ERROR;
if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT &&
touch_policy != YKPIV_TOUCHPOLICY_NEVER &&
touch_policy != YKPIV_TOUCHPOLICY_ALWAYS)
return YKPIV_GENERIC_ERROR;
if (algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
if (algorithm == YKPIV_ALGO_RSA1024)
elem_len = 64;
if (algorithm == YKPIV_ALGO_RSA2048)
elem_len = 128;
if (p == NULL || q == NULL || dp == NULL ||
dq == NULL || qinv == NULL)
return YKPIV_GENERIC_ERROR;
params[0] = p;
lens[0] = p_len;
params[1] = q;
lens[1] = q_len;
params[2] = dp;
lens[2] = dp_len;
params[3] = dq;
lens[3] = dq_len;
params[4] = qinv;
lens[4] = qinv_len;
param_tag = 0x01;
n_params = 5;
}
else if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) {
if (algorithm == YKPIV_ALGO_ECCP256)
elem_len = 32;
if (algorithm == YKPIV_ALGO_ECCP384)
elem_len = 48;
if (ec_data == NULL)
return YKPIV_GENERIC_ERROR;
params[0] = ec_data;
lens[0] = ec_data_len;
param_tag = 0x06;
n_params = 1;
}
else
return YKPIV_ALGORITHM_ERROR;
for (i = 0; i < n_params; i++) {
*in_ptr++ = param_tag + i;
in_ptr += set_length(in_ptr, elem_len);
padding = elem_len - lens[i];
memset(in_ptr, 0, padding);
in_ptr += padding;
memcpy(in_ptr, params[i], lens[i]);
in_ptr += lens[i];
}
if (pin_policy != YKPIV_PINPOLICY_DEFAULT) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = pin_policy;
}
if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = touch_policy;
}
if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
return YKPIV_GENERIC_ERROR;
if (sw == 0x6982)
return YKPIV_AUTHENTICATION_ERROR;
if (sw != 0x9000)
return YKPIV_GENERIC_ERROR;
return YKPIV_OK;
}
+40
View File
@@ -57,6 +57,7 @@ extern "C"
YKPIV_WRONG_PIN = -10,
YKPIV_INVALID_OBJECT = -11,
YKPIV_ALGORITHM_ERROR = -12,
YKPIV_PIN_LOCKED = -13,
} ykpiv_rc;
const char *ykpiv_strerror(ykpiv_rc err);
@@ -85,12 +86,29 @@ extern "C"
unsigned char algorithm, unsigned char key);
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len);
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries);
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len,
const char * new_puk, size_t new_puk_len,
int *tries);
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len);
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
const unsigned char touch);
ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len);
ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *dp, size_t dp_len,
const unsigned char *dq, size_t dq_len,
const unsigned char *qinv, size_t qinv_len,
const unsigned char *ec_data, unsigned char ec_data_len,
const unsigned char pin_policy, const unsigned char touch_policy);
#define YKPIV_ALGO_3DES 0x03
#define YKPIV_ALGO_RSA1024 0x06
@@ -103,6 +121,26 @@ extern "C"
#define YKPIV_KEY_SIGNATURE 0x9c
#define YKPIV_KEY_KEYMGM 0x9d
#define YKPIV_KEY_CARDAUTH 0x9e
#define YKPIV_KEY_RETIRED1 0x82
#define YKPIV_KEY_RETIRED2 0x83
#define YKPIV_KEY_RETIRED3 0x84
#define YKPIV_KEY_RETIRED4 0x85
#define YKPIV_KEY_RETIRED5 0x86
#define YKPIV_KEY_RETIRED6 0x87
#define YKPIV_KEY_RETIRED7 0x88
#define YKPIV_KEY_RETIRED8 0x89
#define YKPIV_KEY_RETIRED9 0x8a
#define YKPIV_KEY_RETIRED10 0x8b
#define YKPIV_KEY_RETIRED11 0x8c
#define YKPIV_KEY_RETIRED12 0x8d
#define YKPIV_KEY_RETIRED13 0x8e
#define YKPIV_KEY_RETIRED14 0x8f
#define YKPIV_KEY_RETIRED15 0x90
#define YKPIV_KEY_RETIRED16 0x91
#define YKPIV_KEY_RETIRED17 0x92
#define YKPIV_KEY_RETIRED18 0x93
#define YKPIV_KEY_RETIRED19 0x94
#define YKPIV_KEY_RETIRED20 0x95
#define YKPIV_OBJ_CAPABILITY 0x5fc107
#define YKPIV_OBJ_CHUID 0x5fc102
@@ -158,11 +196,13 @@ extern "C"
#define YKPIV_INS_ATTEST 0xf9
#define YKPIV_PINPOLICY_TAG 0xaa
#define YKPIV_PINPOLICY_DEFAULT 0
#define YKPIV_PINPOLICY_NEVER 1
#define YKPIV_PINPOLICY_ONCE 2
#define YKPIV_PINPOLICY_ALWAYS 3
#define YKPIV_TOUCHPOLICY_TAG 0xab
#define YKPIV_TOUCHPOLICY_DEFAULT 0
#define YKPIV_TOUCHPOLICY_NEVER 1
#define YKPIV_TOUCHPOLICY_ALWAYS 2
+35 -21
View File
@@ -28,36 +28,50 @@
YKPIV_0.1.0
{
global:
ykpiv_check_version;
ykpiv_strerror_name;
ykpiv_strerror;
ykpiv_init;
ykpiv_done;
ykpiv_connect;
ykpiv_disconnect;
ykpiv_transfer_data;
ykpiv_authenticate;
ykpiv_set_mgmkey;
ykpiv_sign_data;
ykpiv_get_version;
ykpiv_verify;
ykpiv_fetch_object;
ykpiv_save_object;
ykpiv_hex_decode;
ykpiv_check_version;
ykpiv_strerror_name;
ykpiv_strerror;
ykpiv_init;
ykpiv_done;
ykpiv_connect;
ykpiv_disconnect;
ykpiv_transfer_data;
ykpiv_authenticate;
ykpiv_set_mgmkey;
ykpiv_sign_data;
ykpiv_get_version;
ykpiv_verify;
ykpiv_fetch_object;
ykpiv_save_object;
ykpiv_hex_decode;
local:
*;
*;
};
YKPIV_0.2.0
{
global:
ykpiv_decipher_data;
ykpiv_decipher_data;
} YKPIV_0.1.0;
YKPIV_1.1.0
{
global:
ykpiv_set_mgmkey2;
ykpiv_list_readers;
} YKPIV_0.1.0;
ykpiv_set_mgmkey2;
ykpiv_list_readers;
} YKPIV_0.2.0;
YKPIV_1.2.0
{
global:
ykpiv_import_private_key;
} YKPIV_1.1.0;
YKPIV_1.3.0
{
global:
ykpiv_change_pin;
ykpiv_change_puk;
ykpiv_unblock_pin;
} YKPIV_1.2.0;