Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * pgp-pubenc.c
3 : : * Encrypt session key with public 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 : : * contrib/pgcrypto/pgp-pubenc.c
30 : : */
31 : : #include "postgres.h"
32 : :
33 : : #include "pgp.h"
34 : : #include "px.h"
35 : :
36 : : /*
37 : : * padded msg: 02 || non-zero pad bytes || 00 || msg
38 : : */
39 : : static int
6853 bruce@momjian.us 40 :CBC 6 : pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
41 : : {
42 : : uint8 *buf,
43 : : *p;
6756 44 : 6 : int pad_len = res_len - 2 - data_len;
45 : :
6853 46 [ - + ]: 6 : if (pad_len < 8)
6853 bruce@momjian.us 47 :UBC 0 : return PXE_BUG;
48 : :
1297 michael@paquier.xyz 49 :CBC 6 : buf = palloc(res_len);
6853 bruce@momjian.us 50 : 6 : buf[0] = 0x02;
51 : :
1930 michael@paquier.xyz 52 [ - + ]: 6 : if (!pg_strong_random(buf + 1, pad_len))
53 : : {
1297 michael@paquier.xyz 54 :UBC 0 : pfree(buf);
2687 heikki.linnakangas@i 55 : 0 : return PXE_NO_RANDOM;
56 : : }
57 : :
58 : : /* pad must not contain zero bytes */
6853 bruce@momjian.us 59 :CBC 6 : p = buf + 1;
60 [ + + ]: 1282 : while (p < buf + 1 + pad_len)
61 : : {
62 [ + + ]: 1276 : if (*p == 0)
63 : : {
1930 michael@paquier.xyz 64 [ - + ]: 5 : if (!pg_strong_random(p, 1))
65 : : {
2687 heikki.linnakangas@i 66 :UBC 0 : px_memset(buf, 0, res_len);
1297 michael@paquier.xyz 67 : 0 : pfree(buf);
1930 68 : 0 : return PXE_NO_RANDOM;
69 : : }
70 : : }
6853 bruce@momjian.us 71 [ + - ]:CBC 1276 : if (*p != 0)
72 : 1276 : p++;
73 : : }
74 : :
75 : 6 : buf[pad_len + 1] = 0;
76 : 6 : memcpy(buf + pad_len + 2, data, data_len);
77 : 6 : *res_p = buf;
78 : :
79 : 6 : return 0;
80 : : }
81 : :
82 : : static int
5421 83 : 6 : create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
84 : : {
85 : : uint8 *secmsg;
86 : : int res,
87 : : i;
6756 88 : 6 : unsigned cksum = 0;
89 : 6 : int klen = ctx->sess_key_len;
90 : 6 : uint8 *padded = NULL;
91 : 6 : PGP_MPI *m = NULL;
92 : :
93 : : /* calc checksum */
6853 94 [ + + ]: 102 : for (i = 0; i < klen; i++)
95 : 96 : cksum += ctx->sess_key[i];
96 : :
97 : : /*
98 : : * create "secret message"
99 : : */
1297 michael@paquier.xyz 100 : 6 : secmsg = palloc(klen + 3);
6853 bruce@momjian.us 101 : 6 : secmsg[0] = ctx->cipher_algo;
102 : 6 : memcpy(secmsg + 1, ctx->sess_key, klen);
103 : 6 : secmsg[klen + 1] = (cksum >> 8) & 0xFF;
104 : 6 : secmsg[klen + 2] = cksum & 0xFF;
105 : :
106 : : /*
107 : : * now create a large integer of it
108 : : */
109 : 6 : res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
110 [ + - ]: 6 : if (res >= 0)
111 : : {
112 : : /* first byte will be 0x02 */
6756 113 : 6 : int full_bits = full_bytes * 8 - 6;
114 : :
6853 115 : 6 : res = pgp_mpi_create(padded, full_bits, &m);
116 : : }
117 : :
118 [ + - ]: 6 : if (padded)
119 : : {
3650 120 : 6 : px_memset(padded, 0, full_bytes);
1297 michael@paquier.xyz 121 : 6 : pfree(padded);
122 : : }
3650 bruce@momjian.us 123 : 6 : px_memset(secmsg, 0, klen + 3);
1297 michael@paquier.xyz 124 : 6 : pfree(secmsg);
125 : :
6853 bruce@momjian.us 126 [ + - ]: 6 : if (res >= 0)
127 : 6 : *msg_p = m;
128 : :
129 : 6 : return res;
130 : : }
131 : :
132 : : static int
5421 133 : 5 : encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
134 : : {
135 : : int res;
6756 136 : 5 : PGP_MPI *m = NULL,
137 : 5 : *c1 = NULL,
138 : 5 : *c2 = NULL;
139 : :
140 : : /* create padded msg */
6819 141 : 5 : res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
142 [ - + ]: 5 : if (res < 0)
6819 bruce@momjian.us 143 :UBC 0 : goto err;
144 : :
145 : : /* encrypt it */
6819 bruce@momjian.us 146 :CBC 5 : res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
147 [ - + ]: 5 : if (res < 0)
6819 bruce@momjian.us 148 :UBC 0 : goto err;
149 : :
150 : : /* write out */
6819 bruce@momjian.us 151 :CBC 5 : res = pgp_mpi_write(pkt, c1);
152 [ - + ]: 5 : if (res < 0)
6819 bruce@momjian.us 153 :UBC 0 : goto err;
6819 bruce@momjian.us 154 :CBC 5 : res = pgp_mpi_write(pkt, c2);
155 : :
156 : 5 : err:
157 : 5 : pgp_mpi_free(m);
158 : 5 : pgp_mpi_free(c1);
159 : 5 : pgp_mpi_free(c2);
160 : 5 : return res;
161 : : }
162 : :
163 : : static int
5421 164 : 1 : encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
165 : : {
166 : : int res;
6756 167 : 1 : PGP_MPI *m = NULL,
168 : 1 : *c = NULL;
169 : :
170 : : /* create padded msg */
6819 171 : 1 : res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
172 [ - + ]: 1 : if (res < 0)
6819 bruce@momjian.us 173 :UBC 0 : goto err;
174 : :
175 : : /* encrypt it */
6819 bruce@momjian.us 176 :CBC 1 : res = pgp_rsa_encrypt(pk, m, &c);
177 [ - + ]: 1 : if (res < 0)
6819 bruce@momjian.us 178 :UBC 0 : goto err;
179 : :
180 : : /* write out */
6819 bruce@momjian.us 181 :CBC 1 : res = pgp_mpi_write(pkt, c);
182 : :
183 : 1 : err:
184 : 1 : pgp_mpi_free(m);
185 : 1 : pgp_mpi_free(c);
186 : 1 : return res;
187 : : }
188 : :
189 : : int
5421 190 : 6 : pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
191 : : {
192 : : int res;
6853 193 : 6 : PGP_PubKey *pk = ctx->pub_key;
6756 194 : 6 : uint8 ver = 3;
6853 195 : 6 : PushFilter *pkt = NULL;
196 : : uint8 algo;
197 : :
6756 198 [ - + ]: 6 : if (pk == NULL)
199 : : {
6853 bruce@momjian.us 200 :UBC 0 : px_debug("no pubkey?\n");
201 : 0 : return PXE_BUG;
202 : : }
203 : :
4925 heikki.linnakangas@i 204 :CBC 6 : algo = pk->algo;
205 : :
206 : : /*
207 : : * now write packet
208 : : */
6853 bruce@momjian.us 209 : 6 : res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
210 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 211 :UBC 0 : goto err;
6853 bruce@momjian.us 212 :CBC 6 : res = pushf_write(pkt, &ver, 1);
213 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 214 :UBC 0 : goto err;
6853 bruce@momjian.us 215 :CBC 6 : res = pushf_write(pkt, pk->key_id, 8);
216 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 217 :UBC 0 : goto err;
6853 bruce@momjian.us 218 :CBC 6 : res = pushf_write(pkt, &algo, 1);
219 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 220 :UBC 0 : goto err;
221 : :
6819 bruce@momjian.us 222 [ + + - ]:CBC 6 : switch (algo)
223 : : {
224 : 5 : case PGP_PUB_ELG_ENCRYPT:
225 : 5 : res = encrypt_and_write_elgamal(ctx, pk, pkt);
226 : 5 : break;
227 : 1 : case PGP_PUB_RSA_ENCRYPT:
228 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
229 : 1 : res = encrypt_and_write_rsa(ctx, pk, pkt);
230 : 1 : break;
231 : : }
6853 232 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 233 :UBC 0 : goto err;
234 : :
235 : : /*
236 : : * done, signal packet end
237 : : */
6853 bruce@momjian.us 238 :CBC 6 : res = pushf_flush(pkt);
239 : 6 : err:
240 [ + - ]: 6 : if (pkt)
241 : 6 : pushf_free(pkt);
242 : :
243 : 6 : return res;
244 : : }
|