Mention battery-backed cache under hardware selection options.
[PostgreSQL.git] / contrib / pgcrypto / pgp-pubenc.c
blob321d2c379d947acbdabf2e4da9232fa5742d4dda
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 * $PostgreSQL$
31 #include "postgres.h"
33 #include "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
38 * padded msg: 02 || non-zero pad bytes || 00 || msg
40 static int
41 pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
43 int res;
44 uint8 *buf,
45 *p;
46 int pad_len = res_len - 2 - data_len;
48 if (pad_len < 8)
49 return PXE_BUG;
51 buf = px_alloc(res_len);
52 buf[0] = 0x02;
53 res = px_get_random_bytes(buf + 1, pad_len);
54 if (res < 0)
56 px_free(buf);
57 return res;
60 /* pad must not contain zero bytes */
61 p = buf + 1;
62 while (p < buf + 1 + pad_len)
64 if (*p == 0)
66 res = px_get_random_bytes(p, 1);
67 if (res < 0)
68 break;
70 if (*p != 0)
71 p++;
74 if (res < 0)
76 memset(buf, 0, res_len);
77 px_free(buf);
78 return res;
81 buf[pad_len + 1] = 0;
82 memcpy(buf + pad_len + 2, data, data_len);
83 *res_p = buf;
85 return 0;
88 static int
89 create_secmsg(PGP_Context * ctx, PGP_MPI ** msg_p, int full_bytes)
91 uint8 *secmsg;
92 int res,
94 unsigned cksum = 0;
95 int klen = ctx->sess_key_len;
96 uint8 *padded = NULL;
97 PGP_MPI *m = NULL;
99 /* calc checksum */
100 for (i = 0; i < klen; i++)
101 cksum += ctx->sess_key[i];
104 * create "secret message"
106 secmsg = px_alloc(klen + 3);
107 secmsg[0] = ctx->cipher_algo;
108 memcpy(secmsg + 1, ctx->sess_key, klen);
109 secmsg[klen + 1] = (cksum >> 8) & 0xFF;
110 secmsg[klen + 2] = cksum & 0xFF;
113 * now create a large integer of it
115 res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
116 if (res >= 0)
118 /* first byte will be 0x02 */
119 int full_bits = full_bytes * 8 - 6;
121 res = pgp_mpi_create(padded, full_bits, &m);
124 if (padded)
126 memset(padded, 0, full_bytes);
127 px_free(padded);
129 memset(secmsg, 0, klen + 3);
130 px_free(secmsg);
132 if (res >= 0)
133 *msg_p = m;
135 return res;
138 static int
139 encrypt_and_write_elgamal(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt)
141 int res;
142 PGP_MPI *m = NULL,
143 *c1 = NULL,
144 *c2 = NULL;
146 /* create padded msg */
147 res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
148 if (res < 0)
149 goto err;
151 /* encrypt it */
152 res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
153 if (res < 0)
154 goto err;
156 /* write out */
157 res = pgp_mpi_write(pkt, c1);
158 if (res < 0)
159 goto err;
160 res = pgp_mpi_write(pkt, c2);
162 err:
163 pgp_mpi_free(m);
164 pgp_mpi_free(c1);
165 pgp_mpi_free(c2);
166 return res;
169 static int
170 encrypt_and_write_rsa(PGP_Context * ctx, PGP_PubKey * pk, PushFilter * pkt)
172 int res;
173 PGP_MPI *m = NULL,
174 *c = NULL;
176 /* create padded msg */
177 res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
178 if (res < 0)
179 goto err;
181 /* encrypt it */
182 res = pgp_rsa_encrypt(pk, m, &c);
183 if (res < 0)
184 goto err;
186 /* write out */
187 res = pgp_mpi_write(pkt, c);
189 err:
190 pgp_mpi_free(m);
191 pgp_mpi_free(c);
192 return res;
196 pgp_write_pubenc_sesskey(PGP_Context * ctx, PushFilter * dst)
198 int res;
199 PGP_PubKey *pk = ctx->pub_key;
200 uint8 ver = 3;
201 PushFilter *pkt = NULL;
202 uint8 algo = pk->algo;
204 if (pk == NULL)
206 px_debug("no pubkey?\n");
207 return PXE_BUG;
211 * now write packet
213 res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
214 if (res < 0)
215 goto err;
216 res = pushf_write(pkt, &ver, 1);
217 if (res < 0)
218 goto err;
219 res = pushf_write(pkt, pk->key_id, 8);
220 if (res < 0)
221 goto err;
222 res = pushf_write(pkt, &algo, 1);
223 if (res < 0)
224 goto err;
226 switch (algo)
228 case PGP_PUB_ELG_ENCRYPT:
229 res = encrypt_and_write_elgamal(ctx, pk, pkt);
230 break;
231 case PGP_PUB_RSA_ENCRYPT:
232 case PGP_PUB_RSA_ENCRYPT_SIGN:
233 res = encrypt_and_write_rsa(ctx, pk, pkt);
234 break;
236 if (res < 0)
237 goto err;
240 * done, signal packet end
242 res = pushf_flush(pkt);
243 err:
244 if (pkt)
245 pushf_free(pkt);
247 return res;