Return to pgp_cert.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pgp |
1.1 misho 1: /* 2: * Copyright (C) 2009 Martin Willi 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include "pgp_cert.h" 17: #include "pgp_utils.h" 18: 19: #include <time.h> 20: 21: #include <utils/debug.h> 22: 23: typedef struct private_pgp_cert_t private_pgp_cert_t; 24: 25: /** 26: * Private data of an pgp_cert_t object. 27: */ 28: struct private_pgp_cert_t { 29: 30: /** 31: * Implements pgp_cert_t interface. 32: */ 33: pgp_cert_t public; 34: 35: /** 36: * Public key of the certificate 37: */ 38: public_key_t *key; 39: 40: /** 41: * version of the public key 42: */ 43: uint32_t version; 44: 45: /** 46: * creation time 47: */ 48: uint32_t created; 49: 50: /** 51: * days the certificate is valid 52: */ 53: uint32_t valid; 54: 55: /** 56: * userid of the certificate 57: */ 58: identification_t *user_id; 59: 60: /** 61: * v3 or v4 fingerprint of the PGP public key 62: */ 63: chunk_t fingerprint; 64: 65: /** 66: * full PGP encoding 67: */ 68: chunk_t encoding; 69: 70: /** 71: * reference counter 72: */ 73: refcount_t ref; 74: }; 75: 76: 77: METHOD(certificate_t, get_type, certificate_type_t, 78: private_pgp_cert_t *this) 79: { 80: return CERT_GPG; 81: } 82: 83: METHOD(certificate_t, get_subject,identification_t*, 84: private_pgp_cert_t *this) 85: { 86: return this->user_id; 87: } 88: 89: METHOD(certificate_t, get_issuer, identification_t*, 90: private_pgp_cert_t *this) 91: { 92: return this->user_id; 93: } 94: 95: METHOD(certificate_t, has_subject, id_match_t, 96: private_pgp_cert_t *this, identification_t *subject) 97: { 98: id_match_t match_user_id; 99: 100: match_user_id = this->user_id->matches(this->user_id, subject); 101: if (match_user_id == ID_MATCH_NONE && 102: subject->get_type(subject) == ID_KEY_ID && 103: chunk_equals(this->fingerprint, subject->get_encoding(subject))) 104: { 105: return ID_MATCH_PERFECT; 106: } 107: return match_user_id; 108: } 109: 110: METHOD(certificate_t, has_issuer, id_match_t, 111: private_pgp_cert_t *this, identification_t *issuer) 112: { 113: return ID_MATCH_NONE; 114: } 115: 116: METHOD(certificate_t, issued_by,bool, 117: private_pgp_cert_t *this, certificate_t *issuer, signature_params_t **scheme) 118: { 119: /* TODO: check signature blobs for a valid signature */ 120: return FALSE; 121: } 122: 123: METHOD(certificate_t, get_public_key, public_key_t*, 124: private_pgp_cert_t *this) 125: { 126: this->key->get_ref(this->key); 127: return this->key; 128: } 129: 130: METHOD(certificate_t, get_ref, certificate_t*, 131: private_pgp_cert_t *this) 132: { 133: ref_get(&this->ref); 134: return &this->public.interface.interface; 135: } 136: 137: METHOD(certificate_t, get_validity, bool, 138: private_pgp_cert_t *this, time_t *when, time_t *not_before, 139: time_t *not_after) 140: { 141: time_t t, until; 142: 143: if (when) 144: { 145: t = *when; 146: } 147: else 148: { 149: t = time(NULL); 150: } 151: if (not_before) 152: { 153: *not_before = this->created; 154: } 155: if (this->valid) 156: { 157: until = this->valid + this->created * 24 * 60 * 60; 158: } 159: else 160: { 161: /* Jan 19 03:14:07 UTC 2038 */ 162: until = TIME_32_BIT_SIGNED_MAX; 163: } 164: if (not_after) 165: { 166: *not_after = until; 167: } 168: return (t >= this->valid && t <= until); 169: } 170: 171: METHOD(certificate_t, get_encoding, bool, 172: private_pgp_cert_t *this, cred_encoding_type_t type, chunk_t *encoding) 173: { 174: if (type == CERT_PGP_PKT) 175: { 176: *encoding = chunk_clone(this->encoding); 177: return TRUE; 178: } 179: return lib->encoding->encode(lib->encoding, type, NULL, encoding, 180: CRED_PART_PGP_CERT, this->encoding, CRED_PART_END); 181: } 182: 183: METHOD(certificate_t, equals, bool, 184: private_pgp_cert_t *this, certificate_t *other) 185: { 186: chunk_t encoding; 187: bool equal; 188: 189: if (this == (private_pgp_cert_t*)other) 190: { 191: return TRUE; 192: } 193: if (other->get_type(other) != CERT_X509) 194: { 195: return FALSE; 196: } 197: if (other->equals == (void*)equals) 198: { /* skip allocation if we have the same implementation */ 199: return chunk_equals(this->encoding, ((private_pgp_cert_t*)other)->encoding); 200: } 201: if (!other->get_encoding(other, CERT_PGP_PKT, &encoding)) 202: { 203: return FALSE; 204: } 205: equal = chunk_equals(this->encoding, encoding); 206: free(encoding.ptr); 207: return equal; 208: } 209: 210: METHOD(certificate_t, destroy, void, 211: private_pgp_cert_t *this) 212: { 213: if (ref_put(&this->ref)) 214: { 215: DESTROY_IF(this->key); 216: DESTROY_IF(this->user_id); 217: free(this->fingerprint.ptr); 218: free(this->encoding.ptr); 219: free(this); 220: } 221: } 222: 223: METHOD(pgp_certificate_t, get_fingerprint, chunk_t, 224: private_pgp_cert_t *this) 225: { 226: return this->fingerprint; 227: } 228: 229: /** 230: * See header 231: */ 232: private_pgp_cert_t *create_empty() 233: { 234: private_pgp_cert_t *this; 235: 236: INIT(this, 237: .public = { 238: .interface = { 239: .interface = { 240: .get_type = _get_type, 241: .get_subject = _get_subject, 242: .get_issuer = _get_issuer, 243: .has_subject = _has_subject, 244: .has_issuer = _has_issuer, 245: .issued_by = _issued_by, 246: .get_public_key = _get_public_key, 247: .get_validity = _get_validity, 248: .get_encoding = _get_encoding, 249: .equals = _equals, 250: .get_ref = _get_ref, 251: .destroy = _destroy, 252: }, 253: .get_fingerprint = _get_fingerprint, 254: }, 255: }, 256: .ref = 1, 257: ); 258: 259: return this; 260: } 261: 262: /** 263: * Parse the public key packet of a PGP certificate 264: */ 265: static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet) 266: { 267: chunk_t pubkey_packet = packet; 268: 269: if (!pgp_read_scalar(&packet, 1, &this->version)) 270: { 271: return FALSE; 272: } 273: switch (this->version) 274: { 275: case 3: 276: if (!pgp_read_scalar(&packet, 4, &this->created) || 277: !pgp_read_scalar(&packet, 2, &this->valid)) 278: { 279: return FALSE; 280: } 281: break; 282: case 4: 283: if (!pgp_read_scalar(&packet, 4, &this->created)) 284: { 285: return FALSE; 286: } 287: break; 288: default: 289: DBG1(DBG_ASN, "PGP packet version V%d not supported", 290: this->version); 291: return FALSE; 292: } 293: if (this->valid) 294: { 295: DBG2(DBG_ASN, "L2 - created %T, valid %d days", &this->created, FALSE, 296: this->valid); 297: } 298: else 299: { 300: DBG2(DBG_ASN, "L2 - created %T, never expires", &this->created, FALSE); 301: } 302: DESTROY_IF(this->key); 303: this->key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, 304: BUILD_BLOB_PGP, packet, BUILD_END); 305: if (this->key == NULL) 306: { 307: return FALSE; 308: } 309: 310: /* compute V4 or V3 fingerprint according to section 12.2 of RFC 4880 */ 311: if (this->version == 4) 312: { 313: chunk_t pubkey_packet_header = chunk_from_chars( 314: 0x99, pubkey_packet.len / 256, pubkey_packet.len % 256 315: ); 316: hasher_t *hasher; 317: 318: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 319: if (hasher == NULL) 320: { 321: DBG1(DBG_ASN, "no SHA-1 hasher available"); 322: return FALSE; 323: } 324: if (!hasher->allocate_hash(hasher, pubkey_packet_header, NULL) || 325: !hasher->allocate_hash(hasher, pubkey_packet, &this->fingerprint)) 326: { 327: hasher->destroy(hasher); 328: return FALSE; 329: } 330: hasher->destroy(hasher); 331: DBG2(DBG_ASN, "L2 - v4 fingerprint %#B", &this->fingerprint); 332: } 333: else 334: { 335: /* V3 fingerprint is computed by public_key_t class */ 336: if (!this->key->get_fingerprint(this->key, KEYID_PGPV3, 337: &this->fingerprint)) 338: { 339: return FALSE; 340: } 341: this->fingerprint = chunk_clone(this->fingerprint); 342: DBG2(DBG_ASN, "L2 - v3 fingerprint %#B", &this->fingerprint); 343: } 344: return TRUE; 345: } 346: 347: /** 348: * Parse the signature packet of a PGP certificate 349: */ 350: static bool parse_signature(private_pgp_cert_t *this, chunk_t packet) 351: { 352: uint32_t version, len, type, created; 353: 354: if (!pgp_read_scalar(&packet, 1, &version)) 355: { 356: return FALSE; 357: } 358: 359: /* we parse only v3 or v4 signature packets */ 360: if (version != 3 && version != 4) 361: { 362: DBG2(DBG_ASN, "L2 - v%d signature ignored", version); 363: return TRUE; 364: } 365: if (version == 4) 366: { 367: if (!pgp_read_scalar(&packet, 1, &type)) 368: { 369: return FALSE; 370: } 371: DBG2(DBG_ASN, "L2 - v%d signature of type 0x%02x", version, type); 372: } 373: else 374: { 375: if (!pgp_read_scalar(&packet, 1, &len) || len != 5) 376: { 377: return FALSE; 378: } 379: if (!pgp_read_scalar(&packet, 1, &type) || 380: !pgp_read_scalar(&packet, 4, &created)) 381: { 382: return FALSE; 383: } 384: DBG2(DBG_ASN, "L2 - v3 signature of type 0x%02x, created %T", type, 385: &created, FALSE); 386: } 387: /* TODO: parse and save signature to a list */ 388: return TRUE; 389: } 390: 391: /** 392: * Parse the userid packet of a PGP certificate 393: */ 394: static bool parse_user_id(private_pgp_cert_t *this, chunk_t packet) 395: { 396: DESTROY_IF(this->user_id); 397: this->user_id = identification_create_from_encoding(ID_KEY_ID, packet); 398: DBG2(DBG_ASN, "L2 - '%Y'", this->user_id); 399: return TRUE; 400: } 401: 402: /** 403: * See header. 404: */ 405: pgp_cert_t *pgp_cert_load(certificate_type_t type, va_list args) 406: { 407: chunk_t packet, blob = chunk_empty; 408: pgp_packet_tag_t tag; 409: private_pgp_cert_t *this; 410: 411: while (TRUE) 412: { 413: switch (va_arg(args, builder_part_t)) 414: { 415: case BUILD_BLOB_PGP: 416: blob = va_arg(args, chunk_t); 417: continue; 418: case BUILD_END: 419: break; 420: default: 421: return NULL; 422: } 423: break; 424: } 425: 426: this = create_empty(); 427: this->encoding = chunk_clone(blob); 428: while (blob.len) 429: { 430: if (!pgp_read_packet(&blob, &packet, &tag)) 431: { 432: destroy(this); 433: return NULL; 434: } 435: switch (tag) 436: { 437: case PGP_PKT_PUBLIC_KEY: 438: if (!parse_public_key(this, packet)) 439: { 440: destroy(this); 441: return NULL; 442: } 443: break; 444: case PGP_PKT_SIGNATURE: 445: if (!parse_signature(this, packet)) 446: { 447: destroy(this); 448: return NULL; 449: } 450: break; 451: case PGP_PKT_USER_ID: 452: if (!parse_user_id(this, packet)) 453: { 454: destroy(this); 455: return NULL; 456: } 457: break; 458: default: 459: DBG1(DBG_LIB, "ignoring %N packet in PGP certificate", 460: pgp_packet_tag_names, tag); 461: break; 462: } 463: } 464: if (this->key) 465: { 466: return &this->public; 467: } 468: destroy(this); 469: return NULL; 470: } 471: