#include "postgres.h"
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
Go to the source code of this file.
Defines | |
#define | HIDE_CLEAR 0 |
#define | HIDE_CKSUM 255 |
#define | HIDE_SHA1 254 |
Functions | |
int | pgp_key_alloc (PGP_PubKey **pk_p) |
void | pgp_key_free (PGP_PubKey *pk) |
static int | calc_key_id (PGP_PubKey *pk) |
int | _pgp_read_public_key (PullFilter *pkt, PGP_PubKey **pk_p) |
static int | check_key_sha1 (PullFilter *src, PGP_PubKey *pk) |
static int | check_key_cksum (PullFilter *src, PGP_PubKey *pk) |
static int | process_secret_key (PullFilter *pkt, PGP_PubKey **pk_p, const uint8 *key, int key_len) |
static int | internal_read_key (PullFilter *src, PGP_PubKey **pk_p, const uint8 *psw, int psw_len, int pubtype) |
int | pgp_set_pubkey (PGP_Context *ctx, MBuf *keypkt, const uint8 *key, int key_len, int pubtype) |
#define HIDE_CKSUM 255 |
Definition at line 250 of file pgp-pubkey.c.
Referenced by process_secret_key().
#define HIDE_CLEAR 0 |
Definition at line 249 of file pgp-pubkey.c.
Referenced by process_secret_key().
#define HIDE_SHA1 254 |
Definition at line 251 of file pgp-pubkey.c.
Referenced by process_secret_key().
int _pgp_read_public_key | ( | PullFilter * | pkt, | |
PGP_PubKey ** | pk_p | |||
) |
Definition at line 159 of file pgp-pubkey.c.
References PGP_PubKey::algo, calc_key_id(), PGP_PubKey::can_encrypt, PGP_PubKey::dsa, PGP_PubKey::elg, GETBYTE, pgp_key_alloc(), pgp_key_free(), pgp_mpi_read(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, PGP_PubKey::pub, pullf_read_fixed(), px_debug(), PGP_PubKey::rsa, PGP_PubKey::time, and PGP_PubKey::ver.
Referenced by internal_read_key(), process_secret_key(), and read_pubkey_keyid().
{ int res; PGP_PubKey *pk; res = pgp_key_alloc(&pk); if (res < 0) return res; /* get version */ GETBYTE(pkt, pk->ver); if (pk->ver != 4) { res = PXE_PGP_NOT_V4_KEYPKT; goto out; } /* read time */ res = pullf_read_fixed(pkt, 4, pk->time); if (res < 0) goto out; /* pubkey algorithm */ GETBYTE(pkt, pk->algo); switch (pk->algo) { case PGP_PUB_DSA_SIGN: res = pgp_mpi_read(pkt, &pk->pub.dsa.p); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.dsa.q); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.dsa.g); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.dsa.y); if (res < 0) break; res = calc_key_id(pk); break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: res = pgp_mpi_read(pkt, &pk->pub.rsa.n); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.rsa.e); if (res < 0) break; res = calc_key_id(pk); if (pk->algo != PGP_PUB_RSA_SIGN) pk->can_encrypt = 1; break; case PGP_PUB_ELG_ENCRYPT: res = pgp_mpi_read(pkt, &pk->pub.elg.p); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.elg.g); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->pub.elg.y); if (res < 0) break; res = calc_key_id(pk); pk->can_encrypt = 1; break; default: px_debug("unknown public algo: %d", pk->algo); res = PXE_PGP_UNKNOWN_PUBALGO; } out: if (res < 0) pgp_key_free(pk); else *pk_p = pk; return res; }
static int calc_key_id | ( | PGP_PubKey * | pk | ) | [static] |
Definition at line 85 of file pgp-pubkey.c.
References PGP_PubKey::algo, PGP_PubKey::dsa, PGP_PubKey::elg, hash(), PGP_PubKey::key_id, PGP_DIGEST_SHA1, pgp_load_digest(), pgp_mpi_hash(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, PGP_PubKey::pub, px_md_finish, px_md_free, px_md_update, PGP_PubKey::rsa, PGP_PubKey::time, and PGP_PubKey::ver.
Referenced by _pgp_read_public_key().
{ int res; PX_MD *md; int len; uint8 hdr[3]; uint8 hash[20]; res = pgp_load_digest(PGP_DIGEST_SHA1, &md); if (res < 0) return res; len = 1 + 4 + 1; switch (pk->algo) { case PGP_PUB_ELG_ENCRYPT: len += 2 + pk->pub.elg.p->bytes; len += 2 + pk->pub.elg.g->bytes; len += 2 + pk->pub.elg.y->bytes; break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: len += 2 + pk->pub.rsa.n->bytes; len += 2 + pk->pub.rsa.e->bytes; break; case PGP_PUB_DSA_SIGN: len += 2 + pk->pub.dsa.p->bytes; len += 2 + pk->pub.dsa.q->bytes; len += 2 + pk->pub.dsa.g->bytes; len += 2 + pk->pub.dsa.y->bytes; break; } hdr[0] = 0x99; hdr[1] = len >> 8; hdr[2] = len & 0xFF; px_md_update(md, hdr, 3); px_md_update(md, &pk->ver, 1); px_md_update(md, pk->time, 4); px_md_update(md, &pk->algo, 1); switch (pk->algo) { case PGP_PUB_ELG_ENCRYPT: pgp_mpi_hash(md, pk->pub.elg.p); pgp_mpi_hash(md, pk->pub.elg.g); pgp_mpi_hash(md, pk->pub.elg.y); break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: pgp_mpi_hash(md, pk->pub.rsa.n); pgp_mpi_hash(md, pk->pub.rsa.e); break; case PGP_PUB_DSA_SIGN: pgp_mpi_hash(md, pk->pub.dsa.p); pgp_mpi_hash(md, pk->pub.dsa.q); pgp_mpi_hash(md, pk->pub.dsa.g); pgp_mpi_hash(md, pk->pub.dsa.y); break; } px_md_finish(md, hash); px_md_free(md); memcpy(pk->key_id, hash + 12, 8); memset(hash, 0, 20); return 0; }
static int check_key_cksum | ( | PullFilter * | src, | |
PGP_PubKey * | pk | |||
) | [static] |
Definition at line 300 of file pgp-pubkey.c.
References PGP_PubKey::algo, buf, PGP_PubKey::dsa, PGP_PubKey::elg, pgp_mpi_cksum(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, pullf_read_fixed(), px_debug(), PGP_PubKey::rsa, and PGP_PubKey::sec.
Referenced by process_secret_key().
{ int res; unsigned got_cksum, my_cksum = 0; uint8 buf[2]; res = pullf_read_fixed(src, 2, buf); if (res < 0) return res; got_cksum = ((unsigned) buf[0] << 8) + buf[1]; switch (pk->algo) { case PGP_PUB_ELG_ENCRYPT: my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x); break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d); my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p); my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q); my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u); break; case PGP_PUB_DSA_SIGN: my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x); break; } if (my_cksum != got_cksum) { px_debug("key cksum check failed"); return PXE_PGP_KEYPKT_CORRUPT; } return 0; }
static int check_key_sha1 | ( | PullFilter * | src, | |
PGP_PubKey * | pk | |||
) | [static] |
Definition at line 254 of file pgp-pubkey.c.
References PGP_PubKey::algo, PGP_PubKey::dsa, PGP_PubKey::elg, memcmp(), PGP_DIGEST_SHA1, pgp_load_digest(), pgp_mpi_hash(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, pullf_read_fixed(), px_debug(), px_md_finish, px_md_free, PGP_PubKey::rsa, and PGP_PubKey::sec.
Referenced by process_secret_key().
{ int res; uint8 got_sha1[20]; uint8 my_sha1[20]; PX_MD *md; res = pullf_read_fixed(src, 20, got_sha1); if (res < 0) return res; res = pgp_load_digest(PGP_DIGEST_SHA1, &md); if (res < 0) goto err; switch (pk->algo) { case PGP_PUB_ELG_ENCRYPT: pgp_mpi_hash(md, pk->sec.elg.x); break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: pgp_mpi_hash(md, pk->sec.rsa.d); pgp_mpi_hash(md, pk->sec.rsa.p); pgp_mpi_hash(md, pk->sec.rsa.q); pgp_mpi_hash(md, pk->sec.rsa.u); break; case PGP_PUB_DSA_SIGN: pgp_mpi_hash(md, pk->sec.dsa.x); break; } px_md_finish(md, my_sha1); px_md_free(md); if (memcmp(my_sha1, got_sha1, 20) != 0) { px_debug("key sha1 check failed"); res = PXE_PGP_KEYPKT_CORRUPT; } err: memset(got_sha1, 0, 20); memset(my_sha1, 0, 20); return res; }
static int internal_read_key | ( | PullFilter * | src, | |
PGP_PubKey ** | pk_p, | |||
const uint8 * | psw, | |||
int | psw_len, | |||
int | pubtype | |||
) | [static] |
Definition at line 459 of file pgp-pubkey.c.
References _pgp_read_public_key(), PGP_PubKey::can_encrypt, NULL, pgp_create_pkt_reader(), pgp_key_free(), pgp_parse_pkt_hdr(), PGP_PKT_MARKER, PGP_PKT_PRIV_61, PGP_PKT_PUBLIC_KEY, PGP_PKT_PUBLIC_SUBKEY, PGP_PKT_SECRET_KEY, PGP_PKT_SECRET_SUBKEY, PGP_PKT_SIGNATURE, PGP_PKT_TRUST, PGP_PKT_USER_ATTR, PGP_PKT_USER_ID, pgp_skip_packet(), process_secret_key(), pullf_free(), and px_debug().
Referenced by pgp_set_pubkey().
{ PullFilter *pkt = NULL; int res; uint8 tag; int len; PGP_PubKey *enc_key = NULL; PGP_PubKey *pk = NULL; int got_main_key = 0; /* * Search for encryption key. * * Error out on anything fancy. */ while (1) { res = pgp_parse_pkt_hdr(src, &tag, &len, 0); if (res <= 0) break; res = pgp_create_pkt_reader(&pkt, src, len, res, NULL); if (res < 0) break; switch (tag) { case PGP_PKT_PUBLIC_KEY: case PGP_PKT_SECRET_KEY: if (got_main_key) { res = PXE_PGP_MULTIPLE_KEYS; break; } got_main_key = 1; res = pgp_skip_packet(pkt); break; case PGP_PKT_PUBLIC_SUBKEY: if (pubtype != 0) res = PXE_PGP_EXPECT_SECRET_KEY; else res = _pgp_read_public_key(pkt, &pk); break; case PGP_PKT_SECRET_SUBKEY: if (pubtype != 1) res = PXE_PGP_EXPECT_PUBLIC_KEY; else res = process_secret_key(pkt, &pk, psw, psw_len); break; case PGP_PKT_SIGNATURE: case PGP_PKT_MARKER: case PGP_PKT_TRUST: case PGP_PKT_USER_ID: case PGP_PKT_USER_ATTR: case PGP_PKT_PRIV_61: res = pgp_skip_packet(pkt); break; default: px_debug("unknown/unexpected packet: %d", tag); res = PXE_PGP_UNEXPECTED_PKT; } pullf_free(pkt); pkt = NULL; if (pk != NULL) { if (res >= 0 && pk->can_encrypt) { if (enc_key == NULL) { enc_key = pk; pk = NULL; } else res = PXE_PGP_MULTIPLE_SUBKEYS; } if (pk) pgp_key_free(pk); pk = NULL; } if (res < 0) break; } if (pkt) pullf_free(pkt); if (res < 0) { if (enc_key) pgp_key_free(enc_key); return res; } if (!enc_key) res = PXE_PGP_NO_USABLE_KEY; else *pk_p = enc_key; return res; }
int pgp_key_alloc | ( | PGP_PubKey ** | pk_p | ) |
Definition at line 38 of file pgp-pubkey.c.
References px_alloc.
Referenced by _pgp_read_public_key().
{ PGP_PubKey *pk; pk = px_alloc(sizeof(*pk)); memset(pk, 0, sizeof(*pk)); *pk_p = pk; return 0; }
void pgp_key_free | ( | PGP_PubKey * | pk | ) |
Definition at line 49 of file pgp-pubkey.c.
References PGP_PubKey::algo, PGP_PubKey::dsa, PGP_PubKey::elg, NULL, pgp_mpi_free(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, PGP_PubKey::pub, px_free, PGP_PubKey::rsa, and PGP_PubKey::sec.
Referenced by _pgp_read_public_key(), internal_read_key(), pgp_free(), process_secret_key(), and read_pubkey_keyid().
{ if (pk == NULL) return; switch (pk->algo) { case PGP_PUB_ELG_ENCRYPT: pgp_mpi_free(pk->pub.elg.p); pgp_mpi_free(pk->pub.elg.g); pgp_mpi_free(pk->pub.elg.y); pgp_mpi_free(pk->sec.elg.x); break; case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: pgp_mpi_free(pk->pub.rsa.n); pgp_mpi_free(pk->pub.rsa.e); pgp_mpi_free(pk->sec.rsa.d); pgp_mpi_free(pk->sec.rsa.p); pgp_mpi_free(pk->sec.rsa.q); pgp_mpi_free(pk->sec.rsa.u); break; case PGP_PUB_DSA_SIGN: pgp_mpi_free(pk->pub.dsa.p); pgp_mpi_free(pk->pub.dsa.q); pgp_mpi_free(pk->pub.dsa.g); pgp_mpi_free(pk->pub.dsa.y); pgp_mpi_free(pk->sec.dsa.x); break; } memset(pk, 0, sizeof(*pk)); px_free(pk); }
int pgp_set_pubkey | ( | PGP_Context * | ctx, | |
MBuf * | keypkt, | |||
const uint8 * | key, | |||
int | key_len, | |||
int | pubtype | |||
) |
Definition at line 566 of file pgp-pubkey.c.
References internal_read_key(), PGP_Context::pub_key, pullf_create_mbuf_reader(), and pullf_free().
Referenced by decrypt_internal(), and encrypt_internal().
{ int res; PullFilter *src; PGP_PubKey *pk = NULL; res = pullf_create_mbuf_reader(&src, keypkt); if (res < 0) return res; res = internal_read_key(src, &pk, key, key_len, pubtype); pullf_free(src); if (res >= 0) ctx->pub_key = pk; return res < 0 ? res : 0; }
static int process_secret_key | ( | PullFilter * | pkt, | |
PGP_PubKey ** | pk_p, | |||
const uint8 * | key, | |||
int | key_len | |||
) | [static] |
Definition at line 338 of file pgp-pubkey.c.
References _pgp_read_public_key(), PGP_PubKey::algo, check_key_cksum(), check_key_sha1(), debug_expect::cipher_algo, PGP_PubKey::dsa, PGP_PubKey::elg, GETBYTE, HIDE_CKSUM, HIDE_CLEAR, HIDE_SHA1, PGP_S2K::key, PGP_S2K::key_len, NULL, pgp_cfb_create(), pgp_cfb_free(), pgp_decrypt_filter, pgp_expect_packet_end(), pgp_get_cipher_block_size(), pgp_key_free(), pgp_mpi_read(), PGP_PUB_DSA_SIGN, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_PUB_RSA_SIGN, pgp_s2k_process(), pgp_s2k_read(), pullf_create(), pullf_free(), pullf_read_fixed(), px_debug(), PGP_PubKey::rsa, and PGP_PubKey::sec.
Referenced by internal_read_key().
{ int res; int hide_type; int cipher_algo; int bs; uint8 iv[512]; PullFilter *pf_decrypt = NULL, *pf_key; PGP_CFB *cfb = NULL; PGP_S2K s2k; PGP_PubKey *pk; /* first read public key part */ res = _pgp_read_public_key(pkt, &pk); if (res < 0) return res; /* * is secret key encrypted? */ GETBYTE(pkt, hide_type); if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM) { if (key == NULL) return PXE_PGP_NEED_SECRET_PSW; GETBYTE(pkt, cipher_algo); res = pgp_s2k_read(pkt, &s2k); if (res < 0) return res; res = pgp_s2k_process(&s2k, cipher_algo, key, key_len); if (res < 0) return res; bs = pgp_get_cipher_block_size(cipher_algo); if (bs == 0) { px_debug("unknown cipher algo=%d", cipher_algo); return PXE_PGP_UNSUPPORTED_CIPHER; } res = pullf_read_fixed(pkt, bs, iv); if (res < 0) return res; /* * create decrypt filter */ res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv); if (res < 0) return res; res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt); if (res < 0) return res; pf_key = pf_decrypt; } else if (hide_type == HIDE_CLEAR) { pf_key = pkt; } else { px_debug("unknown hide type"); return PXE_PGP_KEYPKT_CORRUPT; } /* read secret key */ switch (pk->algo) { case PGP_PUB_RSA_SIGN: case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: res = pgp_mpi_read(pkt, &pk->sec.rsa.d); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->sec.rsa.p); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->sec.rsa.q); if (res < 0) break; res = pgp_mpi_read(pkt, &pk->sec.rsa.u); if (res < 0) break; break; case PGP_PUB_ELG_ENCRYPT: res = pgp_mpi_read(pf_key, &pk->sec.elg.x); break; case PGP_PUB_DSA_SIGN: res = pgp_mpi_read(pf_key, &pk->sec.dsa.x); break; default: px_debug("unknown public algo: %d", pk->algo); res = PXE_PGP_KEYPKT_CORRUPT; } /* read checksum / sha1 */ if (res >= 0) { if (hide_type == HIDE_SHA1) res = check_key_sha1(pf_key, pk); else res = check_key_cksum(pf_key, pk); } if (res >= 0) res = pgp_expect_packet_end(pf_key); if (pf_decrypt) pullf_free(pf_decrypt); if (cfb) pgp_cfb_free(cfb); if (res < 0) pgp_key_free(pk); else *pk_p = pk; return res; }