OSDN Git Service

Remove #include <openssl/bn.h> as compile fix.
[pg-rex/syncrep.git] / contrib / pgcrypto / pgp-pubdec.c
1 /*
2  * pgp-pubdec.c
3  *        Decrypt public-key encrypted session key.
4  *
5  * Copyright (c) 2005 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  *
29  * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.2 2005/07/10 15:37:03 momjian Exp $
30  */
31 #include <postgres.h>
32
33 #include "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
36
37 /*
38  * padded msg = 02 || PS || 00 || M 
39  * PS - pad bytes
40  * M - msg
41  */
42 static uint8 *
43 check_eme_pkcs1_v15(uint8 *data, int len)
44 {
45         uint8 *data_end = data + len;
46         uint8 *p = data;
47         int rnd = 0;
48
49         if (len < 1 + 8 + 1)
50                 return NULL;
51
52         if (*p++ != 2)
53                 return NULL;
54         
55         while (p < data_end && *p) {
56                 p++;
57                 rnd++;
58         }
59
60         if (p == data_end)
61                 return NULL;
62         if (*p != 0)
63                 return NULL;
64         if (rnd < 8)
65                 return NULL;
66         return p + 1;
67 }
68
69 /*
70  * secret message: 1 byte algo, sesskey, 2 byte cksum
71  * ignore algo in cksum
72  */
73 static int
74 control_cksum(uint8 *msg, int msglen)
75 {
76         int i;
77         unsigned my_cksum, got_cksum;
78
79         if (msglen < 3)
80                 return PXE_PGP_CORRUPT_DATA;
81
82         my_cksum = 0;
83         for (i = 1; i < msglen - 2; i++)
84                 my_cksum += msg[i];
85         my_cksum &= 0xFFFF;
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;
90         }
91         return 0;
92 }
93
94 /* key id is missing - user is expected to try all keys */
95 static const uint8
96 any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};
97
98 int
99 pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
100 {
101         int ver;
102         int algo;
103         int res;
104         uint8 key_id[8];
105         PGP_MPI *c1, *c2;
106         PGP_PubKey *pk;
107         uint8 *msg;
108         int msglen;
109         PGP_MPI *m;
110
111         pk = ctx->pub_key;
112         if (pk == NULL) {
113                 px_debug("no pubkey?");
114                 return PXE_BUG;
115         }
116         if (!pk->elg_p || !pk->elg_g || !pk->elg_y || !pk->elg_x) {
117                 px_debug("seckey not loaded?");
118                 return PXE_BUG;
119         }
120         
121         GETBYTE(pkt, ver);
122         if (ver != 3) {
123                 px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
124                 return PXE_PGP_CORRUPT_DATA;
125         }
126
127         /*
128          * check if keyid's match - user-friendly msg
129          */
130         res = pullf_read_fixed(pkt, 8, key_id);
131         if (res < 0)
132                 return res;
133         if (memcmp(key_id, any_key, 8) != 0
134          && memcmp(key_id, pk->key_id, 8) != 0)
135         {
136                 px_debug("key_id's does not match");
137                 return PXE_PGP_WRONG_KEYID;
138         }
139
140         GETBYTE(pkt, algo);
141         if (algo != PGP_PUB_ELG_ENCRYPT)
142         {
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;
146                 else
147                         return PXE_PGP_UNKNOWN_PUBALGO;
148         }
149
150         /*
151          * read elgamal encrypted data
152          */
153         res = pgp_mpi_read(pkt, &c1);
154         if (res < 0)
155                 return res;
156         res = pgp_mpi_read(pkt, &c2);
157         if (res < 0)
158                 return res;
159
160         /*
161          * decrypt
162          */
163         res = pgp_elgamal_decrypt(pk, c1, c2, &m);
164         if (res < 0)
165                 return res;
166
167         /*
168          * extract message
169          */
170         msg = check_eme_pkcs1_v15(m->data, m->bytes);
171         if (msg == NULL) {
172                 px_debug("check_eme_pkcs1_v15 failed");
173                 return PXE_PGP_CORRUPT_DATA;
174         }
175         msglen = m->bytes - (msg - m->data);
176
177         res = control_cksum(msg, msglen);
178         if (res < 0)
179                 return res;
180
181         /*
182          * got sesskey
183          */
184         ctx->cipher_algo = *msg;
185         ctx->sess_key_len = msglen - 3;
186         memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
187
188         return pgp_expect_packet_end(pkt);
189 }
190
191