list v3 or v4 fingerprint
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 8 Nov 2009 22:21:03 +0000 (23:21 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 8 Nov 2009 22:21:03 +0000 (23:21 +0100)
src/charon/plugins/stroke/stroke_list.c
src/libstrongswan/credentials/certificates/pgp_certificate.h
src/libstrongswan/plugins/pgp/pgp_cert.c

index 3fbabd2..6b97735 100644 (file)
@@ -22,6 +22,7 @@
 #include <credentials/certificates/x509.h>
 #include <credentials/certificates/ac.h>
 #include <credentials/certificates/crl.h>
 #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>
 
 #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;
        {
                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)
                {
 
                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, "\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);
                /* list validity */
                cert->get_validity(cert, &now, &created, &until);
                fprintf(out, "  created:   %T\n", &created, utc);
index 02807a8..94a31e1 100644 (file)
@@ -34,6 +34,13 @@ struct pgp_certificate_t {
         * Implements certificate_t.
         */
        certificate_t interface;
         * 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_ @}*/
 };
 
 #endif /** PGP_CERTIFICATE_H_ @}*/
index 4807e17..6c2bc4a 100644 (file)
@@ -58,6 +58,11 @@ struct private_pgp_cert_t {
        identification_t *user_id;
 
        /**
        identification_t *user_id;
 
        /**
+        * v3 or v4 fingerprint of the PGP public key
+        */
+       chunk_t fingerprint;
+
+       /**
         * full PGP encoding
         */
        chunk_t encoding;
         * 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)
  */
 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);
        {
                DESTROY_IF(this->key);
                DESTROY_IF(this->user_id);
+               free(this->fingerprint.ptr);
                free(this->encoding.ptr);
                free(this);
        }
 }
 
 /**
                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()
  * 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.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->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;
 
        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)
 {
  */
 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;
        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);
        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)
        {
        /* 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)
                return TRUE;
        }
        if (!pgp_read_scalar(&packet, 1, &len) || len != 5)