From efab731338faf89a5ef2548618e02f93ac0853dd Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 19 Jul 2010 17:36:17 +0200 Subject: [PATCH] Added PKCS#11 private key support to the pki tool --- src/pki/commands/issue.c | 34 +++++++++++++++++++++++++--------- src/pki/commands/pub.c | 18 ++++++++++++++++-- src/pki/commands/self.c | 19 ++++++++++++++++--- src/pki/commands/signcrl.c | 32 ++++++++++++++++++++++++-------- 4 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index 2002cd5556..8ea852e31b 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -35,7 +35,7 @@ static int issue() public_key_t *public = NULL; bool pkcs10 = FALSE; char *file = NULL, *dn = NULL, *hex = NULL, *cacert = NULL, *cakey = NULL; - char *error = NULL; + char *error = NULL, *keyid = NULL; identification_t *id = NULL; linked_list_t *san, *cdps, *ocsp; int lifetime = 1095; @@ -85,6 +85,9 @@ static int issue() case 'k': cakey = arg; continue; + case 'x': + keyid = arg; + continue; case 'd': dn = arg; continue; @@ -153,9 +156,9 @@ static int issue() error = "--cacert is required"; goto usage; } - if (!cakey) + if (!cakey && !keyid) { - error = "--cakey is required"; + error = "--cakey or --keyid is required"; goto usage; } if (dn) @@ -190,12 +193,24 @@ static int issue() } DBG2(DBG_LIB, "Reading ca private key:"); - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - public->get_type(public), - BUILD_FROM_FILE, cakey, BUILD_END); + if (cakey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, cakey, BUILD_END); + } + else + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } if (!private) { - error = "parsing CA private key failed"; + error = "loading CA private key failed"; goto end; } if (!private->belongs_to(private, public)) @@ -354,8 +369,8 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { issue, 'i', "issue", "issue a certificate using a CA certificate and key", - {"[--in file] [--type pub|pkcs10]", - " --cacert file --cakey file --dn subject-dn [--san subjectAltName]+", + {"[--in file] [--type pub|pkcs10] --cakey file | --cakeyid hex", + " --cacert file --dn subject-dn [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--crl uri]+ [--ocsp uri]+", "[--ca] [--pathlen len] [--flag serverAuth|clientAuth|ocspSigning]+", "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, @@ -365,6 +380,7 @@ static void __attribute__ ((constructor))reg() {"type", 't', 1, "type of input, default: pub"}, {"cacert", 'c', 1, "CA certificate file"}, {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, {"dn", 'd', 1, "distinguished name to include as subject"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, {"lifetime",'l', 1, "days the certificate is valid, default: 1095"}, diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c index fc2614c7df..30078a8fab 100644 --- a/src/pki/commands/pub.c +++ b/src/pki/commands/pub.c @@ -30,7 +30,7 @@ static int pub() private_key_t *private; public_key_t *public; chunk_t encoding; - char *file = NULL; + char *file = NULL, *keyid = NULL; void *cred; char *arg; @@ -75,6 +75,9 @@ static int pub() case 'i': file = arg; continue; + case 'x': + keyid = arg; + continue; case EOF: break; default: @@ -87,6 +90,15 @@ static int pub() cred = lib->creds->create(lib->creds, type, subtype, BUILD_FROM_FILE, file, BUILD_END); } + else if (keyid) + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } else { cred = lib->creds->create(lib->creds, type, subtype, @@ -145,10 +157,12 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { pub, 'p', "pub", "extract the public key from a private key/certificate", - {"[--in file] [--type rsa|ecdsa|pkcs10|x509] [--outform der|pem|pgp]"}, + {"[--in file|--keyid hex] [--type rsa|ecdsa|pkcs10|x509]", + "[--outform der|pem|pgp]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, + {"keyid", 'x', 1, "keyid on smartcard of private key"}, {"type", 't', 1, "type of credential, default: rsa"}, {"outform", 'f', 1, "encoding of extracted public key"}, } diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index 71776c745f..5e6f0bd149 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -32,7 +32,7 @@ static int self() certificate_t *cert = NULL; private_key_t *private = NULL; public_key_t *public = NULL; - char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL; + char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL, *keyid = NULL; identification_t *id = NULL; linked_list_t *san, *ocsp; int lifetime = 1095; @@ -78,6 +78,9 @@ static int self() case 'i': file = arg; continue; + case 'x': + keyid = arg; + continue; case 'd': dn = arg; continue; @@ -149,6 +152,15 @@ static int self() private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_FROM_FILE, file, BUILD_END); } + else if (keyid) + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } else { private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, @@ -156,7 +168,7 @@ static int self() } if (!private) { - error = "parsing private key failed"; + error = "loading private key failed"; goto end; } public = private->get_public_key(private); @@ -242,7 +254,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { self, 's', "self", "create a self signed certificate", - {"[--in file] [--type rsa|ecdsa]", + {"[--in file | --keyid hex] [--type rsa|ecdsa]", " --dn distinguished-name [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--ca] [--ocsp uri]+", "[--flag serverAuth|clientAuth|ocspSigning]+", @@ -250,6 +262,7 @@ static void __attribute__ ((constructor))reg() { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "private key input file, default: stdin"}, + {"keyid", 'x', 1, "keyid on smartcard of private key"}, {"type", 't', 1, "type of input key, default: rsa"}, {"dn", 'd', 1, "subject and issuer distinguished name"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index b7163a153d..24bf9123fd 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -110,7 +110,7 @@ static int sign_crl() x509_t *x509; hash_algorithm_t digest = HASH_SHA1; char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL; - char serial[512], crl_serial[8]; + char serial[512], crl_serial[8], *keyid = NULL; int serial_len = 0; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); @@ -143,6 +143,9 @@ static int sign_crl() case 'k': cakey = arg; continue; + case 'x': + keyid = arg; + continue; case 'a': lastupdate = arg; continue; @@ -245,9 +248,9 @@ static int sign_crl() error = "--cacert is required"; goto usage; } - if (!cakey) + if (!cakey && !keyid) { - error = "--cakey is required"; + error = "--cakey or --keyid is required"; goto usage; } @@ -270,12 +273,24 @@ static int sign_crl() error = "extracting CA certificate public key failed"; goto error; } - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - public->get_type(public), - BUILD_FROM_FILE, cakey, BUILD_END); + if (cakey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, cakey, BUILD_END); + } + else + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } if (!private) { - error = "parsing CA private key failed"; + error = "loading CA private key failed"; goto error; } if (!private->belongs_to(private, public)) @@ -359,7 +374,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { sign_crl, 'c', "signcrl", "issue a CRL using a CA certificate and key", - {"--cacert file --cakey file --lifetime days", + {"--cacert file --cakey file | --cakeyid hex --lifetime days", "[ [--reason key-compromise|ca-compromise|affiliation-changed|", " superseded|cessation-of-operation|certificate-hold]", " [--date timestamp]", @@ -369,6 +384,7 @@ static void __attribute__ ((constructor))reg() {"help", 'h', 0, "show usage information"}, {"cacert", 'c', 1, "CA certificate file"}, {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, {"lifetime",'l', 1, "days the CRL gets a nextUpdate, default: 15"}, {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, {"cert", 'z', 1, "certificate file to revoke"}, -- 2.47.2