diff options
-rw-r--r-- | src/charon/plugins/stroke/stroke_list.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/credentials/certificates/pgp_certificate.h | 7 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pgp/pgp_cert.c | 57 |
3 files changed, 65 insertions, 3 deletions
diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c index 3fbabd274..6b97735ec 100644 --- a/src/charon/plugins/stroke/stroke_list.c +++ b/src/charon/plugins/stroke/stroke_list.c @@ -22,6 +22,7 @@ #include <credentials/certificates/x509.h> #include <credentials/certificates/ac.h> #include <credentials/certificates/crl.h> +#include <credentials/certificates/pgp_certificate.h> #include <credentials/ietf_attributes/ietf_attributes.h> #include <config/peer_cfg.h> @@ -654,6 +655,8 @@ static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out) { time_t created, until; public_key_t *public; + pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert; + chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert); if (first) { @@ -665,6 +668,7 @@ static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out) fprintf(out, "\n"); fprintf(out, " userid: %Y\n", cert->get_subject(cert)); + fprintf(out, " digest: %#B\n", &fingerprint); /* list validity */ cert->get_validity(cert, &now, &created, &until); fprintf(out, " created: %T\n", &created, utc); diff --git a/src/libstrongswan/credentials/certificates/pgp_certificate.h b/src/libstrongswan/credentials/certificates/pgp_certificate.h index 02807a860..94a31e14d 100644 --- a/src/libstrongswan/credentials/certificates/pgp_certificate.h +++ b/src/libstrongswan/credentials/certificates/pgp_certificate.h @@ -34,6 +34,13 @@ struct pgp_certificate_t { * Implements certificate_t. */ certificate_t interface; + + /** + * Get the v3 or v4 fingerprint of the PGP public key + * + * @return fingerprint as chunk_t, internal data + */ + chunk_t (*get_fingerprint)(pgp_certificate_t *this); }; #endif /** PGP_CERTIFICATE_H_ @}*/ diff --git a/src/libstrongswan/plugins/pgp/pgp_cert.c b/src/libstrongswan/plugins/pgp/pgp_cert.c index 4807e1741..6c2bc4a27 100644 --- a/src/libstrongswan/plugins/pgp/pgp_cert.c +++ b/src/libstrongswan/plugins/pgp/pgp_cert.c @@ -58,6 +58,11 @@ struct private_pgp_cert_t { identification_t *user_id; /** + * v3 or v4 fingerprint of the PGP public key + */ + chunk_t fingerprint; + + /** * full PGP encoding */ chunk_t encoding; @@ -138,7 +143,7 @@ static private_pgp_cert_t* get_ref(private_pgp_cert_t *this) } /** - * Implementation of x509_cert_t.get_validity. + * Implementation of certificate_t.get_validity. */ static bool get_validity(private_pgp_cert_t *this, time_t *when, time_t *not_before, time_t *not_after) @@ -233,12 +238,21 @@ static void destroy(private_pgp_cert_t *this) { DESTROY_IF(this->key); DESTROY_IF(this->user_id); + free(this->fingerprint.ptr); free(this->encoding.ptr); free(this); } } /** + * Implementation of pgp_certificate_t.get_fingerprint. + */ +static chunk_t get_fingerprint(private_pgp_cert_t *this) +{ + return this->fingerprint; +} + +/** * See header */ private_pgp_cert_t *create_empty() @@ -258,12 +272,14 @@ private_pgp_cert_t *create_empty() this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals; this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref; this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy; + this->public.interface.get_fingerprint = (chunk_t (*)(pgp_certificate_t*))get_fingerprint; this->key = NULL; this->version = 0; this->created = 0; this->valid = 0; this->user_id = NULL; + this->fingerprint = chunk_empty; this->encoding = chunk_empty; this->ref = 1; @@ -275,6 +291,8 @@ private_pgp_cert_t *create_empty() */ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet) { + chunk_t pubkey_packet = packet; + if (!pgp_read_scalar(&packet, 1, &this->version)) { return FALSE; @@ -301,7 +319,40 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet) DESTROY_IF(this->key); this->key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, BUILD_BLOB_PGP, packet, BUILD_END); - return this->key != NULL; + if (this->key == NULL) + { + return FALSE; + } + + /* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */ + if (this->version == 4) + { + chunk_t pubkey_packet_header = chunk_from_chars( + 0x99, pubkey_packet.len / 256, pubkey_packet.len % 256 + ); + hasher_t *hasher; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1("no SHA-1 hasher available"); + return FALSE; + } + hasher->allocate_hash(hasher, pubkey_packet_header, NULL); + hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint); + hasher->destroy(hasher); + } + else + { + /* V3 fingerprint is computed by public_key_t class */ + if (!this->key->get_fingerprint(this->key, KEY_ID_PGPV3, + &this->fingerprint)) + { + return FALSE; + } + this->fingerprint = chunk_clone(this->fingerprint); + } + return TRUE; } /** @@ -318,7 +369,7 @@ static bool parse_signature(private_pgp_cert_t *this, chunk_t packet) /* we parse only V3 signature packets */ if (version != 3) { - DBG1("skipped V%d PGP signature", version); + DBG1(" skipped V%d PGP signature", version); return TRUE; } if (!pgp_read_scalar(&packet, 1, &len) || len != 5) |