start adding secp384r1
This commit is contained in:
+15
-10
@@ -508,7 +508,7 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
|||||||
unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key};
|
unsigned char templ[] = {0, YKPIV_INS_AUTHENTICATE, algorithm, key};
|
||||||
unsigned long recv_len = sizeof(data);
|
unsigned long recv_len = sizeof(data);
|
||||||
unsigned char sign_in[256];
|
unsigned char sign_in[256];
|
||||||
size_t pad_len = 0;
|
size_t key_len = 0;
|
||||||
int sw;
|
int sw;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -516,28 +516,33 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state,
|
|||||||
|
|
||||||
switch(algorithm) {
|
switch(algorithm) {
|
||||||
case YKPIV_ALGO_RSA1024:
|
case YKPIV_ALGO_RSA1024:
|
||||||
pad_len = 128;
|
key_len = 128;
|
||||||
case YKPIV_ALGO_RSA2048:
|
case YKPIV_ALGO_RSA2048:
|
||||||
if(pad_len == 0) {
|
if(key_len == 0) {
|
||||||
pad_len = 256;
|
key_len = 256;
|
||||||
}
|
}
|
||||||
if(!decipher) {
|
if(!decipher) {
|
||||||
if(in_len + RSA_PKCS1_PADDING_SIZE > pad_len) {
|
if(in_len + RSA_PKCS1_PADDING_SIZE > key_len) {
|
||||||
return YKPIV_SIZE_ERROR;
|
return YKPIV_SIZE_ERROR;
|
||||||
}
|
}
|
||||||
RSA_padding_add_PKCS1_type_1(sign_in, pad_len, raw_in, in_len);
|
RSA_padding_add_PKCS1_type_1(sign_in, key_len, raw_in, in_len);
|
||||||
in_len = pad_len;
|
in_len = key_len;
|
||||||
} else {
|
} else {
|
||||||
if(in_len != pad_len) {
|
if(in_len != key_len) {
|
||||||
return YKPIV_SIZE_ERROR;
|
return YKPIV_SIZE_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(sign_in, raw_in, in_len);
|
memcpy(sign_in, raw_in, in_len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case YKPIV_ALGO_ECCP256:
|
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;
|
return YKPIV_SIZE_ERROR;
|
||||||
} else if(decipher && in_len != 65) {
|
} else if(decipher && in_len != (key_len * 2) + 1) {
|
||||||
return YKPIV_SIZE_ERROR;
|
return YKPIV_SIZE_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(sign_in, raw_in, in_len);
|
memcpy(sign_in, raw_in, in_len);
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ extern "C"
|
|||||||
#define YKPIV_ALGO_RSA1024 0x06
|
#define YKPIV_ALGO_RSA1024 0x06
|
||||||
#define YKPIV_ALGO_RSA2048 0x07
|
#define YKPIV_ALGO_RSA2048 0x07
|
||||||
#define YKPIV_ALGO_ECCP256 0x11
|
#define YKPIV_ALGO_ECCP256 0x11
|
||||||
|
#define YKPIV_ALGO_ECCP384 0x14
|
||||||
|
|
||||||
#define YKPIV_KEY_AUTHENTICATION 0x9a
|
#define YKPIV_KEY_AUTHENTICATION 0x9a
|
||||||
#define YKPIV_KEY_CARDMGM 0x9b
|
#define YKPIV_KEY_CARDMGM 0x9b
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ text "
|
|||||||
9c is for Digital Signature (PIN always checked)
|
9c is for Digital Signature (PIN always checked)
|
||||||
9d is for Key Management
|
9d is for Key Management
|
||||||
9e is for Card Authentication (PIN never checked)\n"
|
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 "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","SHA512" enum optional default="SHA256"
|
option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA512" enum optional default="SHA256"
|
||||||
option "new-key" n "New authentication key to use" string optional
|
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 "pin-retries" - "Number of retries before the pin code is blocked" int optional dependon="puk-retries"
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ unsigned char get_algorithm(EVP_PKEY *key) {
|
|||||||
int curve = EC_GROUP_get_curve_name(group);
|
int curve = EC_GROUP_get_curve_name(group);
|
||||||
if(curve == NID_X9_62_prime256v1) {
|
if(curve == NID_X9_62_prime256v1) {
|
||||||
return YKPIV_ALGO_ECCP256;
|
return YKPIV_ALGO_ECCP256;
|
||||||
|
} else if(curve == NID_secp384r1) {
|
||||||
|
return YKPIV_ALGO_ECCP384;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown EC curve %d\n", curve);
|
fprintf(stderr, "Unknown EC curve %d\n", curve);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+37
-12
@@ -138,6 +138,9 @@ static bool generate_key(ykpiv_state *state, const char *slot,
|
|||||||
case algorithm_arg_ECCP256:
|
case algorithm_arg_ECCP256:
|
||||||
in_data[4] = YKPIV_ALGO_ECCP256;
|
in_data[4] = YKPIV_ALGO_ECCP256;
|
||||||
break;
|
break;
|
||||||
|
case algorithm_arg_ECCP384:
|
||||||
|
in_data[4] = YKPIV_ALGO_ECCP384;
|
||||||
|
break;
|
||||||
case algorithm__NULL:
|
case algorithm__NULL:
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unexepcted algorithm.\n");
|
fprintf(stderr, "Unexepcted algorithm.\n");
|
||||||
@@ -189,24 +192,34 @@ static bool generate_key(ykpiv_state *state, const char *slot,
|
|||||||
rsa->n = bignum_n;
|
rsa->n = bignum_n;
|
||||||
rsa->e = bignum_e;
|
rsa->e = bignum_e;
|
||||||
EVP_PKEY_set1_RSA(public_key, rsa);
|
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;
|
EC_GROUP *group;
|
||||||
unsigned char *data_ptr = data + 3;
|
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();
|
eckey = EC_KEY_new();
|
||||||
group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
|
group = EC_GROUP_new_by_curve_name(nid);
|
||||||
EC_GROUP_set_asn1_flag(group, NID_X9_62_prime256v1);
|
EC_GROUP_set_asn1_flag(group, nid);
|
||||||
EC_KEY_set_group(eckey, group);
|
EC_KEY_set_group(eckey, group);
|
||||||
point = EC_POINT_new(group);
|
point = EC_POINT_new(group);
|
||||||
if(*data_ptr++ != 0x86) {
|
if(*data_ptr++ != 0x86) {
|
||||||
fprintf(stderr, "Failed to parse public key structure.\n");
|
fprintf(stderr, "Failed to parse public key structure.\n");
|
||||||
goto generate_out;
|
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");
|
fprintf(stderr, "Unexpected length.\n");
|
||||||
goto generate_out;
|
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");
|
fprintf(stderr, "Failed to load public point.\n");
|
||||||
goto generate_out;
|
goto generate_out;
|
||||||
}
|
}
|
||||||
@@ -674,6 +687,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case YKPIV_ALGO_ECCP256:
|
case YKPIV_ALGO_ECCP256:
|
||||||
|
case YKPIV_ALGO_ECCP384:
|
||||||
signinput = digest + oid_len;
|
signinput = digest + oid_len;
|
||||||
len = digest_len;
|
len = digest_len;
|
||||||
switch(hash) {
|
switch(hash) {
|
||||||
@@ -866,6 +880,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case YKPIV_ALGO_ECCP256:
|
case YKPIV_ALGO_ECCP256:
|
||||||
|
case YKPIV_ALGO_ECCP384:
|
||||||
signinput = digest + oid_len;
|
signinput = digest + oid_len;
|
||||||
len = md_len;
|
len = md_len;
|
||||||
switch(hash) {
|
switch(hash) {
|
||||||
@@ -1577,20 +1592,30 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
|||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n");
|
fprintf(stderr, "Failed unwrapping PKCS1 envelope.\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else if(algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) {
|
||||||
unsigned char secret[32];
|
unsigned char secret[48];
|
||||||
unsigned char secret2[32];
|
unsigned char secret2[48];
|
||||||
unsigned char public_key[65];
|
unsigned char public_key[97];
|
||||||
unsigned char *ptr = public_key;
|
unsigned char *ptr = public_key;
|
||||||
size_t len = sizeof(secret);
|
size_t len = sizeof(secret);
|
||||||
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey);
|
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);
|
EC_KEY_generate_key(tmpkey);
|
||||||
ECDH_compute_key(secret, len, EC_KEY_get0_public_key(ec), tmpkey, NULL);
|
ECDH_compute_key(secret, len, EC_KEY_get0_public_key(ec), tmpkey, NULL);
|
||||||
|
|
||||||
i2o_ECPublicKey(tmpkey, &ptr);
|
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");
|
fprintf(stderr, "Failed ECDH exchange!\n");
|
||||||
goto decipher_out;
|
goto decipher_out;
|
||||||
}
|
}
|
||||||
@@ -1600,7 +1625,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
|||||||
fprintf(stderr, "ECDH card generated: ");
|
fprintf(stderr, "ECDH card generated: ");
|
||||||
dump_hex(secret2, len, stderr, true);
|
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");
|
fprintf(stderr, "Successfully performed ECDH exchange with card.\n");
|
||||||
ret = true;
|
ret = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user