start adding secp384r1

This commit is contained in:
Klas Lindfors
2015-05-27 21:01:58 +02:00
parent 67543021cb
commit f17d09f19c
5 changed files with 56 additions and 23 deletions
+15 -10
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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"
+2
View File
@@ -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
View File
@@ -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 {