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
|
#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[] = {
|
unsigned const char sha256oid[] = {
|
||||||
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||||
0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
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
|
#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,
|
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) {
|
const char *output_file_name) {
|
||||||
X509_REQ *req = NULL;
|
X509_REQ *req = NULL;
|
||||||
X509_NAME *name = NULL;
|
X509_NAME *name = NULL;
|
||||||
FILE *input_file = NULL;
|
FILE *input_file = NULL;
|
||||||
FILE *output_file = NULL;
|
FILE *output_file = NULL;
|
||||||
EVP_PKEY *public_key = NULL;
|
EVP_PKEY *public_key = NULL;
|
||||||
|
const EVP_MD *md;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
unsigned char digest[DIGEST_LEN + sizeof(sha256oid)];
|
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; // maximum..
|
||||||
unsigned int digest_len = DIGEST_LEN;
|
unsigned int digest_len;
|
||||||
|
unsigned int md_len;
|
||||||
unsigned char algorithm;
|
unsigned char algorithm;
|
||||||
int key = 0;
|
int key = 0;
|
||||||
unsigned char *signinput;
|
unsigned char *signinput;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
size_t oid_len;
|
||||||
|
const unsigned char *oid;
|
||||||
|
int nid;
|
||||||
|
|
||||||
sscanf(slot, "%x", &key);
|
sscanf(slot, "%x", &key);
|
||||||
|
|
||||||
@@ -511,6 +525,30 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
|||||||
goto request_out;
|
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();
|
req = X509_REQ_new();
|
||||||
if(!req) {
|
if(!req) {
|
||||||
fprintf(stderr, "Failed to allocate request structure.\n");
|
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));
|
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 */
|
/* 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,
|
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ_INFO), md, req->req_info,
|
||||||
digest + sizeof(sha256oid), &digest_len)) {
|
digest + oid_len, &digest_len)) {
|
||||||
fprintf(stderr, "Failed doing digest of request.\n");
|
fprintf(stderr, "Failed doing digest of request.\n");
|
||||||
goto request_out;
|
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_RSA1024:
|
||||||
case YKPIV_ALGO_RSA2048:
|
case YKPIV_ALGO_RSA2048:
|
||||||
signinput = digest;
|
signinput = digest;
|
||||||
len = sizeof(digest);
|
len = oid_len + digest_len;
|
||||||
req->sig_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
|
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;
|
break;
|
||||||
case YKPIV_ALGO_ECCP256:
|
case YKPIV_ALGO_ECCP256:
|
||||||
signinput = digest + sizeof(sha256oid);
|
signinput = digest + oid_len;
|
||||||
len = DIGEST_LEN;
|
len = digest_len;
|
||||||
req->sig_alg->algorithm = OBJ_nid2obj(NID_ecdsa_with_SHA256);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||||
goto request_out;
|
goto request_out;
|
||||||
}
|
}
|
||||||
|
req->sig_alg->algorithm = OBJ_nid2obj(nid);
|
||||||
{
|
{
|
||||||
unsigned char signature[1024];
|
unsigned char signature[1024];
|
||||||
size_t sig_len = sizeof(signature);
|
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,
|
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) {
|
const char *output_file_name) {
|
||||||
FILE *input_file = NULL;
|
FILE *input_file = NULL;
|
||||||
FILE *output_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;
|
EVP_PKEY *public_key = NULL;
|
||||||
X509 *x509 = NULL;
|
X509 *x509 = NULL;
|
||||||
X509_NAME *name = NULL;
|
X509_NAME *name = NULL;
|
||||||
unsigned char digest[DIGEST_LEN + sizeof(sha256oid)];
|
const EVP_MD *md;
|
||||||
unsigned int digest_len = DIGEST_LEN;
|
unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)];
|
||||||
|
unsigned int digest_len;
|
||||||
unsigned char algorithm;
|
unsigned char algorithm;
|
||||||
int key = 0;
|
int key = 0;
|
||||||
unsigned char *signinput;
|
unsigned char *signinput;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
size_t oid_len;
|
||||||
|
const unsigned char *oid;
|
||||||
|
int nid;
|
||||||
|
unsigned int md_len;
|
||||||
|
|
||||||
sscanf(slot, "%x", &key);
|
sscanf(slot, "%x", &key);
|
||||||
|
|
||||||
@@ -633,6 +703,30 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
|||||||
goto selfsign_out;
|
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();
|
x509 = X509_new();
|
||||||
if(!x509) {
|
if(!x509) {
|
||||||
fprintf(stderr, "Failed to allocate certificate structure.\n");
|
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_RSA1024:
|
||||||
case YKPIV_ALGO_RSA2048:
|
case YKPIV_ALGO_RSA2048:
|
||||||
signinput = digest;
|
signinput = digest;
|
||||||
len = sizeof(digest);
|
len = oid_len + md_len;
|
||||||
x509->sig_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
|
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;
|
break;
|
||||||
case YKPIV_ALGO_ECCP256:
|
case YKPIV_ALGO_ECCP256:
|
||||||
signinput = digest + sizeof(sha256oid);
|
signinput = digest + oid_len;
|
||||||
len = DIGEST_LEN;
|
len = md_len;
|
||||||
x509->sig_alg->algorithm = OBJ_nid2obj(NID_ecdsa_with_SHA256);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
fprintf(stderr, "Unsupported algorithm %x.\n", algorithm);
|
||||||
goto selfsign_out;
|
goto selfsign_out;
|
||||||
}
|
}
|
||||||
|
x509->sig_alg->algorithm = OBJ_nid2obj(nid);
|
||||||
x509->cert_info->signature->algorithm = x509->sig_alg->algorithm;
|
x509->cert_info->signature->algorithm = x509->sig_alg->algorithm;
|
||||||
memset(digest, 0, sizeof(digest));
|
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 */
|
/* 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,
|
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), md, x509->cert_info,
|
||||||
digest + sizeof(sha256oid), &digest_len)) {
|
digest + oid_len, &digest_len)) {
|
||||||
fprintf(stderr, "Failed doing digest of certificate.\n");
|
fprintf(stderr, "Failed doing digest of certificate.\n");
|
||||||
goto selfsign_out;
|
goto selfsign_out;
|
||||||
}
|
}
|
||||||
@@ -1118,7 +1239,8 @@ int main(int argc, char *argv[]) {
|
|||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
if(request_certificate(state, args_info.key_format_arg, args_info.input_arg,
|
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;
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1165,7 +1287,8 @@ int main(int argc, char *argv[]) {
|
|||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
if(selfsign_certificate(state, args_info.key_format_arg, args_info.input_arg,
|
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;
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user