merged pluto's PGP certificate parsing with charon's

This commit is contained in:
Andreas Steffen 2009-11-10 23:54:04 +01:00
parent cc543182bc
commit f565d0c575
25 changed files with 471 additions and 1087 deletions

View File

@ -36,7 +36,6 @@ modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pgpcert.c pgpcert.h \
pkcs7.c pkcs7.h \
plutomain.c \
rcv_whack.c rcv_whack.h \

View File

@ -85,7 +85,7 @@ bool ac_verify_cert(certificate_t *cert, bool strict)
identification_t *subject = cert->get_subject(cert);
identification_t *issuer = cert->get_issuer(cert);
chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
x509cert_t *aacert;
cert_t *aacert;
time_t notBefore, valid_until;
DBG1("holder: '%Y'", subject);

View File

@ -64,43 +64,31 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
}
if (blob.ptr)
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
if (pgp)
{
pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
*pgpcert = pgpcert_empty;
if (parse_pgp(chunk_clone(blob), pgpcert))
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->type = CERT_PGP;
cert->u.pgp = pgpcert;
return cert;
}
plog(" error in OpenPGP certificate");
free_pgpcert(pgpcert);
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_GPG,
BUILD_BLOB_PGP, blob,
BUILD_END);
}
else
{
x509cert_t *x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert;
x509cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_X509_FLAG, flags,
BUILD_END);
if (x509cert->cert)
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->type = CERT_X509_SIGNATURE;
cert->u.x509 = x509cert;
return cert;
}
plog(" error in X.509 certificate");
free_x509cert(x509cert);
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_X509_FLAG, flags,
BUILD_END);
}
if (cert->cert)
{
return cert;
}
plog(" error in X.509 certificate");
cert_free(cert);
}
return NULL;
}

View File

@ -37,7 +37,7 @@
/* chained list of X.509 authority certificates (ca, aa, and ocsp) */
static x509cert_t *x509authcerts = NULL;
static cert_t *x509authcerts = NULL;
/* chained list of X.509 certification authority information records */
@ -79,7 +79,7 @@ bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
{
certificate_t *certificate;
identification_t *issuer;
x509cert_t *cacert;
cert_t *cacert;
cacert = get_authcert(a, chunk_empty, X509_CA);
if (cacert == NULL)
@ -161,9 +161,10 @@ bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca,
*/
static void free_first_authcert(void)
{
x509cert_t *first = x509authcerts;
cert_t *first = x509authcerts;
x509authcerts = first->next;
free_x509cert(first);
cert_free(first);
}
/*
@ -174,18 +175,19 @@ void free_authcerts(void)
lock_authcert_list("free_authcerts");
while (x509authcerts != NULL)
{
free_first_authcert();
}
unlock_authcert_list("free_authcerts");
}
/*
* get a X.509 authority certificate with a given subject or keyid
*/
x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags)
{
x509cert_t *cert, *prev_cert = NULL;
cert_t *cert, *prev_cert = NULL;
/* the authority certificate list is empty */
if (x509authcerts == NULL)
@ -238,11 +240,11 @@ x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
/*
* add an authority certificate to the chained list
*/
x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
x509cert_t *old_cert;
cert_t *old_cert;
lock_authcert_list("add_authcert");
@ -258,7 +260,7 @@ x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
)
unlock_authcert_list("add_authcert");
free_x509cert(cert);
cert_free(cert);
return old_cert;
}
else
@ -274,7 +276,7 @@ x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
/* add new authcert to chained list */
cert->next = x509authcerts;
x509authcerts = cert;
share_x509cert(cert); /* set count to one */
cert_share(cert); /* set count to one */
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" authcert inserted")
)
@ -302,16 +304,17 @@ void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
while (enumerator->enumerate(enumerator, NULL, &file, &st))
{
cert_t cert;
cert_t *cert;
if (!S_ISREG(st.st_mode))
{
/* skip special file */
continue;
}
if (load_cert(file, type, auth_flags, &cert))
cert = load_cert(file, type, auth_flags);
if (cert)
{
add_authcert(cert.u.x509, auth_flags);
add_authcert(cert, auth_flags);
}
}
enumerator->destroy(enumerator);
@ -330,8 +333,8 @@ void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
/*
* get a cacert with a given subject or keyid from an alternative list
*/
static const x509cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
const x509cert_t *cert)
static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
const cert_t *cert)
{
if (cert == NULL)
{
@ -369,7 +372,7 @@ static const x509cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid
/* establish trust into a candidate authcert by going up the trust chain.
* validity and revocation status are not checked.
*/
bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain)
{
int pathlen;
@ -382,7 +385,7 @@ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chai
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
const x509cert_t *authcert = NULL;
const cert_t *authcert = NULL;
DBG(DBG_CONTROL,
DBG_log("subject: '%Y'", subject);
@ -551,8 +554,7 @@ ca_info_t* create_ca_info(void)
void add_ca_info(const whack_message_t *msg)
{
smartcard_t *sc = NULL;
cert_t cert;
bool valid_cert = FALSE;
cert_t *cert = NULL;
bool cached_cert = FALSE;
if (find_ca_info_by_name(msg->name, FALSE))
@ -564,18 +566,17 @@ void add_ca_info(const whack_message_t *msg)
if (scx_on_smartcard(msg->cacert))
{
/* load CA cert from smartcard */
valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert);
cert = scx_load_cert(msg->cacert, &sc, &cached_cert);
}
else
{
/* load CA cert from file */
valid_cert = load_ca_cert(msg->cacert, &cert);
cert = load_ca_cert(msg->cacert);
}
if (valid_cert)
if (cert)
{
x509cert_t *cacert = cert.u.x509;
certificate_t *certificate = cacert->cert;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
@ -589,7 +590,7 @@ void add_ca_info(const whack_message_t *msg)
/* ca_info is already present */
loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
"ignoring \"%s\"", ca->name, msg->name);
free_x509cert(cacert);
cert_free(cert);
return;
}
@ -647,13 +648,15 @@ void add_ca_info(const whack_message_t *msg)
unlock_ca_info_list("add_ca_info");
/* add cacert to list of authcerts */
cacert = add_authcert(cacert, X509_CA);
cert = add_authcert(cert, X509_CA);
if (!cached_cert && sc != NULL)
{
if (sc->last_cert.type == CERT_X509_SIGNATURE)
sc->last_cert.u.x509->count--;
sc->last_cert.u.x509 = cacert;
share_cert(sc->last_cert);
if (sc->last_cert != NULL)
{
sc->last_cert->count--;
}
sc->last_cert = cert;
cert_share(sc->last_cert);
}
if (sc != NULL)
time(&sc->last_load);

View File

@ -18,7 +18,7 @@
#include <utils/linked_list.h>
#include <utils/identification.h>
#include "x509.h"
#include "certs.h"
#include "whack.h"
/* CA info structures */
@ -40,14 +40,13 @@ struct ca_info {
extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
extern bool match_requested_ca(linked_list_t *requested_ca,
identification_t *our_ca, int *our_pathlen);
extern x509cert_t* get_authcert(identification_t *subject, chunk_t keyid,
extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags);
extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags);
extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags);
extern cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags);
extern void free_authcerts(void);
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
extern bool trust_authcert_candidate(const x509cert_t *cert,
const x509cert_t *alt_chain);
extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid);
extern bool find_ca_info_by_name(const char *name, bool delete);
extern void add_ca_info(const whack_message_t *msg);

View File

@ -18,60 +18,83 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <freeswan.h>
#include "library.h"
#include "asn1/asn1.h"
#include "credentials/certificates/certificate.h"
#include <library.h>
#include <asn1/asn1.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/pgp_certificate.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "certs.h"
#include "whack.h"
#include "fetch.h"
#include "keys.h"
#include "builder.h"
/**
* used for initializatin of certs
* Initialization
*/
const cert_t cert_empty = {CERT_NONE, {NULL}};
const cert_t cert_empty = {
NULL , /* cert */
NULL , /* *next */
0 , /* count */
FALSE /* smartcard */
};
/**
* extracts the certificate to be sent to the peer
* Chained lists of X.509 and PGP end entity certificates
*/
chunk_t cert_get_encoding(cert_t cert)
static cert_t *certs = NULL;
/**
* Free a pluto certificate
*/
void cert_free(cert_t *cert)
{
switch (cert.type)
if (cert)
{
case CERT_PGP:
return chunk_clone(cert.u.pgp->certificate);
case CERT_X509_SIGNATURE:
return cert.u.x509->cert->get_encoding(cert.u.x509->cert);
default:
return chunk_empty;
certificate_t *certificate = cert->cert;
if (certificate)
{
certificate->destroy(certificate);
}
free(cert);
}
}
public_key_t* cert_get_public_key(const cert_t cert)
/**
* Add a pluto end entity certificate to the chained list
*/
cert_t* cert_add(cert_t *cert)
{
switch (cert.type)
certificate_t *certificate = cert->cert;
cert_t *c = certs;
while (c != NULL)
{
case CERT_PGP:
if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{
public_key_t *public_key = cert.u.pgp->public_key;
return public_key->get_ref(public_key);
cert_free(cert);
return c;
}
case CERT_X509_SIGNATURE:
{
certificate_t *certificate = cert.u.x509->cert;
return certificate->get_public_key(certificate);
}
default:
return NULL;
c = c->next;
}
/* insert new cert at the root of the chain */
lock_certs_and_keys("cert_add");
cert->next = certs;
certs = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" cert inserted")
)
unlock_certs_and_keys("cert_add");
return cert;
}
/**
@ -161,7 +184,7 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
/**
* Loads a X.509 or OpenPGP certificate
*/
bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out)
cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
{
cert_t *cert;
@ -171,83 +194,133 @@ bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out
BUILD_END);
if (cert)
{
/* the API passes an empty cert_t, we move over and free the built one */
plog(" loaded %s certificate from '%s'", label, filename);
*out = *cert;
free(cert);
return TRUE;
}
return FALSE;
return cert;
}
/**
* Loads a host certificate
*/
bool load_host_cert(char *filename, cert_t *cert)
cert_t* load_host_cert(char *filename)
{
char *path = concatenate_paths(HOST_CERT_PATH, filename);
return load_cert(path, "host", X509_NONE, cert);
return load_cert(path, "host", X509_NONE);
}
/**
* Loads a CA certificate
*/
bool load_ca_cert(char *filename, cert_t *cert)
cert_t* load_ca_cert(char *filename)
{
char *path = concatenate_paths(CA_CERT_PATH, filename);
return load_cert(path, "CA", X509_NONE, cert);
}
/**
* establish equality of two certificates
*/
bool same_cert(const cert_t *a, const cert_t *b)
{
return a->type == b->type && a->u.x509 == b->u.x509;
return load_cert(path, "CA", X509_NONE);
}
/**
* for each link pointing to the certificate increase the count by one
*/
void share_cert(cert_t cert)
void cert_share(cert_t *cert)
{
switch (cert.type)
if (cert != NULL)
{
case CERT_PGP:
share_pgpcert(cert.u.pgp);
break;
case CERT_X509_SIGNATURE:
share_x509cert(cert.u.x509);
break;
default:
break;
cert->count++;
}
}
/* release of a certificate decreases the count by one
* the certificate is freed when the counter reaches zero
*/
void release_cert(cert_t cert)
void cert_release(cert_t *cert)
{
switch (cert.type)
if (cert && --cert->count == 0)
{
case CERT_PGP:
release_pgpcert(cert.u.pgp);
break;
case CERT_X509_SIGNATURE:
release_x509cert(cert.u.x509);
break;
default:
break;
cert_t **pp = &certs;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
cert_free(cert);
}
}
/**
* List all PGP end certificates in a chained list
*/
void list_pgp_end_certs(bool utc)
{
cert_t *cert = certs;
time_t now = time(NULL);
bool first = TRUE;
while (cert != NULL)
{
certificate_t *certificate = cert->cert;
if (certificate->get_type(certificate) == CERT_GPG)
{
time_t created, until;
public_key_t *key;
identification_t *userid = certificate->get_subject(certificate);
pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
if (first)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
first = false;
}
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " userid: '%Y'", userid);
whack_log(RC_COMMENT, " digest: %#B", &fingerprint);
/* list validity */
certificate->get_validity(certificate, &now, &created, &until);
whack_log(RC_COMMENT, " created: %T", &created, utc);
whack_log(RC_COMMENT, " until: %T %s%s", &until, utc,
check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE),
(until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
key = certificate->get_public_key(certificate);
if (key)
{
chunk_t keyid;
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(cert)? ", has private key" : "");
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
{
whack_log(RC_COMMENT, " keyid: %#B", &keyid);
}
if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid))
{
whack_log(RC_COMMENT, " subjkey: %#B", &keyid);
}
}
}
cert = cert->next;
}
}
/**
* List all X.509 end certificates in a chained list
*/
void list_x509_end_certs(bool utc)
{
list_x509cert_chain("End Entity", certs, X509_NONE, utc);
}
/**
* list all X.509 and OpenPGP end certificates
*/
void list_certs(bool utc)
void cert_list(bool utc)
{
list_x509_end_certs(utc);
list_pgp_end_certs(utc);

View File

@ -18,9 +18,12 @@
#define _CERTS_H
#include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
#include "x509.h"
#include "pgpcert.h"
#include <freeswan.h>
#include "defs.h"
/* path definitions for private keys, end certs,
* cacerts, attribute certs and crls
@ -43,16 +46,16 @@
#define CRL_WARNING_INTERVAL 7 /* days */
#define ACERT_WARNING_INTERVAL 1 /* day */
/* certificate access structure
* currently X.509 and OpenPGP certificates are supported
*/
typedef struct {
u_char type;
union {
x509cert_t *x509;
pgpcert_t *pgp;
} u;
} cert_t;
/* access structure for a pluto certificate */
typedef struct cert_t cert_t;
struct cert_t {
certificate_t *cert;
cert_t *next;
int count;
bool smartcard;
};
/* used for initialization */
extern const cert_t cert_empty;
@ -62,18 +65,16 @@ extern const cert_t cert_empty;
*/
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 bool load_cert(char *filename, const char *label, x509_flag_t flags,
cert_t *cert);
extern bool load_host_cert(char *filename, cert_t *cert);
extern bool load_ca_cert(char *filename, cert_t *cert);
extern bool same_cert(const cert_t *a, const cert_t *b);
extern void share_cert(cert_t cert);
extern void release_cert(cert_t cert);
extern void list_certs(bool utc);
extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
extern cert_t* load_host_cert(char *filename);
extern cert_t* load_ca_cert(char *filename);
extern cert_t* cert_add(cert_t *cert);
extern void cert_free(cert_t *cert);
extern void cert_share(cert_t *cert);
extern void cert_release(cert_t *cert);
extern void cert_list(bool utc);
#endif /* _CERTS_H */

View File

@ -39,7 +39,6 @@
#include "x509.h"
#include "ca.h"
#include "crl.h"
#include "pgpcert.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
@ -398,9 +397,9 @@ void delete_connection(connection_t *c, bool relations)
gw_delref(&c->gw_info);
lock_certs_and_keys("delete_connection");
release_cert(c->spd.this.cert);
cert_release(c->spd.this.cert);
scx_release(c->spd.this.sc);
release_cert(c->spd.that.cert);
cert_release(c->spd.that.cert);
scx_release(c->spd.that.sc);
unlock_certs_and_keys("delete_connection");
@ -736,7 +735,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.this.pool = clone_str(c->spd.this.pool);
c->spd.this.updown = clone_str(c->spd.this.updown);
scx_share(c->spd.this.sc);
share_cert(c->spd.this.cert);
cert_share(c->spd.this.cert);
if (c->spd.this.ca)
{
c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca);
@ -749,7 +748,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.that.pool = clone_str(c->spd.that.pool);
c->spd.that.updown = clone_str(c->spd.that.updown);
scx_share(c->spd.that.sc);
share_cert(c->spd.that.cert);
cert_share(c->spd.that.cert);
if (c->spd.that.ca)
{
c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca);
@ -767,13 +766,12 @@ static void unshare_connection_strings(connection_t *c)
static void load_end_certificate(char *filename, struct end *dst)
{
time_t valid_until;
cert_t cert;
bool valid_cert = FALSE;
cert_t *cert = NULL;
certificate_t *certificate;
bool cached_cert = FALSE;
/* initialize end certificate */
dst->cert.type = CERT_NONE;
dst->cert.u.x509 = NULL;
dst->cert = NULL;
/* initialize smartcard info record */
dst->sc = NULL;
@ -783,87 +781,73 @@ static void load_end_certificate(char *filename, struct end *dst)
if (scx_on_smartcard(filename))
{
/* load cert from smartcard */
valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
cert = scx_load_cert(filename, &dst->sc, &cached_cert);
}
else
{
/* load cert from file */
valid_cert = load_host_cert(filename, &cert);
cert = load_host_cert(filename);
}
}
if (valid_cert)
if (cert)
{
switch (cert.type)
certificate = cert->cert;
if (dst->id->get_type(dst->id) == ID_ANY ||
!certificate->has_subject(certificate, dst->id))
{
case CERT_PGP:
dst->id = select_pgpcert_id(cert.u.pgp, dst->id);
plog( " id '%Y' not confirmed by certificate, defaulting to '%Y'",
dst->id, certificate->get_subject(certificate));
dst->id->destroy(dst->id);
dst->id = certificate->get_subject(certificate);
dst->id = dst->id->clone(dst->id);
}
if (cached_cert)
if (cached_cert)
{
dst->cert = cert;
}
else
{
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{
dst->cert = cert;
cert_free(cert);
return;
}
else
{
valid_until = cert.u.pgp->until;
add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
dst->cert.type = cert.type;
dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
}
break;
case CERT_X509_SIGNATURE:
dst->id = select_x509cert_id(cert.u.x509, dst->id);
DBG(DBG_CONTROL,
DBG_log("certificate is valid")
)
add_public_key_from_cert(cert, valid_until, DAL_LOCAL);
dst->cert = cert_add(cert);
}
certificate = dst->cert->cert;
if (cached_cert)
{
dst->cert = cert;
}
else
{
certificate_t *certificate = cert.u.x509->cert;
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{
free_x509cert(cert.u.x509);
break;
}
DBG(DBG_CONTROL,
DBG_log("certificate is valid")
)
add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
dst->cert.type = cert.type;
dst->cert.u.x509 = add_x509cert(cert.u.x509);
}
/* if no CA is defined, use issuer as default */
if (dst->ca == NULL && certificate->get_type(certificate) == CERT_X509)
{
identification_t *issuer;
/* if no CA is defined, use issuer as default */
if (dst->ca == NULL)
{
certificate_t *certificate = dst->cert.u.x509->cert;
identification_t *issuer = certificate->get_issuer(certificate);
dst->ca = issuer->clone(issuer);
}
break;
default:
break;
issuer = certificate->get_issuer(certificate);
dst->ca = issuer->clone(issuer);
}
/* cache the certificate that was last retrieved from the smartcard */
if (dst->sc)
{
if (!same_cert(&dst->sc->last_cert, &dst->cert))
if (!certificate->equals(certificate, dst->sc->last_cert->cert))
{
lock_certs_and_keys("load_end_certificates");
release_cert(dst->sc->last_cert);
cert_release(dst->sc->last_cert);
dst->sc->last_cert = dst->cert;
share_cert(dst->cert);
cert_share(dst->cert);
unlock_certs_and_keys("load_end_certificates");
}
time(&dst->sc->last_load);
}
}
scx_share(dst->sc);
share_cert(dst->cert);
cert_share(dst->cert);
}
static bool extract_end(struct end *dst, const whack_end_t *src,

View File

@ -147,7 +147,7 @@ struct end {
u_int16_t host_port; /* host order */
u_int16_t port; /* host order */
u_int8_t protocol;
cert_t cert; /* end certificate */
cert_t *cert; /* end certificate */
identification_t *ca; /* CA distinguished name */
ietf_attributes_t *groups; /* access control groups */
smartcard_t *sc; /* smartcard reader and key info */

View File

@ -113,7 +113,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
crl_t *crl = (crl_t*)cert_crl;
identification_t *issuer = cert_crl->get_issuer(cert_crl);
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
x509cert_t *issuer_cert;
cert_t *issuer_cert;
x509crl_t *oldcrl;
time_t now, nextUpdate;
bool valid_sig;
@ -340,8 +340,7 @@ void check_crls(void)
/*
* verify if a cert hasn't been revoked by a crl
*/
cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
time_t *revocationDate,
cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
crl_reason_t *revocationReason)
{
certificate_t *certificate = cert->cert;
@ -402,7 +401,7 @@ cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
x509cert_t *issuer_cert;
cert_t *issuer_cert;
bool trusted, valid;
DBG(DBG_CONTROL,

View File

@ -26,7 +26,6 @@ struct x509crl {
certificate_t *crl;
x509crl_t *next;
linked_list_t *distributionPoints;
chunk_t signature;
};
/* apply a strict CRL policy
@ -46,7 +45,7 @@ extern long crl_check_interval;
extern void load_crls(void);
extern void check_crls(void);
extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl);
extern cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
extern cert_status_t verify_by_crl(cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason);
extern void list_crls(bool utc, bool strict);

View File

@ -199,9 +199,10 @@ struct db_context *ike_alg_db_new(connection_t *c, lset_t policy)
key_type_t key_type = KEY_ANY;
if (c->spd.this.cert.type != CERT_NONE)
if (c->spd.this.cert)
{
public_key_t *key = cert_get_public_key(c->spd.this.cert);
certificate_t *certificate = c->spd.this.cert->cert;
public_key_t *key = certificate->get_public_key(certificate);
if (key == NULL)
{

View File

@ -905,7 +905,6 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
struct state *st = new_state();
pb_stream reply; /* not actually a reply, but you know what I mean */
pb_stream rbody;
int vids_to_send = 0;
/* set up new state */
@ -925,7 +924,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
{
vids_to_send++;
}
if (c->spd.this.cert.type == CERT_PGP)
if (c->spd.this.cert &&
c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
{
vids_to_send++;
}
@ -1022,7 +1022,8 @@ main_outI1(int whack_sock, connection_t *c, struct state *predecessor
/* if we have an OpenPGP certificate we assume an
* OpenPGP peer and have to send the Vendor ID
*/
if (c->spd.this.cert.type == CERT_PGP)
if (c->spd.this.cert &&
c->spd.this.cert->cert->get_type(c->spd.this.cert->cert) == CERT_GPG)
{
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
, &rbody, VID_OPENPGP))
@ -2166,12 +2167,12 @@ static void decode_cert(struct msg_digest *md)
blob.len = pbs_left(&p->pbs);
if (cert->isacert_type == CERT_X509_SIGNATURE)
{
x509cert_t x509cert = empty_x509cert;
cert_t x509cert = cert_empty;
x509cert.cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (x509cert.cert)
{
if (verify_x509cert(&x509cert, strict_crl_policy, &valid_until))
@ -2179,7 +2180,7 @@ static void decode_cert(struct msg_digest *md)
DBG(DBG_PARSING,
DBG_log("Public key validated")
)
add_x509_public_key(&x509cert, valid_until, DAL_SIGNED);
add_public_key_from_cert(&x509cert, valid_until, DAL_SIGNED);
}
else
{
@ -3518,7 +3519,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
connection_t *c = st->st_connection;
certpolicy_t cert_policy = c->spd.this.sendcert;
cert_t mycert = c->spd.this.cert;
cert_t *mycert = c->spd.this.cert;
bool requested, send_cert, send_cr;
bool pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
@ -3548,8 +3549,9 @@ stf_status main_inR2_outI3(struct msg_digest *md)
* or are requested to send it
*/
requested = cert_policy == CERT_SEND_IF_ASKED && c->got_certrequest;
send_cert = pubkey_auth && mycert.type != CERT_NONE
&& (cert_policy == CERT_ALWAYS_SEND || requested);
send_cert = pubkey_auth && mycert &&
mycert->cert->get_type(mycert->cert) == CERT_X509 &&
(cert_policy == CERT_ALWAYS_SEND || requested);
/* send certificate request if we don't have a preloaded RSA public key */
send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
@ -3599,7 +3601,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
)
if (mycert.type != CERT_NONE)
if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{
const char *request_text = "";
@ -3623,13 +3625,13 @@ stf_status main_inR2_outI3(struct msg_digest *md)
struct isakmp_cert cert_hd;
cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG;
cert_hd.isacert_type = mycert.type;
cert_hd.isacert_type = CERT_X509_SIGNATURE;
if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
{
return STF_INTERNAL_ERROR;
}
cert_encoding = cert_get_encoding(mycert);
cert_encoding = mycert->cert->get_encoding(mycert->cert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
if (!success)
@ -3645,7 +3647,7 @@ stf_status main_inR2_outI3(struct msg_digest *md)
identification_t *ca = st->st_connection->spd.that.ca;
chunk_t cr = (ca) ? ca->get_encoding(ca) : chunk_empty;
if (!build_and_ship_CR(mycert.type, cr, &md->rbody, ISAKMP_NEXT_SIG))
if (!build_and_ship_CR(CERT_X509_SIGNATURE, cr, &md->rbody, ISAKMP_NEXT_SIG))
{
return STF_INTERNAL_ERROR;
}
@ -3971,7 +3973,7 @@ main_inI3_outR3_tail(struct msg_digest *md
u_int8_t auth_payload;
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy;
cert_t mycert;
cert_t *mycert;
bool pubkey_auth, send_cert, requested;
/* ID and HASH_I or SIG_I in
@ -3996,7 +3998,8 @@ main_inI3_outR3_tail(struct msg_digest *md
requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest;
pubkey_auth = uses_pubkey_auth(st->st_oakley.auth);
send_cert = pubkey_auth && mycert.type != CERT_NONE &&
send_cert = pubkey_auth && mycert &&
mycert->cert->get_type(mycert->cert) == CERT_X509 &&
(cert_policy == CERT_ALWAYS_SEND || requested);
/*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
@ -4039,7 +4042,7 @@ main_inI3_outR3_tail(struct msg_digest *md
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %N", cert_policy_names, cert_policy)
)
if (mycert.type != CERT_NONE)
if (mycert && mycert->cert->get_type(mycert->cert) == CERT_X509)
{
const char *request_text = "";
@ -4063,13 +4066,13 @@ main_inI3_outR3_tail(struct msg_digest *md
struct isakmp_cert cert_hd;
cert_hd.isacert_np = ISAKMP_NEXT_SIG;
cert_hd.isacert_type = mycert.type;
cert_hd.isacert_type = CERT_X509_SIGNATURE;
if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
{
return STF_INTERNAL_ERROR;
}
cert_encoding = cert_get_encoding(mycert);
cert_encoding = mycert->cert->get_encoding(mycert->cert);
success = out_chunk(cert_encoding, &cert_pbs, "CERT");
free(cert_encoding.ptr);
if (!success)

View File

@ -36,11 +36,11 @@
#include <library.h>
#include <asn1/asn1.h>
#include <credentials/certificates/pgp_certificate.h>
#include "constants.h"
#include "defs.h"
#include "x509.h"
#include "pgpcert.h"
#include "certs.h"
#include "smartcard.h"
#include "connections.h"
@ -111,9 +111,11 @@ static const secret_t* get_secret(const connection_t *c,
identification_t *my_id, *his_id;
/* is there a certificate assigned to this connection? */
if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
if (kind == PPK_PUBKEY && c->spd.this.cert)
{
public_key_t *pub_key = cert_get_public_key(c->spd.this.cert);
certificate_t *certificate = c->spd.this.cert->cert;
public_key_t *pub_key = certificate->get_public_key(certificate);
for (s = secrets; s != NULL; s = s->next)
{
@ -262,11 +264,11 @@ const chunk_t* get_preshared_secret(const connection_t *c)
/* check the existence of a private key matching a public key contained
* in an X.509 or OpenPGP certificate
*/
bool has_private_key(cert_t cert)
bool has_private_key(cert_t *cert)
{
secret_t *s;
bool has_key = FALSE;
public_key_t *pub_key = cert_get_public_key(cert);
public_key_t *pub_key = cert->cert->get_public_key(cert->cert);
for (s = secrets; s != NULL; s = s->next)
{
@ -284,7 +286,7 @@ bool has_private_key(cert_t cert)
/*
* get the matching private key belonging to a given X.509 certificate
*/
private_key_t* get_x509_private_key(const x509cert_t *cert)
private_key_t* get_x509_private_key(const cert_t *cert)
{
public_key_t *public_key = cert->cert->get_public_key(cert->cert);
private_key_t *private_key = NULL;
@ -1272,80 +1274,86 @@ bool add_public_key(identification_t *id, enum dns_auth_level dns_auth_level,
return TRUE;
}
/* extract id and public key from x.509 certificate and
* insert it into a pubkeyrec
/**
* Extract id and public key a certificate and insert it into a pubkeyrec
*/
void add_x509_public_key(x509cert_t *cert , time_t until,
enum dns_auth_level dns_auth_level)
void add_public_key_from_cert(cert_t *cert , time_t until,
enum dns_auth_level dns_auth_level)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
identification_t *issuer = NULL;
identification_t *id;
chunk_t serialNumber = x509->get_serial(x509);
chunk_t serialNumber = chunk_empty;
pubkey_t *pk;
key_type_t pk_type;
enumerator_t *enumerator;
/* ID type: ID_DER_ASN1_DN (X.509 subject field) */
pk = malloc_thing(pubkey_t);
zero(pk);
pk->public_key = certificate->get_public_key(certificate);
pk_type = pk->public_key->get_type(pk->public_key);
pk->id = subject->clone(subject);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = issuer->clone(issuer);
pk->serial = chunk_clone(serialNumber);
pk_type = pk->public_key->get_type(pk->public_key);
if (certificate->get_type(certificate) == CERT_X509)
{
x509_t *x509 = (x509_t*)certificate;
issuer = certificate->get_issuer(certificate);
serialNumber = x509->get_serial(x509);
pk->issuer = issuer->clone(issuer);
pk->serial = chunk_clone(serialNumber);
}
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
/* insert all subjectAltNames */
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &id))
if (certificate->get_type(certificate) == CERT_X509)
{
if (id->get_type(id) != ID_ANY)
x509_t *x509 = (x509_t*)certificate;
enumerator_t *enumerator;
/* insert all subjectAltNames from X.509 certificates */
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &id))
{
pk = malloc_thing(pubkey_t);
zero(pk);
pk->id = id->clone(id);
pk->public_key = certificate->get_public_key(certificate);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = issuer->clone(issuer);
pk->serial = chunk_clone(serialNumber);
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
if (id->get_type(id) != ID_ANY)
{
pk = malloc_thing(pubkey_t);
zero(pk);
pk->id = id->clone(id);
pk->public_key = certificate->get_public_key(certificate);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk->issuer = issuer->clone(issuer);
pk->serial = chunk_clone(serialNumber);
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
}
}
enumerator->destroy(enumerator);
}
enumerator->destroy(enumerator);
}
else
{
pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
/* extract id and public key from OpenPGP certificate and
* insert it into a pubkeyrec
*/
void add_pgp_public_key(pgpcert_t *cert , time_t until,
enum dns_auth_level dns_auth_level)
{
pubkey_t *pk;
key_type_t pk_type;
pk = malloc_thing(pubkey_t);
zero(pk);
pk->public_key = cert->public_key->get_ref(cert->public_key);
pk->id = cert->fingerprint->clone(cert->fingerprint);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
pk_type = pk->public_key->get_type(pk->public_key);
delete_public_keys(pk->id, pk_type, NULL, chunk_empty);
install_public_key(pk, &pubkeys);
/* add v3 or v4 PGP fingerprint */
pk = malloc_thing(pubkey_t);
zero(pk);
pk->id = identification_create_from_encoding(ID_KEY_ID, fingerprint);
pk->public_key = certificate->get_public_key(certificate);
pk->dns_auth_level = dns_auth_level;
pk->until_time = until;
delete_public_keys(pk->id, pk_type, pk->issuer, pk->serial);
install_public_key(pk, &pubkeys);
}
}
/* when a X.509 certificate gets revoked, all instances of
* the corresponding public key must be removed
*/
void remove_x509_public_key(const x509cert_t *cert)
void remove_x509_public_key(const cert_t *cert)
{
public_key_t *revoked_key = cert->cert->get_public_key(cert->cert);
pubkey_list_t *p, **pp;

View File

@ -45,7 +45,7 @@ struct connection;
extern const chunk_t *get_preshared_secret(const struct connection *c);
extern private_key_t *get_private_key(const struct connection *c);
extern private_key_t *get_x509_private_key(const x509cert_t *cert);
extern private_key_t *get_x509_private_key(const cert_t *cert);
/* public key machinery */
@ -84,12 +84,10 @@ extern bool add_public_key(identification_t *id,
enum pubkey_alg alg,
chunk_t rfc3110_key,
pubkey_list_t **head);
extern bool has_private_key(cert_t cert);
extern void add_x509_public_key(x509cert_t *cert, time_t until
, enum dns_auth_level dns_auth_level);
extern void add_pgp_public_key(pgpcert_t *cert, time_t until
, enum dns_auth_level dns_auth_level);
extern void remove_x509_public_key(const x509cert_t *cert);
extern bool has_private_key(cert_t *cert);
extern void add_public_key_from_cert(cert_t *cert, time_t until,
enum dns_auth_level dns_auth_level);
extern void remove_x509_public_key(const cert_t *cert);
extern void list_public_keys(bool utc);
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */

View File

@ -145,7 +145,7 @@ static chunk_t ocsp_default_uri;
static ocsp_location_t *ocsp_cache = NULL;
/* static temporary storage for ocsp requestor information */
static x509cert_t *ocsp_requestor_cert = NULL;
static cert_t *ocsp_requestor_cert = NULL;
static smartcard_t *ocsp_requestor_sc = NULL;
@ -281,7 +281,7 @@ static const asn1Object_t singleResponseObjects[] = {
* Build an ocsp location from certificate information
* without unsharing its contents
*/
static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
static bool build_ocsp_location(const cert_t *cert, ocsp_location_t *location)
{
certificate_t *certificate = cert->cert;
identification_t *issuer = certificate->get_issuer(certificate);
@ -329,7 +329,7 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
if (authKeyID.ptr == NULL)
{
x509cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
if (authcert)
{
@ -416,7 +416,7 @@ static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
/**
* Verify the ocsp status of a certificate
*/
cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until,
cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason)
{
@ -646,7 +646,7 @@ void list_ocsp_cache(bool utc, bool strict)
static bool get_ocsp_requestor_cert(ocsp_location_t *location)
{
x509cert_t *cert = NULL;
cert_t *cert = NULL;
/* initialize temporary static storage */
ocsp_requestor_cert = NULL;
@ -962,7 +962,7 @@ chunk_t build_ocsp_request(ocsp_location_t *location)
static bool valid_ocsp_response(response_t *res)
{
int pathlen, pathlen_constraint;
x509cert_t *authcert;
cert_t *authcert;
lock_authcert_list("valid_ocsp_response");
@ -992,7 +992,7 @@ static bool valid_ocsp_response(response_t *res)
for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
{
x509cert_t *cert = authcert;
cert_t *cert = authcert;
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
@ -1133,10 +1133,10 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
break;
case BASIC_RESPONSE_CERTIFICATE:
{
x509cert_t *cert = malloc_thing(x509cert_t);
cert_t *cert = malloc_thing(cert_t);
x509_t *x509;
*cert = empty_x509cert;
*cert = cert_empty;
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
@ -1146,7 +1146,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("parsing of embedded ocsp certificate failed")
)
free_x509cert(cert);
cert_free(cert);
break;
}
x509 = (x509_t*)cert->cert;
@ -1161,7 +1161,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("embedded ocsp certificate rejected")
)
free_x509cert(cert);
cert_free(cert);
}
}
break;

View File

@ -69,11 +69,11 @@ extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc
extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info
, ocsp_location_t **chain, bool request);
extern void check_ocsp(void);
extern cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until
extern cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until
, time_t *revocationTime, crl_reason_t *revocationReason);
extern bool ocsp_set_request_cert(char* path);
extern void ocsp_set_default_uri(char* uri);
extern void ocsp_cache_add_cert(const x509cert_t* cert);
extern void ocsp_cache_add_cert(const cert_t* cert);
extern chunk_t build_ocsp_request(ocsp_location_t* location);
extern void parse_ocsp(ocsp_location_t* location, chunk_t blob);
extern void list_ocsp_locations(ocsp_location_t *location, bool requests

View File

@ -32,476 +32,4 @@
#include "whack.h"
#include "keys.h"
typedef enum pgp_packet_tag_t pgp_packet_tag_t;
/**
* OpenPGP packet tags as defined in section 4.3 of RFC 4880
*/
enum pgp_packet_tag_t {
PGP_PKT_RESERVED = 0,
PGP_PKT_PUBKEY_ENC_SESSION_KEY = 1,
PGP_PKT_SIGNATURE = 2,
PGP_PKT_SYMKEY_ENC_SESSION_KEY = 3,
PGP_PKT_ONE_PASS_SIGNATURE_PKT = 4,
PGP_PKT_SECRET_KEY = 5,
PGP_PKT_PUBLIC_KEY = 6,
PGP_PKT_SECRET_SUBKEY = 7,
PGP_PKT_COMPRESSED_DATA = 8,
PGP_PKT_SYMKEY_ENC_DATA = 9,
PGP_PKT_MARKER = 10,
PGP_PKT_LITERAL_DATA = 11,
PGP_PKT_TRUST = 12,
PGP_PKT_USER_ID = 13,
PGP_PKT_PUBLIC_SUBKEY = 14,
PGP_PKT_USER_ATTRIBUTE = 17,
PGP_PKT_SYM_ENC_INT_PROT_DATA = 18,
PGP_PKT_MOD_DETECT_CODE = 19
};
ENUM_BEGIN(pgp_packet_tag_names, PGP_PKT_RESERVED, PGP_PKT_PUBLIC_SUBKEY,
"Reserved",
"Public-Key Encrypted Session Key Packet",
"Signature Packet",
"Symmetric-Key Encrypted Session Key Packet",
"One-Pass Signature Packet",
"Secret Key Packet",
"Public Key Packet",
"Secret Subkey Packet",
"Compressed Data Packet",
"Symmetrically Encrypted Data Packet",
"Marker Packet",
"Literal Data Packet",
"Trust Packet",
"User ID Packet",
"Public Subkey Packet"
);
ENUM_NEXT(pgp_packet_tag_names, PGP_PKT_USER_ATTRIBUTE, PGP_PKT_MOD_DETECT_CODE, PGP_PKT_PUBLIC_SUBKEY,
"User Attribute Packet",
"Sym. Encrypted and Integrity Protected Data Packet",
"Modification Detection Code Packet"
);
ENUM_END(pgp_packet_tag_names, PGP_PKT_MOD_DETECT_CODE);
/**
* Chained list of OpenPGP end certificates
*/
static pgpcert_t *pgpcerts = NULL;
/**
* Size of PGP Key ID
*/
#define PGP_KEYID_SIZE 8
const pgpcert_t pgpcert_empty = {
NULL , /* next */
0 , /* version */
0 , /* count */
{ NULL, 0 }, /* certificate */
0 , /* created */
0 , /* until */
NULL , /* public key */
NULL /* fingerprint */
};
#define PGP_INVALID_LENGTH 0xffffffff
/**
* Returns the length of an OpenPGP (RFC 4880) packet
* The blob pointer is advanced past the length field.
*/
static size_t pgp_length(chunk_t *blob, size_t len)
{
size_t size = 0;
if (len > blob->len)
{
return PGP_INVALID_LENGTH;
}
blob->len -= len;
while (len-- > 0)
{
size = 256*size + *blob->ptr++;
}
return size;
}
/**
* Extracts the length of a PGP packet
*/
static size_t pgp_old_packet_length(chunk_t *blob)
{
/* bits 0 and 1 define the packet length type */
int len_type = 0x03 & *blob->ptr++;
blob->len--;
/* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
return pgp_length(blob, (len_type == 0)? 1: len_type << 1);
}
/**
* Extracts PGP packet version (V3 or V4)
*/
static u_char pgp_version(chunk_t *blob)
{
u_char version = *blob->ptr++;
blob->len--;
DBG(DBG_PARSING,
DBG_log("L3 - version:");
DBG_log(" V%d", version)
)
return version;
}
/**
* Parse OpenPGP signature packet defined in section 5.2.2 of RFC 4880
*/
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);
/* 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");
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;
}
/* 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)
{
chunk_t pubkey_packet = *packet;
if (!parse_pgp_pubkey_version_validity(packet, cert))
{
return FALSE;
}
cert->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
BUILD_BLOB_PGP, *packet, BUILD_END);
if (cert->public_key == NULL)
{
return FALSE;
}
/* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */
if (cert->version == 4)
{
chunk_t pubkey_packet_header = chunk_from_chars(
0x99, pubkey_packet.len / 256, pubkey_packet.len % 256
);
chunk_t hash;
hasher_t *hasher;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (hasher == NULL)
{
plog("no SHA-1 hasher available");
return FALSE;
}
hasher->allocate_hash(hasher, pubkey_packet_header, NULL);
hasher->allocate_hash(hasher, pubkey_packet, &hash);
hasher->destroy(hasher);
cert->fingerprint = identification_create_from_encoding(ID_KEY_ID, hash);
free(hash.ptr);
}
else
{
chunk_t fp;
/* V3 fingerprint is computed by public_key_t class */
if (!cert->public_key->get_fingerprint(cert->public_key, KEY_ID_PGPV3,
&fp))
{
return FALSE;
}
cert->fingerprint = identification_create_from_encoding(ID_KEY_ID, fp);
}
return TRUE;
}
bool parse_pgp(chunk_t blob, pgpcert_t *cert)
{
DBG(DBG_PARSING,
DBG_log("L0 - PGP file:")
)
DBG_cond_dump_chunk(DBG_RAW, "", blob);
if (cert == NULL)
{
/* should not occur, nothing to parse */
return FALSE;
}
/* parse a PGP certificate file */
cert->certificate = blob;
while (blob.len > 0)
{
chunk_t packet = chunk_empty;
u_char packet_tag = *blob.ptr;
DBG(DBG_PARSING,
DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag)
)
/* bit 7 must be set */
if (!(packet_tag & 0x80))
{
plog(" incorrect Packet Tag");
return FALSE;
}
/* bit 6 set defines new packet format */
if (packet_tag & 0x40)
{
plog(" new PGP packet format not supported");
return FALSE;
}
else
{
int packet_type = (packet_tag & 0x3C) >> 2;
packet.len = pgp_old_packet_length(&blob);
packet.ptr = blob.ptr;
blob.ptr += packet.len;
blob.len -= packet.len;
DBG(DBG_PARSING,
DBG_log(" %N (%d), old format, %u bytes",
pgp_packet_tag_names, packet_type,
packet_type, packet.len);
DBG_log("L2 - body:")
)
DBG_cond_dump_chunk(DBG_RAW, "", packet);
/* 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;
}
}
}
return TRUE;
}
/**
* Compare two OpenPGP certificates
*/
static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b)
{
return a->certificate.len == b->certificate.len &&
memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
}
/**
* For each link pointing to the certificate increase the count by one
*/
void share_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
cert->count++;
}
}
/**
* Select the OpenPGP keyid as ID
*/
identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id)
{
id->destroy(id);
return cert->fingerprint->clone(cert->fingerprint);
}
/**
* Add an OpenPGP user/host certificate to the chained list
*/
pgpcert_t* add_pgpcert(pgpcert_t *cert)
{
pgpcert_t *c = pgpcerts;
while (c != NULL)
{
if (same_pgpcert(c, cert)) /* already in chain, free cert */
{
free_pgpcert(cert);
return c;
}
c = c->next;
}
/* insert new cert at the root of the chain */
cert->next = pgpcerts;
pgpcerts = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" pgp cert inserted")
)
return cert;
}
/**
* Release of a certificate decreases the count by one.
* The certificate is freed when the counter reaches zero
*/
void release_pgpcert(pgpcert_t *cert)
{
if (cert != NULL && --cert->count == 0)
{
pgpcert_t **pp = &pgpcerts;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
free_pgpcert(cert);
}
}
/**
* Free a PGP certificate
*/
void free_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
{
DESTROY_IF(cert->public_key);
DESTROY_IF(cert->fingerprint);
free(cert->certificate.ptr);
free(cert);
}
}
/**
* List all PGP end certificates in a chained list
*/
void list_pgp_end_certs(bool utc)
{
pgpcert_t *cert = pgpcerts;
time_t now;
/* determine the current time */
time(&now);
if (cert != NULL)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
}
while (cert != NULL)
{
public_key_t *key = cert->public_key;
chunk_t keyid;
cert_t c;
c.type = CERT_PGP;
c.u.pgp = cert;
whack_log(RC_COMMENT, " ");
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" : "");
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
{
whack_log(RC_COMMENT, " keyid: %#B", &keyid);
}
cert = cert->next;
}
}

View File

@ -17,40 +17,6 @@
#ifndef _PGPCERT_H
#define _PGPCERT_H
#include <utils/identification.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
/*
* Length of PGP V3 fingerprint
*/
#define PGP_FINGERPRINT_SIZE HASH_SIZE_MD5
typedef char fingerprint_t[PGP_FINGERPRINT_SIZE];
/* access structure for an OpenPGP certificate */
typedef struct pgpcert pgpcert_t;
struct pgpcert {
pgpcert_t *next;
int version;
int count;
chunk_t certificate;
time_t created;
time_t until;
public_key_t *public_key;
identification_t *fingerprint;
};
extern const pgpcert_t pgpcert_empty;
extern bool parse_pgp(chunk_t blob, pgpcert_t *cert);
extern void share_pgpcert(pgpcert_t *cert);
extern identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
extern void free_pgpcert(pgpcert_t *cert);
#endif /* _PGPCERT_H */

View File

@ -476,7 +476,7 @@ void whack_handle(int whackctlfd)
if (msg.whack_list & LIST_CERTS)
{
list_certs(msg.whack_utc);
cert_list(msg.whack_utc);
}
if (msg.whack_list & LIST_CACERTS)

View File

@ -59,21 +59,21 @@ static smartcard_t *smartcards = NULL;
static int sc_number = 0;
const smartcard_t empty_sc = {
NULL , /* next */
0 , /* last_load */
{ CERT_NONE, {NULL} }, /* last_cert */
0 , /* count */
0 , /* number */
999999 , /* slot */
NULL , /* id */
NULL , /* label */
{ NULL, 0 } , /* pin */
FALSE , /* pinpad */
FALSE , /* valid */
FALSE , /* session_opened */
FALSE , /* logged_in */
TRUE , /* any_slot */
0L , /* session */
NULL , /* next */
0 , /* last_load */
NULL , /* last_cert */
0 , /* count */
0 , /* number */
999999 , /* slot */
NULL , /* id */
NULL , /* label */
{ NULL, 0 } , /* pin */
FALSE , /* pinpad */
FALSE , /* valid */
FALSE , /* session_opened */
FALSE , /* logged_in */
TRUE , /* any_slot */
0L , /* session */
};
#ifdef SMARTCARD /* compile with smartcard support */
@ -437,14 +437,13 @@ failed: scx_unload_pkcs11_module(mod);
/*
* retrieve a certificate object
*/
static bool scx_find_cert_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
smartcard_t *sc, cert_t *cert)
static cert_t* scx_find_cert_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, smartcard_t *sc)
{
size_t hex_len, label_len;
u_char *hex_id = NULL;
cert_t *cert;
chunk_t blob;
x509cert_t *x509cert;
CK_ATTRIBUTE attr[] = {
{ CKA_ID, NULL_PTR, 0L },
@ -452,16 +451,13 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
{ CKA_VALUE, NULL_PTR, 0L }
};
/* initialize the return argument */
*cert = cert_empty;
/* get the length of the attributes first */
CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3);
if (rv != CKR_OK)
{
plog("couldn't read the attribute sizes: %s"
, enum_show(&pkcs11_return_names, rv));
return FALSE;
return NULL;
}
free(sc->label);
@ -486,7 +482,7 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
free(hex_id);
free(sc->label);
free(blob.ptr);
return FALSE;
return NULL;
}
free(sc->id);
@ -500,22 +496,23 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session,
sc->label[label_len] = '\0';
/* parse the retrieved cert */
x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert;
x509cert->smartcard = TRUE;
x509cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (x509cert->cert)
/* initialize the return argument */
cert = malloc_thing(cert_t);
*cert = cert_empty;
cert->smartcard = TRUE;
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (cert->cert)
{
cert->type = CERT_X509_SIGNATURE;
cert->u.x509 = x509cert;
return TRUE;
return cert;
}
plog("failed to load cert from smartcard, error in X.509 certificate");
free_x509cert(x509cert);
return FALSE;
cert_free(cert);
return NULL;
}
@ -542,7 +539,7 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
CK_ULONG obj_count = 0;
time_t valid_until;
smartcard_t *sc;
x509cert_t *cert;
certificate_t *certificate;
x509_t *x509;
rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count);
@ -562,8 +559,8 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
*sc = empty_sc;
sc->any_slot = FALSE;
sc->slot = slot;
if (!scx_find_cert_object(session, object, sc, &sc->last_cert))
sc->last_cert = scx_find_cert_object(session, object, sc);
if (sc->last_cert == NULL)
{
scx_free(sc);
continue;
@ -574,10 +571,9 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
)
/* check validity of certificate */
cert = sc->last_cert.u.x509;
if (!cert->cert->get_validity(cert->cert, NULL, NULL, &valid_until))
certificate = sc->last_cert->cert;
if (!certificate->get_validity(certificate, NULL, NULL, &valid_until))
{
free_x509cert(cert);
scx_free(sc);
continue;
}
@ -586,20 +582,20 @@ static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
)
sc = scx_add(sc);
x509 = (x509_t*)cert->cert;
x509 = (x509_t*)certificate;
/* put end entity and ca certificates into different chains */
if (x509->get_flags(x509) & X509_CA)
{
sc->last_cert.u.x509 = add_authcert(cert, X509_CA);
sc->last_cert = add_authcert(sc->last_cert, X509_CA);
}
else
{
add_x509_public_key(cert, valid_until, DAL_LOCAL);
sc->last_cert.u.x509 = add_x509cert(cert);
add_public_key_from_cert(sc->last_cert, valid_until, DAL_LOCAL);
sc->last_cert = cert_add(sc->last_cert);
}
share_cert(sc->last_cert);
cert_share(sc->last_cert);
time(&sc->last_load);
}
@ -1070,67 +1066,66 @@ void scx_release_context(smartcard_t *sc)
/*
* Load host certificate from smartcard
*/
bool scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert,
bool *cached)
cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached)
{
#ifdef SMARTCARD /* compile with smartcard support */
CK_OBJECT_HANDLE object;
const char *number_slot_id = filename + strlen(SCX_TOKEN);
smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id));
CK_OBJECT_HANDLE object;
smartcard_t *sc;
cert_t *cert = NULL;
/* return the smartcard object */
*scp = sc;
*scp = sc = scx_add(scx_parse_number_slot_id(number_slot_id));
/* is there a cached smartcard certificate? */
*cached = sc->last_cert.type != CERT_NONE
&& (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
*cached = sc->last_cert &&
(time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL;
if (*cached)
{
*cert = sc->last_cert;
plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
, sc->number
, scx_print_slot(sc, "")
, sc->id
, sc->label);
return TRUE;
return sc->last_cert;
}
if (!scx_establish_context(sc))
{
scx_release_context(sc);
return FALSE;
return NULL;
}
/* find the certificate object */
if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id))
{
scx_release_context(sc);
return FALSE;
return NULL;
}
/* retrieve the certificate object */
if (!scx_find_cert_object(sc->session, object, sc, cert))
cert = scx_find_cert_object(sc->session, object, sc);
if (cert == NULL)
{
scx_release_context(sc);
return FALSE;
return NULL;
}
if (!pkcs11_keep_state)
{
scx_release_context(sc);
}
plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
, sc->number
, scx_print_slot(sc, "")
, sc->id
, sc->label);
return TRUE;
return cert;
#else
plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
return FALSE;
return NULL;
#endif
}
@ -1793,6 +1788,7 @@ void scx_free(smartcard_t *sc)
if (sc != NULL)
{
scx_release_context(sc);
cert_release(sc->last_cert);
free(sc->id);
free(sc->label);
scx_free_pin(&sc->pin);
@ -1811,7 +1807,6 @@ void scx_release(smartcard_t *sc)
while (*pp != sc)
pp = &(*pp)->next;
*pp = sc->next;
release_cert(sc->last_cert);
scx_free(sc);
}
}
@ -1875,14 +1870,16 @@ smartcard_t* scx_add(smartcard_t *smartcard)
/*
* get the smartcard that belongs to an X.509 certificate
*/
smartcard_t* scx_get(x509cert_t *cert)
smartcard_t* scx_get(cert_t *cert)
{
smartcard_t *sc = smartcards;
while (sc != NULL)
{
if (sc->last_cert.u.x509 == cert)
if (sc->last_cert == cert)
{
return sc;
}
sc = sc->next;
}
return NULL;
@ -1929,9 +1926,9 @@ void scx_list(bool utc)
whack_log(RC_COMMENT, " id: %s", sc->id);
if (sc->label != NULL)
whack_log(RC_COMMENT, " label: '%s'", sc->label);
if (sc->last_cert.type == CERT_X509_SIGNATURE)
if (sc->last_cert)
{
certificate_t *certificate = sc->last_cert.u.x509->cert;
certificate_t *certificate = sc->last_cert->cert;
whack_log(RC_COMMENT, " subject: '%Y'",
certificate->get_subject(certificate));

View File

@ -42,7 +42,7 @@ typedef struct smartcard smartcard_t;
struct smartcard {
smartcard_t *next;
time_t last_load;
cert_t last_cert;
cert_t *last_cert;
int count;
int number;
unsigned long slot;
@ -75,8 +75,7 @@ extern void scx_finalize(void);
extern bool scx_establish_context(smartcard_t *sc);
extern bool scx_login(smartcard_t *sc);
extern bool scx_on_smartcard(const char *filename);
extern bool scx_load_cert(const char *filename, smartcard_t **scp
, cert_t *cert, bool *cached);
extern cert_t* scx_load_cert(const char *filename, smartcard_t **scp, bool *cached);
extern bool scx_verify_pin(smartcard_t *sc);
extern void scx_share(smartcard_t *sc);
extern bool scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen
@ -90,7 +89,7 @@ extern bool scx_op_via_whack(const char* msg, int inbase, int outbase
extern bool scx_get_pin(smartcard_t *sc, int whackfd);
extern size_t scx_get_keylength(smartcard_t *sc);
extern smartcard_t* scx_add(smartcard_t *sc);
extern smartcard_t* scx_get(x509cert_t *cert);
extern smartcard_t* scx_get(cert_t *cert);
extern void scx_release(smartcard_t *sc);
extern void scx_release_context(smartcard_t *sc);
extern void scx_free_pin(chunk_t *pin);

View File

@ -42,100 +42,6 @@
#include "fetch.h"
#include "ocsp.h"
/**
* Chained lists of X.509 end certificates
*/
static x509cert_t *x509certs = NULL;
const x509cert_t empty_x509cert = {
NULL , /* cert */
NULL , /* *next */
0 , /* count */
FALSE /* smartcard */
};
/* coding of X.501 distinguished name */
/**
* For each link pointing to the certificate increase the count by one
*/
void share_x509cert(x509cert_t *cert)
{
if (cert != NULL)
{
cert->count++;
}
}
/**
* Add a X.509 user/host certificate to the chained list
*/
x509cert_t* add_x509cert(x509cert_t *cert)
{
certificate_t *certificate = cert->cert;
x509cert_t *c = x509certs;
while (c != NULL)
{
if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
{
free_x509cert(cert);
return c;
}
c = c->next;
}
/* insert new cert at the root of the chain */
lock_certs_and_keys("add_x509cert");
cert->next = x509certs;
x509certs = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" x509 cert inserted")
)
unlock_certs_and_keys("add_x509cert");
return cert;
}
/**
* Choose either subject DN or a subjectAltName as connection end ID
*/
identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject, *subjectAltName;
bool copy_subject_dn = TRUE; /* ID is subject DN */
if (id->get_type(id) != ID_ANY) /* check for a matching subjectAltName */
{
enumerator_t *enumerator;
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &subjectAltName))
{
if (id->equals(id, subjectAltName))
{
copy_subject_dn = FALSE; /* take subjectAltName instead */
break;
}
}
enumerator->destroy(enumerator);
}
if (copy_subject_dn)
{
id->destroy(id);
subject = certificate->get_subject(certificate);
plog(" no subjectAltName matches ID '%Y', replaced by subject DN", id);
return subject->clone(subject);
}
else
{
return id;
}
}
/**
* Check for equality between two key identifiers
*/
@ -151,9 +57,9 @@ bool same_keyid(chunk_t a, chunk_t b)
/**
* Get a X.509 certificate with a given issuer found at a certain position
*/
x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t *chain)
cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
{
x509cert_t *cert = chain ? chain->next : x509certs;
cert_t *cert = chain->next;
while (cert)
{
@ -171,48 +77,12 @@ x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t *ch
return NULL;
}
/**
* Free a X.509 certificate
*/
void free_x509cert(x509cert_t *cert)
{
if (cert)
{
certificate_t *certificate = cert->cert;
if (certificate)
{
certificate->destroy(certificate);
}
free(cert);
cert = NULL;
}
}
/**
* Release of a certificate decreases the count by one
* the certificate is freed when the counter reaches zero
*/
void release_x509cert(x509cert_t *cert)
{
if (cert && --cert->count == 0)
{
x509cert_t **pp = &x509certs;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
free_x509cert(cert);
}
}
/**
* Stores a chained list of end certs and CA certs
*/
void store_x509certs(linked_list_t *certs, bool strict)
{
x509cert_t *x509cert, *cacerts = NULL;
cert_t *x509cert, *cacerts = NULL;
certificate_t *cert;
enumerator_t *enumerator;
@ -235,8 +105,8 @@ void store_x509certs(linked_list_t *certs, bool strict)
else
{
/* insertion into temporary chain of candidate CA certs */
x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert;
x509cert = malloc_thing(cert_t);
*x509cert = cert_empty;
x509cert->cert = cert->get_ref(cert);
x509cert->next = cacerts;
cacerts = x509cert;
@ -249,7 +119,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
while (cacerts)
{
x509cert_t *cert = cacerts;
cert_t *cert = cacerts;
cacerts = cacerts->next;
@ -260,7 +130,7 @@ void store_x509certs(linked_list_t *certs, bool strict)
else
{
plog("intermediate cacert rejected");
free_x509cert(cert);
cert_free(cert);
}
}
@ -274,8 +144,8 @@ void store_x509certs(linked_list_t *certs, bool strict)
if (!(x509->get_flags(x509) & X509_CA))
{
x509cert = malloc_thing(x509cert_t);
*x509cert = empty_x509cert;
x509cert = malloc_thing(cert_t);
*x509cert = cert_empty;
x509cert->cert = cert->get_ref(cert);
if (verify_x509cert(x509cert, strict, &valid_until))
@ -283,12 +153,12 @@ void store_x509certs(linked_list_t *certs, bool strict)
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log("public key validated")
)
add_x509_public_key(x509cert, valid_until, DAL_SIGNED);
add_public_key_from_cert(x509cert, valid_until, DAL_SIGNED);
}
else
{
plog("X.509 certificate rejected");
free_x509cert(x509cert);
cert_free(x509cert);
}
}
}
@ -342,7 +212,7 @@ chunk_t x509_build_signature(chunk_t tbs, int algorithm, private_key_t *key,
/**
* Verifies a X.509 certificate
*/
bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
bool verify_x509cert(cert_t *cert, bool strict, time_t *until)
{
int pathlen, pathlen_constraint;
@ -355,7 +225,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
identification_t *issuer = certificate->get_issuer(certificate);
x509_t *x509 = (x509_t*)certificate;
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
x509cert_t *issuer_cert;
cert_t *issuer_cert;
time_t notBefore, notAfter;
bool valid;
@ -497,7 +367,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
/**
* List all X.509 certs in a chained list
*/
void list_x509cert_chain(const char *caption, x509cert_t* cert,
void list_x509cert_chain(const char *caption, cert_t* cert,
x509_flag_t flags, bool utc)
{
bool first = TRUE;
@ -511,7 +381,8 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
if (flags == X509_NONE || (flags & x509->get_flags(x509)))
if (certificate->get_type(certificate) == CERT_X509 &&
(flags == X509_NONE || (flags & x509->get_flags(x509))))
{
enumerator_t *enumerator;
char buf[BUF_LEN];
@ -522,10 +393,6 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
time_t notBefore, notAfter;
public_key_t *key;
chunk_t serial, keyid, subjkey, authkey;
cert_t c;
c.type = CERT_X509_SIGNATURE;
c.u.x509 = cert;
if (first)
{
@ -581,7 +448,7 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
key_type_names, key->get_type(key),
key->get_keysize(key) * BITS_PER_BYTE,
cert->smartcard ? ", on smartcard" :
(has_private_key(c)? ", has private key" : ""));
(has_private_key(cert)? ", has private key" : ""));
if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
{
@ -613,10 +480,3 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
}
}
/**
* List all X.509 end certificates in a chained list
*/
void list_x509_end_certs(bool utc)
{
list_x509cert_chain("End Entity", x509certs, X509_NONE, utc);
}

View File

@ -20,43 +20,21 @@
#include <utils/identification.h>
#include <utils/linked_list.h>
#include <credentials/keys/public_key.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/x509.h>
#include "constants.h"
/* access structure for an X.509v3 certificate */
typedef struct x509cert x509cert_t;
struct x509cert {
certificate_t *cert;
x509cert_t *next;
int count;
bool smartcard;
};
/* used for initialization */
extern const x509cert_t empty_x509cert;
#include "certs.h"
extern bool same_keyid(chunk_t a, chunk_t b);
extern identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0,
chunk_t *authKeyID,
chunk_t *authKeySerialNumber);
extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm,
certificate_t *issuer_cert);
extern chunk_t x509_build_signature(chunk_t tbs, int algorithm,
private_key_t *key, bool bit_string);
extern bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until);
extern x509cert_t* add_x509cert(x509cert_t *cert);
extern x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cert_t* chain);
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
extern bool verify_x509cert(cert_t *cert, bool strict, time_t *until);
extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
extern void store_x509certs(linked_list_t *certs, bool strict);
extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
extern void list_x509cert_chain(const char *caption, cert_t* cert,
x509_flag_t flags, bool utc);
extern void list_x509_end_certs(bool utc);

View File

@ -18,6 +18,7 @@
#include <freeswan.h>
#include <defs.h>
#include <constants.h>
/* copy of smartcard operations, defined in smartcard.h */
#ifndef SC_OP_T