Branch data Line data Source code
1 : : /*
2 : : * pgp-decrypt.c
3 : : * OpenPGP decrypt.
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-decrypt.c
30 : : */
31 : :
32 : : #include "postgres.h"
33 : :
34 : : #include "mbuf.h"
35 : : #include "pgp.h"
36 : : #include "px.h"
37 : :
38 : : #define NO_CTX_SIZE 0
39 : : #define ALLOW_CTX_SIZE 1
40 : : #define NO_COMPR 0
41 : : #define ALLOW_COMPR 1
42 : : #define NO_MDC 0
43 : : #define NEED_MDC 1
44 : :
45 : : #define PKT_NORMAL 1
46 : : #define PKT_STREAM 2
47 : : #define PKT_CONTEXT 3
48 : :
49 : : #define MAX_CHUNK (16*1024*1024)
50 : :
51 : : static int
52 : 280 : parse_new_len(PullFilter *src, int *len_p)
53 : : {
54 : : uint8 b;
55 : : int len;
56 : 280 : int pkttype = PKT_NORMAL;
57 : :
58 [ - + ]: 280 : GETBYTE(src, b);
59 [ + + ]: 280 : if (b <= 191)
60 : 251 : len = b;
61 [ + - + + ]: 29 : else if (b >= 192 && b <= 223)
62 : : {
63 : 13 : len = ((unsigned) (b) - 192) << 8;
64 [ - + ]: 13 : GETBYTE(src, b);
65 : 13 : len += 192 + b;
66 : : }
67 [ + + ]: 16 : else if (b == 255)
68 : : {
69 [ - + ]: 1 : GETBYTE(src, b);
70 : 1 : len = b;
71 [ - + ]: 1 : GETBYTE(src, b);
72 : 1 : len = (len << 8) | b;
73 [ - + ]: 1 : GETBYTE(src, b);
74 : 1 : len = (len << 8) | b;
75 [ - + ]: 1 : GETBYTE(src, b);
76 : 1 : len = (len << 8) | b;
77 : : }
78 : : else
79 : : {
80 : 15 : len = 1 << (b & 0x1F);
81 : 15 : pkttype = PKT_STREAM;
82 : : }
83 : :
84 [ + - - + ]: 280 : if (len < 0 || len > MAX_CHUNK)
85 : : {
86 : 0 : px_debug("parse_new_len: weird length");
87 : 0 : return PXE_PGP_CORRUPT_DATA;
88 : : }
89 : :
90 : 280 : *len_p = len;
91 : 280 : return pkttype;
92 : : }
93 : :
94 : : static int
95 : 230 : parse_old_len(PullFilter *src, int *len_p, int lentype)
96 : : {
97 : : uint8 b;
98 : : int len;
99 : :
100 [ - + ]: 230 : GETBYTE(src, b);
101 : 230 : len = b;
102 : :
103 [ + + ]: 230 : if (lentype == 1)
104 : : {
105 [ - + ]: 109 : GETBYTE(src, b);
106 : 109 : len = (len << 8) | b;
107 : : }
108 [ - + ]: 121 : else if (lentype == 2)
109 : : {
110 [ # # ]: 0 : GETBYTE(src, b);
111 : 0 : len = (len << 8) | b;
112 [ # # ]: 0 : GETBYTE(src, b);
113 : 0 : len = (len << 8) | b;
114 [ # # ]: 0 : GETBYTE(src, b);
115 : 0 : len = (len << 8) | b;
116 : : }
117 : :
118 [ + - - + ]: 230 : if (len < 0 || len > MAX_CHUNK)
119 : : {
120 : 0 : px_debug("parse_old_len: weird length");
121 : 0 : return PXE_PGP_CORRUPT_DATA;
122 : : }
123 : 230 : *len_p = len;
124 : 230 : return PKT_NORMAL;
125 : : }
126 : :
127 : : /* returns pkttype or 0 on eof */
128 : : int
129 : 679 : pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p, int allow_ctx)
130 : : {
131 : : int lentype;
132 : : int res;
133 : : uint8 *p;
134 : :
135 : : /* EOF is normal here, thus we don't use GETBYTE */
136 : 679 : res = pullf_read(src, 1, &p);
137 [ - + ]: 679 : if (res < 0)
138 : 0 : return res;
139 [ + + ]: 679 : if (res == 0)
140 : 178 : return 0;
141 : :
142 [ + + ]: 501 : if ((*p & 0x80) == 0)
143 : : {
144 : 1 : px_debug("pgp_parse_pkt_hdr: not pkt hdr");
145 : 1 : return PXE_PGP_CORRUPT_DATA;
146 : : }
147 : :
148 [ + + ]: 500 : if (*p & 0x40)
149 : : {
150 : 267 : *tag = *p & 0x3f;
151 : 267 : res = parse_new_len(src, len_p);
152 : : }
153 : : else
154 : : {
155 : 233 : lentype = *p & 3;
156 : 233 : *tag = (*p >> 2) & 0x0F;
157 [ + + ]: 233 : if (lentype == 3)
158 [ + - ]: 3 : res = allow_ctx ? PKT_CONTEXT : PXE_PGP_CORRUPT_DATA;
159 : : else
160 : 230 : res = parse_old_len(src, len_p, lentype);
161 : : }
162 : 500 : return res;
163 : : }
164 : :
165 : : /*
166 : : * Packet reader
167 : : */
168 : : struct PktData
169 : : {
170 : : int type;
171 : : int len;
172 : : };
173 : :
174 : : static int
175 : 2688 : pktreader_pull(void *priv, PullFilter *src, int len,
176 : : uint8 **data_p, uint8 *buf, int buflen)
177 : : {
178 : : int res;
179 : 2688 : struct PktData *pkt = priv;
180 : :
181 : : /* PKT_CONTEXT means: whatever there is */
182 [ - + ]: 2688 : if (pkt->type == PKT_CONTEXT)
183 : 0 : return pullf_read(src, len, data_p);
184 : :
185 [ + + ]: 2701 : while (pkt->len == 0)
186 : : {
187 : : /* this was last chunk in stream */
188 [ + + ]: 423 : if (pkt->type == PKT_NORMAL)
189 : 410 : return 0;
190 : :
191 : : /* next chunk in stream */
192 : 13 : res = parse_new_len(src, &pkt->len);
193 [ - + ]: 13 : if (res < 0)
194 : 0 : return res;
195 : 13 : pkt->type = res;
196 : : }
197 : :
198 [ + + ]: 2278 : if (len > pkt->len)
199 : 276 : len = pkt->len;
200 : :
201 : 2278 : res = pullf_read(src, len, data_p);
202 [ + - ]: 2278 : if (res > 0)
203 : 2278 : pkt->len -= res;
204 : :
205 : 2278 : return res;
206 : : }
207 : :
208 : : static void
209 : 493 : pktreader_free(void *priv)
210 : : {
211 : 493 : struct PktData *pkt = priv;
212 : :
213 : 493 : px_memset(pkt, 0, sizeof(*pkt));
214 : 493 : pfree(pkt);
215 : 493 : }
216 : :
217 : : static struct PullFilterOps pktreader_filter = {
218 : : NULL, pktreader_pull, pktreader_free
219 : : };
220 : :
221 : : /* needs helper function to pass several parameters */
222 : : int
223 : 497 : pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
224 : : int pkttype, PGP_Context *ctx)
225 : : {
226 : : int res;
227 : 497 : struct PktData *pkt = palloc_object(struct PktData);
228 : :
229 : 497 : pkt->type = pkttype;
230 : 497 : pkt->len = len;
231 : 497 : res = pullf_create(pf_p, &pktreader_filter, pkt, src);
232 [ - + ]: 497 : if (res < 0)
233 : 0 : pfree(pkt);
234 : 497 : return res;
235 : : }
236 : :
237 : : /*
238 : : * Prefix check filter
239 : : * https://tools.ietf.org/html/rfc4880#section-5.7
240 : : * https://tools.ietf.org/html/rfc4880#section-5.13
241 : : */
242 : :
243 : : static int
244 : 76 : prefix_init(void **priv_p, void *arg, PullFilter *src)
245 : : {
246 : 76 : PGP_Context *ctx = arg;
247 : : int len;
248 : : int res;
249 : : uint8 *buf;
250 : : uint8 tmpbuf[PGP_MAX_BLOCK + 2];
251 : :
252 : 76 : len = pgp_get_cipher_block_size(ctx->cipher_algo);
253 : : /* Make sure we have space for prefix */
254 [ - + ]: 76 : if (len > PGP_MAX_BLOCK)
255 : 0 : return PXE_BUG;
256 : :
257 : 76 : res = pullf_read_max(src, len + 2, &buf, tmpbuf);
258 [ - + ]: 72 : if (res < 0)
259 : 0 : return res;
260 [ - + ]: 72 : if (res != len + 2)
261 : : {
262 : 0 : px_debug("prefix_init: short read");
263 : 0 : px_memset(tmpbuf, 0, sizeof(tmpbuf));
264 : 0 : return PXE_PGP_CORRUPT_DATA;
265 : : }
266 : :
267 [ + + - + ]: 72 : if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1])
268 : : {
269 : 3 : px_debug("prefix_init: corrupt prefix");
270 : : /* report error in pgp_decrypt() */
271 : 3 : ctx->corrupt_prefix = 1;
272 : : }
273 : 72 : px_memset(tmpbuf, 0, sizeof(tmpbuf));
274 : 72 : return 0;
275 : : }
276 : :
277 : : static struct PullFilterOps prefix_filter = {
278 : : prefix_init, NULL, NULL
279 : : };
280 : :
281 : :
282 : : /*
283 : : * Decrypt filter
284 : : */
285 : :
286 : : static int
287 : 80 : decrypt_init(void **priv_p, void *arg, PullFilter *src)
288 : : {
289 : 80 : PGP_CFB *cfb = arg;
290 : :
291 : 80 : *priv_p = cfb;
292 : :
293 : : /* we need to write somewhere, so ask for a buffer */
294 : 80 : return 4096;
295 : : }
296 : :
297 : : static int
298 : 817 : decrypt_read(void *priv, PullFilter *src, int len,
299 : : uint8 **data_p, uint8 *buf, int buflen)
300 : : {
301 : 817 : PGP_CFB *cfb = priv;
302 : : uint8 *tmp;
303 : : int res;
304 : :
305 : 817 : res = pullf_read(src, len, &tmp);
306 [ + + ]: 817 : if (res > 0)
307 : : {
308 : 742 : pgp_cfb_decrypt(cfb, tmp, res, buf);
309 : 738 : *data_p = buf;
310 : : }
311 : 813 : return res;
312 : : }
313 : :
314 : : struct PullFilterOps pgp_decrypt_filter = {
315 : : decrypt_init, decrypt_read, NULL
316 : : };
317 : :
318 : :
319 : : /*
320 : : * MDC hasher filter
321 : : */
322 : :
323 : : static int
324 : 74 : mdc_init(void **priv_p, void *arg, PullFilter *src)
325 : : {
326 : 74 : PGP_Context *ctx = arg;
327 : :
328 : 74 : *priv_p = ctx;
329 : 74 : return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx);
330 : : }
331 : :
332 : : static void
333 : 70 : mdc_free(void *priv)
334 : : {
335 : 70 : PGP_Context *ctx = priv;
336 : :
337 [ + + ]: 70 : if (ctx->use_mdcbuf_filter)
338 : 3 : return;
339 : 67 : px_md_free(ctx->mdc_ctx);
340 : 67 : ctx->mdc_ctx = NULL;
341 : : }
342 : :
343 : : static int
344 : 65 : mdc_finish(PGP_Context *ctx, PullFilter *src, int len)
345 : : {
346 : : int res;
347 : : uint8 hash[20];
348 : : uint8 tmpbuf[20];
349 : : uint8 *data;
350 : :
351 : : /* should not happen */
352 [ - + ]: 65 : if (ctx->use_mdcbuf_filter)
353 : 0 : return PXE_BUG;
354 : :
355 : : /* It's SHA1 */
356 [ - + ]: 65 : if (len != 20)
357 : 0 : return PXE_PGP_CORRUPT_DATA;
358 : :
359 : : /* mdc_read should not call px_md_update */
360 : 65 : ctx->in_mdc_pkt = 1;
361 : :
362 : : /* read data */
363 : 65 : res = pullf_read_max(src, len, &data, tmpbuf);
364 [ - + ]: 65 : if (res < 0)
365 : 0 : return res;
366 [ - + ]: 65 : if (res == 0)
367 : : {
368 : 0 : px_debug("no mdc");
369 : 0 : return PXE_PGP_CORRUPT_DATA;
370 : : }
371 : :
372 : : /* is the packet sane? */
373 [ - + ]: 65 : if (res != 20)
374 : : {
375 : 0 : px_debug("mdc_finish: read failed, res=%d", res);
376 : 0 : return PXE_PGP_CORRUPT_DATA;
377 : : }
378 : :
379 : : /*
380 : : * ok, we got the hash, now check
381 : : */
382 : 65 : px_md_finish(ctx->mdc_ctx, hash);
383 : 65 : res = memcmp(hash, data, 20);
384 : 65 : px_memset(hash, 0, 20);
385 : 65 : px_memset(tmpbuf, 0, sizeof(tmpbuf));
386 [ - + ]: 65 : if (res != 0)
387 : : {
388 : 0 : px_debug("mdc_finish: mdc failed");
389 : 0 : return PXE_PGP_CORRUPT_DATA;
390 : : }
391 : 65 : return 0;
392 : : }
393 : :
394 : : static int
395 : 778 : mdc_read(void *priv, PullFilter *src, int len,
396 : : uint8 **data_p, uint8 *buf, int buflen)
397 : : {
398 : : int res;
399 : 778 : PGP_Context *ctx = priv;
400 : :
401 : : /* skip this filter? */
402 [ + + + + ]: 778 : if (ctx->use_mdcbuf_filter || ctx->in_mdc_pkt)
403 : 137 : return pullf_read(src, len, data_p);
404 : :
405 : 641 : res = pullf_read(src, len, data_p);
406 [ - + ]: 637 : if (res < 0)
407 : 0 : return res;
408 [ - + ]: 637 : if (res == 0)
409 : : {
410 : 0 : px_debug("mdc_read: unexpected eof");
411 : 0 : return PXE_PGP_CORRUPT_DATA;
412 : : }
413 : 637 : px_md_update(ctx->mdc_ctx, *data_p, res);
414 : :
415 : 637 : return res;
416 : : }
417 : :
418 : : static struct PullFilterOps mdc_filter = {
419 : : mdc_init, mdc_read, mdc_free
420 : : };
421 : :
422 : :
423 : : /*
424 : : * Combined Pkt reader and MDC hasher.
425 : : *
426 : : * For the case of SYMENCRYPTED_DATA_MDC packet, where
427 : : * the data part has 'context length', which means
428 : : * that data packet ends 22 bytes before end of parent
429 : : * packet, which is silly.
430 : : */
431 : : #define MDCBUF_LEN 8192
432 : : struct MDCBufData
433 : : {
434 : : PGP_Context *ctx;
435 : : int eof;
436 : : int buflen;
437 : : int avail;
438 : : uint8 *pos;
439 : : int mdc_avail;
440 : : uint8 mdc_buf[22];
441 : : uint8 buf[MDCBUF_LEN];
442 : : };
443 : :
444 : : static int
445 : 3 : mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
446 : : {
447 : 3 : PGP_Context *ctx = arg;
448 : : struct MDCBufData *st;
449 : :
450 : 3 : st = palloc0_object(struct MDCBufData);
451 : 3 : st->buflen = sizeof(st->buf);
452 : 3 : st->ctx = ctx;
453 : 3 : *priv_p = st;
454 : :
455 : : /* take over the work of mdc_filter */
456 : 3 : ctx->use_mdcbuf_filter = 1;
457 : :
458 : 3 : return 0;
459 : : }
460 : :
461 : : static int
462 : 3 : mdcbuf_finish(struct MDCBufData *st)
463 : : {
464 : : uint8 hash[20];
465 : : int res;
466 : :
467 : 3 : st->eof = 1;
468 : :
469 [ + + - + ]: 3 : if (st->mdc_buf[0] != 0xD3 || st->mdc_buf[1] != 0x14)
470 : : {
471 : 2 : px_debug("mdcbuf_finish: bad MDC pkt hdr");
472 : 2 : return PXE_PGP_CORRUPT_DATA;
473 : : }
474 : 1 : px_md_update(st->ctx->mdc_ctx, st->mdc_buf, 2);
475 : 1 : px_md_finish(st->ctx->mdc_ctx, hash);
476 : 1 : res = memcmp(hash, st->mdc_buf + 2, 20);
477 : 1 : px_memset(hash, 0, 20);
478 [ - + ]: 1 : if (res)
479 : : {
480 : 0 : px_debug("mdcbuf_finish: MDC does not match");
481 : 0 : res = PXE_PGP_CORRUPT_DATA;
482 : : }
483 : 1 : return res;
484 : : }
485 : :
486 : : static void
487 : 6 : mdcbuf_load_data(struct MDCBufData *st, uint8 *src, int len)
488 : : {
489 : 6 : uint8 *dst = st->pos + st->avail;
490 : :
491 : 6 : memcpy(dst, src, len);
492 : 6 : px_md_update(st->ctx->mdc_ctx, src, len);
493 : 6 : st->avail += len;
494 : 6 : }
495 : :
496 : : static void
497 : 3 : mdcbuf_load_mdc(struct MDCBufData *st, uint8 *src, int len)
498 : : {
499 : 3 : memmove(st->mdc_buf + st->mdc_avail, src, len);
500 : 3 : st->mdc_avail += len;
501 : 3 : }
502 : :
503 : : static int
504 : 6 : mdcbuf_refill(struct MDCBufData *st, PullFilter *src)
505 : : {
506 : : uint8 *data;
507 : : int res;
508 : : int need;
509 : :
510 : : /* put avail data in start */
511 [ + + + - ]: 6 : if (st->avail > 0 && st->pos != st->buf)
512 : 3 : memmove(st->buf, st->pos, st->avail);
513 : 6 : st->pos = st->buf;
514 : :
515 : : /* read new data */
516 : 6 : need = st->buflen + 22 - st->avail - st->mdc_avail;
517 : 6 : res = pullf_read(src, need, &data);
518 [ - + ]: 6 : if (res < 0)
519 : 0 : return res;
520 [ + + ]: 6 : if (res == 0)
521 : 3 : return mdcbuf_finish(st);
522 : :
523 : : /* add to buffer */
524 [ + - ]: 3 : if (res >= 22)
525 : : {
526 : 3 : mdcbuf_load_data(st, st->mdc_buf, st->mdc_avail);
527 : 3 : st->mdc_avail = 0;
528 : :
529 : 3 : mdcbuf_load_data(st, data, res - 22);
530 : 3 : mdcbuf_load_mdc(st, data + res - 22, 22);
531 : : }
532 : : else
533 : : {
534 : 0 : int canmove = st->mdc_avail + res - 22;
535 : :
536 [ # # ]: 0 : if (canmove > 0)
537 : : {
538 : 0 : mdcbuf_load_data(st, st->mdc_buf, canmove);
539 : 0 : st->mdc_avail -= canmove;
540 : 0 : memmove(st->mdc_buf, st->mdc_buf + canmove, st->mdc_avail);
541 : : }
542 : 0 : mdcbuf_load_mdc(st, data, res);
543 : : }
544 : 3 : return 0;
545 : : }
546 : :
547 : : static int
548 : 10 : mdcbuf_read(void *priv, PullFilter *src, int len,
549 : : uint8 **data_p, uint8 *buf, int buflen)
550 : : {
551 : 10 : struct MDCBufData *st = priv;
552 : : int res;
553 : :
554 [ + + + + ]: 10 : if (!st->eof && len > st->avail)
555 : : {
556 : 6 : res = mdcbuf_refill(st, src);
557 [ + + ]: 6 : if (res < 0)
558 : 2 : return res;
559 : : }
560 : :
561 [ + + ]: 8 : if (len > st->avail)
562 : 2 : len = st->avail;
563 : :
564 : 8 : *data_p = st->pos;
565 : 8 : st->pos += len;
566 : 8 : st->avail -= len;
567 : 8 : return len;
568 : : }
569 : :
570 : : static void
571 : 3 : mdcbuf_free(void *priv)
572 : : {
573 : 3 : struct MDCBufData *st = priv;
574 : :
575 : 3 : px_md_free(st->ctx->mdc_ctx);
576 : 3 : st->ctx->mdc_ctx = NULL;
577 : 3 : px_memset(st, 0, sizeof(*st));
578 : 3 : pfree(st);
579 : 3 : }
580 : :
581 : : static struct PullFilterOps mdcbuf_filter = {
582 : : mdcbuf_init, mdcbuf_read, mdcbuf_free
583 : : };
584 : :
585 : :
586 : : /*
587 : : * Decrypt separate session key
588 : : */
589 : : static int
590 : 3 : decrypt_key(PGP_Context *ctx, const uint8 *src, int len)
591 : : {
592 : : int res;
593 : : uint8 algo;
594 : : PGP_CFB *cfb;
595 : :
596 : 3 : res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
597 : 3 : ctx->s2k.key, ctx->s2k.key_len, 0, NULL,
598 : : ctx->ignore_cipher_failure);
599 [ - + ]: 3 : if (res < 0)
600 : 0 : return res;
601 : :
602 : 3 : pgp_cfb_decrypt(cfb, src, 1, &algo);
603 : 3 : src++;
604 : 3 : len--;
605 : :
606 : 3 : pgp_cfb_decrypt(cfb, src, len, ctx->sess_key);
607 : 3 : pgp_cfb_free(cfb);
608 : 3 : ctx->sess_key_len = len;
609 : 3 : ctx->cipher_algo = algo;
610 : :
611 [ - + ]: 3 : if (pgp_get_cipher_key_size(algo) != len)
612 : : {
613 : 0 : px_debug("sesskey bad len: algo=%d, expected=%d, got=%d",
614 : : algo, pgp_get_cipher_key_size(algo), len);
615 : 0 : return PXE_PGP_CORRUPT_DATA;
616 : : }
617 : 3 : return 0;
618 : : }
619 : :
620 : : /*
621 : : * Handle key packet
622 : : */
623 : : static int
624 : 60 : parse_symenc_sesskey(PGP_Context *ctx, PullFilter *src)
625 : : {
626 : : uint8 *p;
627 : : int res;
628 : : uint8 tmpbuf[PGP_MAX_KEY + 2];
629 : : uint8 ver;
630 : :
631 [ - + ]: 60 : GETBYTE(src, ver);
632 [ - + ]: 60 : GETBYTE(src, ctx->s2k_cipher_algo);
633 [ - + ]: 60 : if (ver != 4)
634 : : {
635 : 0 : px_debug("bad key pkt ver");
636 : 0 : return PXE_PGP_CORRUPT_DATA;
637 : : }
638 : :
639 : : /*
640 : : * read S2K info
641 : : */
642 : 60 : res = pgp_s2k_read(src, &ctx->s2k);
643 [ - + ]: 60 : if (res < 0)
644 : 0 : return res;
645 : 60 : ctx->s2k_mode = ctx->s2k.mode;
646 : 60 : ctx->s2k_count = s2k_decode_count(ctx->s2k.iter);
647 : 60 : ctx->s2k_digest_algo = ctx->s2k.digest_algo;
648 : :
649 : : /*
650 : : * generate key from password
651 : : */
652 : 60 : res = pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
653 : : ctx->sym_key, ctx->sym_key_len);
654 [ - + ]: 60 : if (res < 0)
655 : 0 : return res;
656 : :
657 : : /*
658 : : * do we have separate session key?
659 : : */
660 : 60 : res = pullf_read_max(src, PGP_MAX_KEY + 2, &p, tmpbuf);
661 [ - + ]: 60 : if (res < 0)
662 : 0 : return res;
663 : :
664 [ + + ]: 60 : if (res == 0)
665 : : {
666 : : /*
667 : : * no, s2k key is session key
668 : : */
669 : 57 : memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
670 : 57 : ctx->sess_key_len = ctx->s2k.key_len;
671 : 57 : ctx->cipher_algo = ctx->s2k_cipher_algo;
672 : 57 : res = 0;
673 : 57 : ctx->use_sess_key = 0;
674 : : }
675 : : else
676 : : {
677 : : /*
678 : : * yes, decrypt it
679 : : */
680 [ + - - + ]: 3 : if (res < 17 || res > PGP_MAX_KEY + 1)
681 : : {
682 : 0 : px_debug("expect key, but bad data");
683 : 0 : return PXE_PGP_CORRUPT_DATA;
684 : : }
685 : 3 : ctx->use_sess_key = 1;
686 : 3 : res = decrypt_key(ctx, p, res);
687 : : }
688 : :
689 : 60 : px_memset(tmpbuf, 0, sizeof(tmpbuf));
690 : 60 : return res;
691 : : }
692 : :
693 : : static int
694 : 2 : copy_crlf(MBuf *dst, uint8 *data, int len, int *got_cr)
695 : : {
696 : 2 : uint8 *data_end = data + len;
697 : : uint8 tmpbuf[1024];
698 : 2 : uint8 *tmp_end = tmpbuf + sizeof(tmpbuf);
699 : : uint8 *p;
700 : : int res;
701 : :
702 : 2 : p = tmpbuf;
703 [ - + ]: 2 : if (*got_cr)
704 : : {
705 [ # # ]: 0 : if (*data != '\n')
706 : 0 : *p++ = '\r';
707 : 0 : *got_cr = 0;
708 : : }
709 [ + - ]: 47 : while (data < data_end)
710 : : {
711 [ + + ]: 47 : if (*data == '\r')
712 : : {
713 [ + + ]: 14 : if (data + 1 < data_end)
714 : : {
715 [ + + ]: 12 : if (*(data + 1) == '\n')
716 : 7 : data++;
717 : : }
718 : : else
719 : : {
720 : 2 : *got_cr = 1;
721 : 2 : break;
722 : : }
723 : : }
724 : 45 : *p++ = *data++;
725 [ - + ]: 45 : if (p >= tmp_end)
726 : : {
727 : 0 : res = mbuf_append(dst, tmpbuf, p - tmpbuf);
728 [ # # ]: 0 : if (res < 0)
729 : 0 : return res;
730 : 0 : p = tmpbuf;
731 : : }
732 : : }
733 [ + - ]: 2 : if (p - tmpbuf > 0)
734 : : {
735 : 2 : res = mbuf_append(dst, tmpbuf, p - tmpbuf);
736 [ - + ]: 2 : if (res < 0)
737 : 0 : return res;
738 : : }
739 : 2 : px_memset(tmpbuf, 0, sizeof(tmpbuf));
740 : 2 : return 0;
741 : : }
742 : :
743 : : static int
744 : 68 : parse_literal_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
745 : : {
746 : : int type;
747 : : int name_len;
748 : : int res;
749 : : uint8 *buf;
750 : : uint8 tmpbuf[4];
751 : 68 : int got_cr = 0;
752 : :
753 [ - + ]: 68 : GETBYTE(pkt, type);
754 [ - + ]: 68 : GETBYTE(pkt, name_len);
755 : :
756 : : /* skip name */
757 [ + + ]: 91 : while (name_len > 0)
758 : : {
759 : 23 : res = pullf_read(pkt, name_len, &buf);
760 [ - + ]: 23 : if (res < 0)
761 : 0 : return res;
762 [ - + ]: 23 : if (res == 0)
763 : 0 : break;
764 : 23 : name_len -= res;
765 : : }
766 [ - + ]: 68 : if (name_len > 0)
767 : : {
768 : 0 : px_debug("parse_literal_data: unexpected eof");
769 : 0 : return PXE_PGP_CORRUPT_DATA;
770 : : }
771 : :
772 : : /* skip date */
773 : 68 : res = pullf_read_max(pkt, 4, &buf, tmpbuf);
774 [ - + ]: 68 : if (res != 4)
775 : : {
776 : 0 : px_debug("parse_literal_data: unexpected eof");
777 : 0 : return PXE_PGP_CORRUPT_DATA;
778 : : }
779 : 68 : px_memset(tmpbuf, 0, 4);
780 : :
781 : : /*
782 : : * If called from an SQL function that returns text, pgp_decrypt() rejects
783 : : * inputs not self-identifying as text.
784 : : */
785 [ + + ]: 68 : if (ctx->text_mode)
786 [ + + + - ]: 63 : if (type != 't' && type != 'u')
787 : : {
788 : 4 : px_debug("parse_literal_data: data type=%c", type);
789 : 4 : ctx->unexpected_binary = true;
790 : : }
791 : :
792 : 68 : ctx->unicode_mode = (type == 'u') ? 1 : 0;
793 : :
794 : : /* read data */
795 : : while (1)
796 : : {
797 : 157 : res = pullf_read(pkt, 32 * 1024, &buf);
798 [ + + ]: 157 : if (res <= 0)
799 : 68 : break;
800 : :
801 [ + + + + ]: 89 : if (ctx->text_mode && ctx->convert_crlf)
802 : 2 : res = copy_crlf(dst, buf, res, &got_cr);
803 : : else
804 : 87 : res = mbuf_append(dst, buf, res);
805 [ - + ]: 89 : if (res < 0)
806 : 0 : break;
807 : : }
808 [ + + + + ]: 68 : if (res >= 0 && got_cr)
809 : 2 : res = mbuf_append(dst, (const uint8 *) "\r", 1);
810 : 68 : return res;
811 : : }
812 : :
813 : : /* process_data_packets and parse_compressed_data call each other */
814 : : static int process_data_packets(PGP_Context *ctx, MBuf *dst,
815 : : PullFilter *src, int allow_compr, int need_mdc);
816 : :
817 : : static int
818 : 6 : parse_compressed_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
819 : : {
820 : : int res;
821 : : uint8 type;
822 : : PullFilter *pf_decompr;
823 : : uint8 *discard_buf;
824 : :
825 [ - + ]: 6 : GETBYTE(pkt, type);
826 : :
827 : 6 : ctx->compress_algo = type;
828 [ - + + - ]: 6 : switch (type)
829 : : {
830 : 0 : case PGP_COMPR_NONE:
831 : 0 : res = process_data_packets(ctx, dst, pkt, NO_COMPR, NO_MDC);
832 : 0 : break;
833 : :
834 : 4 : case PGP_COMPR_ZIP:
835 : : case PGP_COMPR_ZLIB:
836 : 4 : res = pgp_decompress_filter(&pf_decompr, ctx, pkt);
837 [ + - ]: 4 : if (res >= 0)
838 : : {
839 : 4 : res = process_data_packets(ctx, dst, pf_decompr,
840 : : NO_COMPR, NO_MDC);
841 : 4 : pullf_free(pf_decompr);
842 : : }
843 : 4 : break;
844 : :
845 : 2 : case PGP_COMPR_BZIP2:
846 : 2 : px_debug("parse_compressed_data: bzip2 unsupported");
847 : : /* report error in pgp_decrypt() */
848 : 2 : ctx->unsupported_compr = 1;
849 : :
850 : : /*
851 : : * Discard the compressed data, allowing it to first affect any
852 : : * MDC digest computation.
853 : : */
854 : : while (1)
855 : : {
856 : 3 : res = pullf_read(pkt, 32 * 1024, &discard_buf);
857 [ + + ]: 3 : if (res <= 0)
858 : 2 : break;
859 : : }
860 : :
861 : 2 : break;
862 : :
863 : 0 : default:
864 : 0 : px_debug("parse_compressed_data: unknown compr type");
865 : 0 : res = PXE_PGP_CORRUPT_DATA;
866 : : }
867 : :
868 : 6 : return res;
869 : : }
870 : :
871 : : static int
872 : 76 : process_data_packets(PGP_Context *ctx, MBuf *dst, PullFilter *src,
873 : : int allow_compr, int need_mdc)
874 : : {
875 : : uint8 tag;
876 : : int len,
877 : : res;
878 : 76 : int got_data = 0;
879 : 76 : int got_mdc = 0;
880 : 76 : PullFilter *pkt = NULL;
881 : :
882 : : while (1)
883 : : {
884 : 213 : res = pgp_parse_pkt_hdr(src, &tag, &len, ALLOW_CTX_SIZE);
885 [ + + ]: 213 : if (res <= 0)
886 : 73 : break;
887 : :
888 : :
889 : : /* mdc packet should be last */
890 [ - + ]: 140 : if (got_mdc)
891 : : {
892 : 0 : px_debug("process_data_packets: data after mdc");
893 : 0 : res = PXE_PGP_CORRUPT_DATA;
894 : 0 : break;
895 : : }
896 : :
897 : : /*
898 : : * Context length inside SYMENCRYPTED_DATA_MDC packet needs special
899 : : * handling.
900 : : */
901 [ + + + + ]: 140 : if (need_mdc && res == PKT_CONTEXT)
902 : 3 : res = pullf_create(&pkt, &mdcbuf_filter, ctx, src);
903 : : else
904 : 137 : res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
905 [ - + ]: 140 : if (res < 0)
906 : 0 : break;
907 : :
908 [ + + + + ]: 140 : switch (tag)
909 : : {
910 : 68 : case PGP_PKT_LITERAL_DATA:
911 : 68 : got_data = 1;
912 : 68 : res = parse_literal_data(ctx, dst, pkt);
913 : 68 : break;
914 : 6 : case PGP_PKT_COMPRESSED_DATA:
915 [ - + ]: 6 : if (allow_compr == 0)
916 : : {
917 : 0 : px_debug("process_data_packets: unexpected compression");
918 : 0 : res = PXE_PGP_CORRUPT_DATA;
919 : : }
920 [ - + ]: 6 : else if (got_data)
921 : : {
922 : : /*
923 : : * compr data must be alone
924 : : */
925 : 0 : px_debug("process_data_packets: only one cmpr pkt allowed");
926 : 0 : res = PXE_PGP_CORRUPT_DATA;
927 : : }
928 : : else
929 : : {
930 : 6 : got_data = 1;
931 : 6 : res = parse_compressed_data(ctx, dst, pkt);
932 : : }
933 : 6 : break;
934 : 65 : case PGP_PKT_MDC:
935 [ - + ]: 65 : if (need_mdc == NO_MDC)
936 : : {
937 : 0 : px_debug("process_data_packets: unexpected MDC");
938 : 0 : res = PXE_PGP_CORRUPT_DATA;
939 : 0 : break;
940 : : }
941 : :
942 : 65 : res = mdc_finish(ctx, pkt, len);
943 [ + - ]: 65 : if (res >= 0)
944 : 65 : got_mdc = 1;
945 : 65 : break;
946 : 1 : default:
947 : 1 : px_debug("process_data_packets: unexpected pkt tag=%d", tag);
948 : 1 : res = PXE_PGP_CORRUPT_DATA;
949 : : }
950 : :
951 : 140 : pullf_free(pkt);
952 : 140 : pkt = NULL;
953 : :
954 [ + + ]: 140 : if (res < 0)
955 : 3 : break;
956 : : }
957 : :
958 [ - + ]: 76 : if (pkt)
959 : 0 : pullf_free(pkt);
960 : :
961 [ + + ]: 76 : if (res < 0)
962 : 4 : return res;
963 : :
964 [ - + ]: 72 : if (!got_data)
965 : : {
966 : 0 : px_debug("process_data_packets: no data");
967 : 0 : res = PXE_PGP_CORRUPT_DATA;
968 : : }
969 [ + + + + : 72 : if (need_mdc && !got_mdc && !ctx->use_mdcbuf_filter)
- + ]
970 : : {
971 : 0 : px_debug("process_data_packets: got no mdc");
972 : 0 : res = PXE_PGP_CORRUPT_DATA;
973 : : }
974 : 72 : return res;
975 : : }
976 : :
977 : : static int
978 : 2 : parse_symenc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
979 : : {
980 : : int res;
981 : 2 : PGP_CFB *cfb = NULL;
982 : 2 : PullFilter *pf_decrypt = NULL;
983 : 2 : PullFilter *pf_prefix = NULL;
984 : :
985 : 2 : res = pgp_cfb_create(&cfb, ctx->cipher_algo,
986 : 2 : ctx->sess_key, ctx->sess_key_len, 1, NULL,
987 : : ctx->ignore_cipher_failure);
988 [ - + ]: 2 : if (res < 0)
989 : 0 : goto out;
990 : :
991 : 2 : res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
992 [ - + ]: 2 : if (res < 0)
993 : 0 : goto out;
994 : :
995 : 2 : res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_decrypt);
996 [ - + ]: 2 : if (res < 0)
997 : 0 : goto out;
998 : :
999 : 2 : res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NO_MDC);
1000 : :
1001 : 2 : out:
1002 [ + - ]: 2 : if (pf_prefix)
1003 : 2 : pullf_free(pf_prefix);
1004 [ + - ]: 2 : if (pf_decrypt)
1005 : 2 : pullf_free(pf_decrypt);
1006 [ + - ]: 2 : if (cfb)
1007 : 2 : pgp_cfb_free(cfb);
1008 : :
1009 : 2 : return res;
1010 : : }
1011 : :
1012 : : static int
1013 : 74 : parse_symenc_mdc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
1014 : : {
1015 : : int res;
1016 : 74 : PGP_CFB *cfb = NULL;
1017 : 74 : PullFilter *pf_decrypt = NULL;
1018 : 74 : PullFilter *pf_prefix = NULL;
1019 : 74 : PullFilter *pf_mdc = NULL;
1020 : : uint8 ver;
1021 : :
1022 [ - + ]: 74 : GETBYTE(pkt, ver);
1023 [ - + ]: 74 : if (ver != 1)
1024 : : {
1025 : 0 : px_debug("parse_symenc_mdc_data: pkt ver != 1");
1026 : 0 : return PXE_PGP_CORRUPT_DATA;
1027 : : }
1028 : :
1029 : 74 : res = pgp_cfb_create(&cfb, ctx->cipher_algo,
1030 : 74 : ctx->sess_key, ctx->sess_key_len, 0, NULL,
1031 : : ctx->ignore_cipher_failure);
1032 [ - + ]: 74 : if (res < 0)
1033 : 0 : goto out;
1034 : :
1035 : 74 : res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
1036 [ - + ]: 74 : if (res < 0)
1037 : 0 : goto out;
1038 : :
1039 : 74 : res = pullf_create(&pf_mdc, &mdc_filter, ctx, pf_decrypt);
1040 [ - + ]: 74 : if (res < 0)
1041 : 0 : goto out;
1042 : :
1043 : 74 : res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_mdc);
1044 [ - + ]: 70 : if (res < 0)
1045 : 0 : goto out;
1046 : :
1047 : 70 : res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NEED_MDC);
1048 : :
1049 : 70 : out:
1050 [ + - ]: 70 : if (pf_prefix)
1051 : 70 : pullf_free(pf_prefix);
1052 [ + - ]: 70 : if (pf_mdc)
1053 : 70 : pullf_free(pf_mdc);
1054 [ + - ]: 70 : if (pf_decrypt)
1055 : 70 : pullf_free(pf_decrypt);
1056 [ + - ]: 70 : if (cfb)
1057 : 70 : pgp_cfb_free(cfb);
1058 : :
1059 : 70 : return res;
1060 : : }
1061 : :
1062 : : /*
1063 : : * skip over packet contents
1064 : : */
1065 : : int
1066 : 172 : pgp_skip_packet(PullFilter *pkt)
1067 : : {
1068 : 172 : int res = 1;
1069 : : uint8 *tmp;
1070 : :
1071 [ + + ]: 511 : while (res > 0)
1072 : 339 : res = pullf_read(pkt, 32 * 1024, &tmp);
1073 : 172 : return res;
1074 : : }
1075 : :
1076 : : /*
1077 : : * expect to be at packet end, any data is error
1078 : : */
1079 : : int
1080 : 34 : pgp_expect_packet_end(PullFilter *pkt)
1081 : : {
1082 : : int res;
1083 : : uint8 *tmp;
1084 : :
1085 : 34 : res = pullf_read(pkt, 32 * 1024, &tmp);
1086 [ - + ]: 34 : if (res > 0)
1087 : : {
1088 : 0 : px_debug("pgp_expect_packet_end: got data");
1089 : 0 : return PXE_PGP_CORRUPT_DATA;
1090 : : }
1091 : 34 : return res;
1092 : : }
1093 : :
1094 : : int
1095 : 78 : pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst)
1096 : : {
1097 : : int res;
1098 : 78 : PullFilter *src = NULL;
1099 : 78 : PullFilter *pkt = NULL;
1100 : : uint8 tag;
1101 : : int len;
1102 : 78 : int got_key = 0;
1103 : 78 : int got_data = 0;
1104 : :
1105 : 78 : res = pullf_create_mbuf_reader(&src, msrc);
1106 : :
1107 [ + + ]: 228 : while (res >= 0)
1108 : : {
1109 : 222 : res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE);
1110 [ + + ]: 222 : if (res <= 0)
1111 : 68 : break;
1112 : :
1113 : 154 : res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
1114 [ - + ]: 154 : if (res < 0)
1115 : 0 : break;
1116 : :
1117 : 154 : res = PXE_PGP_CORRUPT_DATA;
1118 [ - + + + : 154 : switch (tag)
+ - ]
1119 : : {
1120 : 0 : case PGP_PKT_MARKER:
1121 : 0 : res = pgp_skip_packet(pkt);
1122 : 0 : break;
1123 : 18 : case PGP_PKT_PUBENCRYPTED_SESSKEY:
1124 : : /* fixme: skip those */
1125 : 18 : res = pgp_parse_pubenc_sesskey(ctx, pkt);
1126 : 18 : got_key = 1;
1127 : 18 : break;
1128 : 60 : case PGP_PKT_SYMENCRYPTED_SESSKEY:
1129 [ - + ]: 60 : if (got_key)
1130 : :
1131 : : /*
1132 : : * Theoretically, there could be several keys, both public
1133 : : * and symmetric, all of which encrypt same session key.
1134 : : * Decrypt should try with each one, before failing.
1135 : : */
1136 : 0 : px_debug("pgp_decrypt: using first of several keys");
1137 : : else
1138 : : {
1139 : 60 : got_key = 1;
1140 : 60 : res = parse_symenc_sesskey(ctx, pkt);
1141 : : }
1142 : 60 : break;
1143 : 2 : case PGP_PKT_SYMENCRYPTED_DATA:
1144 [ - + ]: 2 : if (!got_key)
1145 : 0 : px_debug("pgp_decrypt: have data but no key");
1146 [ - + ]: 2 : else if (got_data)
1147 : 0 : px_debug("pgp_decrypt: got second data packet");
1148 : : else
1149 : : {
1150 : 2 : got_data = 1;
1151 : 2 : ctx->disable_mdc = 1;
1152 : 2 : res = parse_symenc_data(ctx, pkt, mdst);
1153 : : }
1154 : 2 : break;
1155 : 74 : case PGP_PKT_SYMENCRYPTED_DATA_MDC:
1156 [ - + ]: 74 : if (!got_key)
1157 : 0 : px_debug("pgp_decrypt: have data but no key");
1158 [ - + ]: 74 : else if (got_data)
1159 : 0 : px_debug("pgp_decrypt: several data pkts not supported");
1160 : : else
1161 : : {
1162 : 74 : got_data = 1;
1163 : 74 : ctx->disable_mdc = 0;
1164 : 74 : res = parse_symenc_mdc_data(ctx, pkt, mdst);
1165 : : }
1166 : 70 : break;
1167 : 0 : default:
1168 : 0 : px_debug("pgp_decrypt: unknown tag: 0x%02x", tag);
1169 : : }
1170 : 150 : pullf_free(pkt);
1171 : 150 : pkt = NULL;
1172 : : }
1173 : :
1174 [ - + ]: 74 : if (pkt)
1175 : 0 : pullf_free(pkt);
1176 : :
1177 [ + - ]: 74 : if (src)
1178 : 74 : pullf_free(src);
1179 : :
1180 [ + + ]: 74 : if (res < 0)
1181 : 6 : return res;
1182 : :
1183 : : /*
1184 : : * Report a failure of the prefix_init() "quick check" now, rather than
1185 : : * upon detection, to hinder timing attacks. pgcrypto is not generally
1186 : : * secure against timing attacks, but this helps.
1187 : : */
1188 [ + - - + ]: 68 : if (!got_data || ctx->corrupt_prefix)
1189 : 0 : return PXE_PGP_CORRUPT_DATA;
1190 : :
1191 : : /*
1192 : : * Code interpreting purportedly-decrypted data prior to this stage shall
1193 : : * report no error other than PXE_PGP_CORRUPT_DATA. (PXE_BUG is okay so
1194 : : * long as it remains unreachable.) This ensures that an attacker able to
1195 : : * choose a ciphertext and receive a corresponding decryption error
1196 : : * message cannot use that oracle to gather clues about the decryption
1197 : : * key. See "An Attack on CFB Mode Encryption As Used By OpenPGP" by
1198 : : * Serge Mister and Robert Zuccherato.
1199 : : *
1200 : : * A problematic value in the first octet of a Literal Data or Compressed
1201 : : * Data packet may indicate a simple user error, such as the need to call
1202 : : * pgp_sym_decrypt_bytea instead of pgp_sym_decrypt. Occasionally,
1203 : : * though, it is the first symptom of the encryption key not matching the
1204 : : * decryption key. When this was the only problem encountered, report a
1205 : : * specific error to guide the user; otherwise, we will have reported
1206 : : * PXE_PGP_CORRUPT_DATA before now. A key mismatch makes the other errors
1207 : : * into red herrings, and this avoids leaking clues to attackers.
1208 : : */
1209 [ + + ]: 68 : if (ctx->unsupported_compr)
1210 : 1 : return PXE_PGP_UNSUPPORTED_COMPR;
1211 [ + + ]: 67 : if (ctx->unexpected_binary)
1212 : 3 : return PXE_PGP_NOT_TEXT;
1213 : :
1214 : 64 : return res;
1215 : : }
|