Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * pgp-pubkey.c
3 : : * Read public or secret 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-pubkey.c
30 : : */
31 : : #include "postgres.h"
32 : :
33 : : #include "mbuf.h"
34 : : #include "pgp.h"
35 : : #include "px.h"
36 : :
37 : : int
5421 bruce@momjian.us 38 :CBC 33 : pgp_key_alloc(PGP_PubKey **pk_p)
39 : : {
40 : : PGP_PubKey *pk;
41 : :
1297 michael@paquier.xyz 42 : 33 : pk = palloc0(sizeof(*pk));
6853 bruce@momjian.us 43 : 33 : *pk_p = pk;
44 : 33 : return 0;
45 : : }
46 : :
47 : : void
5421 48 : 32 : pgp_key_free(PGP_PubKey *pk)
49 : : {
6819 50 [ - + ]: 32 : if (pk == NULL)
6819 bruce@momjian.us 51 :UBC 0 : return;
52 : :
6819 bruce@momjian.us 53 [ + + - - ]:CBC 32 : switch (pk->algo)
54 : : {
55 : 24 : case PGP_PUB_ELG_ENCRYPT:
56 : 24 : pgp_mpi_free(pk->pub.elg.p);
57 : 24 : pgp_mpi_free(pk->pub.elg.g);
58 : 24 : pgp_mpi_free(pk->pub.elg.y);
59 : 24 : pgp_mpi_free(pk->sec.elg.x);
60 : 24 : break;
61 : 8 : case PGP_PUB_RSA_SIGN:
62 : : case PGP_PUB_RSA_ENCRYPT:
63 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
64 : 8 : pgp_mpi_free(pk->pub.rsa.n);
65 : 8 : pgp_mpi_free(pk->pub.rsa.e);
66 : 8 : pgp_mpi_free(pk->sec.rsa.d);
67 : 8 : pgp_mpi_free(pk->sec.rsa.p);
68 : 8 : pgp_mpi_free(pk->sec.rsa.q);
69 : 8 : pgp_mpi_free(pk->sec.rsa.u);
70 : 8 : break;
6819 bruce@momjian.us 71 :UBC 0 : case PGP_PUB_DSA_SIGN:
72 : 0 : pgp_mpi_free(pk->pub.dsa.p);
73 : 0 : pgp_mpi_free(pk->pub.dsa.q);
74 : 0 : pgp_mpi_free(pk->pub.dsa.g);
75 : 0 : pgp_mpi_free(pk->pub.dsa.y);
76 : 0 : pgp_mpi_free(pk->sec.dsa.x);
77 : 0 : break;
78 : : }
3650 bruce@momjian.us 79 :CBC 32 : px_memset(pk, 0, sizeof(*pk));
1297 michael@paquier.xyz 80 : 32 : pfree(pk);
81 : : }
82 : :
83 : : static int
5421 bruce@momjian.us 84 : 33 : calc_key_id(PGP_PubKey *pk)
85 : : {
86 : : int res;
87 : : PX_MD *md;
88 : : int len;
89 : : uint8 hdr[3];
90 : : uint8 hash[20];
91 : :
6853 92 : 33 : res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
93 [ - + ]: 33 : if (res < 0)
6853 bruce@momjian.us 94 :UBC 0 : return res;
95 : :
6853 bruce@momjian.us 96 :CBC 33 : len = 1 + 4 + 1;
97 [ + + - - ]: 33 : switch (pk->algo)
98 : : {
99 : 25 : case PGP_PUB_ELG_ENCRYPT:
6819 100 : 25 : len += 2 + pk->pub.elg.p->bytes;
101 : 25 : len += 2 + pk->pub.elg.g->bytes;
102 : 25 : len += 2 + pk->pub.elg.y->bytes;
103 : 25 : break;
104 : 8 : case PGP_PUB_RSA_SIGN:
105 : : case PGP_PUB_RSA_ENCRYPT:
106 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
107 : 8 : len += 2 + pk->pub.rsa.n->bytes;
108 : 8 : len += 2 + pk->pub.rsa.e->bytes;
109 : 8 : break;
6819 bruce@momjian.us 110 :UBC 0 : case PGP_PUB_DSA_SIGN:
111 : 0 : len += 2 + pk->pub.dsa.p->bytes;
112 : 0 : len += 2 + pk->pub.dsa.q->bytes;
113 : 0 : len += 2 + pk->pub.dsa.g->bytes;
114 : 0 : len += 2 + pk->pub.dsa.y->bytes;
6853 115 : 0 : break;
116 : : }
117 : :
6853 bruce@momjian.us 118 :CBC 33 : hdr[0] = 0x99;
119 : 33 : hdr[1] = len >> 8;
120 : 33 : hdr[2] = len & 0xFF;
121 : 33 : px_md_update(md, hdr, 3);
122 : :
123 : 33 : px_md_update(md, &pk->ver, 1);
124 : 33 : px_md_update(md, pk->time, 4);
125 : 33 : px_md_update(md, &pk->algo, 1);
126 : :
127 [ + + - - ]: 33 : switch (pk->algo)
128 : : {
129 : 25 : case PGP_PUB_ELG_ENCRYPT:
6819 130 : 25 : pgp_mpi_hash(md, pk->pub.elg.p);
131 : 25 : pgp_mpi_hash(md, pk->pub.elg.g);
132 : 25 : pgp_mpi_hash(md, pk->pub.elg.y);
133 : 25 : break;
134 : 8 : case PGP_PUB_RSA_SIGN:
135 : : case PGP_PUB_RSA_ENCRYPT:
136 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
137 : 8 : pgp_mpi_hash(md, pk->pub.rsa.n);
138 : 8 : pgp_mpi_hash(md, pk->pub.rsa.e);
139 : 8 : break;
6819 bruce@momjian.us 140 :UBC 0 : case PGP_PUB_DSA_SIGN:
141 : 0 : pgp_mpi_hash(md, pk->pub.dsa.p);
142 : 0 : pgp_mpi_hash(md, pk->pub.dsa.q);
143 : 0 : pgp_mpi_hash(md, pk->pub.dsa.g);
144 : 0 : pgp_mpi_hash(md, pk->pub.dsa.y);
6853 145 : 0 : break;
146 : : }
147 : :
6853 bruce@momjian.us 148 :CBC 33 : px_md_finish(md, hash);
149 : 33 : px_md_free(md);
150 : :
151 : 33 : memcpy(pk->key_id, hash + 12, 8);
3650 152 : 33 : px_memset(hash, 0, 20);
153 : :
6853 154 : 33 : return 0;
155 : : }
156 : :
157 : : int
5421 158 : 33 : _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
159 : : {
160 : : int res;
161 : : PGP_PubKey *pk;
162 : :
6819 163 : 33 : res = pgp_key_alloc(&pk);
164 [ - + ]: 33 : if (res < 0)
6819 bruce@momjian.us 165 :UBC 0 : return res;
166 : :
167 : : /* get version */
6853 bruce@momjian.us 168 [ - + ]:CBC 33 : GETBYTE(pkt, pk->ver);
6756 169 [ - + ]: 33 : if (pk->ver != 4)
170 : : {
6819 bruce@momjian.us 171 :UBC 0 : res = PXE_PGP_NOT_V4_KEYPKT;
172 : 0 : goto out;
173 : : }
174 : :
175 : : /* read time */
6853 bruce@momjian.us 176 :CBC 33 : res = pullf_read_fixed(pkt, 4, pk->time);
177 [ - + ]: 33 : if (res < 0)
6819 bruce@momjian.us 178 :UBC 0 : goto out;
179 : :
180 : : /* pubkey algorithm */
6853 bruce@momjian.us 181 [ - + ]:CBC 33 : GETBYTE(pkt, pk->algo);
182 : :
6756 183 [ - + + - ]: 33 : switch (pk->algo)
184 : : {
6853 bruce@momjian.us 185 :UBC 0 : case PGP_PUB_DSA_SIGN:
6819 186 : 0 : res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
6756 187 [ # # ]: 0 : if (res < 0)
188 : 0 : break;
6819 189 : 0 : res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
6756 190 [ # # ]: 0 : if (res < 0)
191 : 0 : break;
6819 192 : 0 : res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
6756 193 [ # # ]: 0 : if (res < 0)
194 : 0 : break;
6819 195 : 0 : res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
6756 196 [ # # ]: 0 : if (res < 0)
197 : 0 : break;
198 : :
6819 199 : 0 : res = calc_key_id(pk);
6853 200 : 0 : break;
201 : :
6819 bruce@momjian.us 202 :CBC 8 : case PGP_PUB_RSA_SIGN:
203 : : case PGP_PUB_RSA_ENCRYPT:
204 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
205 : 8 : res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
6756 206 [ - + ]: 8 : if (res < 0)
6756 bruce@momjian.us 207 :UBC 0 : break;
6819 bruce@momjian.us 208 :CBC 8 : res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
6756 209 [ - + ]: 8 : if (res < 0)
6756 bruce@momjian.us 210 :UBC 0 : break;
211 : :
6819 bruce@momjian.us 212 :CBC 8 : res = calc_key_id(pk);
213 : :
214 [ + - ]: 8 : if (pk->algo != PGP_PUB_RSA_SIGN)
215 : 8 : pk->can_encrypt = 1;
216 : 8 : break;
217 : :
6853 218 : 25 : case PGP_PUB_ELG_ENCRYPT:
6819 219 : 25 : res = pgp_mpi_read(pkt, &pk->pub.elg.p);
6756 220 [ - + ]: 25 : if (res < 0)
6756 bruce@momjian.us 221 :UBC 0 : break;
6819 bruce@momjian.us 222 :CBC 25 : res = pgp_mpi_read(pkt, &pk->pub.elg.g);
6756 223 [ - + ]: 25 : if (res < 0)
6756 bruce@momjian.us 224 :UBC 0 : break;
6819 bruce@momjian.us 225 :CBC 25 : res = pgp_mpi_read(pkt, &pk->pub.elg.y);
6756 226 [ - + ]: 25 : if (res < 0)
6756 bruce@momjian.us 227 :UBC 0 : break;
228 : :
6853 bruce@momjian.us 229 :CBC 25 : res = calc_key_id(pk);
230 : :
6819 231 : 25 : pk->can_encrypt = 1;
6853 232 : 25 : break;
233 : :
6853 bruce@momjian.us 234 :UBC 0 : default:
235 : 0 : px_debug("unknown public algo: %d", pk->algo);
236 : 0 : res = PXE_PGP_UNKNOWN_PUBALGO;
237 : : }
238 : :
6819 bruce@momjian.us 239 :CBC 33 : out:
240 [ - + ]: 33 : if (res < 0)
6819 bruce@momjian.us 241 :UBC 0 : pgp_key_free(pk);
242 : : else
6819 bruce@momjian.us 243 :CBC 33 : *pk_p = pk;
244 : :
6853 245 : 33 : return res;
246 : : }
247 : :
248 : : #define HIDE_CLEAR 0
249 : : #define HIDE_CKSUM 255
250 : : #define HIDE_SHA1 254
251 : :
252 : : static int
5421 253 : 2 : check_key_sha1(PullFilter *src, PGP_PubKey *pk)
254 : : {
255 : : int res;
256 : : uint8 got_sha1[20];
257 : : uint8 my_sha1[20];
258 : : PX_MD *md;
259 : :
6853 260 : 2 : res = pullf_read_fixed(src, 20, got_sha1);
261 [ - + ]: 2 : if (res < 0)
6853 bruce@momjian.us 262 :UBC 0 : return res;
263 : :
6853 bruce@momjian.us 264 :CBC 2 : res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
265 [ - + ]: 2 : if (res < 0)
6853 bruce@momjian.us 266 :UBC 0 : goto err;
6853 bruce@momjian.us 267 [ + + - - ]:CBC 2 : switch (pk->algo)
268 : : {
269 : 1 : case PGP_PUB_ELG_ENCRYPT:
6819 270 : 1 : pgp_mpi_hash(md, pk->sec.elg.x);
271 : 1 : break;
272 : 1 : case PGP_PUB_RSA_SIGN:
273 : : case PGP_PUB_RSA_ENCRYPT:
274 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
275 : 1 : pgp_mpi_hash(md, pk->sec.rsa.d);
276 : 1 : pgp_mpi_hash(md, pk->sec.rsa.p);
277 : 1 : pgp_mpi_hash(md, pk->sec.rsa.q);
278 : 1 : pgp_mpi_hash(md, pk->sec.rsa.u);
279 : 1 : break;
6819 bruce@momjian.us 280 :UBC 0 : case PGP_PUB_DSA_SIGN:
281 : 0 : pgp_mpi_hash(md, pk->sec.dsa.x);
6853 282 : 0 : break;
283 : : }
6853 bruce@momjian.us 284 :CBC 2 : px_md_finish(md, my_sha1);
285 : 2 : px_md_free(md);
286 : :
287 [ + - ]: 2 : if (memcmp(my_sha1, got_sha1, 20) != 0)
288 : : {
6853 bruce@momjian.us 289 :UBC 0 : px_debug("key sha1 check failed");
290 : 0 : res = PXE_PGP_KEYPKT_CORRUPT;
291 : : }
6853 bruce@momjian.us 292 :CBC 2 : err:
3650 293 : 2 : px_memset(got_sha1, 0, 20);
294 : 2 : px_memset(my_sha1, 0, 20);
6853 295 : 2 : return res;
296 : : }
297 : :
298 : : static int
5421 299 : 12 : check_key_cksum(PullFilter *src, PGP_PubKey *pk)
300 : : {
301 : : int res;
302 : : unsigned got_cksum,
6756 303 : 12 : my_cksum = 0;
304 : : uint8 buf[2];
305 : :
6853 306 : 12 : res = pullf_read_fixed(src, 2, buf);
307 [ - + ]: 12 : if (res < 0)
6853 bruce@momjian.us 308 :UBC 0 : return res;
309 : :
6756 bruce@momjian.us 310 :CBC 12 : got_cksum = ((unsigned) buf[0] << 8) + buf[1];
6853 311 [ + + - - ]: 12 : switch (pk->algo)
312 : : {
313 : 9 : case PGP_PUB_ELG_ENCRYPT:
6819 314 : 9 : my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
315 : 9 : break;
316 : 3 : case PGP_PUB_RSA_SIGN:
317 : : case PGP_PUB_RSA_ENCRYPT:
318 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
319 : 3 : my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
320 : 3 : my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
321 : 3 : my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
322 : 3 : my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
323 : 3 : break;
6819 bruce@momjian.us 324 :UBC 0 : case PGP_PUB_DSA_SIGN:
325 : 0 : my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
6853 326 : 0 : break;
327 : : }
6853 bruce@momjian.us 328 [ - + ]:CBC 12 : if (my_cksum != got_cksum)
329 : : {
6853 bruce@momjian.us 330 :UBC 0 : px_debug("key cksum check failed");
331 : 0 : return PXE_PGP_KEYPKT_CORRUPT;
332 : : }
6853 bruce@momjian.us 333 :CBC 12 : return 0;
334 : : }
335 : :
336 : : static int
5421 337 : 17 : process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
338 : : const uint8 *key, int key_len)
339 : : {
340 : : int res;
341 : : int hide_type;
342 : : int cipher_algo;
343 : : int bs;
344 : : uint8 iv[512];
6756 345 : 17 : PullFilter *pf_decrypt = NULL,
346 : : *pf_key;
347 : 17 : PGP_CFB *cfb = NULL;
348 : : PGP_S2K s2k;
349 : : PGP_PubKey *pk;
350 : :
351 : : /* first read public key part */
6819 352 : 17 : res = _pgp_read_public_key(pkt, &pk);
6853 353 [ - + ]: 17 : if (res < 0)
6853 bruce@momjian.us 354 :UBC 0 : return res;
355 : :
356 : : /*
357 : : * is secret key encrypted?
358 : : */
6853 bruce@momjian.us 359 [ - + ]:CBC 17 : GETBYTE(pkt, hide_type);
6756 360 [ + + - + ]: 17 : if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
361 : : {
6853 362 [ + + ]: 5 : if (key == NULL)
363 : 1 : return PXE_PGP_NEED_SECRET_PSW;
364 [ - + ]: 4 : GETBYTE(pkt, cipher_algo);
365 : 4 : res = pgp_s2k_read(pkt, &s2k);
366 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 367 :UBC 0 : return res;
368 : :
6853 bruce@momjian.us 369 :CBC 4 : res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
370 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 371 :UBC 0 : return res;
372 : :
6853 bruce@momjian.us 373 :CBC 4 : bs = pgp_get_cipher_block_size(cipher_algo);
6756 374 [ - + ]: 4 : if (bs == 0)
375 : : {
6853 bruce@momjian.us 376 :UBC 0 : px_debug("unknown cipher algo=%d", cipher_algo);
377 : 0 : return PXE_PGP_UNSUPPORTED_CIPHER;
378 : : }
6853 bruce@momjian.us 379 :CBC 4 : res = pullf_read_fixed(pkt, bs, iv);
380 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 381 :UBC 0 : return res;
382 : :
383 : : /*
384 : : * create decrypt filter
385 : : */
6853 bruce@momjian.us 386 :CBC 4 : res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
387 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 388 :UBC 0 : return res;
6853 bruce@momjian.us 389 :CBC 4 : res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
390 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 391 :UBC 0 : return res;
6853 bruce@momjian.us 392 :CBC 4 : pf_key = pf_decrypt;
393 : : }
6756 394 [ + - ]: 12 : else if (hide_type == HIDE_CLEAR)
395 : : {
6853 396 : 12 : pf_key = pkt;
397 : : }
398 : : else
399 : : {
6853 bruce@momjian.us 400 :UBC 0 : px_debug("unknown hide type");
401 : 0 : return PXE_PGP_KEYPKT_CORRUPT;
402 : : }
403 : :
404 : : /* read secret key */
6756 bruce@momjian.us 405 [ + + - - ]:CBC 16 : switch (pk->algo)
406 : : {
6853 407 : 5 : case PGP_PUB_RSA_SIGN:
408 : : case PGP_PUB_RSA_ENCRYPT:
409 : : case PGP_PUB_RSA_ENCRYPT_SIGN:
3992 tgl@sss.pgh.pa.us 410 : 5 : res = pgp_mpi_read(pf_key, &pk->sec.rsa.d);
6756 bruce@momjian.us 411 [ - + ]: 5 : if (res < 0)
6756 bruce@momjian.us 412 :UBC 0 : break;
3992 tgl@sss.pgh.pa.us 413 :CBC 5 : res = pgp_mpi_read(pf_key, &pk->sec.rsa.p);
6756 bruce@momjian.us 414 [ + + ]: 5 : if (res < 0)
415 : 1 : break;
3992 tgl@sss.pgh.pa.us 416 : 4 : res = pgp_mpi_read(pf_key, &pk->sec.rsa.q);
6756 bruce@momjian.us 417 [ - + ]: 4 : if (res < 0)
6756 bruce@momjian.us 418 :UBC 0 : break;
3992 tgl@sss.pgh.pa.us 419 :CBC 4 : res = pgp_mpi_read(pf_key, &pk->sec.rsa.u);
6756 bruce@momjian.us 420 [ - + ]: 4 : if (res < 0)
6756 bruce@momjian.us 421 :UBC 0 : break;
6853 bruce@momjian.us 422 :CBC 4 : break;
423 : 11 : case PGP_PUB_ELG_ENCRYPT:
6819 424 : 11 : res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
425 : 11 : break;
6819 bruce@momjian.us 426 :UBC 0 : case PGP_PUB_DSA_SIGN:
427 : 0 : res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
6853 428 : 0 : break;
429 : 0 : default:
430 : 0 : px_debug("unknown public algo: %d", pk->algo);
431 : 0 : res = PXE_PGP_KEYPKT_CORRUPT;
432 : : }
433 : : /* read checksum / sha1 */
6853 bruce@momjian.us 434 [ + + ]:CBC 16 : if (res >= 0)
435 : : {
436 [ + + ]: 14 : if (hide_type == HIDE_SHA1)
437 : 2 : res = check_key_sha1(pf_key, pk);
438 : : else
439 : 12 : res = check_key_cksum(pf_key, pk);
440 : : }
441 [ + + ]: 16 : if (res >= 0)
442 : 14 : res = pgp_expect_packet_end(pf_key);
443 : :
444 [ + + ]: 16 : if (pf_decrypt)
445 : 4 : pullf_free(pf_decrypt);
446 [ + + ]: 16 : if (cfb)
447 : 4 : pgp_cfb_free(cfb);
448 : :
6819 449 [ + + ]: 16 : if (res < 0)
450 : 2 : pgp_key_free(pk);
451 : : else
452 : 14 : *pk_p = pk;
453 : :
6853 454 : 16 : return res;
455 : : }
456 : :
457 : : static int
5421 458 : 26 : internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
459 : : const uint8 *psw, int psw_len, int pubtype)
460 : : {
6853 461 : 26 : PullFilter *pkt = NULL;
462 : : int res;
463 : : uint8 tag;
464 : : int len;
6819 465 : 26 : PGP_PubKey *enc_key = NULL;
6853 466 : 26 : PGP_PubKey *pk = NULL;
6756 467 : 26 : int got_main_key = 0;
468 : :
469 : : /*
470 : : * Search for encryption key.
471 : : *
472 : : * Error out on anything fancy.
473 : : */
474 : : while (1)
475 : : {
6853 476 : 144 : res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
477 [ + + ]: 144 : if (res <= 0)
478 : 22 : break;
479 : 122 : res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
480 [ - + ]: 122 : if (res < 0)
6853 bruce@momjian.us 481 :UBC 0 : break;
482 : :
6756 bruce@momjian.us 483 [ + + + + :CBC 122 : switch (tag)
- ]
484 : : {
6819 485 : 26 : case PGP_PKT_PUBLIC_KEY:
486 : : case PGP_PKT_SECRET_KEY:
487 [ - + ]: 26 : if (got_main_key)
488 : : {
6853 bruce@momjian.us 489 :UBC 0 : res = PXE_PGP_MULTIPLE_KEYS;
490 : 0 : break;
491 : : }
6819 bruce@momjian.us 492 :CBC 26 : got_main_key = 1;
493 : 26 : res = pgp_skip_packet(pkt);
494 : 26 : break;
495 : :
496 : 6 : case PGP_PKT_PUBLIC_SUBKEY:
497 [ - + ]: 6 : if (pubtype != 0)
6819 bruce@momjian.us 498 :UBC 0 : res = PXE_PGP_EXPECT_SECRET_KEY;
499 : : else
6819 bruce@momjian.us 500 :CBC 6 : res = _pgp_read_public_key(pkt, &pk);
6853 501 : 6 : break;
502 : :
6819 503 : 18 : case PGP_PKT_SECRET_SUBKEY:
504 [ + + ]: 18 : if (pubtype != 1)
505 : 1 : res = PXE_PGP_EXPECT_PUBLIC_KEY;
506 : : else
507 : 17 : res = process_secret_key(pkt, &pk, psw, psw_len);
6853 508 : 18 : break;
509 : :
510 : 72 : case PGP_PKT_SIGNATURE:
511 : : case PGP_PKT_MARKER:
512 : : case PGP_PKT_TRUST:
513 : : case PGP_PKT_USER_ID:
514 : : case PGP_PKT_USER_ATTR:
515 : : case PGP_PKT_PRIV_61:
516 : 72 : res = pgp_skip_packet(pkt);
517 : 72 : break;
6853 bruce@momjian.us 518 :UBC 0 : default:
519 : 0 : px_debug("unknown/unexpected packet: %d", tag);
520 : 0 : res = PXE_PGP_UNEXPECTED_PKT;
521 : : }
6853 bruce@momjian.us 522 :CBC 122 : pullf_free(pkt);
6756 523 : 122 : pkt = NULL;
524 : :
6819 525 [ + + ]: 122 : if (pk != NULL)
526 : : {
527 [ + - + - ]: 20 : if (res >= 0 && pk->can_encrypt)
528 : : {
529 [ + - ]: 20 : if (enc_key == NULL)
530 : : {
531 : 20 : enc_key = pk;
532 : 20 : pk = NULL;
533 : : }
534 : : else
6819 bruce@momjian.us 535 :UBC 0 : res = PXE_PGP_MULTIPLE_SUBKEYS;
536 : : }
537 : :
6819 bruce@momjian.us 538 [ - + ]:CBC 20 : if (pk)
6819 bruce@momjian.us 539 :UBC 0 : pgp_key_free(pk);
6819 bruce@momjian.us 540 :CBC 20 : pk = NULL;
541 : : }
542 : :
543 [ + + ]: 122 : if (res < 0)
6853 544 : 4 : break;
545 : : }
546 : :
547 [ - + ]: 26 : if (pkt)
6853 bruce@momjian.us 548 :UBC 0 : pullf_free(pkt);
549 : :
6853 bruce@momjian.us 550 [ + + ]:CBC 26 : if (res < 0)
551 : : {
6819 552 [ - + ]: 4 : if (enc_key)
6819 bruce@momjian.us 553 :UBC 0 : pgp_key_free(enc_key);
6819 bruce@momjian.us 554 :CBC 4 : return res;
555 : : }
556 : :
557 [ + + ]: 22 : if (!enc_key)
558 : 2 : res = PXE_PGP_NO_USABLE_KEY;
559 : : else
560 : 20 : *pk_p = enc_key;
561 : 22 : return res;
562 : : }
563 : :
564 : : int
5421 565 : 26 : pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
566 : : const uint8 *key, int key_len, int pubtype)
567 : : {
568 : : int res;
569 : : PullFilter *src;
6853 570 : 26 : PGP_PubKey *pk = NULL;
571 : :
572 : 26 : res = pullf_create_mbuf_reader(&src, keypkt);
573 [ - + ]: 26 : if (res < 0)
6853 bruce@momjian.us 574 :UBC 0 : return res;
575 : :
6853 bruce@momjian.us 576 :CBC 26 : res = internal_read_key(src, &pk, key, key_len, pubtype);
577 : 26 : pullf_free(src);
578 : :
579 [ + + ]: 26 : if (res >= 0)
580 : 20 : ctx->pub_key = pk;
581 : :
582 : 26 : return res < 0 ? res : 0;
583 : : }
|