1 /* Support of OpenPGP certificates
2 * Copyright (C) 2002-2009 Andreas Steffen
4 * HSR - Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include <crypto/hashers/hasher.h>
27 #include "constants.h"
38 * chained list of OpenPGP end certificates
40 static pgpcert_t
*pgpcerts
= NULL
;
45 #define PGP_KEYID_SIZE 8
47 const pgpcert_t empty_pgpcert
= {
51 { NULL
, 0 }, /* certificate */
54 NULL
, /* public key */
55 NULL
/* fingerprint */
60 * extracts the length of a PGP packet
62 static size_t pgp_old_packet_length(chunk_t
*blob
)
64 /* bits 0 and 1 define the packet length type */
65 int len_type
= 0x03 & *blob
->ptr
++;
69 /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */
70 return pgp_length(blob
, (len_type
== 0)?
1: len_type
<< 1);
74 * extracts PGP packet version (V3 or V4)
76 static u_char
pgp_version(chunk_t
*blob
)
78 u_char version
= *blob
->ptr
++;
81 DBG_log("L3 - version:");
82 DBG_log(" V%d", version
)
88 * Parse OpenPGP public key packet defined in section 5.5.2 of RFC 2440
90 static bool parse_pgp_pubkey_packet(chunk_t
*packet
, pgpcert_t
*cert
)
92 u_char version
= pgp_version(packet
);
95 if (version
< 3 || version
> 4)
97 plog("PGP packet version V%d not supported", version
);
101 /* creation date - 4 bytes */
102 cert
->created
= (time_t)pgp_length(packet
, 4);
104 DBG_log("L3 - created:");
105 DBG_log(" %T", &cert
->created
, TRUE
)
110 /* validity in days - 2 bytes */
111 cert
->until
= (time_t)pgp_length(packet
, 2);
113 /* validity of 0 days means that the key never expires */
116 cert
->until
= cert
->created
+ 24*3600*cert
->until
;
119 DBG_log("L3 - until:");
120 DBG_log(" %T", &cert
->until
, TRUE
);
124 /* public key algorithm - 1 byte */
126 DBG_log("L3 - public key algorithm:")
129 switch (pgp_length(packet
, 1))
131 case PGP_PUBKEY_ALG_RSA
:
132 case PGP_PUBKEY_ALG_RSA_SIGN_ONLY
:
136 key
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
137 BUILD_BLOB_PGP
, *packet
,
143 cert
->public_key
= key
;
147 cert
->fingerprint
= key
->get_id(key
, ID_KEY_ID
);
148 if (cert
->fingerprint
== NULL
)
155 plog(" computation of V4 key ID not implemented yet");
158 case PGP_PUBKEY_ALG_DSA
:
162 plog(" DSA public keys not supported");
168 plog(" exotic not RSA public keys not supported");
175 * Parse OpenPGP signature packet defined in section 5.2.2 of RFC 2440
177 static bool parse_pgp_signature_packet(chunk_t
*packet
, pgpcert_t
*cert
)
182 u_char version
= pgp_version(packet
);
184 /* we parse only V3 signature packets */
188 /* size byte must have the value 5 */
189 if (pgp_length(packet
, 1) != 5)
191 plog(" size must be 5");
195 /* signature type - 1 byte */
196 sig_type
= (u_char
)pgp_length(packet
, 1);
198 DBG_log("L3 - signature type: 0x%2x", sig_type
)
201 /* creation date - 4 bytes */
202 created
= (time_t)pgp_length(packet
, 4);
204 DBG_log("L3 - created:");
205 DBG_log(" %T", &cert
->created
, TRUE
)
208 /* key ID of signer - 8 bytes */
209 keyid
.ptr
= packet
->ptr
;
210 keyid
.len
= PGP_KEYID_SIZE
;
211 DBG_cond_dump_chunk(DBG_PARSING
, "L3 - key ID of signer", keyid
);
216 bool parse_pgp(chunk_t blob
, pgpcert_t
*cert
, private_key_t
**key
)
219 DBG_log("L0 - PGP file:")
221 DBG_cond_dump_chunk(DBG_RAW
, "", blob
);
225 /* parse a PGP certificate file */
226 cert
->certificate
= blob
;
227 time(&cert
->installed
);
229 else if (key
== NULL
)
231 /* should not occur, nothing to parse */
237 chunk_t packet
= chunk_empty
;
238 u_char packet_tag
= *blob
.ptr
;
241 DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag
)
244 /* bit 7 must be set */
245 if (!(packet_tag
& 0x80))
247 plog(" incorrect Packet Tag");
251 /* bit 6 set defines new packet format */
252 if (packet_tag
& 0x40)
254 plog(" new PGP packet format not supported");
259 int packet_type
= (packet_tag
& 0x3C) >> 2;
261 packet
.len
= pgp_old_packet_length(&blob
);
262 packet
.ptr
= blob
.ptr
;
263 blob
.ptr
+= packet
.len
;
264 blob
.len
-= packet
.len
;
266 DBG_log(" %N (%d), old format, %u bytes",
267 pgp_packet_tag_names
, packet_type
,
268 packet_type
, packet
.len
);
269 DBG_log("L2 - body:")
271 DBG_cond_dump_chunk(DBG_RAW
, "", packet
);
275 /* parse a PGP certificate */
278 case PGP_PKT_PUBLIC_KEY
:
279 if (!parse_pgp_pubkey_packet(&packet
, cert
))
284 case PGP_PKT_SIGNATURE
:
285 if (!parse_pgp_signature_packet(&packet
, cert
))
290 case PGP_PKT_USER_ID
:
292 DBG_log("L3 - user ID:");
293 DBG_log(" '%.*s'", (int)packet
.len
, packet
.ptr
)
302 /* parse a PGP private key file */
305 case PGP_PKT_SECRET_KEY
:
306 *key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, KEY_RSA
,
307 BUILD_BLOB_PGP
, packet
,
325 * compare two OpenPGP certificates
327 static bool same_pgpcert(pgpcert_t
*a
, pgpcert_t
*b
)
329 return a
->certificate
.len
== b
->certificate
.len
&&
330 memeq(a
->certificate
.ptr
, b
->certificate
.ptr
, b
->certificate
.len
);
334 * for each link pointing to the certificate increase the count by one
336 void share_pgpcert(pgpcert_t
*cert
)
345 * select the OpenPGP keyid as ID
347 void select_pgpcert_id(pgpcert_t
*cert
, struct id
*end_id
)
349 end_id
->kind
= ID_KEY_ID
;
350 end_id
->name
= cert
->fingerprint
->get_encoding(cert
->fingerprint
);
351 end_id
->name
= chunk_clone(end_id
->name
);
355 * add an OpenPGP user/host certificate to the chained list
357 pgpcert_t
* add_pgpcert(pgpcert_t
*cert
)
359 pgpcert_t
*c
= pgpcerts
;
363 if (same_pgpcert(c
, cert
)) /* already in chain, free cert */
371 /* insert new cert at the root of the chain */
372 cert
->next
= pgpcerts
;
374 DBG(DBG_CONTROL
| DBG_PARSING
,
375 DBG_log(" pgp cert inserted")
380 /* release of a certificate decreases the count by one
381 " the certificate is freed when the counter reaches zero
383 void release_pgpcert(pgpcert_t
*cert
)
385 if (cert
!= NULL
&& --cert
->count
== 0)
387 pgpcert_t
**pp
= &pgpcerts
;
398 * free a PGP certificate
400 void free_pgpcert(pgpcert_t
*cert
)
404 DESTROY_IF(cert
->public_key
);
405 DESTROY_IF(cert
->fingerprint
);
406 free(cert
->certificate
.ptr
);
412 * list all PGP end certificates in a chained list
414 void list_pgp_end_certs(bool utc
)
416 pgpcert_t
*cert
= pgpcerts
;
419 /* determine the current time */
424 whack_log(RC_COMMENT
, " ");
425 whack_log(RC_COMMENT
, "List of PGP End certificates:");
426 whack_log(RC_COMMENT
, " ");
431 public_key_t
*key
= cert
->public_key
;
437 whack_log(RC_COMMENT
, "%T, count: %d", &cert
->installed
, utc
, cert
->count
);
438 whack_log(RC_COMMENT
, " fingerprint: %Y", cert
->fingerprint
);
439 whack_log(RC_COMMENT
, " pubkey: %N %4d bits%s",
440 key_type_names
, key
->get_type(key
),
441 key
->get_keysize(key
) * BITS_PER_BYTE
,
442 has_private_key(c
)?
", has private key" : "");
443 whack_log(RC_COMMENT
, " keyid: %Y",
444 key
->get_id(key
, ID_PUBKEY_INFO_SHA1
));
445 whack_log(RC_COMMENT
, " created: %T", &cert
->created
, utc
);
446 whack_log(RC_COMMENT
, " until: %T %s", &cert
->until
, utc
,
447 check_expiry(cert
->until
, CA_CERT_WARNING_INTERVAL
, TRUE
));