Merge branch 'master' into attestation2
This commit is contained in:
+3
-6
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user