diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/credentials/keys/key_encoding.h | 4 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_util.c | 80 | ||||
-rw-r--r-- | src/pki/pki.c | 34 |
3 files changed, 81 insertions, 37 deletions
diff --git a/src/libstrongswan/credentials/keys/key_encoding.h b/src/libstrongswan/credentials/keys/key_encoding.h index 27a120e89..a338f07ad 100644 --- a/src/libstrongswan/credentials/keys/key_encoding.h +++ b/src/libstrongswan/credentials/keys/key_encoding.h @@ -72,9 +72,11 @@ enum key_encoding_type_t { /** PGPv4 fingerprint */ KEY_ID_PGPV4, - /** PKCS#1/ASN.1 key encoding */ + /** PKCS#1 and similar ASN.1 key encoding */ KEY_PUB_ASN1_DER, KEY_PRIV_ASN1_DER, + /** subjectPublicKeyInfo encoding */ + KEY_PUB_SPKI_ASN1_DER, /** PEM oncoded PKCS#1 key */ KEY_PUB_PEM, KEY_PRIV_PEM, diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index 67b732736..60b4e74e0 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -125,9 +125,39 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b) } /** + * wrap publicKey in subjectPublicKeyInfo + */ +static chunk_t build_info(chunk_t key) +{ + X509_PUBKEY *pubkey; + chunk_t enc; + u_char *p; + + pubkey = X509_PUBKEY_new(); + ASN1_OBJECT_free(pubkey->algor->algorithm); + pubkey->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption); + + if (pubkey->algor->parameter == NULL || + pubkey->algor->parameter->type != V_ASN1_NULL) + { + ASN1_TYPE_free(pubkey->algor->parameter); + pubkey->algor->parameter = ASN1_TYPE_new(); + pubkey->algor->parameter->type = V_ASN1_NULL; + } + M_ASN1_BIT_STRING_set(pubkey->public_key, key.ptr, key.len); + + enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL)); + p = enc.ptr; + i2d_X509_PUBKEY(pubkey, &p); + X509_PUBKEY_free(pubkey); + + return enc; +} + +/** * Build fingerprints of a private/public RSA key. */ -static bool build_fingerprint(chunk_t key, key_encoding_type_t type, int nid, +static bool build_fingerprint(chunk_t key, key_encoding_type_t type, chunk_t *fingerprint) { hasher_t *hasher; @@ -140,29 +170,9 @@ static bool build_fingerprint(chunk_t key, key_encoding_type_t type, int nid, } if (type == KEY_ID_PUBKEY_INFO_SHA1) { - X509_PUBKEY *pubkey; chunk_t enc; - u_char *p; - - /* wrap publicKey in subjectPublicKeyInfo */ - pubkey = X509_PUBKEY_new(); - ASN1_OBJECT_free(pubkey->algor->algorithm); - pubkey->algor->algorithm = OBJ_nid2obj(nid); - - if (pubkey->algor->parameter == NULL || - pubkey->algor->parameter->type != V_ASN1_NULL) - { - ASN1_TYPE_free(pubkey->algor->parameter); - pubkey->algor->parameter = ASN1_TYPE_new(); - pubkey->algor->parameter->type = V_ASN1_NULL; - } - M_ASN1_BIT_STRING_set(pubkey->public_key, enc.ptr, enc.len); - - enc = chunk_alloc(i2d_X509_PUBKEY(pubkey, NULL)); - p = enc.ptr; - i2d_X509_PUBKEY(pubkey, &p); - X509_PUBKEY_free(pubkey); + enc = build_info(key); hasher->allocate_hash(hasher, enc, fingerprint); chunk_free(&enc); } @@ -184,11 +194,27 @@ bool openssl_encode(key_encoding_type_t type, chunk_t *encoding, va_list args) switch (type) { case KEY_PUB_ASN1_DER: + /* this encoding is currently not supported for ECDSA keys */ + if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, + KEY_PART_END)) + { + *encoding = chunk_clone(key); + return TRUE; + } + return FALSE; + case KEY_PUB_SPKI_ASN1_DER: + /* key encoding, wrapped in a subjectPublicKeyInfo field */ if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, - KEY_PART_END) || - key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER, &key, KEY_PART_END)) { + *encoding = build_info(key); + return TRUE; + } + else if (key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER, &key, + KEY_PART_END)) + { + /* ECDSA keys are already wrapped in the publickeyInfo field, + * they are incomplete without */ *encoding = chunk_clone(key); return TRUE; } @@ -208,13 +234,13 @@ bool openssl_encode(key_encoding_type_t type, chunk_t *encoding, va_list args) if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER, &key, KEY_PART_END)) { - return build_fingerprint(key, type, NID_rsaEncryption, encoding); + return build_fingerprint(key, type, encoding); } else if (key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER, &key, KEY_PART_END)) { - return build_fingerprint(key, type, NID_X9_62_id_ecPublicKey, - encoding); + /* for ECDSA the two keyids are currently the same */ + return build_fingerprint(key, KEY_ID_PUBKEY_SHA1, encoding); } return FALSE; default: diff --git a/src/pki/pki.c b/src/pki/pki.c index 962835159..1d1509405 100644 --- a/src/pki/pki.c +++ b/src/pki/pki.c @@ -43,7 +43,7 @@ static int usage(char *error) fprintf(out, " show this usage information\n"); fprintf(out, " pki --gen [--type rsa|ecdsa] [--size bits] [--form der|pem|pgp]\n"); fprintf(out, " generate a new private key\n"); - fprintf(out, " pki --pub [--type rsa|ecdsa|x509] [--form der|pem|pgp]\n"); + fprintf(out, " pki --pub [--in file] [--type rsa|ecdsa|x509] [--form der|pem|pgp]\n"); fprintf(out, " extract the public key from a private key/certificate\n"); return !!error; } @@ -55,7 +55,8 @@ static bool get_form(char *form, key_encoding_type_t *type, bool pub) { if (streq(form, "der")) { - *type = pub ? KEY_PUB_ASN1_DER : KEY_PRIV_ASN1_DER; + /* der encoded keys usually contain the complete SubjectPublicKeyInfo */ + *type = pub ? KEY_PUB_SPKI_ASN1_DER : KEY_PRIV_ASN1_DER; } else if (streq(form, "pem")) { @@ -171,17 +172,20 @@ static int gen(int argc, char *argv[]) */ static int pub(int argc, char *argv[]) { - key_encoding_type_t form = KEY_PUB_ASN1_DER; + key_encoding_type_t form = KEY_PUB_SPKI_ASN1_DER; credential_type_t type = CRED_PRIVATE_KEY; int subtype = KEY_RSA; certificate_t *cert; private_key_t *private; public_key_t *public; chunk_t encoding; + char *file = NULL; + void *cred; struct option long_opts[] = { { "type", required_argument, NULL, 't' }, { "form", required_argument, NULL, 'f' }, + { "in", required_argument, NULL, 'i' }, { 0,0,0,0 } }; while (TRUE) @@ -215,6 +219,9 @@ static int pub(int argc, char *argv[]) return usage("invalid output format"); } continue; + case 'i': + file = optarg; + continue; case EOF: break; default: @@ -222,13 +229,23 @@ static int pub(int argc, char *argv[]) } break; } - if (type == CRED_PRIVATE_KEY) + if (file) + { + cred = lib->creds->create(lib->creds, type, subtype, + BUILD_FROM_FILE, file, BUILD_END); + } + else { - private = lib->creds->create(lib->creds, type, subtype, + cred = lib->creds->create(lib->creds, type, subtype, BUILD_FROM_FD, 0, BUILD_END); + } + + if (type == CRED_PRIVATE_KEY) + { + private = cred; if (!private) { - fprintf(stderr, "parsing private key failed"); + fprintf(stderr, "parsing private key failed\n"); return 1; } public = private->get_public_key(private); @@ -236,11 +253,10 @@ static int pub(int argc, char *argv[]) } else { - cert = lib->creds->create(lib->creds, type, subtype, - BUILD_FROM_FD, 0, BUILD_END); + cert = cred; if (!cert) { - fprintf(stderr, "parsing certificate failed"); + fprintf(stderr, "parsing certificate failed\n"); return 1; } public = cert->get_public_key(cert); |