Refactor yubico-piv-tool to use import_private_key from libykpiv.
This commit is contained in:
+6
-5
@@ -291,15 +291,16 @@ int key_to_object_id(int key) {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_component_with_len(unsigned char **in_ptr, const BIGNUM *bn, int element_len) {
|
bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len) {
|
||||||
int real_len = BN_num_bytes(bn);
|
int real_len = BN_num_bytes(bn);
|
||||||
*in_ptr += set_length(*in_ptr, element_len);
|
|
||||||
if(real_len > element_len) {
|
if(real_len > element_len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memset(*in_ptr, 0, (size_t)(element_len - real_len));
|
memset(in_ptr, 0, (size_t)(element_len - real_len));
|
||||||
*in_ptr += element_len - real_len;
|
in_ptr += element_len - real_len;
|
||||||
*in_ptr += BN_bn2bin(bn, *in_ptr);
|
BN_bn2bin(bn, in_ptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ unsigned char get_algorithm(EVP_PKEY*);
|
|||||||
FILE *open_file(const char*, int);
|
FILE *open_file(const char*, int);
|
||||||
int get_object_id(enum enum_slot slot);
|
int get_object_id(enum enum_slot slot);
|
||||||
int key_to_object_id(int key);
|
int key_to_object_id(int key);
|
||||||
bool set_component_with_len(unsigned char**, const BIGNUM*, int);
|
bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len);
|
||||||
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
|
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
|
||||||
unsigned int*, int);
|
unsigned int*, int);
|
||||||
bool read_pw(const char*, char*, size_t, int);
|
bool read_pw(const char*, char*, size_t, int);
|
||||||
|
|||||||
+93
-88
@@ -316,14 +316,15 @@ static bool set_pin_retries(ykpiv_state *state, int pin_retries, int puk_retries
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
||||||
const char *input_file_name, const char *slot, char *password,
|
const char *input_file_name, const char *slot, char *password,
|
||||||
enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) {
|
enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) {
|
||||||
int key = 0;
|
int key = 0;
|
||||||
FILE *input_file = NULL;
|
FILE *input_file = NULL;
|
||||||
EVP_PKEY *private_key = NULL;
|
EVP_PKEY *private_key = NULL;
|
||||||
PKCS12 *p12 = NULL;
|
PKCS12 *p12 = NULL;
|
||||||
X509 *cert = NULL;
|
X509 *cert = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
ykpiv_rc rc = YKPIV_GENERIC_ERROR;
|
||||||
|
|
||||||
sscanf(slot, "%2x", &key);
|
sscanf(slot, "%2x", &key);
|
||||||
|
|
||||||
@@ -360,119 +361,123 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
|||||||
|
|
||||||
{
|
{
|
||||||
unsigned char algorithm = get_algorithm(private_key);
|
unsigned char algorithm = get_algorithm(private_key);
|
||||||
|
unsigned char pp = YKPIV_PINPOLICY_DEFAULT;
|
||||||
|
unsigned char tp = YKPIV_TOUCHPOLICY_DEFAULT;
|
||||||
|
|
||||||
if(algorithm == 0) {
|
if(algorithm == 0) {
|
||||||
goto import_out;
|
goto import_out;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
unsigned char data[0xff];
|
|
||||||
unsigned long recv_len = sizeof(data);
|
|
||||||
unsigned char in_data[1024];
|
|
||||||
unsigned char *in_ptr = in_data;
|
|
||||||
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
|
|
||||||
int sw;
|
|
||||||
if(YKPIV_IS_RSA(algorithm)) {
|
|
||||||
RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
|
|
||||||
unsigned char e[4];
|
|
||||||
unsigned char *e_ptr = e;
|
|
||||||
int element_len = 128;
|
|
||||||
if(algorithm == YKPIV_ALGO_RSA1024) {
|
|
||||||
element_len = 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((set_component_with_len(&e_ptr, rsa_private_key->e, 3) == false) ||
|
if(pin_policy != pin_policy__NULL) {
|
||||||
!(e[1] == 0x01 && e[2] == 0x00 && e[3] == 0x01)) {
|
pp = get_pin_policy(pin_policy);
|
||||||
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
|
}
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*in_ptr++ = 0x01;
|
if(touch_policy != touch_policy__NULL) {
|
||||||
if(set_component_with_len(&in_ptr, rsa_private_key->p, element_len) == false) {
|
tp = get_touch_policy(touch_policy);
|
||||||
fprintf(stderr, "Failed setting p component.\n");
|
}
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*in_ptr++ = 0x02;
|
if(YKPIV_IS_RSA(algorithm)) {
|
||||||
if(set_component_with_len(&in_ptr, rsa_private_key->q, element_len) == false) {
|
RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
|
||||||
fprintf(stderr, "Failed setting q component.\n");
|
unsigned char e[4];
|
||||||
goto import_out;
|
unsigned char p[128];
|
||||||
}
|
unsigned char q[128];
|
||||||
|
unsigned char dmp1[128];
|
||||||
|
unsigned char dmq1[128];
|
||||||
|
unsigned char iqmp[128];
|
||||||
|
|
||||||
*in_ptr++ = 0x03;
|
int element_len = 128;
|
||||||
if(set_component_with_len(&in_ptr, rsa_private_key->dmp1, element_len) == false) {
|
if(algorithm == YKPIV_ALGO_RSA1024) {
|
||||||
fprintf(stderr, "Failed setting dmp1 component.\n");
|
element_len = 64;
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*in_ptr++ = 0x04;
|
|
||||||
if(set_component_with_len(&in_ptr, rsa_private_key->dmq1, element_len) == false) {
|
|
||||||
fprintf(stderr, "Failed setting dmq1 component.\n");
|
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*in_ptr++ = 0x05;
|
|
||||||
if(set_component_with_len(&in_ptr, rsa_private_key->iqmp, element_len) == false) {
|
|
||||||
fprintf(stderr, "Failed setting iqmp component.\n");
|
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
} else if(YKPIV_IS_EC(algorithm)) {
|
|
||||||
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key);
|
|
||||||
const BIGNUM *s = EC_KEY_get0_private_key(ec);
|
|
||||||
int element_len = 32;
|
|
||||||
|
|
||||||
if(algorithm == YKPIV_ALGO_ECCP384) {
|
|
||||||
element_len = 48;
|
|
||||||
}
|
|
||||||
|
|
||||||
*in_ptr++ = 0x06;
|
|
||||||
if(set_component_with_len(&in_ptr, s, element_len) == false) {
|
|
||||||
fprintf(stderr, "Failed setting ec private key.\n");
|
|
||||||
goto import_out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pin_policy != pin_policy__NULL) {
|
if((set_component(e, rsa_private_key->e, 3) == false) ||
|
||||||
*in_ptr++ = YKPIV_PINPOLICY_TAG;
|
!(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
|
||||||
*in_ptr++ = 1;
|
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
|
||||||
*in_ptr++ = get_pin_policy(pin_policy);
|
goto import_out;
|
||||||
}
|
|
||||||
if(touch_policy != touch_policy__NULL) {
|
|
||||||
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
|
|
||||||
*in_ptr++ = 1;
|
|
||||||
*in_ptr++ = get_touch_policy(touch_policy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data,
|
if(set_component(p, rsa_private_key->p, element_len) == false) {
|
||||||
&recv_len, &sw) != YKPIV_OK) {
|
fprintf(stderr, "Failed setting p component.\n");
|
||||||
return false;
|
goto import_out;
|
||||||
} else if(sw == 0x6a80) {
|
|
||||||
fprintf(stderr, "Failed import.");
|
|
||||||
if(pin_policy != pin_policy__NULL) {
|
|
||||||
fprintf(stderr, "Maybe pin-policy is not supported on this key?\n");
|
|
||||||
} else if(touch_policy != touch_policy__NULL) {
|
|
||||||
fprintf(stderr, "Maybe touch-policy is not supported on this key?\n");
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Maybe algorithm is not supported on this key?\n");
|
|
||||||
}
|
|
||||||
} else if(sw != 0x9000) {
|
|
||||||
fprintf(stderr, "Failed import command with code %x.\n", sw);
|
|
||||||
} else {
|
|
||||||
ret = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(set_component(q, rsa_private_key->q, element_len) == false) {
|
||||||
|
fprintf(stderr, "Failed setting q component.\n");
|
||||||
|
goto import_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(set_component(dmp1, rsa_private_key->dmp1, element_len) == false) {
|
||||||
|
fprintf(stderr, "Failed setting dmp1 component.\n");
|
||||||
|
goto import_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(set_component(dmq1, rsa_private_key->dmq1, element_len) == false) {
|
||||||
|
fprintf(stderr, "Failed setting dmq1 component.\n");
|
||||||
|
goto import_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(set_component(iqmp, rsa_private_key->iqmp, element_len) == false) {
|
||||||
|
fprintf(stderr, "Failed setting iqmp component.\n");
|
||||||
|
goto import_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ykpiv_import_private_key(state, key, algorithm,
|
||||||
|
p, element_len,
|
||||||
|
q, element_len,
|
||||||
|
dmp1, element_len,
|
||||||
|
dmq1, element_len,
|
||||||
|
iqmp, element_len,
|
||||||
|
NULL, 0,
|
||||||
|
pp, tp);
|
||||||
|
}
|
||||||
|
else if(YKPIV_IS_EC(algorithm)) {
|
||||||
|
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key);
|
||||||
|
const BIGNUM *s = EC_KEY_get0_private_key(ec);
|
||||||
|
unsigned char s_ptr[48];
|
||||||
|
|
||||||
|
int element_len = 32;
|
||||||
|
if(algorithm == YKPIV_ALGO_ECCP384) {
|
||||||
|
element_len = 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(set_component(s_ptr, s, element_len) == false) {
|
||||||
|
fprintf(stderr, "Failed setting ec private key.\n");
|
||||||
|
goto import_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
rc = ykpiv_import_private_key(state, key, algorithm,
|
||||||
|
NULL, 0,
|
||||||
|
NULL, 0,
|
||||||
|
NULL, 0,
|
||||||
|
NULL, 0,
|
||||||
|
NULL, 0,
|
||||||
|
s_ptr, element_len,
|
||||||
|
pp, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rc != YKPIV_OK) {
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import_out:
|
import_out:
|
||||||
if(private_key) {
|
if(private_key) {
|
||||||
EVP_PKEY_free(private_key);
|
EVP_PKEY_free(private_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p12) {
|
if(p12) {
|
||||||
PKCS12_free(p12);
|
PKCS12_free(p12);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cert) {
|
if(cert) {
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(input_file != stdin) {
|
if(input_file != stdin) {
|
||||||
fclose(input_file);
|
fclose(input_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user