static int decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p) { int res; PGP_MPI *c1 = NULL; PGP_MPI *c2 = NULL; if (pk->algo != PGP_PUB_ELG_ENCRYPT) return PXE_PGP_WRONG_KEY; /* read elgamal encrypted data */ res = pgp_mpi_read(pkt, &c1); if (res < 0) goto out; res = pgp_mpi_read(pkt, &c2); if (res < 0) goto out; /* decrypt */ res = pgp_elgamal_decrypt(pk, c1, c2, m_p); out: pgp_mpi_free(c1); pgp_mpi_free(c2); return res; }
static int decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p) { int res; PGP_MPI *c; if (pk->algo != PGP_PUB_RSA_ENCRYPT && pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN) return PXE_PGP_WRONG_KEY; /* read rsa encrypted data */ res = pgp_mpi_read(pkt, &c); if (res < 0) return res; /* decrypt */ res = pgp_rsa_decrypt(pk, c, m_p); pgp_mpi_free(c); return res; }
static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p, const uint8 *key, int key_len) { 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; }
int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p) { 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; }