At update of non-LP_NORMAL TID, fail instead of corrupting page header.
[pgsql.git] / contrib / pgcrypto / pgp-pubenc.c
blobc254a3727506a23639871bf7fac80f4ee46bd471
1 /*
2 * pgp-pubenc.c
3 * Encrypt session key with public key.
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
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.
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.
29 * contrib/pgcrypto/pgp-pubenc.c
31 #include "postgres.h"
33 #include "pgp.h"
34 #include "px.h"
37 * padded msg: 02 || non-zero pad bytes || 00 || msg
39 static int
40 pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
42 uint8 *buf,
43 *p;
44 int pad_len = res_len - 2 - data_len;
46 if (pad_len < 8)
47 return PXE_BUG;
49 buf = palloc(res_len);
50 buf[0] = 0x02;
52 if (!pg_strong_random(buf + 1, pad_len))
54 pfree(buf);
55 return PXE_NO_RANDOM;
58 /* pad must not contain zero bytes */
59 p = buf + 1;
60 while (p < buf + 1 + pad_len)
62 if (*p == 0)
64 if (!pg_strong_random(p, 1))
66 px_memset(buf, 0, res_len);
67 pfree(buf);
68 return PXE_NO_RANDOM;
71 if (*p != 0)
72 p++;
75 buf[pad_len + 1] = 0;
76 memcpy(buf + pad_len + 2, data, data_len);
77 *res_p = buf;
79 return 0;
82 static int
83 create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
85 uint8 *secmsg;
86 int res,
88 unsigned cksum = 0;
89 int klen = ctx->sess_key_len;
90 uint8 *padded = NULL;
91 PGP_MPI *m = NULL;
93 /* calc checksum */
94 for (i = 0; i < klen; i++)
95 cksum += ctx->sess_key[i];
98 * create "secret message"
100 secmsg = palloc(klen + 3);
101 secmsg[0] = ctx->cipher_algo;
102 memcpy(secmsg + 1, ctx->sess_key, klen);
103 secmsg[klen + 1] = (cksum >> 8) & 0xFF;
104 secmsg[klen + 2] = cksum & 0xFF;
107 * now create a large integer of it
109 res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
110 if (res >= 0)
112 /* first byte will be 0x02 */
113 int full_bits = full_bytes * 8 - 6;
115 res = pgp_mpi_create(padded, full_bits, &m);
118 if (padded)
120 px_memset(padded, 0, full_bytes);
121 pfree(padded);
123 px_memset(secmsg, 0, klen + 3);
124 pfree(secmsg);
126 if (res >= 0)
127 *msg_p = m;
129 return res;
132 static int
133 encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
135 int res;
136 PGP_MPI *m = NULL,
137 *c1 = NULL,
138 *c2 = NULL;
140 /* create padded msg */
141 res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
142 if (res < 0)
143 goto err;
145 /* encrypt it */
146 res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
147 if (res < 0)
148 goto err;
150 /* write out */
151 res = pgp_mpi_write(pkt, c1);
152 if (res < 0)
153 goto err;
154 res = pgp_mpi_write(pkt, c2);
156 err:
157 pgp_mpi_free(m);
158 pgp_mpi_free(c1);
159 pgp_mpi_free(c2);
160 return res;
163 static int
164 encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
166 int res;
167 PGP_MPI *m = NULL,
168 *c = NULL;
170 /* create padded msg */
171 res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
172 if (res < 0)
173 goto err;
175 /* encrypt it */
176 res = pgp_rsa_encrypt(pk, m, &c);
177 if (res < 0)
178 goto err;
180 /* write out */
181 res = pgp_mpi_write(pkt, c);
183 err:
184 pgp_mpi_free(m);
185 pgp_mpi_free(c);
186 return res;
190 pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
192 int res;
193 PGP_PubKey *pk = ctx->pub_key;
194 uint8 ver = 3;
195 PushFilter *pkt = NULL;
196 uint8 algo;
198 if (pk == NULL)
200 px_debug("no pubkey?\n");
201 return PXE_BUG;
204 algo = pk->algo;
207 * now write packet
209 res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
210 if (res < 0)
211 goto err;
212 res = pushf_write(pkt, &ver, 1);
213 if (res < 0)
214 goto err;
215 res = pushf_write(pkt, pk->key_id, 8);
216 if (res < 0)
217 goto err;
218 res = pushf_write(pkt, &algo, 1);
219 if (res < 0)
220 goto err;
222 switch (algo)
224 case PGP_PUB_ELG_ENCRYPT:
225 res = encrypt_and_write_elgamal(ctx, pk, pkt);
226 break;
227 case PGP_PUB_RSA_ENCRYPT:
228 case PGP_PUB_RSA_ENCRYPT_SIGN:
229 res = encrypt_and_write_rsa(ctx, pk, pkt);
230 break;
232 if (res < 0)
233 goto err;
236 * done, signal packet end
238 res = pushf_flush(pkt);
239 err:
240 if (pkt)
241 pushf_free(pkt);
243 return res;