Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * pgp-encrypt.c
3 : : * OpenPGP encrypt.
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-encrypt.c
30 : : */
31 : :
32 : : #include "postgres.h"
33 : :
34 : : #include <time.h>
35 : :
36 : : #include "mbuf.h"
37 : : #include "pgp.h"
38 : : #include "px.h"
39 : :
40 : : #define MDC_DIGEST_LEN 20
41 : : #define STREAM_ID 0xE0
42 : : #define STREAM_BLOCK_SHIFT 14
43 : :
44 : : static uint8 *
6853 bruce@momjian.us 45 :CBC 111 : render_newlen(uint8 *h, int len)
46 : : {
47 [ + + ]: 111 : if (len <= 191)
48 : : {
49 : 104 : *h++ = len & 255;
50 : : }
51 [ + - + + ]: 7 : else if (len > 191 && len <= 8383)
52 : : {
53 : 6 : *h++ = ((len - 192) >> 8) + 192;
54 : 6 : *h++ = (len - 192) & 255;
55 : : }
56 : : else
57 : : {
58 : 1 : *h++ = 255;
59 : 1 : *h++ = (len >> 24) & 255;
60 : 1 : *h++ = (len >> 16) & 255;
61 : 1 : *h++ = (len >> 8) & 255;
62 : 1 : *h++ = len & 255;
63 : : }
64 : 111 : return h;
65 : : }
66 : :
67 : : static int
5421 68 : 81 : write_tag_only(PushFilter *dst, int tag)
69 : : {
6756 70 : 81 : uint8 hdr = 0xC0 | tag;
71 : :
6853 72 : 81 : return pushf_write(dst, &hdr, 1);
73 : : }
74 : :
75 : : static int
5421 76 : 30 : write_normal_header(PushFilter *dst, int tag, int len)
77 : : {
78 : : uint8 hdr[8];
6853 79 : 30 : uint8 *h = hdr;
80 : :
81 : 30 : *h++ = 0xC0 | tag;
82 : 30 : h = render_newlen(h, len);
83 : 30 : return pushf_write(dst, hdr, h - hdr);
84 : : }
85 : :
86 : :
87 : : /*
88 : : * MAC writer
89 : : */
90 : :
91 : : static int
5421 92 : 35 : mdc_init(PushFilter *dst, void *init_arg, void **priv_p)
93 : : {
94 : : int res;
95 : : PX_MD *md;
96 : :
6853 97 : 35 : res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
98 [ - + ]: 35 : if (res < 0)
6853 bruce@momjian.us 99 :UBC 0 : return res;
100 : :
6853 bruce@momjian.us 101 :CBC 35 : *priv_p = md;
102 : 35 : return 0;
103 : : }
104 : :
105 : : static int
5421 106 : 149 : mdc_write(PushFilter *dst, void *priv, const uint8 *data, int len)
107 : : {
6853 108 : 149 : PX_MD *md = priv;
109 : :
110 : 149 : px_md_update(md, data, len);
111 : 149 : return pushf_write(dst, data, len);
112 : : }
113 : :
114 : : static int
5421 115 : 35 : mdc_flush(PushFilter *dst, void *priv)
116 : : {
117 : : int res;
118 : : uint8 pkt[2 + MDC_DIGEST_LEN];
6853 119 : 35 : PX_MD *md = priv;
120 : :
121 : : /*
122 : : * create mdc pkt
123 : : */
124 : 35 : pkt[0] = 0xD3;
6756 125 : 35 : pkt[1] = 0x14; /* MDC_DIGEST_LEN */
6853 126 : 35 : px_md_update(md, pkt, 2);
127 : 35 : px_md_finish(md, pkt + 2);
128 : :
129 : 35 : res = pushf_write(dst, pkt, 2 + MDC_DIGEST_LEN);
3650 130 : 35 : px_memset(pkt, 0, 2 + MDC_DIGEST_LEN);
6853 131 : 35 : return res;
132 : : }
133 : :
134 : : static void
135 : 35 : mdc_free(void *priv)
136 : : {
137 : 35 : PX_MD *md = priv;
138 : :
139 : 35 : px_md_free(md);
140 : 35 : }
141 : :
142 : : static const PushFilterOps mdc_filter = {
143 : : mdc_init, mdc_write, mdc_flush, mdc_free
144 : : };
145 : :
146 : :
147 : : /*
148 : : * Encrypted pkt writer
149 : : */
150 : : #define ENCBUF 8192
151 : : struct EncStat
152 : : {
153 : : PGP_CFB *ciph;
154 : : uint8 buf[ENCBUF];
155 : : };
156 : :
157 : : static int
5421 158 : 36 : encrypt_init(PushFilter *next, void *init_arg, void **priv_p)
159 : : {
160 : : struct EncStat *st;
6853 161 : 36 : PGP_Context *ctx = init_arg;
162 : : PGP_CFB *ciph;
6756 163 : 36 : int resync = 1;
164 : : int res;
165 : :
166 : : /* should we use newer packet format? */
6853 167 [ + + ]: 36 : if (ctx->disable_mdc == 0)
168 : : {
6756 169 : 35 : uint8 ver = 1;
170 : :
6853 171 : 35 : resync = 0;
172 : 35 : res = pushf_write(next, &ver, 1);
173 [ - + ]: 35 : if (res < 0)
6853 bruce@momjian.us 174 :UBC 0 : return res;
175 : : }
6853 bruce@momjian.us 176 :CBC 36 : res = pgp_cfb_create(&ciph, ctx->cipher_algo,
6756 177 : 36 : ctx->sess_key, ctx->sess_key_len, resync, NULL);
6853 178 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 179 :UBC 0 : return res;
180 : :
1297 michael@paquier.xyz 181 :CBC 36 : st = palloc0(sizeof(*st));
6853 bruce@momjian.us 182 : 36 : st->ciph = ciph;
183 : :
184 : 36 : *priv_p = st;
185 : 36 : return ENCBUF;
186 : : }
187 : :
188 : : static int
5421 189 : 46 : encrypt_process(PushFilter *next, void *priv, const uint8 *data, int len)
190 : : {
191 : : int res;
6853 192 : 46 : struct EncStat *st = priv;
6756 193 : 46 : int avail = len;
194 : :
6853 195 [ + + ]: 92 : while (avail > 0)
196 : : {
6756 197 : 46 : int tmplen = avail > ENCBUF ? ENCBUF : avail;
198 : :
6853 199 : 46 : res = pgp_cfb_encrypt(st->ciph, data, tmplen, st->buf);
200 [ - + ]: 46 : if (res < 0)
6853 bruce@momjian.us 201 :UBC 0 : return res;
202 : :
6853 bruce@momjian.us 203 :CBC 46 : res = pushf_write(next, st->buf, tmplen);
204 [ - + ]: 46 : if (res < 0)
6853 bruce@momjian.us 205 :UBC 0 : return res;
206 : :
6853 bruce@momjian.us 207 :CBC 46 : data += tmplen;
208 : 46 : avail -= tmplen;
209 : : }
210 : 46 : return 0;
211 : : }
212 : :
213 : : static void
214 : 36 : encrypt_free(void *priv)
215 : : {
216 : 36 : struct EncStat *st = priv;
217 : :
2680 heikki.linnakangas@i 218 [ + - ]: 36 : if (st->ciph)
219 : 36 : pgp_cfb_free(st->ciph);
3650 bruce@momjian.us 220 : 36 : px_memset(st, 0, sizeof(*st));
1297 michael@paquier.xyz 221 : 36 : pfree(st);
6853 bruce@momjian.us 222 : 36 : }
223 : :
224 : : static const PushFilterOps encrypt_filter = {
225 : : encrypt_init, encrypt_process, NULL, encrypt_free
226 : : };
227 : :
228 : : /*
229 : : * Write Streamable pkts
230 : : */
231 : :
232 : : struct PktStreamStat
233 : : {
234 : : int final_done;
235 : : int pkt_block;
236 : : };
237 : :
238 : : static int
5421 239 : 81 : pkt_stream_init(PushFilter *next, void *init_arg, void **priv_p)
240 : : {
241 : : struct PktStreamStat *st;
242 : :
1297 michael@paquier.xyz 243 : 81 : st = palloc(sizeof(*st));
6853 bruce@momjian.us 244 : 81 : st->final_done = 0;
245 : 81 : st->pkt_block = 1 << STREAM_BLOCK_SHIFT;
246 : 81 : *priv_p = st;
247 : :
248 : 81 : return st->pkt_block;
249 : : }
250 : :
251 : : static int
5421 252 : 90 : pkt_stream_process(PushFilter *next, void *priv, const uint8 *data, int len)
253 : : {
254 : : int res;
255 : : uint8 hdr[8];
6853 256 : 90 : uint8 *h = hdr;
257 : 90 : struct PktStreamStat *st = priv;
258 : :
259 [ - + ]: 90 : if (st->final_done)
6853 bruce@momjian.us 260 :UBC 0 : return PXE_BUG;
261 : :
6853 bruce@momjian.us 262 [ + + ]:CBC 90 : if (len == st->pkt_block)
263 : 10 : *h++ = STREAM_ID | STREAM_BLOCK_SHIFT;
264 : : else
265 : : {
266 : 80 : h = render_newlen(h, len);
267 : 80 : st->final_done = 1;
268 : : }
269 : :
270 : 90 : res = pushf_write(next, hdr, h - hdr);
271 [ - + ]: 90 : if (res < 0)
6853 bruce@momjian.us 272 :UBC 0 : return res;
273 : :
6853 bruce@momjian.us 274 :CBC 90 : return pushf_write(next, data, len);
275 : : }
276 : :
277 : : static int
5421 278 : 81 : pkt_stream_flush(PushFilter *next, void *priv)
279 : : {
280 : : int res;
281 : : uint8 hdr[8];
6853 282 : 81 : uint8 *h = hdr;
283 : 81 : struct PktStreamStat *st = priv;
284 : :
285 : : /* stream MUST end with normal packet. */
286 [ + + ]: 81 : if (!st->final_done)
287 : : {
288 : 1 : h = render_newlen(h, 0);
289 : 1 : res = pushf_write(next, hdr, h - hdr);
290 [ - + ]: 1 : if (res < 0)
6853 bruce@momjian.us 291 :UBC 0 : return res;
6853 bruce@momjian.us 292 :CBC 1 : st->final_done = 1;
293 : : }
294 : 81 : return 0;
295 : : }
296 : :
297 : : static void
298 : 81 : pkt_stream_free(void *priv)
299 : : {
300 : 81 : struct PktStreamStat *st = priv;
301 : :
3650 302 : 81 : px_memset(st, 0, sizeof(*st));
1297 michael@paquier.xyz 303 : 81 : pfree(st);
6853 bruce@momjian.us 304 : 81 : }
305 : :
306 : : static const PushFilterOps pkt_stream_filter = {
307 : : pkt_stream_init, pkt_stream_process, pkt_stream_flush, pkt_stream_free
308 : : };
309 : :
310 : : int
5421 311 : 6 : pgp_create_pkt_writer(PushFilter *dst, int tag, PushFilter **res_p)
312 : : {
313 : : int res;
314 : :
6853 315 : 6 : res = write_tag_only(dst, tag);
316 [ - + ]: 6 : if (res < 0)
6853 bruce@momjian.us 317 :UBC 0 : return res;
318 : :
6853 bruce@momjian.us 319 :CBC 6 : return pushf_create(res_p, &pkt_stream_filter, NULL, dst);
320 : : }
321 : :
322 : : /*
323 : : * Text conversion filter
324 : : */
325 : :
326 : : static int
5421 327 : 2 : crlf_process(PushFilter *dst, void *priv, const uint8 *data, int len)
328 : : {
6756 329 : 2 : const uint8 *data_end = data + len;
330 : : const uint8 *p2,
331 : 2 : *p1 = data;
332 : : int line_len;
333 : : static const uint8 crlf[] = {'\r', '\n'};
334 : 2 : int res = 0;
335 : :
6853 336 [ + + ]: 9 : while (p1 < data_end)
337 : : {
338 : 7 : p2 = memchr(p1, '\n', data_end - p1);
339 [ + + ]: 7 : if (p2 == NULL)
340 : 1 : p2 = data_end;
341 : :
342 : 7 : line_len = p2 - p1;
343 : :
344 : : /* write data */
345 : 7 : res = 0;
346 [ + - ]: 7 : if (line_len > 0)
347 : : {
348 : 7 : res = pushf_write(dst, p1, line_len);
349 [ - + ]: 7 : if (res < 0)
6853 bruce@momjian.us 350 :UBC 0 : break;
6853 bruce@momjian.us 351 :CBC 7 : p1 += line_len;
352 : : }
353 : :
354 : : /* write crlf */
355 [ + + + + ]: 14 : while (p1 < data_end && *p1 == '\n')
356 : : {
357 : 7 : res = pushf_write(dst, crlf, 2);
358 [ - + ]: 7 : if (res < 0)
6853 bruce@momjian.us 359 :UBC 0 : break;
6853 bruce@momjian.us 360 :CBC 7 : p1++;
361 : : }
362 : : }
363 : 2 : return res;
364 : : }
365 : :
366 : : static const PushFilterOps crlf_filter = {
367 : : NULL, crlf_process, NULL, NULL
368 : : };
369 : :
370 : : /*
371 : : * Initialize literal data packet
372 : : */
373 : : static int
5421 374 : 36 : init_litdata_packet(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
375 : : {
376 : : int res;
377 : : int hdrlen;
378 : : uint8 hdr[6];
379 : : uint32 t;
380 : : PushFilter *pkt;
381 : : int type;
382 : :
383 : : /*
384 : : * Create header
385 : : */
386 : :
6853 387 [ + + ]: 36 : if (ctx->text_mode)
388 [ - + ]: 32 : type = ctx->unicode_mode ? 'u' : 't';
389 : : else
390 : 4 : type = 'b';
391 : :
392 : : /*
393 : : * Store the creation time into packet. The goal is to have as few known
394 : : * bytes as possible.
395 : : */
6756 396 : 36 : t = (uint32) time(NULL);
397 : :
6853 398 : 36 : hdr[0] = type;
399 : 36 : hdr[1] = 0;
400 : 36 : hdr[2] = (t >> 24) & 255;
401 : 36 : hdr[3] = (t >> 16) & 255;
402 : 36 : hdr[4] = (t >> 8) & 255;
403 : 36 : hdr[5] = t & 255;
404 : 36 : hdrlen = 6;
405 : :
406 : 36 : res = write_tag_only(dst, PGP_PKT_LITERAL_DATA);
407 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 408 :UBC 0 : return res;
409 : :
6853 bruce@momjian.us 410 :CBC 36 : res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
411 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 412 :UBC 0 : return res;
413 : :
6853 bruce@momjian.us 414 :CBC 36 : res = pushf_write(pkt, hdr, hdrlen);
415 [ - + ]: 36 : if (res < 0)
416 : : {
6853 bruce@momjian.us 417 :UBC 0 : pushf_free(pkt);
418 : 0 : return res;
419 : : }
420 : :
6853 bruce@momjian.us 421 :CBC 36 : *pf_res = pkt;
422 : 36 : return 0;
423 : : }
424 : :
425 : : /*
426 : : * Initialize compression filter
427 : : */
428 : : static int
5421 429 : 3 : init_compress(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
430 : : {
431 : : int res;
6756 432 : 3 : uint8 type = ctx->compress_algo;
433 : : PushFilter *pkt;
434 : :
6853 435 : 3 : res = write_tag_only(dst, PGP_PKT_COMPRESSED_DATA);
436 [ - + ]: 3 : if (res < 0)
6853 bruce@momjian.us 437 :UBC 0 : return res;
438 : :
6853 bruce@momjian.us 439 :CBC 3 : res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
440 [ - + ]: 3 : if (res < 0)
6853 bruce@momjian.us 441 :UBC 0 : return res;
442 : :
6853 bruce@momjian.us 443 :CBC 3 : res = pushf_write(pkt, &type, 1);
444 [ + - ]: 3 : if (res >= 0)
445 : 3 : res = pgp_compress_filter(pf_res, ctx, pkt);
446 : :
447 [ - + ]: 3 : if (res < 0)
6853 bruce@momjian.us 448 :UBC 0 : pushf_free(pkt);
449 : :
6853 bruce@momjian.us 450 :CBC 3 : return res;
451 : : }
452 : :
453 : : /*
454 : : * Initialize encdata packet
455 : : */
456 : : static int
5421 457 : 36 : init_encdata_packet(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
458 : : {
459 : : int res;
460 : : int tag;
461 : :
6853 462 [ + + ]: 36 : if (ctx->disable_mdc)
463 : 1 : tag = PGP_PKT_SYMENCRYPTED_DATA;
464 : : else
465 : 35 : tag = PGP_PKT_SYMENCRYPTED_DATA_MDC;
466 : :
467 : 36 : res = write_tag_only(dst, tag);
468 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 469 :UBC 0 : return res;
470 : :
6853 bruce@momjian.us 471 :CBC 36 : return pushf_create(pf_res, &pkt_stream_filter, ctx, dst);
472 : : }
473 : :
474 : : /*
475 : : * write prefix
476 : : */
477 : : static int
5421 478 : 36 : write_prefix(PGP_Context *ctx, PushFilter *dst)
479 : : {
480 : : uint8 prefix[PGP_MAX_BLOCK + 2];
481 : : int res,
482 : : bs;
483 : :
6853 484 : 36 : bs = pgp_get_cipher_block_size(ctx->cipher_algo);
1930 michael@paquier.xyz 485 [ - + ]: 36 : if (!pg_strong_random(prefix, bs))
2687 heikki.linnakangas@i 486 :UBC 0 : return PXE_NO_RANDOM;
487 : :
6853 bruce@momjian.us 488 :CBC 36 : prefix[bs + 0] = prefix[bs - 2];
489 : 36 : prefix[bs + 1] = prefix[bs - 1];
490 : :
491 : 36 : res = pushf_write(dst, prefix, bs + 2);
3650 492 : 36 : px_memset(prefix, 0, bs + 2);
6853 493 : 36 : return res < 0 ? res : 0;
494 : : }
495 : :
496 : : /*
497 : : * write symmetrically encrypted session key packet
498 : : */
499 : :
500 : : static int
5421 501 : 4 : symencrypt_sesskey(PGP_Context *ctx, uint8 *dst)
502 : : {
503 : : int res;
504 : : PGP_CFB *cfb;
6756 505 : 4 : uint8 algo = ctx->cipher_algo;
506 : :
6853 507 : 4 : res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
6756 508 : 4 : ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
6853 509 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 510 :UBC 0 : return res;
511 : :
6853 bruce@momjian.us 512 :CBC 4 : pgp_cfb_encrypt(cfb, &algo, 1, dst);
513 : 4 : pgp_cfb_encrypt(cfb, ctx->sess_key, ctx->sess_key_len, dst + 1);
514 : :
515 : 4 : pgp_cfb_free(cfb);
516 : 4 : return ctx->sess_key_len + 1;
517 : : }
518 : :
519 : : /* 5.3: Symmetric-Key Encrypted Session-Key */
520 : : static int
5421 521 : 30 : write_symenc_sesskey(PGP_Context *ctx, PushFilter *dst)
522 : : {
523 : : uint8 pkt[256];
524 : : int pktlen;
525 : : int res;
6756 526 : 30 : uint8 *p = pkt;
527 : :
6853 528 : 30 : *p++ = 4; /* 5.3 - version number */
529 : 30 : *p++ = ctx->s2k_cipher_algo;
530 : :
531 : 30 : *p++ = ctx->s2k.mode;
532 : 30 : *p++ = ctx->s2k.digest_algo;
533 [ + + ]: 30 : if (ctx->s2k.mode > 0)
534 : : {
535 : 29 : memcpy(p, ctx->s2k.salt, 8);
536 : 29 : p += 8;
537 : : }
538 [ + + ]: 30 : if (ctx->s2k.mode == 3)
539 : 28 : *p++ = ctx->s2k.iter;
540 : :
541 [ + + ]: 30 : if (ctx->use_sess_key)
542 : : {
543 : 4 : res = symencrypt_sesskey(ctx, p);
544 [ - + ]: 4 : if (res < 0)
6853 bruce@momjian.us 545 :UBC 0 : return res;
6853 bruce@momjian.us 546 :CBC 4 : p += res;
547 : : }
548 : :
549 : 30 : pktlen = p - pkt;
550 : 30 : res = write_normal_header(dst, PGP_PKT_SYMENCRYPTED_SESSKEY, pktlen);
551 [ + - ]: 30 : if (res >= 0)
552 : 30 : res = pushf_write(dst, pkt, pktlen);
553 : :
3650 554 : 30 : px_memset(pkt, 0, pktlen);
6853 555 : 30 : return res;
556 : : }
557 : :
558 : : /*
559 : : * key setup
560 : : */
561 : : static int
5421 562 : 30 : init_s2k_key(PGP_Context *ctx)
563 : : {
564 : : int res;
565 : :
6853 566 [ + - ]: 30 : if (ctx->s2k_cipher_algo < 0)
567 : 30 : ctx->s2k_cipher_algo = ctx->cipher_algo;
568 : :
2958 alvherre@alvh.no-ip. 569 : 30 : res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo, ctx->s2k_count);
6853 bruce@momjian.us 570 [ - + ]: 30 : if (res < 0)
6853 bruce@momjian.us 571 :UBC 0 : return res;
572 : :
6853 bruce@momjian.us 573 :CBC 30 : return pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
574 : : ctx->sym_key, ctx->sym_key_len);
575 : : }
576 : :
577 : : static int
5421 578 : 36 : init_sess_key(PGP_Context *ctx)
579 : : {
6853 580 [ + + + + ]: 36 : if (ctx->use_sess_key || ctx->pub_key)
581 : : {
582 : 10 : ctx->sess_key_len = pgp_get_cipher_key_size(ctx->cipher_algo);
1930 michael@paquier.xyz 583 [ - + ]: 10 : if (!pg_strong_random(ctx->sess_key, ctx->sess_key_len))
2687 heikki.linnakangas@i 584 :UBC 0 : return PXE_NO_RANDOM;
585 : : }
586 : : else
587 : : {
6853 bruce@momjian.us 588 :CBC 26 : ctx->sess_key_len = ctx->s2k.key_len;
589 : 26 : memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
590 : : }
591 : :
592 : 36 : return 0;
593 : : }
594 : :
595 : : /*
596 : : * combine
597 : : */
598 : : int
5421 599 : 36 : pgp_encrypt(PGP_Context *ctx, MBuf *src, MBuf *dst)
600 : : {
601 : : int res;
602 : : int len;
603 : : uint8 *buf;
604 : : PushFilter *pf,
605 : : *pf_tmp;
606 : :
607 : : /*
608 : : * do we have any key
609 : : */
6853 610 [ + + - + ]: 36 : if (!ctx->sym_key && !ctx->pub_key)
6853 bruce@momjian.us 611 :UBC 0 : return PXE_ARGUMENT_ERROR;
612 : :
613 : : /* MBuf writer */
6853 bruce@momjian.us 614 :CBC 36 : res = pushf_create_mbuf_writer(&pf, dst);
615 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 616 :UBC 0 : goto out;
617 : :
618 : : /*
619 : : * initialize sym_key
620 : : */
6853 bruce@momjian.us 621 [ + + ]:CBC 36 : if (ctx->sym_key)
622 : : {
623 : 30 : res = init_s2k_key(ctx);
624 [ - + ]: 30 : if (res < 0)
6853 bruce@momjian.us 625 :UBC 0 : goto out;
626 : : }
627 : :
6853 bruce@momjian.us 628 :CBC 36 : res = init_sess_key(ctx);
629 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 630 :UBC 0 : goto out;
631 : :
632 : : /*
633 : : * write keypkt
634 : : */
6853 bruce@momjian.us 635 [ + + ]:CBC 36 : if (ctx->pub_key)
636 : 6 : res = pgp_write_pubenc_sesskey(ctx, pf);
637 : : else
638 : 30 : res = write_symenc_sesskey(ctx, pf);
639 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 640 :UBC 0 : goto out;
641 : :
642 : : /* encrypted data pkt */
6853 bruce@momjian.us 643 :CBC 36 : res = init_encdata_packet(&pf_tmp, ctx, pf);
644 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 645 :UBC 0 : goto out;
6853 bruce@momjian.us 646 :CBC 36 : pf = pf_tmp;
647 : :
648 : : /* encrypter */
649 : 36 : res = pushf_create(&pf_tmp, &encrypt_filter, ctx, pf);
650 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 651 :UBC 0 : goto out;
6853 bruce@momjian.us 652 :CBC 36 : pf = pf_tmp;
653 : :
654 : : /* hasher */
655 [ + + ]: 36 : if (ctx->disable_mdc == 0)
656 : : {
657 : 35 : res = pushf_create(&pf_tmp, &mdc_filter, ctx, pf);
658 [ - + ]: 35 : if (res < 0)
6853 bruce@momjian.us 659 :UBC 0 : goto out;
6853 bruce@momjian.us 660 :CBC 35 : pf = pf_tmp;
661 : : }
662 : :
663 : : /* prefix */
664 : 36 : res = write_prefix(ctx, pf);
665 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 666 :UBC 0 : goto out;
667 : :
668 : : /* compressor */
6853 bruce@momjian.us 669 [ + + + + ]:CBC 36 : if (ctx->compress_algo > 0 && ctx->compress_level > 0)
670 : : {
671 : 3 : res = init_compress(&pf_tmp, ctx, pf);
672 [ - + ]: 3 : if (res < 0)
6853 bruce@momjian.us 673 :UBC 0 : goto out;
6853 bruce@momjian.us 674 :CBC 3 : pf = pf_tmp;
675 : : }
676 : :
677 : : /* data streamer */
678 : 36 : res = init_litdata_packet(&pf_tmp, ctx, pf);
679 [ - + ]: 36 : if (res < 0)
6853 bruce@momjian.us 680 :UBC 0 : goto out;
6853 bruce@momjian.us 681 :CBC 36 : pf = pf_tmp;
682 : :
683 : :
684 : : /* text conversion? */
685 [ + + + + ]: 36 : if (ctx->text_mode && ctx->convert_crlf)
686 : : {
687 : 2 : res = pushf_create(&pf_tmp, &crlf_filter, ctx, pf);
688 [ - + ]: 2 : if (res < 0)
6853 bruce@momjian.us 689 :UBC 0 : goto out;
6853 bruce@momjian.us 690 :CBC 2 : pf = pf_tmp;
691 : : }
692 : :
693 : : /*
694 : : * chain complete
695 : : */
696 : :
697 : 36 : len = mbuf_grab(src, mbuf_avail(src), &buf);
698 : 36 : res = pushf_write(pf, buf, len);
699 [ - + ]: 36 : if (res >= 0)
700 : 36 : res = pushf_flush(pf);
6853 bruce@momjian.us 701 :UBC 0 : out:
6853 bruce@momjian.us 702 :CBC 36 : pushf_free_all(pf);
703 : 36 : return res;
704 : : }
|