Merge branch 'devel/p384' into ykcs11
Conflicts: NEWS configure.ac lib/ykpiv.c lib/ykpiv.h tool/util.c tool/util.h
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
yubico-piv-tool NEWS -- History of user-visible changes. -*- outline -*-
|
||||
|
||||
* Version 1.0.2 (unreleased)
|
||||
* Version 1.1.0 (unreleased)
|
||||
|
||||
** Support for YubiKey 4 stuff
|
||||
ECCP384, touch, retired keys etc
|
||||
|
||||
* Version 1.0.1 (released 2015-07-10)
|
||||
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
AC_INIT([yubico-piv-tool], [1.0.2])
|
||||
AC_INIT([yubico-piv-tool], [1.1.0])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@@ -34,9 +34,9 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
# Interfaces changed/added/removed: CURRENT++ REVISION=0
|
||||
# Interfaces added: AGE++
|
||||
# Interfaces removed: AGE=0
|
||||
AC_SUBST([LT_CURRENT], 1)
|
||||
AC_SUBST([LT_REVISION], 7)
|
||||
AC_SUBST([LT_AGE], 0)
|
||||
AC_SUBST([LT_CURRENT], 2)
|
||||
AC_SUBST([LT_REVISION], 0)
|
||||
AC_SUBST([LT_AGE], 1)
|
||||
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
+24
-40
@@ -452,6 +452,10 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) {
|
||||
}
|
||||
|
||||
ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) {
|
||||
return ykpiv_set_mgmkey2(state, new_key, 0);
|
||||
}
|
||||
|
||||
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, const unsigned char touch) {
|
||||
APDU apdu;
|
||||
unsigned char data[0xff];
|
||||
unsigned long recv_len = sizeof(data);
|
||||
@@ -478,7 +482,13 @@ ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) {
|
||||
memset(apdu.raw, 0, sizeof(apdu));
|
||||
apdu.st.ins = YKPIV_INS_SET_MGMKEY;
|
||||
apdu.st.p1 = 0xff;
|
||||
if(touch == 0) {
|
||||
apdu.st.p2 = 0xff;
|
||||
} else if(touch == 1) {
|
||||
apdu.st.p2 = 0xfe;
|
||||
} else {
|
||||
return YKPIV_GENERIC_ERROR;
|
||||
}
|
||||
apdu.st.lc = DES_KEY_SZ * 3 + 3;
|
||||
apdu.st.data[0] = YKPIV_ALGO_3DES;
|
||||
apdu.st.data[1] = YKPIV_KEY_CARDMGM;
|
||||
@@ -524,7 +534,7 @@ ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len,
|
||||
}
|
||||
|
||||
static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
||||
const unsigned char *raw_in, size_t in_len,
|
||||
const unsigned char *sign_in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
unsigned char algorithm, unsigned char key, bool decipher, bool padding) {
|
||||
unsigned char indata[1024];
|
||||
@@ -532,8 +542,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
||||
unsigned char data[1024];
|
||||
unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key};
|
||||
unsigned long recv_len = sizeof(data);
|
||||
unsigned char sign_in[256];
|
||||
size_t pad_len = 0;
|
||||
size_t key_len = 0;
|
||||
int sw;
|
||||
size_t bytes;
|
||||
size_t len = 0;
|
||||
@@ -541,51 +550,26 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
||||
|
||||
switch(algorithm) {
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
pad_len = 128;
|
||||
|
||||
key_len = 128;
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
if(pad_len == 0) {
|
||||
pad_len = 256;
|
||||
if(key_len == 0) {
|
||||
key_len = 256;
|
||||
}
|
||||
if(!decipher) {
|
||||
// Signature
|
||||
if (padding) {
|
||||
// Padding required
|
||||
if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) {
|
||||
if(in_len != key_len) {
|
||||
return YKPIV_SIZE_ERROR;
|
||||
}
|
||||
|
||||
// Add padding and copy data
|
||||
RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len);
|
||||
in_len = pad_len;
|
||||
}
|
||||
else {
|
||||
// No padding required
|
||||
if (in_len != pad_len)
|
||||
return YKPIV_SIZE_ERROR;
|
||||
|
||||
// Just copy data
|
||||
memcpy(sign_in, raw_in, in_len);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Decryption
|
||||
if(in_len != pad_len) {
|
||||
return YKPIV_SIZE_ERROR;
|
||||
}
|
||||
|
||||
// Just copy data
|
||||
memcpy(sign_in, raw_in, in_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
if(!decipher && in_len > 32) {
|
||||
key_len = 32;
|
||||
case YKPIV_ALGO_ECCP384:
|
||||
if(key_len == 0) {
|
||||
key_len = 48;
|
||||
}
|
||||
if(!decipher && in_len > key_len) {
|
||||
return YKPIV_SIZE_ERROR;
|
||||
} else if(decipher && in_len != 65) {
|
||||
} else if(decipher && in_len != (key_len * 2) + 1) {
|
||||
return YKPIV_SIZE_ERROR;
|
||||
}
|
||||
memcpy(sign_in, raw_in, in_len);
|
||||
break;
|
||||
default:
|
||||
return YKPIV_ALGORITHM_ERROR;
|
||||
@@ -603,7 +587,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
||||
dataptr += set_length(dataptr, in_len + bytes + 3);
|
||||
*dataptr++ = 0x82;
|
||||
*dataptr++ = 0x00;
|
||||
*dataptr++ = algorithm == YKPIV_ALGO_ECCP256 && decipher ? 0x85 : 0x81;
|
||||
*dataptr++ = YKPIV_IS_EC(algorithm) && decipher ? 0x85 : 0x81;
|
||||
dataptr += set_length(dataptr, in_len);
|
||||
memcpy(dataptr, sign_in, (size_t)in_len);
|
||||
dataptr += in_len;
|
||||
|
||||
+36
@@ -88,6 +88,8 @@ extern "C"
|
||||
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, 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);
|
||||
|
||||
@@ -95,6 +97,7 @@ extern "C"
|
||||
#define YKPIV_ALGO_RSA1024 0x06
|
||||
#define YKPIV_ALGO_RSA2048 0x07
|
||||
#define YKPIV_ALGO_ECCP256 0x11
|
||||
#define YKPIV_ALGO_ECCP384 0x14
|
||||
|
||||
#define YKPIV_KEY_AUTHENTICATION 0x9a
|
||||
#define YKPIV_KEY_CARDMGM 0x9b
|
||||
@@ -116,6 +119,27 @@ extern "C"
|
||||
#define YKPIV_OBJ_KEY_HISTORY 0x5fc10c
|
||||
#define YKPIV_OBJ_IRIS 0x5fc121
|
||||
|
||||
#define YKPIV_OBJ_RETIRED1 0x5fc10d
|
||||
#define YKPIV_OBJ_RETIRED2 0x5fc10e
|
||||
#define YKPIV_OBJ_RETIRED3 0x5fc10f
|
||||
#define YKPIV_OBJ_RETIRED4 0x5fc110
|
||||
#define YKPIV_OBJ_RETIRED5 0x5fc111
|
||||
#define YKPIV_OBJ_RETIRED6 0x5fc112
|
||||
#define YKPIV_OBJ_RETIRED7 0x5fc113
|
||||
#define YKPIV_OBJ_RETIRED8 0x5fc114
|
||||
#define YKPIV_OBJ_RETIRED9 0x5fc115
|
||||
#define YKPIV_OBJ_RETIRED10 0x5fc116
|
||||
#define YKPIV_OBJ_RETIRED11 0x5fc117
|
||||
#define YKPIV_OBJ_RETIRED12 0x5fc118
|
||||
#define YKPIV_OBJ_RETIRED13 0x5fc119
|
||||
#define YKPIV_OBJ_RETIRED14 0x5fc11a
|
||||
#define YKPIV_OBJ_RETIRED15 0x5fc11b
|
||||
#define YKPIV_OBJ_RETIRED16 0x5fc11c
|
||||
#define YKPIV_OBJ_RETIRED17 0x5fc11d
|
||||
#define YKPIV_OBJ_RETIRED18 0x5fc11e
|
||||
#define YKPIV_OBJ_RETIRED19 0x5fc11f
|
||||
#define YKPIV_OBJ_RETIRED20 0x5fc120
|
||||
|
||||
#define YKPIV_INS_VERIFY 0x20
|
||||
#define YKPIV_INS_CHANGE_REFERENCE 0x24
|
||||
#define YKPIV_INS_RESET_RETRY 0x2c
|
||||
@@ -131,6 +155,18 @@ extern "C"
|
||||
#define YKPIV_INS_RESET 0xfb
|
||||
#define YKPIV_INS_SET_PIN_RETRIES 0xfa
|
||||
|
||||
#define YKPIV_PINPOLICY_TAG 0xaa
|
||||
#define YKPIV_PINPOLICY_NEVER 1
|
||||
#define YKPIV_PINPOLICY_ONCE 2
|
||||
#define YKPIV_PINPOLICY_ALWAYS 3
|
||||
|
||||
#define YKPIV_TOUCHPOLICY_TAG 0xab
|
||||
#define YKPIV_TOUCHPOLICY_NEVER 1
|
||||
#define YKPIV_TOUCHPOLICY_ALWAYS 2
|
||||
|
||||
#define YKPIV_IS_EC(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384))
|
||||
#define YKPIV_IS_RSA(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -56,3 +56,9 @@ global:
|
||||
ykpiv_connect2;
|
||||
ykpiv_sign_data2;
|
||||
} YKPIV_0.1.0;
|
||||
|
||||
YKPIV_1.1.0
|
||||
{
|
||||
global:
|
||||
ykpiv_set_mgmkey2;
|
||||
} YKPIV_0.1.0;
|
||||
|
||||
+7
-4
@@ -36,14 +36,15 @@ option "action" a "Action to take" values="version","generate","set-mgm-key",
|
||||
text "
|
||||
Multiple actions may be given at once and will be executed in order
|
||||
for example --action=verify-pin --action=request-certificate\n"
|
||||
option "slot" s "What key slot to operate on" values="9a","9c","9d","9e" enum optional
|
||||
option "slot" s "What key slot to operate on" values="9a","9c","9d","9e","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95" enum optional
|
||||
text "
|
||||
9a is for PIV Authentication
|
||||
9c is for Digital Signature (PIN always checked)
|
||||
9d is for Key Management
|
||||
9e is for Card Authentication (PIN never checked)\n"
|
||||
option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256" enum optional default="RSA2048"
|
||||
option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA512" enum optional default="SHA256"
|
||||
9e is for Card Authentication (PIN never checked)
|
||||
82-95 is for Retired Key Management\n"
|
||||
option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256","ECCP384" enum optional default="RSA2048"
|
||||
option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA384","SHA512" enum optional default="SHA256"
|
||||
option "new-key" n "New authentication key to use" string optional
|
||||
option "pin-retries" - "Number of retries before the pin code is blocked" int optional dependon="puk-retries"
|
||||
option "puk-retries" - "Number of retries before the puk code is blocked" int optional dependon="pin-retries"
|
||||
@@ -57,4 +58,6 @@ text "
|
||||
/CN=host.example.com/OU=test/O=example.com/\n"
|
||||
option "pin" P "Pin/puk code for verification" string optional
|
||||
option "new-pin" N "New pin/puk code for changing" string optional dependon="pin"
|
||||
option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional
|
||||
option "touch-policy" - "Set touch policy for action generate, import-key or set-mgm-key" values="never","always" enum optional
|
||||
option "sign" - "Sign data" flag off hidden
|
||||
|
||||
+193
@@ -82,6 +82,8 @@ unsigned char get_algorithm(EVP_PKEY *key) {
|
||||
int curve = EC_GROUP_get_curve_name(group);
|
||||
if(curve == NID_X9_62_prime256v1) {
|
||||
return YKPIV_ALGO_ECCP256;
|
||||
} else if(curve == NID_secp384r1) {
|
||||
return YKPIV_ALGO_ECCP384;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown EC curve %d\n", curve);
|
||||
return 0;
|
||||
@@ -200,6 +202,66 @@ int get_object_id(enum enum_slot slot) {
|
||||
case slot_arg_9e:
|
||||
object = YKPIV_OBJ_CARD_AUTH;
|
||||
break;
|
||||
case slot_arg_82:
|
||||
object = YKPIV_OBJ_RETIRED1;
|
||||
break;
|
||||
case slot_arg_83:
|
||||
object = YKPIV_OBJ_RETIRED2;
|
||||
break;
|
||||
case slot_arg_84:
|
||||
object = YKPIV_OBJ_RETIRED3;
|
||||
break;
|
||||
case slot_arg_85:
|
||||
object = YKPIV_OBJ_RETIRED4;
|
||||
break;
|
||||
case slot_arg_86:
|
||||
object = YKPIV_OBJ_RETIRED5;
|
||||
break;
|
||||
case slot_arg_87:
|
||||
object = YKPIV_OBJ_RETIRED6;
|
||||
break;
|
||||
case slot_arg_88:
|
||||
object = YKPIV_OBJ_RETIRED7;
|
||||
break;
|
||||
case slot_arg_89:
|
||||
object = YKPIV_OBJ_RETIRED8;
|
||||
break;
|
||||
case slot_arg_8a:
|
||||
object = YKPIV_OBJ_RETIRED9;
|
||||
break;
|
||||
case slot_arg_8b:
|
||||
object = YKPIV_OBJ_RETIRED10;
|
||||
break;
|
||||
case slot_arg_8c:
|
||||
object = YKPIV_OBJ_RETIRED11;
|
||||
break;
|
||||
case slot_arg_8d:
|
||||
object = YKPIV_OBJ_RETIRED12;
|
||||
break;
|
||||
case slot_arg_8e:
|
||||
object = YKPIV_OBJ_RETIRED13;
|
||||
break;
|
||||
case slot_arg_8f:
|
||||
object = YKPIV_OBJ_RETIRED14;
|
||||
break;
|
||||
case slot_arg_90:
|
||||
object = YKPIV_OBJ_RETIRED15;
|
||||
break;
|
||||
case slot_arg_91:
|
||||
object = YKPIV_OBJ_RETIRED16;
|
||||
break;
|
||||
case slot_arg_92:
|
||||
object = YKPIV_OBJ_RETIRED17;
|
||||
break;
|
||||
case slot_arg_93:
|
||||
object = YKPIV_OBJ_RETIRED18;
|
||||
break;
|
||||
case slot_arg_94:
|
||||
object = YKPIV_OBJ_RETIRED19;
|
||||
break;
|
||||
case slot_arg_95:
|
||||
object = YKPIV_OBJ_RETIRED20;
|
||||
break;
|
||||
case slot__NULL:
|
||||
default:
|
||||
object = 0;
|
||||
@@ -284,3 +346,134 @@ bool read_pw(const char *name, char *pwbuf, size_t pwbuflen, int verify) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned const char sha1oid[] = {
|
||||
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00,
|
||||
0x04, 0x14
|
||||
};
|
||||
|
||||
static unsigned const char sha256oid[] = {
|
||||
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
static unsigned const char sha384oid[] = {
|
||||
0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x02, 0x05, 0x00, 0x04, 0x30
|
||||
};
|
||||
|
||||
static unsigned const char sha512oid[] = {
|
||||
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x03, 0x05, 0x00, 0x04, 0x40
|
||||
};
|
||||
|
||||
const EVP_MD *get_hash(enum enum_hash hash, const unsigned char **oid, size_t *oid_len) {
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
if(oid) {
|
||||
*oid = sha1oid;
|
||||
*oid_len = sizeof(sha1oid);
|
||||
}
|
||||
return EVP_sha1();
|
||||
case hash_arg_SHA256:
|
||||
if(oid) {
|
||||
*oid = sha256oid;
|
||||
*oid_len = sizeof(sha256oid);
|
||||
}
|
||||
return EVP_sha256();
|
||||
case hash_arg_SHA384:
|
||||
if(oid) {
|
||||
*oid = sha384oid;
|
||||
*oid_len = sizeof(sha384oid);
|
||||
}
|
||||
return EVP_sha384();
|
||||
case hash_arg_SHA512:
|
||||
if(oid) {
|
||||
*oid = sha512oid;
|
||||
*oid_len = sizeof(sha512oid);
|
||||
}
|
||||
return EVP_sha512();
|
||||
case hash__NULL:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int get_hashnid(enum enum_hash hash, unsigned char algorithm) {
|
||||
switch(algorithm) {
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
return NID_sha1WithRSAEncryption;
|
||||
case hash_arg_SHA256:
|
||||
return NID_sha256WithRSAEncryption;
|
||||
case hash_arg_SHA384:
|
||||
return NID_sha384WithRSAEncryption;
|
||||
case hash_arg_SHA512:
|
||||
return NID_sha512WithRSAEncryption;
|
||||
case hash__NULL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
case YKPIV_ALGO_ECCP384:
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
return NID_ecdsa_with_SHA1;
|
||||
case hash_arg_SHA256:
|
||||
return NID_ecdsa_with_SHA256;
|
||||
case hash_arg_SHA384:
|
||||
return NID_ecdsa_with_SHA384;
|
||||
case hash_arg_SHA512:
|
||||
return NID_ecdsa_with_SHA512;
|
||||
case hash__NULL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char get_piv_algorithm(enum enum_algorithm algorithm) {
|
||||
switch(algorithm) {
|
||||
case algorithm_arg_RSA2048:
|
||||
return YKPIV_ALGO_RSA2048;
|
||||
case algorithm_arg_RSA1024:
|
||||
return YKPIV_ALGO_RSA1024;
|
||||
case algorithm_arg_ECCP256:
|
||||
return YKPIV_ALGO_ECCP256;
|
||||
case algorithm_arg_ECCP384:
|
||||
return YKPIV_ALGO_ECCP384;
|
||||
case algorithm__NULL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char get_pin_policy(enum enum_pin_policy policy) {
|
||||
switch(policy) {
|
||||
case pin_policy_arg_never:
|
||||
return YKPIV_PINPOLICY_NEVER;
|
||||
case pin_policy_arg_once:
|
||||
return YKPIV_PINPOLICY_ONCE;
|
||||
case pin_policy_arg_always:
|
||||
return YKPIV_PINPOLICY_ALWAYS;
|
||||
case pin_policy__NULL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char get_touch_policy(enum enum_touch_policy policy) {
|
||||
switch(policy) {
|
||||
case touch_policy_arg_never:
|
||||
return YKPIV_TOUCHPOLICY_NEVER;
|
||||
case touch_policy_arg_always:
|
||||
return YKPIV_TOUCHPOLICY_ALWAYS;
|
||||
case touch_policy__NULL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,5 +50,10 @@ bool set_component_with_len(unsigned char**, const BIGNUM*, int);
|
||||
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
|
||||
unsigned int*, int);
|
||||
bool read_pw(const char*, char*, size_t, int);
|
||||
const EVP_MD *get_hash(enum enum_hash, const unsigned char**, size_t*);
|
||||
int get_hashnid(enum enum_hash, unsigned char);
|
||||
unsigned char get_piv_algorithm(enum enum_algorithm);
|
||||
unsigned char get_pin_policy(enum enum_pin_policy);
|
||||
unsigned char get_touch_policy(enum enum_touch_policy);
|
||||
|
||||
#endif
|
||||
|
||||
+146
-218
@@ -63,20 +63,7 @@ unsigned const char chuid_tmpl[] = {
|
||||
};
|
||||
#define CHUID_GUID_OFFS 29
|
||||
|
||||
unsigned const char sha1oid[] = {
|
||||
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00,
|
||||
0x04, 0x14
|
||||
};
|
||||
|
||||
unsigned const char sha256oid[] = {
|
||||
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
unsigned const char sha512oid[] = {
|
||||
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x03, 0x05, 0x00, 0x04, 0x40
|
||||
};
|
||||
#define MAX_OID_LEN 19
|
||||
|
||||
#define KEY_LEN 24
|
||||
|
||||
@@ -100,8 +87,10 @@ static void print_version(ykpiv_state *state, const char *output_file_name) {
|
||||
|
||||
static bool generate_key(ykpiv_state *state, const char *slot,
|
||||
enum enum_algorithm algorithm, const char *output_file_name,
|
||||
enum enum_key_format key_format) {
|
||||
unsigned char in_data[5];
|
||||
enum enum_key_format key_format, enum enum_pin_policy pin_policy,
|
||||
enum enum_touch_policy touch_policy) {
|
||||
unsigned char in_data[11];
|
||||
unsigned char *in_ptr = in_data;
|
||||
unsigned char data[1024];
|
||||
unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0};
|
||||
unsigned long recv_len = sizeof(data);
|
||||
@@ -124,31 +113,46 @@ static bool generate_key(ykpiv_state *state, const char *slot,
|
||||
return false;
|
||||
}
|
||||
|
||||
in_data[0] = 0xac;
|
||||
in_data[1] = 3;
|
||||
in_data[2] = 0x80;
|
||||
in_data[3] = 1;
|
||||
switch(algorithm) {
|
||||
case algorithm_arg_RSA2048:
|
||||
in_data[4] = YKPIV_ALGO_RSA2048;
|
||||
break;
|
||||
case algorithm_arg_RSA1024:
|
||||
in_data[4] = YKPIV_ALGO_RSA1024;
|
||||
break;
|
||||
case algorithm_arg_ECCP256:
|
||||
in_data[4] = YKPIV_ALGO_ECCP256;
|
||||
break;
|
||||
case algorithm__NULL:
|
||||
default:
|
||||
*in_ptr++ = 0xac;
|
||||
*in_ptr++ = 3;
|
||||
*in_ptr++ = 0x80;
|
||||
*in_ptr++ = 1;
|
||||
*in_ptr++ = get_piv_algorithm(algorithm);
|
||||
if(in_data[4] == 0) {
|
||||
fprintf(stderr, "Unexepcted algorithm.\n");
|
||||
goto generate_out;
|
||||
}
|
||||
if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data,
|
||||
if(pin_policy != pin_policy__NULL) {
|
||||
in_data[1] += 3;
|
||||
*in_ptr++ = YKPIV_PINPOLICY_TAG;
|
||||
*in_ptr++ = 1;
|
||||
*in_ptr++ = get_pin_policy(pin_policy);
|
||||
}
|
||||
if(touch_policy != touch_policy__NULL) {
|
||||
in_data[1] += 3;
|
||||
*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,
|
||||
&recv_len, &sw) != YKPIV_OK) {
|
||||
fprintf(stderr, "Failed to communicate.\n");
|
||||
goto generate_out;
|
||||
} else if(sw != 0x9000) {
|
||||
fprintf(stderr, "Failed to generate new key.\n");
|
||||
fprintf(stderr, "Failed to generate new key (");
|
||||
if(sw == 0x6b00) {
|
||||
fprintf(stderr, "slot not supported?)\n");
|
||||
} else if(sw == 0x6a80) {
|
||||
if(pin_policy != pin_policy__NULL) {
|
||||
fprintf(stderr, "pin policy not supported?)\n");
|
||||
} else if(touch_policy != touch_policy__NULL) {
|
||||
fprintf(stderr, "touch policy not supported?)\n");
|
||||
} else {
|
||||
fprintf(stderr, "algorithm not supported?)\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "error %x)\n", sw);
|
||||
}
|
||||
goto generate_out;
|
||||
}
|
||||
|
||||
@@ -187,24 +191,34 @@ static bool generate_key(ykpiv_state *state, const char *slot,
|
||||
rsa->n = bignum_n;
|
||||
rsa->e = bignum_e;
|
||||
EVP_PKEY_set1_RSA(public_key, rsa);
|
||||
} else if(algorithm == algorithm_arg_ECCP256) {
|
||||
} else if(algorithm == algorithm_arg_ECCP256 || algorithm == algorithm_arg_ECCP384) {
|
||||
EC_GROUP *group;
|
||||
unsigned char *data_ptr = data + 3;
|
||||
int nid;
|
||||
size_t len;
|
||||
|
||||
if(algorithm == algorithm_arg_ECCP256) {
|
||||
nid = NID_X9_62_prime256v1;
|
||||
len = 65;
|
||||
} else {
|
||||
nid = NID_secp384r1;
|
||||
len = 97;
|
||||
}
|
||||
|
||||
eckey = EC_KEY_new();
|
||||
group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
EC_GROUP_set_asn1_flag(group, NID_X9_62_prime256v1);
|
||||
group = EC_GROUP_new_by_curve_name(nid);
|
||||
EC_GROUP_set_asn1_flag(group, nid);
|
||||
EC_KEY_set_group(eckey, group);
|
||||
point = EC_POINT_new(group);
|
||||
if(*data_ptr++ != 0x86) {
|
||||
fprintf(stderr, "Failed to parse public key structure.\n");
|
||||
goto generate_out;
|
||||
}
|
||||
if(*data_ptr++ != 65) { /* the curve point should always be 65 bytes */
|
||||
if(*data_ptr++ != len) { /* the curve point should always be 65 bytes */
|
||||
fprintf(stderr, "Unexpected length.\n");
|
||||
goto generate_out;
|
||||
}
|
||||
if(!EC_POINT_oct2point(group, point, data_ptr, 65, NULL)) {
|
||||
if(!EC_POINT_oct2point(group, point, data_ptr, len, NULL)) {
|
||||
fprintf(stderr, "Failed to load public point.\n");
|
||||
goto generate_out;
|
||||
}
|
||||
@@ -283,7 +297,8 @@ 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,
|
||||
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) {
|
||||
int key = 0;
|
||||
FILE *input_file = NULL;
|
||||
EVP_PKEY *private_key = NULL;
|
||||
@@ -336,7 +351,7 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
||||
unsigned char *in_ptr = in_data;
|
||||
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
|
||||
int sw;
|
||||
if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
|
||||
unsigned char e[4];
|
||||
unsigned char *e_ptr = e;
|
||||
@@ -380,20 +395,45 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
||||
fprintf(stderr, "Failed setting iqmp component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
} else if(algorithm == YKPIV_ALGO_ECCP256) {
|
||||
} 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, 32) == false) {
|
||||
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) {
|
||||
*in_ptr++ = YKPIV_PINPOLICY_TAG;
|
||||
*in_ptr++ = 1;
|
||||
*in_ptr++ = get_pin_policy(pin_policy);
|
||||
}
|
||||
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,
|
||||
&recv_len, &sw) != YKPIV_OK) {
|
||||
return false;
|
||||
} 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 {
|
||||
@@ -559,7 +599,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
EVP_PKEY *public_key = NULL;
|
||||
const EVP_MD *md;
|
||||
bool ret = false;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; // maximum..
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN];
|
||||
unsigned int digest_len;
|
||||
unsigned int md_len;
|
||||
unsigned char algorithm;
|
||||
@@ -597,24 +637,8 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
md = EVP_sha1();
|
||||
oid = sha1oid;
|
||||
oid_len = sizeof(sha1oid);
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
md = EVP_sha256();
|
||||
oid = sha256oid;
|
||||
oid_len = sizeof(sha256oid);
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
md = EVP_sha512();
|
||||
oid = sha512oid;
|
||||
oid_len = sizeof(sha512oid);
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
md = get_hash(hash, &oid, &oid_len);
|
||||
if(md == NULL) {
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
@@ -651,48 +675,19 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
switch(algorithm) {
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
nid = get_hashnid(hash, algorithm);
|
||||
if(nid == 0) {
|
||||
fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash);
|
||||
goto request_out;
|
||||
}
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
signinput = digest;
|
||||
len = oid_len + digest_len;
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
nid = NID_sha1WithRSAEncryption;
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
nid = NID_sha256WithRSAEncryption;
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
nid = NID_sha512WithRSAEncryption;
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
goto request_out;
|
||||
}
|
||||
break;
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
} else {
|
||||
signinput = digest + oid_len;
|
||||
len = digest_len;
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
nid = NID_ecdsa_with_SHA1;
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
nid = NID_ecdsa_with_SHA256;
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
nid = NID_ecdsa_with_SHA512;
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
goto request_out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
req->sig_alg->algorithm = OBJ_nid2obj(nid);
|
||||
{
|
||||
unsigned char signature[1024];
|
||||
@@ -743,7 +738,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
const EVP_MD *md;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)];
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN];
|
||||
unsigned int digest_len;
|
||||
unsigned char algorithm;
|
||||
int key = 0;
|
||||
@@ -781,27 +776,10 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
goto selfsign_out;
|
||||
}
|
||||
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
md = EVP_sha1();
|
||||
oid = sha1oid;
|
||||
oid_len = sizeof(sha1oid);
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
md = EVP_sha256();
|
||||
oid = sha256oid;
|
||||
oid_len = sizeof(sha256oid);
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
md = EVP_sha512();
|
||||
oid = sha512oid;
|
||||
oid_len = sizeof(sha512oid);
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
md = get_hash(hash, &oid, &oid_len);
|
||||
if(md == NULL) {
|
||||
goto selfsign_out;
|
||||
}
|
||||
|
||||
md_len = (unsigned int)EVP_MD_size(md);
|
||||
digest_len = sizeof(digest) - md_len;
|
||||
|
||||
@@ -843,48 +821,18 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
fprintf(stderr, "Failed setting certificate issuer.\n");
|
||||
goto selfsign_out;
|
||||
}
|
||||
switch(algorithm) {
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
nid = get_hashnid(hash, algorithm);
|
||||
if(nid == 0) {
|
||||
goto selfsign_out;
|
||||
}
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
signinput = digest;
|
||||
len = oid_len + md_len;
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
nid = NID_sha1WithRSAEncryption;
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
nid = NID_sha256WithRSAEncryption;
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
nid = NID_sha512WithRSAEncryption;
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
goto selfsign_out;
|
||||
}
|
||||
break;
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
} else {
|
||||
signinput = digest + oid_len;
|
||||
len = md_len;
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
nid = NID_ecdsa_with_SHA1;
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
nid = NID_ecdsa_with_SHA256;
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
nid = NID_ecdsa_with_SHA512;
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
goto selfsign_out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||
goto selfsign_out;
|
||||
}
|
||||
|
||||
x509->sig_alg->algorithm = OBJ_nid2obj(nid);
|
||||
x509->cert_info->signature->algorithm = x509->sig_alg->algorithm;
|
||||
memcpy(digest, oid, oid_len);
|
||||
@@ -1138,36 +1086,16 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(algorithm) {
|
||||
case algorithm_arg_RSA2048:
|
||||
algo = YKPIV_ALGO_RSA2048;
|
||||
break;
|
||||
case algorithm_arg_RSA1024:
|
||||
algo = YKPIV_ALGO_RSA1024;
|
||||
break;
|
||||
case algorithm_arg_ECCP256:
|
||||
algo = YKPIV_ALGO_ECCP256;
|
||||
break;
|
||||
case algorithm__NULL:
|
||||
default:
|
||||
algo = get_piv_algorithm(algorithm);
|
||||
if(algo == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
EVP_MD_CTX *mdctx;
|
||||
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
md = EVP_sha256();
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
md = EVP_sha512();
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
md = get_hash(hash, NULL, NULL);
|
||||
if(md == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1187,7 +1115,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
}
|
||||
|
||||
if(algo == YKPIV_ALGO_RSA1024 || algo == YKPIV_ALGO_RSA2048) {
|
||||
if(YKPIV_IS_RSA(algo)) {
|
||||
prepare_rsa_signature(hashed, hash_len, hashed, &hash_len, EVP_MD_type(md));
|
||||
}
|
||||
|
||||
@@ -1268,6 +1196,9 @@ static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_M
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
fprintf(output, "ECCP256\n");
|
||||
break;
|
||||
case YKPIV_ALGO_ECCP384:
|
||||
fprintf(output, "ECCP384\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(output, "Unknown\n");
|
||||
}
|
||||
@@ -1328,18 +1259,8 @@ static bool status(ykpiv_state *state, enum enum_hash hash,
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
md = EVP_sha256();
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
md = EVP_sha512();
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
md = get_hash(hash, NULL, NULL);
|
||||
if(md == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1404,18 +1325,8 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
|
||||
goto test_out;
|
||||
}
|
||||
|
||||
switch(hash) {
|
||||
case hash_arg_SHA1:
|
||||
md = EVP_sha1();
|
||||
break;
|
||||
case hash_arg_SHA256:
|
||||
md = EVP_sha256();
|
||||
break;
|
||||
case hash_arg_SHA512:
|
||||
md = EVP_sha512();
|
||||
break;
|
||||
case hash__NULL:
|
||||
default:
|
||||
md = get_hash(hash, NULL, NULL);
|
||||
if(md == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1456,7 +1367,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
|
||||
goto test_out;
|
||||
}
|
||||
sscanf(cmdline_parser_slot_values[slot], "%2x", &key);
|
||||
if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
prepare_rsa_signature(data, data_len, encoded, &enc_len, EVP_MD_type(md));
|
||||
ptr = encoded;
|
||||
} else {
|
||||
@@ -1490,6 +1401,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
|
||||
|
||||
break;
|
||||
case YKPIV_ALGO_ECCP256:
|
||||
case YKPIV_ALGO_ECCP384:
|
||||
{
|
||||
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey);
|
||||
if(ECDSA_verify(0, data, (int)data_len, signature, (int)sig_len, ec) == 1) {
|
||||
@@ -1561,7 +1473,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
||||
goto decipher_out;
|
||||
}
|
||||
sscanf(cmdline_parser_slot_values[slot], "%2x", &key);
|
||||
if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
unsigned char secret[32];
|
||||
unsigned char secret2[32];
|
||||
unsigned char data[256];
|
||||
@@ -1602,20 +1514,30 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
||||
} else {
|
||||
fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n");
|
||||
}
|
||||
} else {
|
||||
unsigned char secret[32];
|
||||
unsigned char secret2[32];
|
||||
unsigned char public_key[65];
|
||||
} else if(YKPIV_IS_EC(algorithm)) {
|
||||
unsigned char secret[48];
|
||||
unsigned char secret2[48];
|
||||
unsigned char public_key[97];
|
||||
unsigned char *ptr = public_key;
|
||||
size_t len = sizeof(secret);
|
||||
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey);
|
||||
int nid;
|
||||
size_t key_len;
|
||||
|
||||
tmpkey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if(algorithm == YKPIV_ALGO_ECCP256) {
|
||||
nid = NID_X9_62_prime256v1;
|
||||
key_len = 32;
|
||||
} else {
|
||||
nid = NID_secp384r1;
|
||||
key_len = 48;
|
||||
}
|
||||
|
||||
tmpkey = EC_KEY_new_by_curve_name(nid);
|
||||
EC_KEY_generate_key(tmpkey);
|
||||
ECDH_compute_key(secret, len, EC_KEY_get0_public_key(ec), tmpkey, NULL);
|
||||
|
||||
i2o_ECPublicKey(tmpkey, &ptr);
|
||||
if(ykpiv_decipher_data(state, public_key, sizeof(public_key), secret2, &len, algorithm, key) != YKPIV_OK) {
|
||||
if(ykpiv_decipher_data(state, public_key, (key_len * 2) + 1, secret2, &len, algorithm, key) != YKPIV_OK) {
|
||||
fprintf(stderr, "Failed ECDH exchange!\n");
|
||||
goto decipher_out;
|
||||
}
|
||||
@@ -1625,7 +1547,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
||||
fprintf(stderr, "ECDH card generated: ");
|
||||
dump_hex(secret2, len, stderr, true);
|
||||
}
|
||||
if(memcmp(secret, secret2, 32) == 0) {
|
||||
if(memcmp(secret, secret2, key_len) == 0) {
|
||||
fprintf(stderr, "Successfully performed ECDH exchange with card.\n");
|
||||
ret = true;
|
||||
} else {
|
||||
@@ -1786,7 +1708,8 @@ int main(int argc, char *argv[]) {
|
||||
print_version(state, args_info.output_arg);
|
||||
break;
|
||||
case action_arg_generate:
|
||||
if(generate_key(state, args_info.slot_orig, args_info.algorithm_arg, args_info.output_arg, args_info.key_format_arg) == false) {
|
||||
if(generate_key(state, args_info.slot_orig, args_info.algorithm_arg, args_info.output_arg, args_info.key_format_arg,
|
||||
args_info.pin_policy_arg, args_info.touch_policy_arg) == false) {
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
fprintf(stderr, "Successfully generated a new private key.\n");
|
||||
@@ -1807,8 +1730,12 @@ int main(int argc, char *argv[]) {
|
||||
if(ykpiv_hex_decode(new_mgm_key, strlen(new_mgm_key), new_key, &new_key_len) != YKPIV_OK) {
|
||||
fprintf(stderr, "Failed decoding new key!\n");
|
||||
ret = EXIT_FAILURE;
|
||||
} else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) {
|
||||
fprintf(stderr, "Failed setting the new key!\n");
|
||||
} else if(ykpiv_set_mgmkey2(state, new_key, args_info.touch_policy_arg == touch_policy_arg_always ? 1 : 0) != YKPIV_OK) {
|
||||
fprintf(stderr, "Failed setting the new key!");
|
||||
if(args_info.touch_policy_arg != touch_policy__NULL) {
|
||||
fprintf(stderr, " Maybe touch policy is not supported on this key?");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
fprintf(stderr, "Successfully set new management key.\n");
|
||||
@@ -1835,7 +1762,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
case action_arg_importMINUS_key:
|
||||
if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg) == false) {
|
||||
if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg,
|
||||
args_info.pin_policy_arg, args_info.touch_policy_arg) == false) {
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
fprintf(stderr, "Successfully imported a new private key.\n");
|
||||
|
||||
Reference in New Issue
Block a user