fixed OpenPGP parsing
This commit is contained in:
parent
ca062e48ee
commit
d17a120598
|
@ -23,6 +23,7 @@
|
|||
#define PGP_H_
|
||||
|
||||
typedef enum pgp_packet_tag_t pgp_packet_tag_t;
|
||||
typedef enum pgp_pubkey_alg_t pgp_pubkey_alg_t;
|
||||
typedef enum pgp_sym_alg_t pgp_sym_alg_t;
|
||||
|
||||
#include <chunk.h>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
118
src/pluto/keys.c
118
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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue