add sha384 hash and refactor some common patterns

This commit is contained in:
Klas Lindfors
2015-05-27 21:38:46 +02:00
parent f17d09f19c
commit d06852959c
4 changed files with 155 additions and 207 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ text "
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","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","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"
+105
View File
@@ -239,3 +239,108 @@ bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigne
*out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out);
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;
}
}
+3
View File
@@ -47,5 +47,8 @@ int get_object_id(enum enum_slot slot);
bool set_component_with_len(unsigned char**, const BIGNUM*, int);
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
unsigned int*, 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);
#endif
+32 -192
View File
@@ -62,20 +62,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
@@ -128,21 +115,8 @@ static bool generate_key(ykpiv_state *state, const char *slot,
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_arg_ECCP384:
in_data[4] = YKPIV_ALGO_ECCP384;
break;
case algorithm__NULL:
default:
in_data[4] = get_piv_algorithm(algorithm);
if(in_data[4] == 0) {
fprintf(stderr, "Unexepcted algorithm.\n");
goto generate_out;
}
@@ -574,7 +548,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;
@@ -612,24 +586,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;
}
@@ -666,49 +624,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(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
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:
case YKPIV_ALGO_ECCP384:
} 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];
@@ -759,7 +687,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;
@@ -797,27 +725,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;
@@ -859,49 +770,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(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
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:
case YKPIV_ALGO_ECCP384:
} 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);
@@ -1128,36 +1008,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;
}
@@ -1318,18 +1178,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;
}
@@ -1394,18 +1244,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;
}