1 /* rfc2440.c - OpenPGP message format
2  *   Copyright (C) 2002, 2007 Timo Schulz
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <defines.h>
19 #include <random.h>
20 #include <time.h>
21 #include <assert.h>
22 #ifdef HAVE_LIBZ
23 #include <zlib.h>
24 #endif
25 #include <stdio.h>
26 
27 #include "keys.h"
28 #include "errors.h"
29 #include "rfc2440.h"
30 #include "defines.h"
31 
32 #ifndef _mcrypt_calloc
33 #define _mcrypt_calloc calloc
34 #endif
35 
36 /*-- mcrypt.c --*/
37 extern char *algorithm;
38 extern int keysize;
39 extern char* keymode;
40 extern char* mode;
41 extern int openpgp_z;
42 extern int real_random_flag;
43 /*--------------*/
44 
45 extern int total_bytes; /* openpgp.c */
46 
47 /* typedef short cuts for common primitive data types. */
48 typedef unsigned int uint32;
49 typedef unsigned char uchar;
50 
51 #define S2K_DEFAULT_COUNT 96
52 
53 #ifndef DIM /* helper to figure out the amount of elements. */
54 #define DIM(x) (sizeof (x) / sizeof (x)[0])
55 #endif
56 
57 typedef struct packet_s {
58     unsigned blockmode:1;
59     unsigned old:1;
60 } PACKET;
61 
62 
63 /* FIXME: the 'mmap' interface could be a problem for larger
64           files. In general it would be better to provide a
65           more flexible solutions with smaller buffers. */
66 
67 
68 static USTRING
make_ustring(const uchar * buffer,size_t length)69 make_ustring(const uchar *buffer, size_t length)
70 {
71     USTRING a;
72 
73     a = _mcrypt_calloc(1, sizeof *a + length);
74     a->len = length;
75     a->d = (void*)a + sizeof *a;
76     memset(a->d, 1, length);
77     if (buffer != NULL)
78         memcpy(a->d, buffer, length);
79     return a;
80 }
81 
82 static USTRING
realloc_ustring(const USTRING src,size_t length)83 realloc_ustring(const USTRING src, size_t length)
84 {
85     USTRING a;
86     size_t len;
87 
88     len = length;
89     if (src != NULL)
90 	len += src->len;
91     a = _mcrypt_calloc(1,  sizeof *a + len);
92     a->len = len;
93     a->d = (void*)a + sizeof *a;
94     memset(a->d, 1, len);
95     if (src != NULL) {
96 	memcpy(a->d, src->d, src->len);
97 	free(src);
98     }
99     return a;
100 }
101 
102 static uchar*
file_to_buf(const char * file,off_t offset,size_t * ret_len)103 file_to_buf(const char *file, off_t offset, size_t *ret_len )
104 {
105     struct stat statbuf;
106     uchar *buf;
107     FILE *fp;
108     size_t len;
109 
110     /* Return NULL if the file cannot be stat or has a length of zero. */
111     if (stat(file, &statbuf) == -1 ||
112 	statbuf.st_size == 0)
113         return NULL;
114 
115     len = statbuf.st_size;
116     fp = fopen(file, "rb");
117     if (fp == NULL)
118         return NULL;
119     buf = _mcrypt_calloc(1,  len);
120     fseeko(fp, offset, SEEK_SET);
121     fread(buf, 1, len, fp);
122     fclose(fp);
123     *ret_len = len - offset;
124     return buf;
125 }
126 
127 static void
_mcrypt_sync(MCRYPT hd,uchar * rndpref,int blocklen)128 _mcrypt_sync(MCRYPT hd, uchar *rndpref, int blocklen)
129 {
130     uchar sync[19];
131 
132     if (blocklen != 8 && blocklen != 16)
133         return;
134     sync[0] = 0;
135     memcpy(sync + 1, rndpref + 2, blocklen);
136     mcrypt_enc_set_state(hd, sync, blocklen + 1);
137 }
138 
139 
140 static int
_mcrypt_encrypt(MCRYPT hd,uchar * out,size_t outlen,uchar * in,size_t inlen)141 _mcrypt_encrypt(MCRYPT hd, uchar *out, size_t outlen,
142 		uchar *in, size_t inlen)
143 {
144     if (!in)
145         return mcrypt_generic(hd, out, outlen);
146     if (outlen < inlen)
147         return -1;
148     memcpy(out, in, inlen);
149     mcrypt_generic(hd, out, inlen);
150     return 0;
151 }
152 
153 static int
_mcrypt_decrypt(MCRYPT hd,uchar * out,size_t outlen,uchar * in,size_t inlen)154 _mcrypt_decrypt(MCRYPT hd, uchar *out, size_t outlen,
155 		uchar *in, size_t inlen)
156 {
157     if (!in)
158         return mdecrypt_generic(hd, out, outlen);
159     if (outlen < inlen)
160         return -1;
161     memcpy(out, in, inlen);
162     mdecrypt_generic(hd, out, inlen);
163     return 0;
164 }
165 
166 
167 static char*
_mhash_keymode2str(keygenid ki,hashid hi)168 _mhash_keymode2str(keygenid ki, hashid hi)
169 {
170     static char ret[512];
171 
172     ret[0] = 0;
173     if (ki == KEYGEN_S2K_SIMPLE)
174         strcat(ret, "s2k-simple-");
175     else if (ki == KEYGEN_S2K_SALTED)
176         strcat(ret, "s2k-salted-");
177     else if (ki == KEYGEN_S2K_ISALTED)
178         strcat(ret, "s2k-isalted-");
179 
180     if (hi == MHASH_SHA1)
181         strcat(ret, "sha1");
182     else if (hi == MHASH_MD5)
183         strcat(ret, "md5");
184     else if (hi == MHASH_RIPEMD160)
185         strcat(ret, "ripemd");
186     else if (hi == MHASH_SHA256)
187 	strcat(ret, "sha256");
188     return ret;
189 }
190 
191 /* Convert the OpenPGP type ID to the local mhash ID. */
192 static int
_mhash_keygen(uchar algid)193 _mhash_keygen(uchar algid)
194 {
195     switch (algid) {
196     case OPENPGP_S2K_SIMPLE: return KEYGEN_S2K_SIMPLE;
197     case OPENPGP_S2K_SALTED: return KEYGEN_S2K_SALTED;
198     case OPENPGP_S2K_ISALTED: return KEYGEN_S2K_ISALTED;
199     }
200     return KEYGEN_S2K_ISALTED; /* return default keygen mode. */
201 }
202 
203 int
_mhash_keygen_to_rfc2440(int algo)204 _mhash_keygen_to_rfc2440(int algo)
205 {
206     switch (algo) {
207     case KEYGEN_S2K_SIMPLE: return OPENPGP_S2K_SIMPLE;
208     case KEYGEN_S2K_SALTED: return OPENPGP_S2K_SALTED;
209     case KEYGEN_S2K_ISALTED: return OPENPGP_S2K_ISALTED;
210     }
211     return OPENPGP_S2K_ISALTED;
212 }
213 
214 static int
_mhash_algo(uchar algid)215 _mhash_algo(uchar algid)
216 {
217     switch ( algid ) {
218     case OPENPGP_MD_MD5: return MHASH_MD5;
219     case OPENPGP_MD_SHA1: return MHASH_SHA1;
220     case OPENPGP_MD_RMD160: return MHASH_RIPEMD160;
221     }
222     return MHASH_SHA1;
223 }
224 
225 static int
_mhash_algo_to_rfc2440(int algo)226 _mhash_algo_to_rfc2440(int algo)
227 {
228     switch (algo) {
229     case MHASH_MD5: return OPENPGP_MD_MD5;
230     case MHASH_SHA1: return OPENPGP_MD_SHA1;
231     case MHASH_RIPEMD160: return OPENPGP_MD_RMD160;
232     }
233     return OPENPGP_MD_SHA1;
234 }
235 
236 
237 static char*
_mcrypt_algid_to_algo(uchar algid)238 _mcrypt_algid_to_algo(uchar algid)
239 {
240     switch (algid) {
241     case OPENPGP_ENC_3DES:
242 	keysize = 24;
243 	return "tripledes";
244 
245     case OPENPGP_ENC_CAST5:
246 	keysize = 16;
247 	return "cast-128";
248 
249     case OPENPGP_ENC_BLOWFISH:
250 	keysize = 16;
251 	return "blowfish";
252 
253     case OPENPGP_ENC_AES128:
254 	keysize = 16;
255 	return "rijndael-128";
256 
257     case OPENPGP_ENC_AES192:
258 	keysize = 24;
259 	return "rijndael-128";
260 
261     case OPENPGP_ENC_AES256:
262 	keysize = 32;
263 	return "rijndael-128";
264 
265     case OPENPGP_ENC_TWOFISH:
266 	keysize = 32;
267 	return "twofish";
268     }
269 
270     /* default cipher is CAST5. */
271     keysize = 16;
272     return "cast-128";
273 }
274 
275 /* convert mcrypt specific ID to an OpenPGP ID. */
276 static uchar
_mcrypt_algo_to_algid(char * algo)277 _mcrypt_algo_to_algid(char *algo)
278 {
279     if  (!strcmp(algo, "tripledes"))
280         return OPENPGP_ENC_3DES;
281     else if (!strcmp(algo, "cast-128"))
282         return OPENPGP_ENC_CAST5;
283     else if (!strcmp(algo, "blowfish"))
284         return OPENPGP_ENC_BLOWFISH;
285     else if (!strcmp(algo, "rijndael-128") && keysize == 16)
286         return OPENPGP_ENC_AES128;
287     else if ( !strcmp(algo, "rijndael-128") && keysize == 24)
288         return OPENPGP_ENC_AES192;
289     else if ( !strcmp(algo, "rijndael-128") && keysize == 32)
290         return OPENPGP_ENC_AES256;
291     else if ( !strcmp(algo, "twofish"))
292         return OPENPGP_ENC_TWOFISH;
293 
294     return OPENPGP_ENC_AES128;
295 }
296 
297 static char*
pgp_get_algo(char * algo)298 pgp_get_algo(char *algo)
299 {
300     /* Return default cipher algorithm. */
301     if (!algo)
302         return "cast-128";
303 
304     /* make sure we only use OpenPGP compatible algorithms */
305     if (!strcmp(algo, "tripledes") ||
306 	!strcmp(algo, "cast-128") ||
307 	!strcmp(algo, "blowfish") ||
308 	!strcmp(algo, "rijndael-128") ||
309 	!strcmp(algo, "twofish"))
310         return algo;
311 
312     fprintf(stderr,
313 	    _("Algorithm %s is not available in OpenPGP encryption.\n"),
314 	    algo);
315     fprintf(stderr, _("%s will be used instead.\n"), DEFAULT_PGP_ALGO);
316     return DEFAULT_PGP_ALGO;
317 }
318 
319 
320 static uint32
get_pkt_tag(const uchar * buf,PACKET * pkt)321 get_pkt_tag(const uchar *buf, PACKET *pkt)
322 {
323     uint32 tag = -1;
324 
325     assert(buf);
326     if (!(buf[0] & 0x80))
327         return -1; /* invalid */
328     if (buf[0] & 0x40) { /* new style */
329         tag = buf[0] & 0x3f;
330         if (pkt)
331 	    pkt->old = 0;
332     }
333     else { /* old style */
334         tag = (buf[0] & 0x3c) >> 2;
335         if (pkt)
336 	    pkt->old = 1;
337     }
338     return tag;
339 }
340 
341 
342 static uint32
length_len(const uint32 len,PACKET * pkt)343 length_len(const uint32 len, PACKET *pkt)
344 {
345     uint32 ret = 0;
346 
347     if (pkt && pkt->blockmode)
348         return 1;
349     else if (pkt && pkt->old) {
350         if (len < 0xff)
351             ret = 1;
352         else if (len < 0xffff)
353             ret = 2;
354         else if (len < 0xffffffff)
355             ret = 4;
356     }
357     else {
358         if (len < 192)
359             ret = 1;
360         else if (len < 8384)
361             ret = 2;
362         else
363             ret = 5;
364     }
365     return ret;
366 }
367 
368 
369 static void
length_encode(uint32 len,uchar * lenbuf,uchar * lensize)370 length_encode(uint32 len, uchar *lenbuf, uchar *lensize)
371 {
372     assert(len > 0);
373 
374     if (len < 192) {
375         lenbuf[0] = len;
376 	*lensize = 1;
377     }
378     else if (len < 8384) {
379         len -= 192;
380         lenbuf[0] = len / 256 + 192;
381         lenbuf[1] = len % 256;
382 	*lensize = 2;
383     }
384     else {
385         lenbuf[0] = 255;
386         lenbuf[1] = len >> 24;
387         lenbuf[2] = len >> 16;
388         lenbuf[3] = len >>  8;
389         lenbuf[4] = len;
390 	*lensize = 5;
391     }
392 }
393 
394 
395 static uint32
length_decode(const uchar * buf,int pos,PACKET * pkt)396 length_decode(const uchar *buf, int pos, PACKET *pkt)
397 {
398     uint32 len = 0;
399 
400     assert (buf != NULL);
401     assert (pos >= 0);
402 
403     if (buf[pos] < 192)
404         len = buf[pos];
405     else if (buf[pos] >= 192 && buf[pos] <= 223) {
406         len = (buf[pos] - 192) << 8;
407         len += (buf[pos+1] + 192);
408     }
409     else if (buf[pos] == 255) {
410         len += (buf[pos+1] << 24);
411         len += (buf[pos+2] << 16);
412         len += (buf[pos+3] << 8);
413         len += buf[pos+4];
414     }
415     else {
416         len = 1 << (buf[pos]);
417         if (pkt)
418 	    pkt->blockmode = 1;
419     }
420     return len;
421 }
422 
423 static void
header_decode(const uchar * buf,uint32 * tag,uint32 * len,uint32 * headlen,PACKET * pkt)424 header_decode(const uchar *buf, uint32 *tag, uint32 *len,
425 	      uint32 *headlen, PACKET *pkt)
426 {
427     assert (buf != NULL);
428 
429     *tag = get_pkt_tag(buf, pkt);
430     if (buf[0] & 0x40) {
431         *len = length_decode( buf, 1, pkt );
432         *headlen = 1 + length_len( *len, pkt );
433     }
434     else {
435         if ((buf[0] & 0x03) == 0) {
436             *len = buf[1];
437             *headlen = 2;
438         }
439         else if ((buf[0] & 0x03) == 1) {
440             *len = (buf[1] << 8) | buf[2];
441             *headlen = 3;
442         }
443         else if ((buf[0] & 0x03) == 2) {
444             *len = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
445             *headlen = 5;
446         }
447         else if ((buf[0] & 0x03) == 3) {
448             *len = 0;
449             *headlen = 1;
450         }
451     }
452 }
453 
454 int
plaintext_decode(const USTRING pt,USTRING * result)455 plaintext_decode(const USTRING pt, USTRING *result)
456 {
457     uint32 headlen = 0, tag = 0, offset = 0;
458     PACKET pkt;
459     USTRING t;
460 
461     memset( &pkt, 0, sizeof(pkt));
462 
463     assert(pt->len > 0);
464     header_decode(pt->d, &tag, &headlen, &offset, &pkt);
465     if (tag != PKT_PLAINTEXT)
466         return PGP_ERR_PKT;
467 
468     if (pt->len < 8) /* wrong len */
469         return PGP_ERR_PKT;
470     if (!pkt.blockmode && (pt->len-1-length_len(headlen, &pkt)) != headlen)
471         return PGP_ERR_PKT; /* malformed */
472     if (pt->d[offset] != 0x62 && pt->d[offset] != 0x74)
473         return PGP_ERR_PKT;
474     offset++;
475 
476     /* we ignore the file name but need to skip past it if its present */
477     if (pt->d[offset] > 0)
478         offset += pt->d[offset];
479     offset++; /* file name length */
480     offset += 4; /* timestamp */
481 
482     t = make_ustring( pt->d+offset, pt->len-offset);
483     *result = t;
484 
485     return PGP_SUCCESS;
486 }
487 
488 
489 USTRING
plaintext_encode(const USTRING dat)490 plaintext_encode(const USTRING dat)
491 {
492     USTRING result = NULL, newdat = NULL;
493     uint32 pos = 0;
494     uchar lenbuf[5], lensize = 0;
495     time_t t;
496 
497     assert(dat->len > 0);
498     result = make_ustring( NULL,  2 * dat->len); /* xxx */
499     newdat = (USTRING)dat;
500     result->d[pos++] = (0x80 | 0x40 | PKT_PLAINTEXT);
501 
502     /* 1 byte data type, 4 bytes timestamp, 1 byte non-file-name */
503     length_encode(dat->len + 6, lenbuf, &lensize);
504     memcpy(result->d + pos, lenbuf, lensize);
505     pos += lensize;
506 
507     t = time(NULL); /* time of creation. */
508     result->d[pos++] = 0x62; /* binary */
509     result->d[pos++] = 0; /* no file name */
510     result->d[pos++] = t >> 24;
511     result->d[pos++] = t >> 16;
512     result->d[pos++] = t >>  8;
513     result->d[pos++] = t;
514 
515     memcpy(result->d + pos, newdat->d, newdat->len);
516     result->len = pos + newdat->len;
517     return result;
518 }
519 
520 void
dek_free(DEK * d)521 dek_free(DEK *d)
522 {
523     if (!d)
524 	return;
525     mcrypt_generic_deinit(d->hd);
526     mcrypt_module_close(d->hd);
527     free(d);
528 }
529 
530 
531 static int
pgp_get_keysize(const char * algo)532 pgp_get_keysize(const char *algo)
533 {
534     int keylen = keysize;
535 
536     /* OpenPGP uses fixed key sizes which means we need to
537        change the size for variable ciphers. */
538     if (!strcmp(algo, "twofish" ))
539         keylen = 32;
540     if (!strcmp(algo, "blowfish"))
541         keylen = 16;
542     if (!strcmp(algo, "cast-128"))
543         keylen = 16;
544     keysize = keylen; /* set the global key size to this */
545     return keylen;
546 }
547 
548 
549 void
dek_load(DEK * d,char * pass)550 dek_load(DEK *d, char *pass)
551 {
552     KEYGEN keygen_data;
553     char* mode = DEFAULT_PGP_MODE;
554     int ret;
555 
556     d->keylen = pgp_get_keysize(d->algo);
557     keygen_data.hash_algorithm[0] = d->s2k.algo;
558     keygen_data.count = d->s2k.count;
559     keygen_data.salt = d->s2k.salt;
560     keygen_data.salt_size = 8;
561 
562     d->blocklen = mcrypt_module_get_algo_block_size(d->algo, NULL);
563     ret = mhash_keygen_ext(d->s2k.mode, keygen_data, d->key,
564 			   DIM (d->key), pass, strlen(pass));
565     if (ret < 0)
566     	err_quit(_("mhash_keygen_ext() failed.\n"));
567     d->hd = mcrypt_module_open(d->algo, NULL, mode, NULL);
568     if (d->hd == MCRYPT_FAILED)
569     	err_quit(_("Could not open module\n"));
570 }
571 
572 
573 DEK*
dek_create(char * algo,char * pass)574 dek_create(char* algo, char *pass)
575 {
576     DEK *d;
577     KEYGEN keygen_data;
578     char* mode = DEFAULT_PGP_MODE;
579     keygenid mh_keymode;
580     hashid mh_alg;
581     int ret;
582 
583     d = _mcrypt_calloc(1, sizeof *d);
584     d->algo = algo;
585     d->keylen = pgp_get_keysize(algo);
586     d->blocklen = mcrypt_module_get_algo_block_size(algo, NULL);
587 
588     algorithm = d->algo;
589     keysize = d->keylen;
590 
591     /* There are two ways for symmetric encryption.
592        1. To derrive the session key directly from the passphrase
593        2. Use a random session key and it encrypt it with a derrived
594          key from the passphrase.
595        For the sake of simplicity, we always use method 1. */
596     if (_mcrypt_pgp_conv_keymode(keymode, &mh_keymode, &mh_alg) < 0) {
597         char tmp[255];
598 
599         snprintf(tmp, DIM (tmp)-1, _("OpenPGP: Unsupported key mode %s\n"),
600                   keymode);
601     	err_quit(tmp);
602     }
603 
604     d->s2k.mode = mh_keymode;
605     d->s2k.algo = mh_alg;
606     d->s2k.count = S2K_DEFAULT_COUNT;
607 
608     keygen_data.hash_algorithm[0] = mh_alg;
609     keygen_data.count = S2K_DEFAULT_COUNT;
610     keygen_data.salt = d->s2k.salt;
611     keygen_data.salt_size = 8;
612 
613     mcrypt_randomize(d->s2k.salt, 8, 0);
614     ret = mhash_keygen_ext(mh_keymode, keygen_data, d->key,
615 			   DIM (d->key), pass, strlen(pass));
616     if (ret < 0)
617     	err_quit(_("mhash_keygen_ext() failed.\n"));
618     d->hd = mcrypt_module_open(algo, NULL, mode, NULL);
619     if (d->hd == MCRYPT_FAILED)
620     	err_quit(_("Could not open module\n"));
621     return d;
622 }
623 
624 
625 int
symkey_enc_decode(const USTRING dat,DEK ** ret_dek)626 symkey_enc_decode(const USTRING dat, DEK **ret_dek)
627 {
628     DEK *d;
629     int tag = 0, headlen = 0, offset = 0;
630 
631     assert(dat->len > 0);
632 
633     header_decode(dat->d, &tag, &headlen, &offset, NULL);
634     if (tag != PKT_SYMKEY_ENC)
635         return PGP_ERR_PKT;
636     if (headlen < 3)
637         return PGP_ERR_PKT;
638     if (dat->d[offset++] != 4)
639         return PGP_ERR_PKT; /* invalid version */
640 
641     d = _mcrypt_calloc(1,  sizeof *d);
642     d->algo = _mcrypt_algid_to_algo(dat->d[offset++]);
643     d->s2k.mode = _mhash_keygen(dat->d[offset++]);
644     d->s2k.algo = _mhash_algo(dat->d[offset++]);
645     if (d->s2k.mode != KEYGEN_S2K_SIMPLE) {
646         memcpy(d->s2k.salt, dat->d + offset, 8);
647         offset += 8;
648     }
649     if (d->s2k.mode == KEYGEN_S2K_ISALTED)
650         d->s2k.count = dat->d[offset++];
651     *ret_dek = d;
652 
653     /* in order to print the proper algorithm later. */
654     algorithm = d->algo;
655     keymode = _mhash_keymode2str(d->s2k.mode, d->s2k.algo);
656     mode = DEFAULT_PGP_MODE;  /* no other options */
657 
658     return 0;
659 }
660 
661 
662 USTRING
symkey_enc_encode(const DEK * dek)663 symkey_enc_encode(const DEK *dek)
664 {
665     USTRING result;
666     int pos = 0;
667     uchar buf[16];
668 
669     assert(dek->keylen > 0);
670 
671     buf[pos++] = (0x80 | 0x40 | PKT_SYMKEY_ENC);
672     buf[pos++] = 4; /* length */
673     buf[pos++] = 4; /* version */
674     buf[pos++] = _mcrypt_algo_to_algid(dek->algo);
675     buf[pos++] = _mhash_keygen_to_rfc2440(dek->s2k.mode);
676     buf[pos++] = _mhash_algo_to_rfc2440(dek->s2k.algo);
677     if (dek->s2k.mode != KEYGEN_S2K_SIMPLE) {
678         memcpy(buf+pos, dek->s2k.salt, 8);
679         pos += 8;
680         buf[1] += 8;
681     }
682     if (dek->s2k.mode == KEYGEN_S2K_ISALTED) {
683         buf[pos++] = dek->s2k.count;
684         buf[1] += 1;
685     }
686     result = make_ustring(buf, pos);
687     result->len = pos;
688     return result;
689 }
690 
691 
692 USTRING
read_partial(const uchar * buf,size_t blen,size_t pktlen)693 read_partial(const uchar *buf, size_t blen, size_t pktlen)
694 {
695     USTRING dat;
696     uchar data[2048];
697     int pos = 0, partial = 1;
698     PACKET pkt;
699 
700     memset( &pkt, 0, sizeof(pkt));
701 
702     dat = make_ustring(NULL, blen);
703     while (pktlen > 0) {
704         /*fprintf( stderr, "ptklen=%d pos=%d blen=%d partial=%d llen=%d\n",
705                  pktlen, pos, blen, partial, length_len( pktlen, &pkt) );*/
706         while (pktlen > 2048 && pos < blen) {
707             memcpy(data, buf, 2048);
708             memcpy(dat->d + pos, data, 2048);
709             pos += 2048;
710             buf += 2048; pktlen -= 2048;
711         }
712         if (pktlen > 0 && pos < blen) {
713             memcpy(data, buf, pktlen);
714             memcpy(dat->d + pos, data, pktlen);
715             pos += pktlen;
716             buf += pktlen; pktlen -= pktlen;
717         }
718         if (!partial)
719             break;
720         else {
721             memset(&pkt, 0, sizeof (pkt));
722             pktlen = length_decode(buf, 0, &pkt);
723             buf += length_len(pktlen, &pkt);
724             partial = pkt.blockmode;
725         }
726     }
727     dat->len = pos;
728     return dat;
729 }
730 
731 int
encrypted_decode(const DEK * dek,const USTRING dat,USTRING * result)732 encrypted_decode(const DEK *dek, const USTRING dat, USTRING *result)
733 {
734     int rc, nprefix;
735     uint32 tag = 0, headlen = 0, offset = 0;
736     uchar rndprefix[18], encprefix[18];
737     PACKET pkt;
738     USTRING t = NULL, p = NULL;
739 
740     memset(&pkt, 0, sizeof(pkt));
741 
742     assert(dat->len > 0);
743     header_decode(dat->d, &tag, &headlen, &offset, &pkt);
744 
745     if (tag != PKT_ENCRYPTED)
746         return PGP_ERR_PKT;
747     if (dat->len < dek->blocklen + 3)
748         return PGP_ERR_PKT; /* wrong len */
749     if (!pkt.blockmode && (dat->len-1-length_len(headlen, &pkt)) != headlen)
750         return PGP_ERR_PKT; /* moderately malformed */
751 
752     rc = mcrypt_generic_init(dek->hd, (uchar *)&dek->key, dek->keylen, NULL);
753     if (rc < 0)
754     	err_quit(_("mcrypt_generic_init() failed\n"));
755 
756     nprefix = dek->blocklen;
757     memcpy(encprefix, dat->d + offset, nprefix + 2);
758     _mcrypt_decrypt(dek->hd, rndprefix, nprefix + 2,
759 		    dat->d + offset, nprefix + 2);
760     offset += (nprefix + 2);
761 
762     /* Note that we don't decrypt the whole thing at once;
763        if 7 != 9 or 8 != 10 then we immediately stop */
764     if (rndprefix[nprefix] != rndprefix[nprefix-2] ||
765 	rndprefix[nprefix+1] != rndprefix[nprefix-1]) {
766         err_warn(_("decryption: wrong key.\n"));
767         return PGP_ERR_GENERAL;
768     }
769     _mcrypt_sync(dek->hd, encprefix, dek->blocklen);
770 
771     if (!pkt.blockmode) {
772         t = make_ustring( dat->d+offset,  dat->len - offset); /* xxx */
773 
774         _mcrypt_decrypt(dek->hd, t->d, t->len, NULL, 0);
775     }
776     else {
777         p = read_partial(dat->d + (offset - (nprefix+2)),
778 			 dat->len - (offset - (nprefix+2)), headlen);
779         if (!p || !p->len) {
780             *result = NULL;
781             return PGP_ERR_GENERAL;
782         }
783         t = make_ustring(p->d + (nprefix+2), p->len - (nprefix+2));
784         _mcrypt_decrypt(dek->hd, t->d, t->len, NULL, 0);
785         free(p); p=NULL;
786     }
787     *result = t;
788     return 0;
789 }
790 
791 
792 USTRING
encrypted_encode(const USTRING pt,const DEK * dek)793 encrypted_encode(const USTRING pt, const DEK *dek)
794 {
795     USTRING ct, result;
796     uchar rndpref[18], lenbuf[5], lensize;
797     int pos, rc;
798 
799     assert(pt->len > 0);
800 
801     rc = mcrypt_generic_init(dek->hd, (uchar *)&dek->key, dek->keylen, NULL);
802     if (rc < 0)
803     	err_quit( _("mcrypt_generic_init() failed\n") );
804 
805     mcrypt_randomize(rndpref, dek->blocklen, real_random_flag);
806     rndpref[dek->blocklen] = rndpref[dek->blocklen - 2];
807     rndpref[dek->blocklen + 1] = rndpref[dek->blocklen - 1];
808     _mcrypt_encrypt(dek->hd, rndpref, dek->blocklen + 2, NULL, 0);
809     _mcrypt_sync(dek->hd, rndpref, dek->blocklen);
810 
811     ct = make_ustring( rndpref,   2 * pt->len); /* xxx */
812     pos = dek->blocklen + 2;
813 
814     _mcrypt_encrypt(dek->hd, ct->d + pos, pt->len, pt->d, pt->len);
815     ct->len = (pos += pt->len);
816     pos = 0;
817 
818     result = make_ustring( NULL,  ct->len + 8); /* xxx */
819     result->d[pos++] = (0x80 | 0x40 | PKT_ENCRYPTED);
820     length_encode(ct->len, lenbuf, &lensize);
821     memcpy(result->d + pos, lenbuf, lensize);
822     pos += lensize;
823 
824     memcpy(result->d + pos, ct->d, ct->len);
825     result->len = ct->len + pos;
826     free(ct);
827 
828     return result;
829 }
830 
831 
832 static int
do_compress(int algo,int flush,uchar * inbuf,size_t insize,USTRING * ret_out)833 do_compress(int algo, int flush, uchar *inbuf, size_t insize,
834 	    USTRING *ret_out)
835 {
836 #ifdef HAVE_LIBZ
837     uchar buf[4096];
838     int pos = 0, len = 0;
839     int zrc = 0;
840     z_stream *zs = NULL;
841     USTRING out = NULL;
842 
843     zs = _mcrypt_calloc( 1,  sizeof *zs );
844     zrc = (algo == 1)? deflateInit2(zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
845 				    -13, openpgp_z, Z_DEFAULT_STRATEGY):
846     deflateInit(zs, Z_DEFAULT_COMPRESSION);
847     if (zrc)
848         goto leave;
849 
850     zs->next_in = inbuf;
851     zs->avail_in = insize;
852 
853     do {
854         zs->next_out = buf;
855         zs->avail_out = sizeof(buf);
856         zrc = deflate( zs, flush );
857         if ( zrc == Z_STREAM_END ) {
858             deflateEnd( zs );
859             if ( zs->avail_out ) {
860                 len = sizeof(buf) - zs->avail_out;
861                 out = realloc_ustring( out, len );
862                 memcpy( out->d + pos, buf, len );
863                 pos += len;
864                 break;
865             }
866         }
867         if ( zrc == Z_OK ) {
868             len = sizeof(buf) - zs->avail_out;
869             out = realloc_ustring( out, len );
870             memcpy( out->d + pos, buf, len );
871             pos += len;
872         }
873 
874         if ( zrc ) {
875             if ( zs->msg )
876                 fprintf( stderr, _("zlib error `%s'.\n"), zs->msg );
877             fprintf( stderr, _("compress: deflate returned %d.\n"), zrc );
878         }
879     } while ( zs->avail_out == 0 );
880 
881 leave:
882     *ret_out = out;
883     free( zs );
884     if ( zrc == Z_OK || zrc == Z_STREAM_END )
885         zrc = 0;
886     return zrc;
887 #else
888     return 0;
889 #endif
890 } /* do_compress */
891 
892 USTRING
compressed_encode(const USTRING dat,int algo)893 compressed_encode( const USTRING dat, int algo )
894 {
895 #ifdef HAVE_LIBZ
896     USTRING result = NULL, z = NULL;
897     int rc = 0;
898 
899     assert( dat->len );
900     rc = do_compress( algo, Z_NO_FLUSH, dat->d, dat->len, &z );
901     if ( !rc )
902         rc = do_compress( algo, Z_FINISH, dat->d, dat->len, &z );
903     if ( rc )
904         goto leave;
905 
906     result = make_ustring( NULL,  z->len + 8); /* xxx */
907     result->len = z->len + 3;
908     result->d[0] = (0x80 | 0x40 | PKT_COMPRESSED);
909     result->d[1] = 0;
910     result->d[2] = algo;
911     memcpy( result->d + 3, z->d, z->len );
912 
913 leave:
914     free( z );
915     return result;
916 #else
917     return NULL;
918 #endif
919 } /* compressed_encode */
920 
921 static int
do_uncompress(int algo,uchar * inbuf,size_t insize,USTRING * ret_out)922 do_uncompress( int algo, uchar *inbuf, size_t insize, USTRING *ret_out )
923 {
924 #ifdef HAVE_LIBZ
925     USTRING out = NULL;
926     z_stream *zs = NULL;
927     uchar buf[4096];
928     int pos = 0, len = 0;
929     int zrc = 0;
930 
931     zs = _mcrypt_calloc( 1,  sizeof *zs );
932     zrc = ( algo == 1 )? inflateInit2( zs, -13 ) : inflateInit( zs );
933     if ( zrc )
934         goto leave;
935 
936     zs->next_in = inbuf;
937     zs->avail_in = insize;
938 
939     do {
940         zs->next_out = buf;
941         zs->avail_out = sizeof(buf);
942 
943         zrc = inflate( zs, Z_SYNC_FLUSH );
944         if ( zrc == Z_STREAM_END ) {
945             inflateEnd( zs );
946             if ( zs->avail_out ) {
947                 len = sizeof(buf) - zs->avail_out;
948                 out = realloc_ustring( out, len );
949                 memcpy( out->d + pos, buf, len );
950                 out->len = (pos += len);
951                 /*fprintf( stderr, "DBG: end len=%d pos=%d\n", len, pos );*/
952             }
953             break;
954         }
955         if ( zrc == Z_OK ) {
956             len = sizeof(buf) - zs->avail_out;
957             out = realloc_ustring( out, len );
958             memcpy( out->d + pos, buf, len );
959             out->len = (pos += len);
960             /*fprintf( stderr, "DBG: ok len=%d pos=%d\n", len, pos );*/
961         }
962         if ( zrc ) {
963             if ( zs->msg )
964                 fprintf( stderr, _("zlib error `%s'.\n"), zs->msg );
965             fprintf( stderr, _("uncompress: inflate returned %d.\n"), zrc );
966             break;
967         }
968     } while ( 1 );
969 
970 leave:
971     *ret_out = out;
972     free( zs );
973     if ( zrc == Z_OK || zrc == Z_STREAM_END )
974         zrc = 0;
975     return zrc;
976 #else
977     return 0;
978 #endif
979 } /* do_uncompress */
980 
981 int
compressed_decode(const USTRING zip,USTRING * result)982 compressed_decode( const USTRING zip, USTRING *result )
983 {
984 #ifdef HAVE_LIBZ
985     uint32 tag = 0, headlen = 0, offset = 0;
986     USTRING t = NULL;
987     int rc = 0;
988 
989     assert( zip->len );
990     header_decode( zip->d, &tag, &headlen, &offset, NULL );
991 
992     if ( tag != PKT_COMPRESSED )
993         return PGP_ERR_PKT;
994     if ( zip->d[offset] != 1 && zip->d[offset] != 2 )
995         return PGP_ERR_PKT;
996 
997     err_info( _("Will decompress input file.\n") );
998     rc = do_uncompress( zip->d[offset], zip->d + offset + 1,
999                         zip->len - offset - 1, &t );
1000     *result = t;
1001 
1002     return rc;
1003 #else
1004     return 0;
1005 #endif
1006 } /* compressed_decode */
1007 
1008 
1009 int
pgp_encrypt_file(const char * infile,const char * outfile,char * pass)1010 pgp_encrypt_file(const char *infile, const char *outfile, char *pass)
1011 {
1012     USTRING t = NULL, pt = NULL, sym = NULL, enc = NULL, zip = NULL;
1013     DEK *dek = NULL;
1014     FILE *fp = NULL;
1015     uchar *buf = NULL, tmp[16*1024];
1016     size_t len = 0, nread = 0;
1017     int tag=0;
1018 
1019     if (!infile || *infile == '-') {
1020         while (!feof(stdin)) {
1021             nread = fread(tmp, 1, DIM (tmp), stdin);
1022 	    if (nread > 0) {
1023                 t = realloc_ustring (t, nread);
1024                 memcpy (t->d + len, tmp, nread);
1025             }
1026             len += nread;
1027         }
1028         fp = stdout;
1029     }
1030     else {
1031         fp = fopen(outfile, "wb");
1032         if (fp == NULL)
1033             return PGP_ERR_FILE;
1034         buf = file_to_buf(infile, 0, &len);
1035         if (!buf) {
1036 	    fclose (fp);
1037             return PGP_ERR_FILE;
1038 	}
1039         t = make_ustring(buf, len);
1040     }
1041     tag = get_pkt_tag(t->d, NULL);
1042     free(buf);
1043     dek = dek_create(pgp_get_algo(algorithm), pass);
1044     sym = symkey_enc_encode(dek);
1045     fwrite(sym->d, 1, sym->len, fp);
1046     free(sym);
1047     total_bytes += t->len; /* increase input bytes */
1048 
1049     pt = plaintext_encode(t);
1050     free(t);
1051 #ifdef HAVE_LIBZ
1052     if (openpgp_z > 0 && tag == -1 && pt && len > 32) {
1053         err_info( _("Output file will be compressed.\n") );
1054         zip = compressed_encode(pt, 1);
1055         free(pt);
1056     }
1057     else zip = pt;
1058 #else
1059     zip = pt;
1060 #endif
1061     if (zip) {
1062         enc = encrypted_encode(zip, dek);
1063         free(zip);
1064     }
1065     if (enc) {
1066         fwrite(enc->d, 1, enc->len, fp);
1067         free(enc);
1068     }
1069     dek_free(dek);
1070     if (fp != stdout)
1071 	fclose(fp);
1072     else
1073 	fflush (fp);
1074     return 0;
1075 }
1076 
1077 int
pgp_decrypt_file(const char * infile,const char * outfile,char * pass)1078 pgp_decrypt_file(const char *infile, const char *outfile, char *pass)
1079 {
1080     USTRING r = NULL, dat = NULL, pt = NULL, result = NULL;
1081     uchar *buf = NULL, tmp[16*1024];
1082     const uchar *p;
1083     DEK *dek = NULL;
1084     PACKET pkt;
1085     uint32 off = 0, tag = 0, len = 0;
1086     size_t flen = 0, nread;
1087     int rc = 0;
1088     FILE *fp;
1089 
1090     memset(&pkt, 0, sizeof(pkt));
1091 
1092     if (!infile || *infile == '-') {
1093         while (!feof(stdin)) {
1094             nread = fread(tmp, 1, DIM (tmp), stdin);
1095             if (nread) {
1096                 buf = realloc(buf, flen + nread);
1097                 memcpy(buf + flen, tmp, nread);
1098             }
1099             flen += nread;
1100         }
1101     }
1102     else {
1103         buf = file_to_buf(infile, 0, &flen);
1104         if (!buf)
1105 	    return PGP_ERR_FILE;
1106     }
1107     total_bytes = flen;
1108     p = buf;
1109     while (flen > 0) {
1110         memset(&pkt, 0, sizeof (pkt));
1111         header_decode(p, &tag, &len, &off, &pkt);
1112         switch (tag) {
1113         case PKT_SYMKEY_ENC:
1114             r = make_ustring(p, len + off);
1115             rc = symkey_enc_decode(r, &dek);
1116 	    free (r);
1117             /*fprintf(stderr, "symkey_enc_decode=%d\n", rc);*/
1118 	    if (rc) {
1119 		free (buf);
1120 		return rc;
1121 	    }
1122 	    dek_load(dek, pass);
1123             break;
1124 
1125         case PKT_ENCRYPTED:
1126             r = make_ustring(p, flen);
1127             rc = encrypted_decode(dek, r, &dat);
1128             /*fprintf(stderr, "encrypted=%d\n", rc);*/
1129             free(r);
1130 	    if (rc) {
1131 		free (buf);
1132 		return rc;
1133 	    }
1134             flen = 0; /* automatic EOF */
1135             break;
1136 
1137         default:
1138             /*fprintf(stderr, "tag=%d\n", tag);*/
1139 	    free (buf);
1140             return PGP_ERR_PKT;
1141         }
1142         if (flen > 0) {
1143             p += (len + off);
1144             flen -= (len + off);
1145         }
1146     }
1147     free(buf);
1148     dek_free(dek);
1149     if (!dat)
1150 	return PGP_ERR_FILE;
1151 
1152     if (get_pkt_tag(dat->d, NULL) == PKT_COMPRESSED) {
1153 	rc = compressed_decode(dat, &pt);
1154 	/*fprintf(stderr,"compressed=%d\n",rc);*/
1155 	free(dat);
1156 	if (rc)
1157 	    return rc;
1158     }
1159     else
1160 	pt = dat;
1161 
1162     if (get_pkt_tag(pt->d, NULL) != PKT_PLAINTEXT) {
1163 	err_warn(_("Unsupported OpenPGP packet!\n"));
1164 	free (pt);
1165     }
1166     rc = plaintext_decode(pt, &result);
1167     free (pt);
1168     /*fprintf(stderr,"plaintext=%d\n", rc);*/
1169     if (rc)
1170 	return rc;
1171 
1172     if (!outfile)
1173 	fp = stdout;
1174     else {
1175 	fp = fopen(outfile, "wb");
1176 	if (fp == NULL) {
1177 	    free(result);
1178 	    return PGP_ERR_FILE;
1179 	}
1180     }
1181     fwrite(result->d, 1, result->len, fp);
1182     free(result);
1183     if (outfile)
1184 	fclose(fp);
1185     else
1186 	fflush (fp);
1187     return 0;
1188 }
1189 
1190