3 * Decrypt public-key encrypted session key.
5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.3 2005/07/11 15:07:59 tgl Exp $
38 * padded msg = 02 || PS || 00 || M
43 check_eme_pkcs1_v15(uint8 *data, int len)
45 uint8 *data_end = data + len;
55 while (p < data_end && *p) {
70 * secret message: 1 byte algo, sesskey, 2 byte cksum
71 * ignore algo in cksum
74 control_cksum(uint8 *msg, int msglen)
77 unsigned my_cksum, got_cksum;
80 return PXE_PGP_CORRUPT_DATA;
83 for (i = 1; i < msglen - 2; i++)
86 got_cksum = ((unsigned)(msg[msglen-2]) << 8) + msg[msglen-1];
87 if (my_cksum != got_cksum) {
88 px_debug("pubenc cksum failed");
89 return PXE_PGP_CORRUPT_DATA;
94 /* key id is missing - user is expected to try all keys */
96 any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};
99 pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
113 px_debug("no pubkey?");
116 if (!pk->elg_p || !pk->elg_g || !pk->elg_y || !pk->elg_x) {
117 px_debug("seckey not loaded?");
123 px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
124 return PXE_PGP_CORRUPT_DATA;
128 * check if keyid's match - user-friendly msg
130 res = pullf_read_fixed(pkt, 8, key_id);
133 if (memcmp(key_id, any_key, 8) != 0
134 && memcmp(key_id, pk->key_id, 8) != 0)
136 px_debug("key_id's does not match");
137 return PXE_PGP_WRONG_KEYID;
141 if (algo != PGP_PUB_ELG_ENCRYPT)
143 px_debug("unknown public-key algo=%d", algo);
144 if (algo == PGP_PUB_RSA_ENCRYPT || algo == PGP_PUB_RSA_ENCRYPT_SIGN)
145 return PXE_PGP_RSA_UNSUPPORTED;
147 return PXE_PGP_UNKNOWN_PUBALGO;
151 * read elgamal encrypted data
153 res = pgp_mpi_read(pkt, &c1);
156 res = pgp_mpi_read(pkt, &c2);
163 res = pgp_elgamal_decrypt(pk, c1, c2, &m);
170 msg = check_eme_pkcs1_v15(m->data, m->bytes);
172 px_debug("check_eme_pkcs1_v15 failed");
173 return PXE_PGP_CORRUPT_DATA;
175 msglen = m->bytes - (msg - m->data);
177 res = control_cksum(msg, msglen);
184 ctx->cipher_algo = *msg;
185 ctx->sess_key_len = msglen - 3;
186 memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
188 return pgp_expect_packet_end(pkt);