fixed OpenPGP parsing
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 6 Jun 2009 11:13:11 +0000 (13:13 +0200)
committerMartin Willi <martin@strongswan.org>
Tue, 9 Jun 2009 09:03:33 +0000 (11:03 +0200)
src/libstrongswan/pgp/pgp.h
src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
src/pluto/certs.c
src/pluto/certs.h
src/pluto/ipsec_doi.c
src/pluto/keys.c
src/pluto/pgpcert.c
src/pluto/pgpcert.h
src/pluto/smartcard.c

index 5c512d8..677c5b1 100644 (file)
@@ -23,6 +23,7 @@
 #define PGP_H_
 
 typedef enum pgp_packet_tag_t pgp_packet_tag_t;
+typedef enum pgp_pubkey_alg_t pgp_pubkey_alg_t;
 typedef enum pgp_sym_alg_t pgp_sym_alg_t;
 
 #include <chunk.h>
index bfe9d3c..bc79beb 100644 (file)
@@ -815,7 +815,6 @@ static gmp_rsa_private_key_t *load_pgp(chunk_t blob)
 {
        mpz_t u;
        int objectID;
-       pgp_sym_alg_t s2k;
        chunk_t packet = blob;
        private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
        
@@ -828,27 +827,33 @@ static gmp_rsa_private_key_t *load_pgp(chunk_t blob)
        mpz_init(this->exp2);
        mpz_init(this->coeff);
 
-       /* string-to-key usage */
-       s2k = pgp_length(&packet, 1);
-       DBG2("L3 - string-to-key:  %d", s2k);
-
-       if (s2k == 255 || s2k == 254)
-       {
-               DBG1("string-to-key specifiers not supported");
-               goto end;
-       }
-       DBG2("  %N", pgp_sym_alg_names, s2k);
-
-       if (s2k != PGP_SYM_ALG_PLAIN)
-       {
-               DBG1("%N encryption not supported",  pgp_sym_alg_names, s2k);
-               goto end;
-       }
-
        for (objectID = PRIV_KEY_MODULUS; objectID <= PRIV_KEY_PRIME2; objectID++)
        {
                chunk_t object; 
 
+               if (objectID == PRIV_KEY_PRIV_EXP)
+               {
+                       pgp_sym_alg_t s2k;
+
+                       /* string-to-key usage */
+                       s2k = pgp_length(&packet, 1);
+                       DBG2("L3 - string-to-key:  %d", s2k);
+
+                       if (s2k == 255 || s2k == 254)
+                       {
+                               DBG1("string-to-key specifiers not supported");
+                               goto end;
+                       }
+                       DBG2("  %N", pgp_sym_alg_names, s2k);
+
+                       if (s2k != PGP_SYM_ALG_PLAIN)
+                       {
+                               DBG1("%N encryption not supported",  pgp_sym_alg_names, s2k);
+                               goto end;
+                       }
+               }
+
+               DBG2("L3 - %s:", privkeyObjects[objectID].name);
                object.len = pgp_length(&packet, 2);
 
                if (object.len == PGP_INVALID_LENGTH)
@@ -865,6 +870,7 @@ static gmp_rsa_private_key_t *load_pgp(chunk_t blob)
                object.ptr = packet.ptr;
                packet.ptr += object.len;
                packet.len -= object.len;
+               DBG4("%B", &object);
 
                switch (objectID)
                {
index 29e7dbf..39ff8df 100644 (file)
 /**
  * used for initializatin of certs
  */
-const cert_t empty_cert = {CERT_NONE, {NULL}};
+const cert_t cert_empty = {CERT_NONE, {NULL}};
 
 /**
  * extracts the certificate to be sent to the peer
  */
-chunk_t get_mycert(cert_t cert)
+chunk_t cert_get_encoding(cert_t cert)
 {
        switch (cert.type)
        {
@@ -51,6 +51,21 @@ chunk_t get_mycert(cert_t cert)
        }
 }
 
+public_key_t* cert_get_public_key(const cert_t cert)
+{
+       switch (cert.type)
+       {
+               case CERT_PGP:
+                       return cert.u.pgp->public_key;
+                       break;
+               case CERT_X509_SIGNATURE:
+                       return cert.u.x509->public_key;
+                       break;
+               default:
+                       return NULL;
+       }
+}
+
 /* load a coded key or certificate file with autodetection
  * of binary DER or base64 PEM ASN.1 formats and armored PGP format
  */
@@ -142,13 +157,13 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
                }
                if (key == NULL)
                {
-                       plog("syntax error in %s private key file", pgp ? "PGP":"PKCS#");
+                       plog("  syntax error in %s private key file", pgp ? "PGP":"PKCS#");
                }                       
                free(blob.ptr);
        }
        else
        {
-               plog("error loading RSA private key file");
+               plog("  error loading RSA private key file");
        }
        return key;
 }
@@ -170,7 +185,7 @@ bool load_cert(char *filename, const char *label, cert_t *cert)
                if (pgp)
                {
                        pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
-                       *pgpcert = empty_pgpcert;
+                       *pgpcert = pgpcert_empty;
                        if (parse_pgp(blob, pgpcert, NULL))
                        {
                                cert->type = CERT_PGP;
index a88fc15..0810c52 100644 (file)
@@ -55,16 +55,17 @@ typedef struct {
 } cert_t;
 
 /* used for initialization */
-extern const cert_t empty_cert;
+extern const cert_t cert_empty;
 
 /*  do not send certificate requests
  *  flag set in plutomain.c and used in ipsec_doi.c
  */
 extern bool no_cr_send;
 
+extern public_key_t* cert_get_public_key(const cert_t cert);
+extern chunk_t cert_get_encoding(cert_t cert);
 extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
                                                                           key_type_t type);
-extern chunk_t get_mycert(cert_t cert);
 extern bool load_coded_file(char *filename, prompt_pass_t *pass,
                                                        const char *type, chunk_t *blob, bool *pgp);
 extern bool load_cert(char *filename, const char *label, cert_t *cert);
index 49f40e3..181040a 100644 (file)
@@ -3415,7 +3415,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
 
                if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
                        return STF_INTERNAL_ERROR;
-               if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT"))
+               if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
                        return STF_INTERNAL_ERROR;
                close_output_pbs(&cert_pbs);
        }
@@ -3825,7 +3825,7 @@ main_inI3_outR3_tail(struct msg_digest *md
 
                if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
                return STF_INTERNAL_ERROR;
-               if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT"))
+               if (!out_chunk(cert_get_encoding(mycert), &cert_pbs, "CERT"))
                        return STF_INTERNAL_ERROR;
                close_output_pbs(&cert_pbs);
        }
index c0eb6ae..4a49681 100644 (file)
@@ -71,34 +71,14 @@ struct secret {
        id_list_t *ids;
        enum PrivateKeyKind kind;
        union {
-               chunk_t preshared_secret;
-               xauth_t xauth_secret;
+               chunk_t        preshared_secret;
+               xauth_t        xauth_secret;
                private_key_t *private_key;
-               smartcard_t *smartcard;
+               smartcard_t   *smartcard;
        } u;
        secret_t *next;
 };
 
-static public_key_t* get_public_key(const cert_t cert)
-{
-       switch (cert.type)
-       {
-               case CERT_PGP:
-               /*
-                       e = cert.u.pgp->publicExponent;
-                       n = cert.u.pgp->modulus;
-                       init_RSA_public_key(&pk->public_key, e, n);
-               */
-                       return NULL;
-                       break;
-               case CERT_X509_SIGNATURE:
-                       return cert.u.x509->public_key;
-                       break;
-               default:
-                       return NULL;
-       }
-}
-
 /*
  * free a public key struct
  */
@@ -121,9 +101,9 @@ static const secret_t* get_secret(const struct connection *c,
                                                                  enum PrivateKeyKind kind, bool asym)
 {
        enum {      /* bits */
-               match_default = 01,
-               match_him 02,
-               match_me 04
+               match_default = 0x01,
+               match_him     = 0x02,
+               match_me      = 0x04
        };
 
        unsigned int best_match = 0;
@@ -136,7 +116,7 @@ static const secret_t* get_secret(const struct connection *c,
        /* is there a certificate assigned to this connection? */
        if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
        {
-               public_key_t *pub_key = get_public_key(c->spd.this.cert);
+               public_key_t *pub_key = cert_get_public_key(c->spd.this.cert);
 
                for (s = secrets; s != NULL; s = s->next)
                {
@@ -190,10 +170,13 @@ static const secret_t* get_secret(const struct connection *c,
                                for (i = s->ids; i != NULL; i = i->next)
                                {
                                        if (same_id(my_id, &i->id))
+                                       {
                                                match |= match_me;
-
+                                       }
                                        if (same_id(his_id, &i->id))
+                                       {
                                                match |= match_him;
+                                       }
                                }
 
                                /* If our end matched the only id in the list,
@@ -214,7 +197,9 @@ static const secret_t* get_secret(const struct connection *c,
                                 * there are other ids in the list.
                                 */
                                if (!asym)
+                               {
                                        break;
+                               }
                                /* FALLTHROUGH */
                        case match_default: /* default all */
                        case match_me | match_default:      /* default peer */
@@ -281,7 +266,7 @@ bool has_private_key(cert_t cert)
 {
        secret_t *s;
        bool has_key = FALSE;
-       public_key_t *pub_key = get_public_key(cert);
+       public_key_t *pub_key = cert_get_public_key(cert);
 
        for (s = secrets; s != NULL; s = s->next)
        {
@@ -396,7 +381,20 @@ static err_t process_psk_secret(chunk_t *psk)
        return ugh;
 }
 
-const char *rsa_private_keywords[] = {
+typedef enum rsa_private_key_part_t rsa_private_key_part_t;
+
+enum rsa_private_key_part_t {
+       RSA_PART_MODULUS          = 0,
+       RSA_PART_PUBLIC_EXPONENT  = 1,
+       RSA_PART_PRIVATE_EXPONENT = 2,
+       RSA_PART_PRIME1           = 3,
+       RSA_PART_PRIME2           = 4,
+       RSA_PART_EXPONENT1        = 5,
+       RSA_PART_EXPONENT2        = 6,
+       RSA_PART_COEFFICIENT      = 7
+}; 
+
+const char *rsa_private_key_part_names[] = {
        "Modulus",
        "PublicExponent",
        "PrivateExponent",
@@ -414,17 +412,17 @@ const char *rsa_private_keywords[] = {
  */
 static err_t process_rsa_secret(private_key_t **key)
 {
-       chunk_t asn1_chunks[countof(rsa_private_keywords)];
+       chunk_t asn1_chunk[countof(rsa_private_key_part_names)];
        chunk_t pkcs1_chunk;
        u_char buf[RSA_MAX_ENCODING_BYTES];   /* limit on size of binary representation of key */
-       err_t ugh;
-       int i, j;
+       rsa_private_key_part_t part, p;
        size_t sz, len = 0;
+       err_t ugh;
 
-       for (i = 0; i < countof(rsa_private_keywords); i++)
+       for (part = RSA_PART_MODULUS; part <= RSA_PART_COEFFICIENT; part++)
        {
-               chunk_t rsa_private_key_chunk;
-               const char *keyword = rsa_private_keywords[i];
+               chunk_t rsa_private_key_part;
+               const char *keyword = rsa_private_key_part_names[part];
 
                if (!shift())
                {
@@ -447,12 +445,12 @@ static err_t process_rsa_secret(private_key_t **key)
                if (ugh)
                {
                        ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
-                       i++;
+                       part++;
                        goto end;
                }
-               rsa_private_key_chunk = chunk_create(buf, sz);
-               asn1_chunks[i] = asn1_integer("c", rsa_private_key_chunk);
-               len += asn1_chunks[i].len;
+               rsa_private_key_part = chunk_create(buf, sz);
+               asn1_chunk[part] = asn1_integer("c", rsa_private_key_part);
+               len += asn1_chunk[part].len;
        }
 
        /* We require an (indented) '}' and the end of the record.
@@ -472,14 +470,14 @@ static err_t process_rsa_secret(private_key_t **key)
 
        pkcs1_chunk = asn1_wrap(ASN1_SEQUENCE, "ccccccccc",
                                                        ASN1_INTEGER_0,
-                                                       asn1_chunks[0],
-                                                       asn1_chunks[1],
-                                                       asn1_chunks[2],
-                                                       asn1_chunks[3],
-                                                       asn1_chunks[4],
-                                                       asn1_chunks[5],
-                                                       asn1_chunks[6],
-                                                       asn1_chunks[7]);
+                                                       asn1_chunk[RSA_PART_MODULUS],
+                                                       asn1_chunk[RSA_PART_PUBLIC_EXPONENT],
+                                                       asn1_chunk[RSA_PART_PRIVATE_EXPONENT],
+                                                       asn1_chunk[RSA_PART_PRIME1],
+                                                       asn1_chunk[RSA_PART_PRIME2],
+                                                       asn1_chunk[RSA_PART_EXPONENT1],
+                                                       asn1_chunk[RSA_PART_EXPONENT2],
+                                                       asn1_chunk[RSA_PART_COEFFICIENT]);
 
        *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
                                                                                  BUILD_BLOB_ASN1_DER, pkcs1_chunk,
@@ -491,9 +489,10 @@ static err_t process_rsa_secret(private_key_t **key)
        }
 
 end:
-       for (j = 0 ; j < i; j++)
+       /* clean up and return */
+       for (p = RSA_PART_MODULUS ; p < part; p++)
        {
-               free(asn1_chunks[j].ptr);
+               free(asn1_chunk[p].ptr);
        }
        return ugh;     
 }
@@ -867,8 +866,9 @@ static void process_secret_records(int whackfd)
        {
                (void)flushline(NULL);  /* silently ditch leftovers, if any */
                if (flp->bdry == B_file)
+               {
                        break;
-
+               }
                flp->bdry = B_none;     /* eat the Record Boundary */
                (void)shift();  /* get real first token */
 
@@ -897,7 +897,9 @@ static void process_secret_records(int whackfd)
                                 * will be rediscovered and reported later.
                                 */
                                if (pl > sizeof(fn))
+                               {
                                        pl = sizeof(fn);
+                               }
                                memcpy(fn, flp->filename, pl);
                                p += pl;
                        }
@@ -1138,7 +1140,9 @@ pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
        pubkey_list_t *nxt = p->next;
 
        if (p->key != NULL)
+       {
                unreference_key(&p->key);
+       }
        free(p);
        return nxt;
 }
@@ -1146,7 +1150,9 @@ pubkey_list_t* free_public_keyentry(pubkey_list_t *p)
 void free_public_keys(pubkey_list_t **keys)
 {
        while (*keys != NULL)
+       {
                *keys = free_public_keyentry(*keys);
+       }
 }
 
 /* root of chained public key list */
@@ -1186,7 +1192,9 @@ void transfer_to_public_keys(struct gw_info *gateways_from_dns
                pubkey_list_t **pp = keys;
 
                while (*pp != NULL)
+               {
                        pp = &(*pp)->next;
+               }
                *pp = pubkeys;
                pubkeys = *keys;
                *keys = NULL;
@@ -1255,7 +1263,9 @@ unreference_key(pubkey_t **pkp)
        char b[BUF_LEN];
 
        if (pk == NULL)
+       {
                return;
+       }
 
        /* print stuff */
        DBG(DBG_CONTROLMORE,
@@ -1269,7 +1279,9 @@ unreference_key(pubkey_t **pkp)
        passert(pk->refcnt != 0);
        pk->refcnt--;
        if (pk->refcnt == 0)
+       {
                free_public_key(pk);
+       }
 }
 
 bool add_public_key(const struct id *id, enum dns_auth_level dns_auth_level,
@@ -1369,7 +1381,6 @@ void add_pgp_public_key(pgpcert_t *cert , time_t until,
        pk->public_key = cert->public_key->get_ref(cert->public_key);
        pk->id.kind = ID_KEY_ID;
        pk->id.name = cert->fingerprint->get_encoding(cert->fingerprint);
-       pk->id.name = chunk_clone(pk->id.name);
        pk->dns_auth_level = dns_auth_level;
        pk->until_time = until;
        pk_type = pk->public_key->get_type(pk->public_key);
@@ -1394,8 +1405,7 @@ void remove_x509_public_key(const x509cert_t *cert)
                {
                        /* remove p from list and free memory */
                        *pp = free_public_keyentry(p);
-                       loglog(RC_LOG_SERIOUS,
-                               "invalid RSA public key deleted");
+                       loglog(RC_LOG_SERIOUS, "invalid public key deleted");
                }
                else
                {
index 531a04a..f22aed1 100644 (file)
 #include "whack.h"
 #include "keys.h"
 
-/*
- * chained list of OpenPGP end certificates
+/**
+ * Chained list of OpenPGP end certificates
  */
 static pgpcert_t *pgpcerts   = NULL;
 
-/*
+/**
  * Size of PGP Key ID
  */
 #define PGP_KEYID_SIZE          8
 
-const pgpcert_t empty_pgpcert = {
-         NULL     , /* *next */
+const pgpcert_t pgpcert_empty = {
+         NULL     , /* next */
+            0  , /* version */
                        0  , /* installed */
                        0  , /* count */
        { NULL, 0 }, /* certificate */
@@ -56,8 +57,8 @@ const pgpcert_t empty_pgpcert = {
 };
 
 
-/*
- * extracts the length of a PGP packet
+/**
+ * Extracts the length of a PGP packet
  */
 static size_t pgp_old_packet_length(chunk_t *blob)
 {
@@ -70,8 +71,8 @@ static size_t pgp_old_packet_length(chunk_t *blob)
        return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
 }
 
-/*
- * extracts PGP packet version (V3 or V4)
+/**
+ * Extracts PGP packet version (V3 or V4)
  */
 static u_char pgp_version(chunk_t *blob)
 {
@@ -84,17 +85,60 @@ static u_char pgp_version(chunk_t *blob)
        return version;
 }
 
-/*
- * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 2440
+/**
+ * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
  */
-static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
+static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
 {
+       time_t created;
+       chunk_t keyid;
+       u_char  sig_type;
        u_char version = pgp_version(packet);
-       public_key_t *key;
 
-       if (version < 3 || version > 4)
+       /* we parse only V3 signature packets */
+       if (version != 3)
+       {
+               return TRUE;
+       }
+
+       /* size byte must have the value 5 */
+       if (pgp_length(packet, 1) != 5)
        {
-               plog("PGP packet version V%d not supported", version);
+               plog("  size must be 5");
+               return FALSE;
+       }
+
+       /* signature type - 1 byte */
+       sig_type = (u_char)pgp_length(packet, 1);
+       DBG(DBG_PARSING,
+               DBG_log("L3 - signature type:  0x%2x", sig_type)
+       )
+
+       /* creation date - 4 bytes */
+       created = (time_t)pgp_length(packet, 4);
+       DBG(DBG_PARSING,
+               DBG_log("L3 - created:");
+               DBG_log("  %T", &cert->created, TRUE)
+       )
+
+       /* key ID of signer - 8 bytes */
+       keyid.ptr = packet->ptr;
+       keyid.len = PGP_KEYID_SIZE;
+       DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
+
+   return TRUE;
+}
+
+/**
+ * Parses the version and validity of an OpenPGP public key packet
+ */
+static bool parse_pgp_pubkey_version_validity(chunk_t *packet, pgpcert_t *cert)
+{
+       cert->version = pgp_version(packet);
+
+       if (cert->version < 3 || cert->version > 4)
+       {
+               plog("OpenPGP packet version V%d not supported", cert->version);
                return FALSE;
        }
 
@@ -105,7 +149,7 @@ static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
                DBG_log("  %T", &cert->created, TRUE)
        )
 
-       if (version == 3)
+       if (cert->version == 3)
        {
                /* validity in days - 2 bytes */
                cert->until   = (time_t)pgp_length(packet, 2);
@@ -120,97 +164,96 @@ static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
                        DBG_log("  %T", &cert->until, TRUE);
                )
        }
+       return TRUE;
+}
+
+/**
+ * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 4880
+ */
+static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert)
+{
+       pgp_pubkey_alg_t pubkey_alg;
+       public_key_t *key;
+
+       if (!parse_pgp_pubkey_version_validity(packet, cert))
+       {
+               return FALSE;
+       }
 
        /* public key algorithm - 1 byte */
+       pubkey_alg = pgp_length(packet, 1);
        DBG(DBG_PARSING,
-               DBG_log("L3 - public key algorithm:")
+               DBG_log("L3 - public key algorithm:");
+               DBG_log("  %N", pgp_pubkey_alg_names, pubkey_alg)
        )
-
-       switch (pgp_length(packet, 1))
+       
+       switch (pubkey_alg)
        {
-       case PGP_PUBKEY_ALG_RSA:
-       case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
-               DBG(DBG_PARSING,
-                       DBG_log("  RSA")
-               )
-               key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
-                                                                                        BUILD_BLOB_PGP, *packet,
-                                                                                        BUILD_END);
-               if (key == NULL)
-               {
-                       return FALSE;
-               }
-               cert->public_key = key;
+               case PGP_PUBKEY_ALG_RSA:
+               case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
+                       key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
+                                                                                                BUILD_BLOB_PGP, *packet,
+                                                                                                BUILD_END);
+                       if (key == NULL)
+                       {
+                               return FALSE;
+                       }
+                       cert->public_key = key;
 
-               if (version == 3)
-               {
-                       cert->fingerprint = key->get_id(key, ID_KEY_ID);
-                       if (cert->fingerprint == NULL)
+                       if (cert->version == 3)
                        {
+                               cert->fingerprint = key->get_id(key, ID_KEY_ID);
+                               if (cert->fingerprint == NULL)
+                               {
+                                       return FALSE;
+                               }
+                       }
+                       else
+                       {
+                               plog("  computation of V4 key ID not implemented yet");
                                return FALSE;
                        }
-               }
-               else
-               {
-                       plog("  computation of V4 key ID not implemented yet");
-               }
-               break;
-       case PGP_PUBKEY_ALG_DSA:
-               DBG(DBG_PARSING,
-                       DBG_log("  DSA")
-               )
-               plog("  DSA public keys not supported");
-               return FALSE;
-        default:
-               DBG(DBG_PARSING,
-                       DBG_log("  other")
-               )
-               plog(" exotic not RSA public keys not supported");
-               return FALSE;
+                       break;
+               default:
+                       plog("  non RSA public keys not supported");
+                       return FALSE;
        }
        return TRUE;
 }
 
 /*
- * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
+ * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 4880
  */
-static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert)
+static bool parse_pgp_secretkey_packet(chunk_t *packet, private_key_t **key)
 {
-       time_t created;
-       chunk_t keyid;
-       u_char  sig_type;
-       u_char version = pgp_version(packet);
+       pgp_pubkey_alg_t pubkey_alg;
+       pgpcert_t cert = pgpcert_empty;
 
-       /* we parse only V3 signature packets */
-       if (version != 3)
-               return TRUE;
-
-       /* size byte must have the value 5 */
-       if (pgp_length(packet, 1) != 5)
+       if (!parse_pgp_pubkey_version_validity(packet, &cert))
        {
-               plog(" size must be 5");
                return FALSE;
        }
 
-       /* signature type - 1 byte */
-       sig_type = (u_char)pgp_length(packet, 1);
-       DBG(DBG_PARSING,
-               DBG_log("L3 - signature type:  0x%2x", sig_type)
-       )
-
-       /* creation date - 4 bytes */
-       created = (time_t)pgp_length(packet, 4);
+       /* public key algorithm - 1 byte */
+       pubkey_alg = pgp_length(packet, 1);
        DBG(DBG_PARSING,
-               DBG_log("L3 - created:");
-               DBG_log("  %T", &cert->created, TRUE)
+               DBG_log("L3 - public key algorithm:");
+               DBG_log("  %N", pgp_pubkey_alg_names, pubkey_alg)
        )
-
-       /* key ID of signer - 8 bytes */
-       keyid.ptr = packet->ptr;
-       keyid.len = PGP_KEYID_SIZE;
-       DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid);
-
-   return TRUE;
+       
+       switch (pubkey_alg)
+       {
+               case PGP_PUBKEY_ALG_RSA:
+               case PGP_PUBKEY_ALG_RSA_SIGN_ONLY:
+                       *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+                                                                                                 BUILD_BLOB_PGP, *packet,
+                                                                                                 BUILD_END);
+                       break;
+               default:
+                       plog("  non RSA private keys not supported");
+                       return FALSE;
+       }
+       return (*key != NULL);
 }
 
 bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
@@ -275,26 +318,26 @@ bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
                                /* parse a PGP certificate */
                                switch (packet_type)
                                {
-                               case PGP_PKT_PUBLIC_KEY:
-                                       if (!parse_pgp_pubkey_packet(&packet, cert))
-                                       {
-                                               return FALSE;
-                                       }
-                                       break;
-                               case PGP_PKT_SIGNATURE:
-                                       if (!parse_pgp_signature_packet(&packet, cert))
-                                       {
-                                               return FALSE;
-                                       }
-                                       break;
-                               case PGP_PKT_USER_ID:
-                                       DBG(DBG_PARSING,
-                                               DBG_log("L3 - user ID:");
-                                               DBG_log("  '%.*s'", (int)packet.len, packet.ptr)
-                                       )
-                                       break;
-                               default:
-                                       break;
+                                       case PGP_PKT_PUBLIC_KEY:
+                                               if (!parse_pgp_pubkey_packet(&packet, cert))
+                                               {
+                                                       return FALSE;
+                                               }
+                                               break;
+                                       case PGP_PKT_SIGNATURE:
+                                               if (!parse_pgp_signature_packet(&packet, cert))
+                                               {
+                                                       return FALSE;
+                                               }
+                                               break;
+                                       case PGP_PKT_USER_ID:
+                                               DBG(DBG_PARSING,
+                                                       DBG_log("L3 - user ID:");
+                                                       DBG_log("  '%.*s'", (int)packet.len, packet.ptr)
+                                               )
+                                               break;
+                                       default:
+                                               break;
                                }
                        }
                        else
@@ -302,17 +345,20 @@ bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
                                /* parse a PGP private key file */
                                switch (packet_type)
                                {
-                               case PGP_PKT_SECRET_KEY:
-                                       *key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
-                                                                                         BUILD_BLOB_PGP, packet,
-                                                                                         BUILD_END);
-                                       break;
-                               default:
-                                       break;
-                               }
-                               if (*key == NULL)
-                               {
-                                       return FALSE;
+                                       case PGP_PKT_SECRET_KEY:
+                                               if (!parse_pgp_secretkey_packet(&packet, key))
+                                               {
+                                                       return FALSE;
+                                               }
+                                               break;
+                                       case PGP_PKT_USER_ID:
+                                               DBG(DBG_PARSING,
+                                                       DBG_log("L3 - user ID:");
+                                                       DBG_log("  '%.*s'", (int)packet.len, packet.ptr)
+                                               )
+                                               break;
+                                       default:
+                                               break;
                                }
 
                        }
@@ -321,8 +367,8 @@ bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key)
        return TRUE;
 }
 
-/*
- *  compare two OpenPGP certificates
+/**
+ *  Compare two OpenPGP certificates
  */
 static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
 {
@@ -330,8 +376,8 @@ static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
                memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
 }
 
-/*
- * for each link pointing to the certificate increase the count by one
+/**
+ * For each link pointing to the certificate increase the count by one
  */
 void share_pgpcert(pgpcert_t *cert)
 {
@@ -341,18 +387,17 @@ void share_pgpcert(pgpcert_t *cert)
        }
 }
 
-/*
- * select the OpenPGP keyid as ID
+/**
+ * Select the OpenPGP keyid as ID
  */
 void select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
 {
        end_id->kind = ID_KEY_ID;
        end_id->name = cert->fingerprint->get_encoding(cert->fingerprint);
-       end_id->name = chunk_clone(end_id->name);
 }
 
-/*
- *  add an OpenPGP user/host certificate to the chained list
+/**
+ *  Add an OpenPGP user/host certificate to the chained list
  */
 pgpcert_t* add_pgpcert(pgpcert_t *cert)
 {
@@ -377,8 +422,9 @@ pgpcert_t* add_pgpcert(pgpcert_t *cert)
        return cert;
 }
 
-/*  release of a certificate decreases the count by one
- "  the certificate is freed when the counter reaches zero
+/**
+ *  Release of a certificate decreases the count by one.
+ *  The certificate is freed when the counter reaches zero
  */
 void release_pgpcert(pgpcert_t *cert)
 {
@@ -394,8 +440,8 @@ void release_pgpcert(pgpcert_t *cert)
        }
 }
 
-/*
- *  free a PGP certificate
+/**
+ *  Free a PGP certificate
  */
 void free_pgpcert(pgpcert_t *cert)
 {
@@ -408,8 +454,8 @@ void free_pgpcert(pgpcert_t *cert)
        }
 }
 
-/*
- *  list all PGP end certificates in a chained list
+/**
+ *  List all PGP end certificates in a chained list
  */
 void list_pgp_end_certs(bool utc)
 {
@@ -435,16 +481,16 @@ void list_pgp_end_certs(bool utc)
                c.u.pgp = cert;
 
                whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc, cert->count);
-               whack_log(RC_COMMENT, "       fingerprint:  %Y", cert->fingerprint);
+               whack_log(RC_COMMENT, "       digest:   %Y", cert->fingerprint);
+               whack_log(RC_COMMENT, "       created:  %T", &cert->created, utc);
+               whack_log(RC_COMMENT, "       until:    %T %s", &cert->until, utc,
+                               check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
                whack_log(RC_COMMENT, "       pubkey:   %N %4d bits%s",
                                key_type_names, key->get_type(key),
                                key->get_keysize(key) * BITS_PER_BYTE,                          
                                has_private_key(c)? ", has private key" : "");
                whack_log(RC_COMMENT, "       keyid:    %Y",
                                key->get_id(key, ID_PUBKEY_INFO_SHA1));
-               whack_log(RC_COMMENT, "       created:  %T", &cert->created, utc);
-               whack_log(RC_COMMENT, "       until:    %T %s", &cert->until, utc,
-                               check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE));
                cert = cert->next;
        }
 }
index 9d8912e..7276483 100644 (file)
@@ -34,6 +34,7 @@ typedef struct pgpcert pgpcert_t;
 
 struct pgpcert {
        pgpcert_t        *next;
+       int              version;
        time_t           installed;
        int              count;
        chunk_t          certificate;
@@ -43,7 +44,7 @@ struct pgpcert {
        identification_t *fingerprint;
 };
 
-extern const pgpcert_t empty_pgpcert;
+extern const pgpcert_t pgpcert_empty;
 extern bool parse_pgp(chunk_t blob, pgpcert_t *cert, private_key_t **key);
 extern void share_pgpcert(pgpcert_t *cert);
 extern void select_pgpcert_id(pgpcert_t *cert, struct id *end_id);
index 855a8a1..10ab262 100644 (file)
@@ -451,7 +451,7 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object
        };
 
        /* initialize the return argument */
-       *cert = empty_cert;
+       *cert = cert_empty;
 
        /* get the length of the attributes first */
        CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);