refactor to let request-cert and selfsign-cert use different hashes
namely sha1 and sha512 as well with sha256 as default
This commit is contained in:
+148
-25
@@ -59,11 +59,20 @@ unsigned const char chuid_tmpl[] = {
|
||||
};
|
||||
#define CHUID_GUID_OFFS 28
|
||||
|
||||
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
|
||||
};
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
unsigned const char sha512oid[] = {
|
||||
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x02, 0x03, 0x05, 0x00, 0x04, 0x40
|
||||
};
|
||||
|
||||
#define KEY_LEN 24
|
||||
|
||||
@@ -473,20 +482,25 @@ static bool set_chuid(ykpiv_state *state, int verbose) {
|
||||
}
|
||||
|
||||
static bool request_certificate(ykpiv_state *state, enum enum_key_format key_format,
|
||||
const char *input_file_name, const char *slot, char *subject,
|
||||
const char *input_file_name, const char *slot, char *subject, enum enum_hash hash,
|
||||
const char *output_file_name) {
|
||||
X509_REQ *req = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
FILE *input_file = NULL;
|
||||
FILE *output_file = NULL;
|
||||
EVP_PKEY *public_key = NULL;
|
||||
const EVP_MD *md;
|
||||
bool ret = false;
|
||||
unsigned char digest[DIGEST_LEN + sizeof(sha256oid)];
|
||||
unsigned int digest_len = DIGEST_LEN;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; // maximum..
|
||||
unsigned int digest_len;
|
||||
unsigned int md_len;
|
||||
unsigned char algorithm;
|
||||
int key = 0;
|
||||
unsigned char *signinput;
|
||||
size_t len = 0;
|
||||
size_t oid_len;
|
||||
const unsigned char *oid;
|
||||
int nid;
|
||||
|
||||
sscanf(slot, "%x", &key);
|
||||
|
||||
@@ -511,6 +525,30 @@ 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:
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
md_len = (unsigned int)EVP_MD_block_size(md);
|
||||
digest_len = sizeof(digest) - md_len;
|
||||
|
||||
req = X509_REQ_new();
|
||||
if(!req) {
|
||||
fprintf(stderr, "Failed to allocate request structure.\n");
|
||||
@@ -534,10 +572,10 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
}
|
||||
|
||||
memset(digest, 0, sizeof(digest));
|
||||
memcpy(digest, sha256oid, sizeof(sha256oid));
|
||||
memcpy(digest, oid, oid_len);
|
||||
/* XXX: this should probably use X509_REQ_digest() but that's buggy */
|
||||
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ_INFO), EVP_sha256(), req->req_info,
|
||||
digest + sizeof(sha256oid), &digest_len)) {
|
||||
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ_INFO), md, req->req_info,
|
||||
digest + oid_len, &digest_len)) {
|
||||
fprintf(stderr, "Failed doing digest of request.\n");
|
||||
goto request_out;
|
||||
}
|
||||
@@ -546,18 +584,45 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
signinput = digest;
|
||||
len = sizeof(digest);
|
||||
req->sig_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
|
||||
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:
|
||||
signinput = digest + sizeof(sha256oid);
|
||||
len = DIGEST_LEN;
|
||||
req->sig_alg->algorithm = OBJ_nid2obj(NID_ecdsa_with_SHA256);
|
||||
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];
|
||||
size_t sig_len = sizeof(signature);
|
||||
@@ -595,7 +660,7 @@ request_out:
|
||||
}
|
||||
|
||||
static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_format,
|
||||
const char *input_file_name, const char *slot, char *subject,
|
||||
const char *input_file_name, const char *slot, char *subject, enum enum_hash hash,
|
||||
const char *output_file_name) {
|
||||
FILE *input_file = NULL;
|
||||
FILE *output_file = NULL;
|
||||
@@ -603,12 +668,17 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
EVP_PKEY *public_key = NULL;
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
unsigned char digest[DIGEST_LEN + sizeof(sha256oid)];
|
||||
unsigned int digest_len = DIGEST_LEN;
|
||||
const EVP_MD *md;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)];
|
||||
unsigned int digest_len;
|
||||
unsigned char algorithm;
|
||||
int key = 0;
|
||||
unsigned char *signinput;
|
||||
size_t len = 0;
|
||||
size_t oid_len;
|
||||
const unsigned char *oid;
|
||||
int nid;
|
||||
unsigned int md_len;
|
||||
|
||||
sscanf(slot, "%x", &key);
|
||||
|
||||
@@ -633,6 +703,30 @@ 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:
|
||||
goto selfsign_out;
|
||||
}
|
||||
|
||||
md_len = (unsigned int)EVP_MD_block_size(md);
|
||||
digest_len = sizeof(digest) - md_len;
|
||||
|
||||
x509 = X509_new();
|
||||
if(!x509) {
|
||||
fprintf(stderr, "Failed to allocate certificate structure.\n");
|
||||
@@ -675,24 +769,51 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
case YKPIV_ALGO_RSA1024:
|
||||
case YKPIV_ALGO_RSA2048:
|
||||
signinput = digest;
|
||||
len = sizeof(digest);
|
||||
x509->sig_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
|
||||
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:
|
||||
signinput = digest + sizeof(sha256oid);
|
||||
len = DIGEST_LEN;
|
||||
x509->sig_alg->algorithm = OBJ_nid2obj(NID_ecdsa_with_SHA256);
|
||||
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;
|
||||
memset(digest, 0, sizeof(digest));
|
||||
memcpy(digest, sha256oid, sizeof(sha256oid));
|
||||
memcpy(digest, oid, oid_len);
|
||||
/* XXX: this should probably use X509_digest() but that looks buggy */
|
||||
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), EVP_sha256(), x509->cert_info,
|
||||
digest + sizeof(sha256oid), &digest_len)) {
|
||||
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), md, x509->cert_info,
|
||||
digest + oid_len, &digest_len)) {
|
||||
fprintf(stderr, "Failed doing digest of certificate.\n");
|
||||
goto selfsign_out;
|
||||
}
|
||||
@@ -1118,7 +1239,8 @@ int main(int argc, char *argv[]) {
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
if(request_certificate(state, args_info.key_format_arg, args_info.input_arg,
|
||||
args_info.slot_orig, args_info.subject_arg, args_info.output_arg) == false) {
|
||||
args_info.slot_orig, args_info.subject_arg, args_info.hash_arg,
|
||||
args_info.output_arg) == false) {
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -1165,7 +1287,8 @@ int main(int argc, char *argv[]) {
|
||||
ret = EXIT_FAILURE;
|
||||
} else {
|
||||
if(selfsign_certificate(state, args_info.key_format_arg, args_info.input_arg,
|
||||
args_info.slot_orig, args_info.subject_arg, args_info.output_arg) == false) {
|
||||
args_info.slot_orig, args_info.subject_arg, args_info.hash_arg,
|
||||
args_info.output_arg) == false) {
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user