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 PGP_MPI * bn_to_mpi(BIGNUM *bn) { int res; PGP_MPI *n; res = pgp_mpi_alloc(BN_num_bits(bn), &n); if (res < 0) return NULL; if (BN_num_bytes(bn) != n->bytes) { px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d", BN_num_bytes(bn), n->bytes); pgp_mpi_free(n); return NULL; } BN_bn2bin(bn, n->data); return n; }
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; }
int pgp_mpi_read(PullFilter * src, PGP_MPI ** mpi) { int res; uint8 hdr[2]; int bits; PGP_MPI *n; res = pullf_read_fixed(src, 2, hdr); if (res < 0) return res; bits = ((unsigned) hdr[0] << 8) + hdr[1]; res = pgp_mpi_alloc(bits, &n); if (res < 0) return res; res = pullf_read_fixed(src, n->bytes, n->data); if (res < 0) pgp_mpi_free(n); else *mpi = n; return res; }
void pgp_key_free(PGP_PubKey *pk) { 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_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt) { int ver; int algo; int res; uint8 key_id[8]; PGP_PubKey *pk; uint8 *msg; int msglen; PGP_MPI *m; pk = ctx->pub_key; if (pk == NULL) { px_debug("no pubkey?"); return PXE_BUG; } GETBYTE(pkt, ver); if (ver != 3) { px_debug("unknown pubenc_sesskey pkt ver=%d", ver); return PXE_PGP_CORRUPT_DATA; } /* * check if keyid's match - user-friendly msg */ res = pullf_read_fixed(pkt, 8, key_id); if (res < 0) return res; if (memcmp(key_id, any_key, 8) != 0 && memcmp(key_id, pk->key_id, 8) != 0) { px_debug("key_id's does not match"); return PXE_PGP_WRONG_KEY; } /* * Decrypt */ GETBYTE(pkt, algo); switch (algo) { case PGP_PUB_ELG_ENCRYPT: res = decrypt_elgamal(pk, pkt, &m); break; case PGP_PUB_RSA_ENCRYPT: case PGP_PUB_RSA_ENCRYPT_SIGN: res = decrypt_rsa(pk, pkt, &m); break; default: res = PXE_PGP_UNKNOWN_PUBALGO; } if (res < 0) return res; /* * extract message */ msg = check_eme_pkcs1_v15(m->data, m->bytes); if (msg == NULL) { px_debug("check_eme_pkcs1_v15 failed"); res = PXE_PGP_WRONG_KEY; goto out; } msglen = m->bytes - (msg - m->data); res = control_cksum(msg, msglen); if (res < 0) goto out; /* * got sesskey */ ctx->cipher_algo = *msg; ctx->sess_key_len = msglen - 3; memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len); out: pgp_mpi_free(m); if (res < 0) return res; return pgp_expect_packet_end(pkt); }