tpgpget.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tpgpget.c (18668B)
---
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Read OpenPGP packets
9 $Id: pgpget.c 934 2006-06-24 13:40:39Z rabbi $ */
10
11
12 #include "mix3.h"
13 #ifdef USE_PGP
14 #include "pgp.h"
15 #include "crypto.h"
16 #include <time.h>
17 #include <assert.h>
18 #include <string.h>
19
20 int pgp_getmsg(BUFFER *in, BUFFER *key, BUFFER *sig, char *pubring,
21 char *secring)
22 {
23 BUFFER *p;
24 BUFFER *out;
25 int type, algo = 0;
26 int err = PGP_NOMSG;
27 pgpsig signature = {0, NULL, 0, 0, {0,} };
28
29 p = buf_new();
30 out = buf_new();
31
32 if (sig)
33 signature.userid = buf_new();
34
35 while ((type = pgp_getpacket(in, p)) > 0)
36 switch (type) {
37 case PGP_LITERAL:
38 pgp_getliteral(p);
39 buf_move(out, p);
40 err = 0;
41 break;
42 case PGP_COMPRESSED:
43 err = pgp_uncompress(p);
44 if (err == 0)
45 err = pgp_getmsg(p, key, sig, pubring, secring);
46 if (err != PGP_ERR && err != PGP_PASS)
47 buf_move(out, p);
48 break;
49 case PGP_ENCRYPTED:
50 case PGP_ENCRYPTEDMDC:
51 if (!key) {
52 err = -1;
53 break;
54 }
55 if (/*key->length > 0 &&*/ algo == 0) {
56 algo = PGP_K_IDEA;
57 digest_md5(key, key);
58 }
59 if (key->length > 0)
60 err = pgp_getsymmetric(p, key, algo, type==PGP_ENCRYPTEDMDC);
61 else
62 err = -1;
63 if (err == 0)
64 err = pgp_getmsg(p, NULL, sig, pubring, secring);
65 if (err != PGP_ERR)
66 buf_move(out, p);
67 break;
68 case PGP_SESKEY:
69 if (!key) {
70 err = -1;
71 break;
72 }
73 err = pgp_getsessionkey(p, key, secring);
74 if (err >= 0) {
75 algo = err;
76 err = 0;
77 buf_set(key, p);
78 }
79 break;
80 case PGP_SYMSESKEY:
81 if (!key) {
82 err = -1;
83 break;
84 }
85 err = pgp_getsymsessionkey(p, key);
86 if (err >= 0) {
87 algo = err;
88 err = 0;
89 if (key) buf_set(key, p);
90 }
91 break;
92 case PGP_MARKER:
93 err = 0;
94 break; /* ignore per RFC2440 */
95 case PGP_SIG:
96 pgp_getsig(p, &signature, pubring);
97 /* fallthru */
98 default:
99 if (err == PGP_NOMSG)
100 err = PGP_NODATA;
101 }
102
103 if (signature.ok == PGP_SIGVRFY)
104 pgp_verify(out, sig, &signature);
105 if (signature.ok == PGP_SIGOK) {
106 char line[LINELEN];
107 time_t t;
108 struct tm *tc;
109
110 t = signature.sigtime;
111 tc = localtime(&t);
112 #if 0
113 strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S]", tc);
114 #else /* end of 0 */
115 strftime(line, LINELEN, "[%a %b %d %H:%M:%S %Y]", tc);
116 #endif /* else if not 0 */
117 if (sig) {
118 buf_cat(sig, signature.userid);
119 buf_appendc(sig, ' ');
120 buf_appends(sig, line);
121 }
122 }
123 if (sig) {
124 if (signature.ok == PGP_SIGNKEY)
125 buf_appendf(sig, "%02X%02X%02X%02X", signature.userid->data[4],
126 signature.userid->data[5], signature.userid->data[6],
127 signature.userid->data[7]);
128 buf_free(signature.userid);
129 }
130
131 if ((err == 0 || err == PGP_NODATA) && signature.ok != 0)
132 err = signature.ok;
133
134 buf_move(in, out);
135 buf_free(out);
136 buf_free(p);
137
138 return (err);
139 }
140
141 int pgp_ispacket(BUFFER *b)
142 {
143 return ((b->data[b->ptr] >> 6) == 2 || (b->data[b->ptr] >> 6) == 3);
144 }
145
146 int pgp_packettype(BUFFER *b, long *len, int *partial)
147 {
148 int ctb;
149
150 ctb = buf_getc(b);
151 switch (ctb >> 6) {
152 case 2:
153 /* old packet type */
154 switch (ctb & 3) {
155 case 0:
156 *len = buf_getc(b);
157 break;
158 case 1:
159 *len = buf_geti(b);
160 break;
161 case 2:
162 *len = buf_getl(b);
163 break;
164 case 3:
165 *len = b->length - b->ptr;
166 break;
167 }
168 *partial = 0;
169 return (ctb >> 2) & 15;
170 case 3:
171 case 1: /* in GnuPG secret key ring */
172 /* new packet type */
173 *len = buf_getc(b);
174 if (*len >= 192 && *len <= 223)
175 *len = (*len - 192) * 256 + buf_getc(b) + 192;
176 else if (*len == 255)
177 *len = buf_getl(b);
178 else if (*len > 223) {
179 *len = 1 <<(*len & 0x1f);
180 *partial = 1;
181 }
182 return (ctb & 63);
183 }
184 return (-1);
185 }
186
187 int pgp_packetpartial(BUFFER *b, long *len, int *partial)
188 {
189 *partial = 0;
190 *len = buf_getc(b);
191 if (*len >= 192 && *len <= 223)
192 *len = (*len - 192) * 256 + buf_getc(b) + 192;
193 else if (*len == 255)
194 *len = buf_getl(b);
195 else if (*len > 223) {
196 *len = 1 <<(*len & 0x1f);
197 *partial = 1;
198 }
199 return 1;
200 }
201
202 int pgp_isconventional(BUFFER *b)
203 {
204 int type;
205 BUFFER *p;
206 p = buf_new();
207
208 type = pgp_getpacket(b, p);
209 if (type == PGP_MARKER)
210 type = pgp_getpacket(b, p);
211 buf_rewind(b);
212 buf_free(p);
213 return (type == PGP_ENCRYPTED || type == PGP_SYMSESKEY);
214 }
215
216 int pgp_getpacket(BUFFER *in, BUFFER *p)
217 /* returns <0 = error, >0 = packet type */
218 {
219 int type;
220 long len;
221 int partial = 0;
222 BUFFER *tmp;
223
224 tmp = buf_new();
225 type = pgp_packettype(in, &len, &partial);
226 if (type > 0 && len > 0) {
227 buf_clear(p);
228 while(partial && len > 0) {
229 buf_get(in, tmp, len);
230 buf_cat(p, tmp);
231 pgp_packetpartial(in, &len, &partial);
232 }
233 if (len > 0) {
234 buf_get(in, tmp, len);
235 buf_cat(p, tmp);
236 }
237 }
238
239 buf_free(tmp);
240 return (type);
241 }
242
243 int pgp_getsig(BUFFER *p, pgpsig *sig, char *pubring)
244 {
245 BUFFER *sigkey, *id, *i;
246 int algo, hashalgo;
247 int hash;
248
249 sigkey = buf_new();
250 id = buf_new();
251 i = buf_new();
252
253 sig->ok = PGP_SIGBAD;
254
255 if (buf_getc(p) > 3)
256 goto end;
257 if (buf_getc(p) != 5)
258 goto end;
259 sig->sigtype = buf_getc(p);
260 sig->sigtime = buf_getl(p);
261 buf_get(p, id, 8);
262 algo = buf_getc(p);
263 hashalgo = buf_getc(p);
264 if (hashalgo != PGP_H_MD5)
265 goto end;
266 hash = buf_geti(p);
267 if (pgpdb_getkey(PK_VERIFY, algo, NULL, NULL, NULL, sigkey, NULL, sig->userid, id,
268 pubring, NULL) < 0) {
269 sig->ok = PGP_SIGNKEY;
270 if (sig->userid)
271 buf_set(sig->userid, id);
272 goto end;
273 }
274 switch (algo) {
275 case PGP_ES_RSA:
276 mpi_get(p, i);
277 if (pgp_rsa(i, sigkey, PK_VERIFY) == -1 ||
278 memcmp(i->data, MD5PREFIX, sizeof(MD5PREFIX) - 1) != 0)
279 goto end;
280 memcpy(sig->hash, i->data + sizeof(MD5PREFIX) - 1, 16);
281 if (sig->hash[0] * 256 + sig->hash[1] != hash)
282 goto end;
283 sig->ok = PGP_SIGVRFY;
284 break;
285 default:
286 break;
287 }
288 end:
289 buf_free(sigkey);
290 buf_free(id);
291 buf_free(i);
292 return (sig->ok);
293 }
294
295 void pgp_verify(BUFFER *msg, BUFFER *detached, pgpsig *sig)
296 {
297 MD5_CTX c;
298 BUFFER *t;
299 byte md[16];
300
301 t = buf_new();
302 sig->ok = PGP_SIGBAD;
303
304 if (msg->length == 0) { /* detached signature */
305 if (detached && detached->length) {
306 buf_move(msg, detached);
307 if (sig->sigtype == PGP_SIG_CANONIC)
308 pgp_sigcanonic(msg); /* for cleartext signatures */
309 } else
310 sig->ok = PGP_NODATA;
311 }
312 MD5_Init(&c);
313 switch (sig->sigtype) {
314 case PGP_SIG_BINARY:
315 MD5_Update(&c, msg->data, msg->length);
316 break;
317 case PGP_SIG_CANONIC:
318 while (buf_getline(msg, t) != -1) {
319 #if 0
320 pgp_sigcanonic(t); /* according to OpenPGP */
321 #else /* end of 0 */
322 buf_appends(t, "\r\n");
323 #endif /* else if not 0 */
324 MD5_Update(&c, t->data, t->length);
325 }
326 break;
327 default:
328 sig->ok = PGP_SIGBAD;
329 }
330 MD5_Update(&c, &(sig->sigtype), 1);
331 buf_appendl(t, sig->sigtime);
332 MD5_Update(&c, t->data, 4);
333 MD5_Final(md, &c);
334 if (memcmp(md, sig->hash, 16) == 0)
335 sig->ok = PGP_SIGOK;
336 buf_free(t);
337 }
338
339 #ifdef USE_IDEA
340 static int pgp_ideadecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
341 {
342 int err = 0;
343 byte iv[8];
344 byte hdr[10];
345 int i, n;
346 IDEA_KEY_SCHEDULE ks;
347 SHA_CTX c;
348 char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
349
350 if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
351 return (-1);
352
353 if (mdc) {
354 mdc = 1;
355 if (in->data[0] != 1)
356 return (-1);
357 }
358
359 buf_prepare(out, in->length - 10 - mdc);
360
361 for (i = 0; i < 8; i++)
362 iv[i] = 0;
363
364 idea_set_encrypt_key(key->data, &ks);
365
366 n = 0;
367 idea_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, IDEA_DECRYPT);
368 if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
369 err = -1;
370 goto end;
371 }
372 if (mdc) {
373 SHA1_Init(&c);
374 SHA1_Update(&c, hdr, 10);
375 } else {
376 iv[6] = iv[0], iv[7] = iv[1];
377 memcpy(iv, in->data + 2, 6);
378 n = 0;
379 }
380 idea_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks, iv, &n,
381 IDEA_DECRYPT);
382 if (mdc) {
383 if (out->length > 22) {
384 out->length -= 22;
385 if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
386 SHA1_Update(&c, out->data, out->length + 2);
387 SHA1_Final(md, &c);
388 if (memcmp(out->data + out->length + 2, md, 20))
389 err = -1;
390 } else
391 err = -1;
392 } else
393 err = -1;
394 }
395 end:
396 return (err);
397 }
398 #endif /* USE_IDEA */
399
400 static int pgp_3desdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
401 {
402 int err = 0;
403 DES_cblock iv;
404 byte hdr[10];
405 int i, n;
406 DES_key_schedule ks1;
407 DES_key_schedule ks2;
408 DES_key_schedule ks3;
409 SHA_CTX c;
410 char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
411
412 if (key->length != 24 || in->length <= (mdc?(1+10+22):10))
413 return (-1);
414
415 if (mdc) {
416 mdc = 1;
417 if (in->data[0] != 1)
418 return (-1);
419 }
420
421 buf_prepare(out, in->length - 10 - mdc);
422
423 for (i = 0; i < 8; i++)
424 iv[i] = 0;
425
426 DES_set_key((const_DES_cblock *) key->data, &ks1);
427 DES_set_key((const_DES_cblock *) (key->data + 8), &ks2);
428 DES_set_key((const_DES_cblock *) (key->data+ 16), &ks3);
429
430 n = 0;
431 DES_ede3_cfb64_encrypt(in->data + mdc, hdr, 10, &ks1, &ks2, &ks3, &iv, &n, DECRYPT);
432 if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
433 err = -1;
434 goto end;
435 }
436 if (mdc) {
437 SHA1_Init(&c);
438 SHA1_Update(&c, hdr, 10);
439 } else {
440 iv[6] = iv[0], iv[7] = iv[1];
441 memcpy(iv, in->data + 2, 6);
442 n = 0;
443 }
444 DES_ede3_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 + mdc, &ks1,
445 &ks2, &ks3, &iv, &n, DECRYPT);
446 if (mdc) {
447 if (out->length > 22) {
448 out->length -= 22;
449 if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
450 SHA1_Update(&c, out->data, out->length + 2);
451 SHA1_Final(md, &c);
452 if (memcmp(out->data + out->length + 2, md, 20))
453 err = -1;
454 } else
455 err = -1;
456 } else
457 err = -1;
458 }
459 end:
460 return (err);
461 }
462
463 static int pgp_castdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
464 {
465 int err = 0;
466 byte iv[8];
467 byte hdr[10];
468 int i, n;
469 SHA_CTX c;
470 char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
471
472 CAST_KEY ks;
473
474 if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
475 return (-1);
476
477 if (mdc) {
478 mdc = 1;
479 if (in->data[0] != 1)
480 return (-1);
481 }
482
483 buf_prepare(out, in->length - 10 - mdc);
484
485 for (i = 0; i < 8; i++)
486 iv[i] = 0;
487
488 CAST_set_key(&ks, 16, key->data);
489
490 n = 0;
491 CAST_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, CAST_DECRYPT);
492 if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
493 err = -1;
494 goto end;
495 }
496 if (mdc) {
497 SHA1_Init(&c);
498 SHA1_Update(&c, hdr, 10);
499 } else {
500 iv[6] = iv[0], iv[7] = iv[1];
501 memcpy(iv, in->data + 2, 6);
502 n = 0;
503 }
504 CAST_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
505 iv, &n, CAST_DECRYPT);
506 if (mdc) {
507 if (out->length > 22) {
508 out->length -= 22;
509 if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
510 SHA1_Update(&c, out->data, out->length + 2);
511 SHA1_Final(md, &c);
512 if (memcmp(out->data + out->length + 2, md, 20))
513 err = -1;
514 } else
515 err = -1;
516 } else
517 err = -1;
518 }
519 end:
520 return (err);
521 }
522
523 static int pgp_bfdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
524 {
525 int err = 0;
526 byte iv[8];
527 byte hdr[10];
528 int i, n;
529 SHA_CTX c;
530 char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
531
532 BF_KEY ks;
533
534 if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
535 return (-1);
536
537 if (mdc) {
538 mdc = 1;
539 if (in->data[0] != 1)
540 return (-1);
541 }
542
543 buf_prepare(out, in->length - 10 - mdc);
544
545 for (i = 0; i < 8; i++)
546 iv[i] = 0;
547
548 BF_set_key(&ks, 16, key->data);
549
550 n = 0;
551 BF_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, BF_DECRYPT);
552 if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
553 err = -1;
554 goto end;
555 }
556 if (mdc) {
557 SHA1_Init(&c);
558 SHA1_Update(&c, hdr, 10);
559 } else {
560 iv[6] = iv[0], iv[7] = iv[1];
561 memcpy(iv, in->data + 2, 6);
562 n = 0;
563 }
564 BF_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
565 iv, &n, BF_DECRYPT);
566 if (mdc) {
567 if (out->length > 22) {
568 out->length -= 22;
569 if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
570 SHA1_Update(&c, out->data, out->length + 2);
571 SHA1_Final(md, &c);
572 if (memcmp(out->data + out->length + 2, md, 20))
573 err = -1;
574 } else
575 err = -1;
576 } else
577 err = -1;
578 }
579 end:
580 return (err);
581 }
582
583 #ifdef USE_AES
584 static int pgp_aesdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
585 {
586 int err = 0;
587 byte iv[16];
588 byte hdr[18];
589 int i, n;
590 SHA_CTX c;
591 char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
592
593 AES_KEY ks;
594
595 if ((key->length != 16 && key->length != 24 && key->length != 32) || in->length <= (mdc?(1+18+22):18))
596 return (-1);
597
598 if (mdc) {
599 mdc = 1;
600 if (in->data[0] != 1)
601 return (-1);
602 }
603
604 buf_prepare(out, in->length - 18 - mdc);
605
606 for (i = 0; i < 16; i++)
607 iv[i] = 0;
608
609 AES_set_encrypt_key(key->data, key->length<<3, &ks);
610
611 n = 0;
612 AES_cfb128_encrypt(in->data + mdc, hdr, 18, &ks, iv, &n, AES_DECRYPT);
613 if (n != 2 || hdr[16] != hdr[14] || hdr[17] != hdr[15]) {
614 err = -1;
615 goto end;
616 }
617 if (mdc) {
618 SHA1_Init(&c);
619 SHA1_Update(&c, hdr, 18);
620 } else {
621 iv[14] = iv[0], iv[15] = iv[1];
622 memcpy(iv, in->data + 2, 14);
623 n = 0;
624 }
625 AES_cfb128_encrypt(in->data + 18 + mdc, out->data, in->length - 18 - mdc, &ks,
626 iv, &n, AES_DECRYPT);
627 if (mdc) {
628 if (out->length > 22) {
629 out->length -= 22;
630 if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
631 SHA1_Update(&c, out->data, out->length + 2);
632 SHA1_Final(md, &c);
633 if (memcmp(out->data + out->length + 2, md, 20))
634 err = -1;
635 } else
636 err = -1;
637 } else
638 err = -1;
639 }
640 end:
641 return (err);
642 }
643 #endif /* USE_AES */
644
645 int pgp_getsymmetric(BUFFER *in, BUFFER *key, int algo, int mdc)
646 {
647 int err = -1;
648 BUFFER *out;
649
650 out = buf_new();
651
652 switch (algo) {
653 #ifdef USE_AES
654 case PGP_K_AES128:
655 case PGP_K_AES192:
656 case PGP_K_AES256:
657 err = pgp_aesdecrypt(in, out, key, mdc);
658 break;
659 #endif /* USE_AES */
660 #ifdef USE_IDEA
661 case PGP_K_IDEA:
662 err = pgp_ideadecrypt(in, out, key, mdc);
663 break;
664 #endif /* USE_IDEA */
665 case PGP_K_3DES:
666 err = pgp_3desdecrypt(in, out, key, mdc);
667 break;
668 case PGP_K_CAST5:
669 err = pgp_castdecrypt(in, out, key, mdc);
670 break;
671 case PGP_K_BF:
672 err = pgp_bfdecrypt(in, out, key, mdc);
673 break;
674 }
675
676 if (err < 0)
677 errlog(ERRORMSG, "PGP decryption failed.\n");
678
679 buf_move(in, out);
680 buf_free(out);
681 return (err);
682 }
683
684 int pgp_getliteral(BUFFER *in)
685 {
686 long fnlen;
687 int err = 0;
688 int mode;
689 BUFFER *out;
690 BUFFER *line;
691
692 out = buf_new();
693 line = buf_new();
694 mode = buf_getc(in);
695 fnlen = buf_getc(in);
696 in->ptr += fnlen; /* skip filename */
697 if (in->ptr + 4 > in->length)
698 err = -1;
699 else {
700 buf_getl(in); /* timestamp */
701 if (mode == 't')
702 while (buf_getline(in, line) != -1) {
703 buf_cat(out, line);
704 buf_nl(out);
705 } else
706 buf_rest(out, in);
707 }
708 buf_move(in, out);
709 buf_free(line);
710 buf_free(out);
711 return (err);
712 }
713
714 int pgp_uncompress(BUFFER *in)
715 {
716 int err = -1;
717
718 switch(buf_getc(in)) {
719 case 0:
720 err = 0;
721 break;
722 case 1:
723 err = buf_unzip(in, 0);
724 break;
725 case 2:
726 err = buf_unzip(in, 1);
727 break;
728 default:
729 err = -1;
730 break;
731 }
732 return (err);
733 }
734
735 int pgp_getsessionkey(BUFFER *in, BUFFER *pass, char *secring)
736 {
737 BUFFER *out;
738 BUFFER *key;
739 BUFFER *keyid;
740 int type;
741 int i, csum = 0;
742 int algo = 0;
743 int err = -1;
744 long expires;
745
746 out = buf_new();
747 key = buf_new();
748 keyid = buf_new();
749 type = buf_getc(in); /* packet type */
750 if (type < 2 || type > 3)
751 goto end;
752 buf_get(in, keyid, 8);
753 algo = buf_getc(in);
754 err = pgpdb_getkey(PK_DECRYPT, algo, NULL, NULL, &expires, key, NULL, NULL, keyid,
755 secring, pass);
756 if (err < 0)
757 goto end;
758 if (expires > 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
759 errlog(DEBUGINFO, "Key expired.\n"); /* DEBUGINFO ? */
760 err = -1;
761 goto end;
762 }
763 switch (algo) {
764 case PGP_ES_RSA:
765 mpi_get(in, out);
766 err = pgp_rsa(out, key, PK_DECRYPT);
767 break;
768 case PGP_E_ELG:
769 buf_rest(out, in);
770 err = pgp_elgdecrypt(out, key);
771 break;
772 default:
773 err = -1;
774 }
775 if (err == 0 && out->length > 3) {
776 algo = buf_getc(out);
777 buf_get(out, in, out->length - 3); /* return recovered key */
778 csum = buf_geti(out);
779 for (i = 0; i < in->length; i++)
780 csum = (csum - in->data[i]) % 65536;
781 if (csum != 0)
782 err = -1;
783 } else
784 err = -1;
785 end:
786 buf_free(out);
787 buf_free(key);
788 buf_free(keyid);
789 return (err == 0 ? algo : err);
790 }
791
792 void pgp_iteratedsk(BUFFER *out, BUFFER *salt, BUFFER *pass, byte c)
793 {
794 int count;
795 BUFFER *temp;
796 temp = buf_new();
797
798 count = (16l + (c & 15)) << ((c >> 4) + 6);
799 while (temp->length < count) {
800 buf_cat(temp, salt);
801 buf_cat(temp, pass);
802 }
803 buf_get(temp, out, count);
804 buf_free(temp);
805 }
806
807 int pgp_getsk(BUFFER *p, BUFFER *pass, BUFFER *key)
808 {
809 int skalgo, skspecifier, hashalgo;
810 BUFFER *salted; /* passphrase with salt */
811
812 if (!pass)
813 return(-1);
814
815 salted = buf_new();
816
817 skalgo = buf_getc(p);
818 skspecifier = buf_getc(p);
819 hashalgo = buf_getc(p);
820 switch (skspecifier) {
821 case 0:
822 buf_set(salted, pass);
823 break;
824 case 1:
825 buf_get(p, salted, 8); /* salt */
826 buf_cat(salted, pass);
827 break;
828 case 3:
829 buf_get(p, salted, 8); /* salt */
830 pgp_iteratedsk(salted, salted, pass, buf_getc(p));
831 break;
832 default:
833 skalgo = -1;
834 goto end;
835 }
836 if (pgp_expandsk(key, skalgo, hashalgo, salted) == -1)
837 skalgo = -1;
838
839 end:
840 buf_free(salted);
841 return (skalgo);
842 }
843
844 int pgp_getsymsessionkey(BUFFER *in, BUFFER *pass)
845 {
846 BUFFER *temp, *key, *iv;
847 int algo = -1;
848 temp = buf_new();
849 key = buf_new();
850 iv = buf_new();
851
852 if (buf_getc(in) == 4) { /* version */
853 algo = pgp_getsk(in, pass, key);
854 buf_rest(temp, in);
855 if (temp->length) {
856 /* encrypted session key present */
857 buf_appendzero(iv, pgp_blocklen(algo));
858 skcrypt(temp, algo, key, iv, DECRYPT);
859 algo = buf_getc(temp);
860 buf_rest(in, temp);
861 } else
862 buf_set(in, key);
863 }
864 buf_free(temp);
865 buf_free(key);
866 buf_free(iv);
867 return (algo);
868 }
869
870 #endif /* USE_PGP */