From d17a1205982eae5c92203a0a77d1a8553e108972 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sat, 6 Jun 2009 13:13:11 +0200 Subject: [PATCH] fixed OpenPGP parsing --- src/libstrongswan/pgp/pgp.h | 1 + .../plugins/gmp/gmp_rsa_private_key.c | 42 ++- src/pluto/certs.c | 25 +- src/pluto/certs.h | 5 +- src/pluto/ipsec_doi.c | 4 +- src/pluto/keys.c | 118 +++--- src/pluto/pgpcert.c | 342 ++++++++++-------- src/pluto/pgpcert.h | 3 +- src/pluto/smartcard.c | 2 +- 9 files changed, 311 insertions(+), 231 deletions(-) diff --git a/src/libstrongswan/pgp/pgp.h b/src/libstrongswan/pgp/pgp.h index 5c512d8a0..677c5b1cc 100644 --- a/src/libstrongswan/pgp/pgp.h +++ b/src/libstrongswan/pgp/pgp.h @@ -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 diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index bfe9d3cdd..bc79beb6a 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -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) { diff --git a/src/pluto/certs.c b/src/pluto/certs.c index 29e7dbfa4..39ff8df7f 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -33,12 +33,12 @@ /** * 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; diff --git a/src/pluto/certs.h b/src/pluto/certs.h index a88fc152e..0810c52fa 100644 --- a/src/pluto/certs.h +++ b/src/pluto/certs.h @@ -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); diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 49f40e38d..181040a6d 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -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); } diff --git a/src/pluto/keys.c b/src/pluto/keys.c index c0eb6ae74..4a4968175 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -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 { diff --git a/src/pluto/pgpcert.c b/src/pluto/pgpcert.c index 531a04a69..f22aed1a5 100644 --- a/src/pluto/pgpcert.c +++ b/src/pluto/pgpcert.c @@ -34,18 +34,19 @@ #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,94 +85,7 @@ static u_char pgp_version(chunk_t *blob) return version; } -/* - * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 2440 - */ -static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert) -{ - u_char version = pgp_version(packet); - public_key_t *key; - - if (version < 3 || version > 4) - { - plog("PGP packet version V%d not supported", version); - return FALSE; - } - - /* creation date - 4 bytes */ - cert->created = (time_t)pgp_length(packet, 4); - DBG(DBG_PARSING, - DBG_log("L3 - created:"); - DBG_log(" %T", &cert->created, TRUE) - ) - - if (version == 3) - { - /* validity in days - 2 bytes */ - cert->until = (time_t)pgp_length(packet, 2); - - /* validity of 0 days means that the key never expires */ - if (cert->until > 0) - { - cert->until = cert->created + 24*3600*cert->until; - } - DBG(DBG_PARSING, - DBG_log("L3 - until:"); - DBG_log(" %T", &cert->until, TRUE); - ) - } - - /* public key algorithm - 1 byte */ - DBG(DBG_PARSING, - DBG_log("L3 - public key algorithm:") - ) - - switch (pgp_length(packet, 1)) - { - 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; - - if (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"); - } - 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; - } - return TRUE; -} - -/* +/** * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440 */ static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert) @@ -183,12 +97,14 @@ static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert) /* 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(" size must be 5"); + plog(" size must be 5"); return FALSE; } @@ -213,6 +129,133 @@ static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert) 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; + } + + /* creation date - 4 bytes */ + cert->created = (time_t)pgp_length(packet, 4); + DBG(DBG_PARSING, + DBG_log("L3 - created:"); + DBG_log(" %T", &cert->created, TRUE) + ) + + if (cert->version == 3) + { + /* validity in days - 2 bytes */ + cert->until = (time_t)pgp_length(packet, 2); + + /* validity of 0 days means that the key never expires */ + if (cert->until > 0) + { + cert->until = cert->created + 24*3600*cert->until; + } + DBG(DBG_PARSING, + DBG_log("L3 - until:"); + 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(" %N", pgp_pubkey_alg_names, pubkey_alg) + ) + + switch (pubkey_alg) + { + 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 (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; + } + break; + default: + plog(" non RSA public keys not supported"); + return FALSE; + } + return TRUE; +} + +/* + * Parse OpenPGP secret key packet defined in section 5.5.3 of RFC 4880 + */ +static bool parse_pgp_secretkey_packet(chunk_t *packet, private_key_t **key) +{ + pgp_pubkey_alg_t pubkey_alg; + pgpcert_t cert = pgpcert_empty; + + 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(" %N", pgp_pubkey_alg_names, pubkey_alg) + ) + + 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) { DBG(DBG_PARSING, @@ -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; } } diff --git a/src/pluto/pgpcert.h b/src/pluto/pgpcert.h index 9d8912ec5..727648391 100644 --- a/src/pluto/pgpcert.h +++ b/src/pluto/pgpcert.h @@ -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); diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c index 855a8a12b..10ab26214 100644 --- a/src/pluto/smartcard.c +++ b/src/pluto/smartcard.c @@ -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);