#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;
}
1.7.1