155714Skris/* crypto/des/des.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <stdlib.h>
6159191Skris#include <string.h>
6255714Skris#include <openssl/opensslconf.h>
63109998Smarkm#ifndef OPENSSL_SYS_MSDOS
64280304Sjkim# ifndef OPENSSL_SYS_VMS
65280304Sjkim#  include OPENSSL_UNISTD
66280304Sjkim# else                          /* OPENSSL_SYS_VMS */
67280304Sjkim#  ifdef __DECC
68280304Sjkim#   include <unistd.h>
69280304Sjkim#  else                         /* not __DECC */
70280304Sjkim#   include <math.h>
71280304Sjkim#  endif                        /* __DECC */
72280304Sjkim# endif                         /* OPENSSL_SYS_VMS */
73280304Sjkim#else                           /* OPENSSL_SYS_MSDOS */
74280304Sjkim# include <io.h>
7555714Skris#endif
7655714Skris
7755714Skris#include <time.h>
7855714Skris#include "des_ver.h"
7955714Skris
80109998Smarkm#ifdef OPENSSL_SYS_VMS
81280304Sjkim# include <types.h>
82280304Sjkim# include <stat.h>
8355714Skris#else
84280304Sjkim# ifndef _IRIX
85280304Sjkim#  include <sys/types.h>
86280304Sjkim# endif
87280304Sjkim# include <sys/stat.h>
8855714Skris#endif
8955714Skris#include <openssl/des.h>
9055714Skris#include <openssl/rand.h>
91109998Smarkm#include <openssl/ui_compat.h>
9255714Skris
9355714Skrisvoid usage(void);
9455714Skrisvoid doencryption(void);
9555714Skrisint uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
9655714Skrisvoid uufwriteEnd(FILE *fp);
97280304Sjkimint uufread(unsigned char *out, int size, unsigned int num, FILE *fp);
98280304Sjkimint uuencode(unsigned char *in, int num, unsigned char *out);
99280304Sjkimint uudecode(unsigned char *in, int num, unsigned char *out);
100280304Sjkimvoid DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length,
101280304Sjkim                      DES_key_schedule sk1, DES_key_schedule sk2,
102280304Sjkim                      DES_cblock *ivec1, DES_cblock *ivec2, int enc);
103109998Smarkm#ifdef OPENSSL_SYS_VMS
104280304Sjkim# define EXIT(a) exit(a&0x10000000L)
10555714Skris#else
106280304Sjkim# define EXIT(a) exit(a)
10755714Skris#endif
10855714Skris
10955714Skris#define BUFSIZE (8*1024)
11055714Skris#define VERIFY  1
111280304Sjkim#define KEYSIZ  8
112280304Sjkim#define KEYSIZB 1024            /* should hit tty line limit first :-) */
113280304Sjkimchar key[KEYSIZB + 1];
114280304Sjkimint do_encrypt, longk = 0;
115280304SjkimFILE *DES_IN, *DES_OUT, *CKSUM_OUT;
11655714Skrischar uuname[200];
11755714Skrisunsigned char uubuf[50];
118280304Sjkimint uubufnum = 0;
119280304Sjkim#define INUUBUFN        (45*100)
120280304Sjkim#define OUTUUBUF        (65*100)
12155714Skrisunsigned char b[OUTUUBUF];
12255714Skrisunsigned char bb[300];
123280304SjkimDES_cblock cksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
12455714Skris
125280304Sjkimchar cksumname[200] = "";
12655714Skris
127280304Sjkimint vflag, cflag, eflag, dflag, kflag, bflag, fflag, sflag, uflag, flag3,
128280304Sjkim    hflag, error;
129280304Sjkim
13055714Skrisint main(int argc, char **argv)
131280304Sjkim{
132280304Sjkim    int i;
133280304Sjkim    struct stat ins, outs;
134280304Sjkim    char *p;
135280304Sjkim    char *in = NULL, *out = NULL;
13655714Skris
137280304Sjkim    vflag = cflag = eflag = dflag = kflag = hflag = bflag = fflag = sflag =
138280304Sjkim        uflag = flag3 = 0;
139280304Sjkim    error = 0;
140280304Sjkim    memset(key, 0, sizeof(key));
14155714Skris
142280304Sjkim    for (i = 1; i < argc; i++) {
143280304Sjkim        p = argv[i];
144280304Sjkim        if ((p[0] == '-') && (p[1] != '\0')) {
145280304Sjkim            p++;
146280304Sjkim            while (*p) {
147280304Sjkim                switch (*(p++)) {
148280304Sjkim                case '3':
149280304Sjkim                    flag3 = 1;
150280304Sjkim                    longk = 1;
151280304Sjkim                    break;
152280304Sjkim                case 'c':
153280304Sjkim                    cflag = 1;
154280304Sjkim                    strncpy(cksumname, p, 200);
155280304Sjkim                    cksumname[sizeof(cksumname) - 1] = '\0';
156280304Sjkim                    p += strlen(cksumname);
157280304Sjkim                    break;
158280304Sjkim                case 'C':
159280304Sjkim                    cflag = 1;
160280304Sjkim                    longk = 1;
161280304Sjkim                    strncpy(cksumname, p, 200);
162280304Sjkim                    cksumname[sizeof(cksumname) - 1] = '\0';
163280304Sjkim                    p += strlen(cksumname);
164280304Sjkim                    break;
165280304Sjkim                case 'e':
166280304Sjkim                    eflag = 1;
167280304Sjkim                    break;
168280304Sjkim                case 'v':
169280304Sjkim                    vflag = 1;
170280304Sjkim                    break;
171280304Sjkim                case 'E':
172280304Sjkim                    eflag = 1;
173280304Sjkim                    longk = 1;
174280304Sjkim                    break;
175280304Sjkim                case 'd':
176280304Sjkim                    dflag = 1;
177280304Sjkim                    break;
178280304Sjkim                case 'D':
179280304Sjkim                    dflag = 1;
180280304Sjkim                    longk = 1;
181280304Sjkim                    break;
182280304Sjkim                case 'b':
183280304Sjkim                    bflag = 1;
184280304Sjkim                    break;
185280304Sjkim                case 'f':
186280304Sjkim                    fflag = 1;
187280304Sjkim                    break;
188280304Sjkim                case 's':
189280304Sjkim                    sflag = 1;
190280304Sjkim                    break;
191280304Sjkim                case 'u':
192280304Sjkim                    uflag = 1;
193280304Sjkim                    strncpy(uuname, p, 200);
194280304Sjkim                    uuname[sizeof(uuname) - 1] = '\0';
195280304Sjkim                    p += strlen(uuname);
196280304Sjkim                    break;
197280304Sjkim                case 'h':
198280304Sjkim                    hflag = 1;
199280304Sjkim                    break;
200280304Sjkim                case 'k':
201280304Sjkim                    kflag = 1;
202280304Sjkim                    if ((i + 1) == argc) {
203280304Sjkim                        fputs("must have a key with the -k option\n", stderr);
204280304Sjkim                        error = 1;
205280304Sjkim                    } else {
206280304Sjkim                        int j;
20755714Skris
208280304Sjkim                        i++;
209280304Sjkim                        strncpy(key, argv[i], KEYSIZB);
210280304Sjkim                        for (j = strlen(argv[i]) - 1; j >= 0; j--)
211280304Sjkim                            argv[i][j] = '\0';
212280304Sjkim                    }
213280304Sjkim                    break;
214280304Sjkim                default:
215280304Sjkim                    fprintf(stderr, "'%c' unknown flag\n", p[-1]);
216280304Sjkim                    error = 1;
217280304Sjkim                    break;
218280304Sjkim                }
219280304Sjkim            }
220280304Sjkim        } else {
221280304Sjkim            if (in == NULL)
222280304Sjkim                in = argv[i];
223280304Sjkim            else if (out == NULL)
224280304Sjkim                out = argv[i];
225280304Sjkim            else
226280304Sjkim                error = 1;
227280304Sjkim        }
228280304Sjkim    }
229280304Sjkim    if (error)
230280304Sjkim        usage();
231280304Sjkim    /*-
232280304Sjkim     * We either
233280304Sjkim     * do checksum or
234280304Sjkim     * do encrypt or
235280304Sjkim     * do decrypt or
236280304Sjkim     * do decrypt then ckecksum or
237280304Sjkim     * do checksum then encrypt
238280304Sjkim     */
239280304Sjkim    if (((eflag + dflag) == 1) || cflag) {
240280304Sjkim        if (eflag)
241280304Sjkim            do_encrypt = DES_ENCRYPT;
242280304Sjkim        if (dflag)
243280304Sjkim            do_encrypt = DES_DECRYPT;
244280304Sjkim    } else {
245280304Sjkim        if (vflag) {
246280304Sjkim#ifndef _Windows
247280304Sjkim            fprintf(stderr, "des(1) built with %s\n", libdes_version);
248280304Sjkim#endif
249280304Sjkim            EXIT(1);
250280304Sjkim        } else
251280304Sjkim            usage();
252280304Sjkim    }
25355714Skris
254280304Sjkim#ifndef _Windows
255280304Sjkim    if (vflag)
256280304Sjkim        fprintf(stderr, "des(1) built with %s\n", libdes_version);
257280304Sjkim#endif
258280304Sjkim    if ((in != NULL) && (out != NULL) &&
259109998Smarkm#ifndef OPENSSL_SYS_MSDOS
260280304Sjkim        (stat(in, &ins) != -1) &&
261280304Sjkim        (stat(out, &outs) != -1) &&
262280304Sjkim        (ins.st_dev == outs.st_dev) && (ins.st_ino == outs.st_ino))
263280304Sjkim#else                           /* OPENSSL_SYS_MSDOS */
264280304Sjkim        (strcmp(in, out) == 0))
26555714Skris#endif
266280304Sjkim    {
267280304Sjkim        fputs("input and output file are the same\n", stderr);
268280304Sjkim        EXIT(3);
269280304Sjkim    }
27055714Skris
271280304Sjkim    if (!kflag)
272280304Sjkim        if (des_read_pw_string
273280304Sjkim            (key, KEYSIZB + 1, "Enter key:", eflag ? VERIFY : 0)) {
274280304Sjkim            fputs("password error\n", stderr);
275280304Sjkim            EXIT(2);
276280304Sjkim        }
27755714Skris
278280304Sjkim    if (in == NULL)
279280304Sjkim        DES_IN = stdin;
280280304Sjkim    else if ((DES_IN = fopen(in, "r")) == NULL) {
281280304Sjkim        perror("opening input file");
282280304Sjkim        EXIT(4);
283280304Sjkim    }
28455714Skris
285280304Sjkim    CKSUM_OUT = stdout;
286280304Sjkim    if (out == NULL) {
287280304Sjkim        DES_OUT = stdout;
288280304Sjkim        CKSUM_OUT = stderr;
289280304Sjkim    } else if ((DES_OUT = fopen(out, "w")) == NULL) {
290280304Sjkim        perror("opening output file");
291280304Sjkim        EXIT(5);
292280304Sjkim    }
293109998Smarkm#ifdef OPENSSL_SYS_MSDOS
294280304Sjkim    /* This should set the file to binary mode. */
295280304Sjkim    {
296280304Sjkim# include <fcntl.h>
297280304Sjkim        if (!(uflag && dflag))
298280304Sjkim            setmode(fileno(DES_IN), O_BINARY);
299280304Sjkim        if (!(uflag && eflag))
300280304Sjkim            setmode(fileno(DES_OUT), O_BINARY);
301280304Sjkim    }
30255714Skris#endif
30355714Skris
304280304Sjkim    doencryption();
305280304Sjkim    fclose(DES_IN);
306280304Sjkim    fclose(DES_OUT);
307280304Sjkim    EXIT(0);
308280304Sjkim}
30955714Skris
31055714Skrisvoid usage(void)
311280304Sjkim{
312280304Sjkim    char **u;
313280304Sjkim    static const char *Usage[] = {
314280304Sjkim        "des <options> [input-file [output-file]]",
315280304Sjkim        "options:",
316280304Sjkim        "-v         : des(1) version number",
317280304Sjkim        "-e         : encrypt using SunOS compatible user key to DES key conversion.",
318280304Sjkim        "-E         : encrypt ",
319280304Sjkim        "-d         : decrypt using SunOS compatible user key to DES key conversion.",
320280304Sjkim        "-D         : decrypt ",
321280304Sjkim        "-c[ckname] : generate a cbc_cksum using SunOS compatible user key to",
322280304Sjkim        "             DES key conversion and output to ckname (stdout default,",
323280304Sjkim        "             stderr if data being output on stdout).  The checksum is",
324280304Sjkim        "             generated before encryption and after decryption if used",
325280304Sjkim        "             in conjunction with -[eEdD].",
326280304Sjkim        "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].",
327280304Sjkim        "-k key     : use key 'key'",
328280304Sjkim        "-h         : the key that is entered will be a hexadecimal number",
329280304Sjkim        "             that is used directly as the des key",
330280304Sjkim        "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]",
331280304Sjkim        "             (uuname is the filename to put in the uuencode header).",
332280304Sjkim        "-b         : encrypt using DES in ecb encryption mode, the default is cbc mode.",
333280304Sjkim        "-3         : encrypt using triple DES encryption.  This uses 2 keys",
334280304Sjkim        "             generated from the input key.  If the input key is less",
335280304Sjkim        "             than 8 characters long, this is equivalent to normal",
336280304Sjkim        "             encryption.  Default is triple cbc, -b makes it triple ecb.",
337280304Sjkim        NULL
338280304Sjkim    };
339280304Sjkim    for (u = (char **)Usage; *u; u++) {
340280304Sjkim        fputs(*u, stderr);
341280304Sjkim        fputc('\n', stderr);
342280304Sjkim    }
34355714Skris
344280304Sjkim    EXIT(1);
345280304Sjkim}
34655714Skris
34755714Skrisvoid doencryption(void)
348280304Sjkim{
34955714Skris#ifdef _LIBC
350280304Sjkim    extern unsigned long time();
35155714Skris#endif
35255714Skris
353280304Sjkim    register int i;
354280304Sjkim    DES_key_schedule ks, ks2;
355280304Sjkim    DES_cblock iv, iv2;
356280304Sjkim    char *p;
357280304Sjkim    int num = 0, j, k, l, rem, ll, len, last, ex = 0;
358280304Sjkim    DES_cblock kk, k2;
359280304Sjkim    FILE *O;
360280304Sjkim    int Exit = 0;
361109998Smarkm#ifndef OPENSSL_SYS_MSDOS
362280304Sjkim    static unsigned char buf[BUFSIZE + 8], obuf[BUFSIZE + 8];
36355714Skris#else
364280304Sjkim    static unsigned char *buf = NULL, *obuf = NULL;
36555714Skris
366280304Sjkim    if (buf == NULL) {
367280304Sjkim        if (((buf = OPENSSL_malloc(BUFSIZE + 8)) == NULL) ||
368280304Sjkim            ((obuf = OPENSSL_malloc(BUFSIZE + 8)) == NULL)) {
369280304Sjkim            fputs("Not enough memory\n", stderr);
370280304Sjkim            Exit = 10;
371280304Sjkim            goto problems;
372280304Sjkim        }
373280304Sjkim    }
37455714Skris#endif
37555714Skris
376280304Sjkim    if (hflag) {
377280304Sjkim        j = (flag3 ? 16 : 8);
378280304Sjkim        p = key;
379280304Sjkim        for (i = 0; i < j; i++) {
380280304Sjkim            k = 0;
381280304Sjkim            if ((*p <= '9') && (*p >= '0'))
382280304Sjkim                k = (*p - '0') << 4;
383280304Sjkim            else if ((*p <= 'f') && (*p >= 'a'))
384280304Sjkim                k = (*p - 'a' + 10) << 4;
385280304Sjkim            else if ((*p <= 'F') && (*p >= 'A'))
386280304Sjkim                k = (*p - 'A' + 10) << 4;
387280304Sjkim            else {
388280304Sjkim                fputs("Bad hex key\n", stderr);
389280304Sjkim                Exit = 9;
390280304Sjkim                goto problems;
391280304Sjkim            }
392280304Sjkim            p++;
393280304Sjkim            if ((*p <= '9') && (*p >= '0'))
394280304Sjkim                k |= (*p - '0');
395280304Sjkim            else if ((*p <= 'f') && (*p >= 'a'))
396280304Sjkim                k |= (*p - 'a' + 10);
397280304Sjkim            else if ((*p <= 'F') && (*p >= 'A'))
398280304Sjkim                k |= (*p - 'A' + 10);
399280304Sjkim            else {
400280304Sjkim                fputs("Bad hex key\n", stderr);
401280304Sjkim                Exit = 9;
402280304Sjkim                goto problems;
403280304Sjkim            }
404280304Sjkim            p++;
405280304Sjkim            if (i < 8)
406280304Sjkim                kk[i] = k;
407280304Sjkim            else
408280304Sjkim                k2[i - 8] = k;
409280304Sjkim        }
410280304Sjkim        DES_set_key_unchecked(&k2, &ks2);
411280304Sjkim        OPENSSL_cleanse(k2, sizeof(k2));
412280304Sjkim    } else if (longk || flag3) {
413280304Sjkim        if (flag3) {
414280304Sjkim            DES_string_to_2keys(key, &kk, &k2);
415280304Sjkim            DES_set_key_unchecked(&k2, &ks2);
416280304Sjkim            OPENSSL_cleanse(k2, sizeof(k2));
417280304Sjkim        } else
418280304Sjkim            DES_string_to_key(key, &kk);
419280304Sjkim    } else
420280304Sjkim        for (i = 0; i < KEYSIZ; i++) {
421280304Sjkim            l = 0;
422280304Sjkim            k = key[i];
423280304Sjkim            for (j = 0; j < 8; j++) {
424280304Sjkim                if (k & 1)
425280304Sjkim                    l++;
426280304Sjkim                k >>= 1;
427280304Sjkim            }
428280304Sjkim            if (l & 1)
429280304Sjkim                kk[i] = key[i] & 0x7f;
430280304Sjkim            else
431280304Sjkim                kk[i] = key[i] | 0x80;
432280304Sjkim        }
43355714Skris
434280304Sjkim    DES_set_key_unchecked(&kk, &ks);
435280304Sjkim    OPENSSL_cleanse(key, sizeof(key));
436280304Sjkim    OPENSSL_cleanse(kk, sizeof(kk));
437280304Sjkim    /* woops - A bug that does not showup under unix :-( */
438280304Sjkim    memset(iv, 0, sizeof(iv));
439280304Sjkim    memset(iv2, 0, sizeof(iv2));
44055714Skris
441280304Sjkim    l = 1;
442280304Sjkim    rem = 0;
443280304Sjkim    /* first read */
444280304Sjkim    if (eflag || (!dflag && cflag)) {
445280304Sjkim        for (;;) {
446280304Sjkim            num = l = fread(&(buf[rem]), 1, BUFSIZE, DES_IN);
447280304Sjkim            l += rem;
448280304Sjkim            num += rem;
449280304Sjkim            if (l < 0) {
450280304Sjkim                perror("read error");
451280304Sjkim                Exit = 6;
452280304Sjkim                goto problems;
453280304Sjkim            }
45455714Skris
455280304Sjkim            rem = l % 8;
456280304Sjkim            len = l - rem;
457280304Sjkim            if (feof(DES_IN)) {
458284285Sjkim                for (i = 7 - rem; i > 0; i--) {
459284285Sjkim                    if (RAND_pseudo_bytes(buf + l++, 1) < 0)
460284285Sjkim                        goto problems;
461284285Sjkim                }
462280304Sjkim                buf[l++] = rem;
463280304Sjkim                ex = 1;
464280304Sjkim                len += rem;
465280304Sjkim            } else
466280304Sjkim                l -= rem;
46755714Skris
468280304Sjkim            if (cflag) {
469280304Sjkim                DES_cbc_cksum(buf, &cksum, (long)len, &ks, &cksum);
470280304Sjkim                if (!eflag) {
471280304Sjkim                    if (feof(DES_IN))
472280304Sjkim                        break;
473280304Sjkim                    else
474280304Sjkim                        continue;
475280304Sjkim                }
476280304Sjkim            }
47755714Skris
478280304Sjkim            if (bflag && !flag3)
479280304Sjkim                for (i = 0; i < l; i += 8)
480280304Sjkim                    DES_ecb_encrypt((DES_cblock *)&(buf[i]),
481280304Sjkim                                    (DES_cblock *)&(obuf[i]),
482280304Sjkim                                    &ks, do_encrypt);
483280304Sjkim            else if (flag3 && bflag)
484280304Sjkim                for (i = 0; i < l; i += 8)
485280304Sjkim                    DES_ecb2_encrypt((DES_cblock *)&(buf[i]),
486280304Sjkim                                     (DES_cblock *)&(obuf[i]),
487280304Sjkim                                     &ks, &ks2, do_encrypt);
488280304Sjkim            else if (flag3 && !bflag) {
489280304Sjkim                char tmpbuf[8];
49055714Skris
491280304Sjkim                if (rem)
492280304Sjkim                    memcpy(tmpbuf, &(buf[l]), (unsigned int)rem);
493280304Sjkim                DES_3cbc_encrypt((DES_cblock *)buf, (DES_cblock *)obuf,
494280304Sjkim                                 (long)l, ks, ks2, &iv, &iv2, do_encrypt);
495280304Sjkim                if (rem)
496280304Sjkim                    memcpy(&(buf[l]), tmpbuf, (unsigned int)rem);
497280304Sjkim            } else {
498280304Sjkim                DES_cbc_encrypt(buf, obuf, (long)l, &ks, &iv, do_encrypt);
499280304Sjkim                if (l >= 8)
500280304Sjkim                    memcpy(iv, &(obuf[l - 8]), 8);
501280304Sjkim            }
502280304Sjkim            if (rem)
503280304Sjkim                memcpy(buf, &(buf[l]), (unsigned int)rem);
50455714Skris
505280304Sjkim            i = 0;
506280304Sjkim            while (i < l) {
507280304Sjkim                if (uflag)
508280304Sjkim                    j = uufwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
509280304Sjkim                else
510280304Sjkim                    j = fwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
511280304Sjkim                if (j == -1) {
512280304Sjkim                    perror("Write error");
513280304Sjkim                    Exit = 7;
514280304Sjkim                    goto problems;
515280304Sjkim                }
516280304Sjkim                i += j;
517280304Sjkim            }
518280304Sjkim            if (feof(DES_IN)) {
519280304Sjkim                if (uflag)
520280304Sjkim                    uufwriteEnd(DES_OUT);
521280304Sjkim                break;
522280304Sjkim            }
523280304Sjkim        }
524280304Sjkim    } else {                    /* decrypt */
52555714Skris
526280304Sjkim        ex = 1;
527280304Sjkim        for (;;) {
528280304Sjkim            if (ex) {
529280304Sjkim                if (uflag)
530280304Sjkim                    l = uufread(buf, 1, BUFSIZE, DES_IN);
531280304Sjkim                else
532280304Sjkim                    l = fread(buf, 1, BUFSIZE, DES_IN);
533280304Sjkim                ex = 0;
534280304Sjkim                rem = l % 8;
535280304Sjkim                l -= rem;
536280304Sjkim            }
537280304Sjkim            if (l < 0) {
538280304Sjkim                perror("read error");
539280304Sjkim                Exit = 6;
540280304Sjkim                goto problems;
541280304Sjkim            }
54255714Skris
543280304Sjkim            if (bflag && !flag3)
544280304Sjkim                for (i = 0; i < l; i += 8)
545280304Sjkim                    DES_ecb_encrypt((DES_cblock *)&(buf[i]),
546280304Sjkim                                    (DES_cblock *)&(obuf[i]),
547280304Sjkim                                    &ks, do_encrypt);
548280304Sjkim            else if (flag3 && bflag)
549280304Sjkim                for (i = 0; i < l; i += 8)
550280304Sjkim                    DES_ecb2_encrypt((DES_cblock *)&(buf[i]),
551280304Sjkim                                     (DES_cblock *)&(obuf[i]),
552280304Sjkim                                     &ks, &ks2, do_encrypt);
553280304Sjkim            else if (flag3 && !bflag) {
554280304Sjkim                DES_3cbc_encrypt((DES_cblock *)buf, (DES_cblock *)obuf,
555280304Sjkim                                 (long)l, ks, ks2, &iv, &iv2, do_encrypt);
556280304Sjkim            } else {
557280304Sjkim                DES_cbc_encrypt(buf, obuf, (long)l, &ks, &iv, do_encrypt);
558280304Sjkim                if (l >= 8)
559280304Sjkim                    memcpy(iv, &(buf[l - 8]), 8);
560280304Sjkim            }
56155714Skris
562280304Sjkim            if (uflag)
563280304Sjkim                ll = uufread(&(buf[rem]), 1, BUFSIZE, DES_IN);
564280304Sjkim            else
565280304Sjkim                ll = fread(&(buf[rem]), 1, BUFSIZE, DES_IN);
566280304Sjkim            ll += rem;
567280304Sjkim            rem = ll % 8;
568280304Sjkim            ll -= rem;
569280304Sjkim            if (feof(DES_IN) && (ll == 0)) {
570280304Sjkim                last = obuf[l - 1];
57155714Skris
572280304Sjkim                if ((last > 7) || (last < 0)) {
573280304Sjkim                    fputs("The file was not decrypted correctly.\n", stderr);
574280304Sjkim                    Exit = 8;
575280304Sjkim                    last = 0;
576280304Sjkim                }
577280304Sjkim                l = l - 8 + last;
578280304Sjkim            }
579280304Sjkim            i = 0;
580280304Sjkim            if (cflag)
581280304Sjkim                DES_cbc_cksum(obuf,
582280304Sjkim                              (DES_cblock *)cksum, (long)l / 8 * 8, &ks,
583280304Sjkim                              (DES_cblock *)cksum);
584280304Sjkim            while (i != l) {
585280304Sjkim                j = fwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
586280304Sjkim                if (j == -1) {
587280304Sjkim                    perror("Write error");
588280304Sjkim                    Exit = 7;
589280304Sjkim                    goto problems;
590280304Sjkim                }
591280304Sjkim                i += j;
592280304Sjkim            }
593280304Sjkim            l = ll;
594280304Sjkim            if ((l == 0) && feof(DES_IN))
595280304Sjkim                break;
596280304Sjkim        }
597280304Sjkim    }
598280304Sjkim    if (cflag) {
599280304Sjkim        l = 0;
600280304Sjkim        if (cksumname[0] != '\0') {
601280304Sjkim            if ((O = fopen(cksumname, "w")) != NULL) {
602280304Sjkim                CKSUM_OUT = O;
603280304Sjkim                l = 1;
604280304Sjkim            }
605280304Sjkim        }
606280304Sjkim        for (i = 0; i < 8; i++)
607280304Sjkim            fprintf(CKSUM_OUT, "%02X", cksum[i]);
608280304Sjkim        fprintf(CKSUM_OUT, "\n");
609280304Sjkim        if (l)
610280304Sjkim            fclose(CKSUM_OUT);
611280304Sjkim    }
612280304Sjkim problems:
613280304Sjkim    OPENSSL_cleanse(buf, sizeof(buf));
614280304Sjkim    OPENSSL_cleanse(obuf, sizeof(obuf));
615280304Sjkim    OPENSSL_cleanse(&ks, sizeof(ks));
616280304Sjkim    OPENSSL_cleanse(&ks2, sizeof(ks2));
617280304Sjkim    OPENSSL_cleanse(iv, sizeof(iv));
618280304Sjkim    OPENSSL_cleanse(iv2, sizeof(iv2));
619280304Sjkim    OPENSSL_cleanse(kk, sizeof(kk));
620280304Sjkim    OPENSSL_cleanse(k2, sizeof(k2));
621280304Sjkim    OPENSSL_cleanse(uubuf, sizeof(uubuf));
622280304Sjkim    OPENSSL_cleanse(b, sizeof(b));
623280304Sjkim    OPENSSL_cleanse(bb, sizeof(bb));
624280304Sjkim    OPENSSL_cleanse(cksum, sizeof(cksum));
625280304Sjkim    if (Exit)
626280304Sjkim        EXIT(Exit);
627280304Sjkim}
628280304Sjkim
62955714Skris/*    We ignore this parameter but it should be > ~50 I believe    */
63055714Skrisint uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp)
631280304Sjkim{
632280304Sjkim    int i, j, left, rem, ret = num;
633280304Sjkim    static int start = 1;
63455714Skris
635280304Sjkim    if (start) {
636280304Sjkim        fprintf(fp, "begin 600 %s\n",
637280304Sjkim                (uuname[0] == '\0') ? "text.d" : uuname);
638280304Sjkim        start = 0;
639280304Sjkim    }
64055714Skris
641280304Sjkim    if (uubufnum) {
642280304Sjkim        if (uubufnum + num < 45) {
643280304Sjkim            memcpy(&(uubuf[uubufnum]), data, (unsigned int)num);
644280304Sjkim            uubufnum += num;
645280304Sjkim            return (num);
646280304Sjkim        } else {
647280304Sjkim            i = 45 - uubufnum;
648280304Sjkim            memcpy(&(uubuf[uubufnum]), data, (unsigned int)i);
649280304Sjkim            j = uuencode((unsigned char *)uubuf, 45, b);
650280304Sjkim            fwrite(b, 1, (unsigned int)j, fp);
651280304Sjkim            uubufnum = 0;
652280304Sjkim            data += i;
653280304Sjkim            num -= i;
654280304Sjkim        }
655280304Sjkim    }
65655714Skris
657280304Sjkim    for (i = 0; i < (((int)num) - INUUBUFN); i += INUUBUFN) {
658280304Sjkim        j = uuencode(&(data[i]), INUUBUFN, b);
659280304Sjkim        fwrite(b, 1, (unsigned int)j, fp);
660280304Sjkim    }
661280304Sjkim    rem = (num - i) % 45;
662280304Sjkim    left = (num - i - rem);
663280304Sjkim    if (left) {
664280304Sjkim        j = uuencode(&(data[i]), left, b);
665280304Sjkim        fwrite(b, 1, (unsigned int)j, fp);
666280304Sjkim        i += left;
667280304Sjkim    }
668280304Sjkim    if (i != num) {
669280304Sjkim        memcpy(uubuf, &(data[i]), (unsigned int)rem);
670280304Sjkim        uubufnum = rem;
671280304Sjkim    }
672280304Sjkim    return (ret);
673280304Sjkim}
67455714Skris
67555714Skrisvoid uufwriteEnd(FILE *fp)
676280304Sjkim{
677280304Sjkim    int j;
678280304Sjkim    static const char *end = " \nend\n";
67955714Skris
680280304Sjkim    if (uubufnum != 0) {
681280304Sjkim        uubuf[uubufnum] = '\0';
682280304Sjkim        uubuf[uubufnum + 1] = '\0';
683280304Sjkim        uubuf[uubufnum + 2] = '\0';
684280304Sjkim        j = uuencode(uubuf, uubufnum, b);
685280304Sjkim        fwrite(b, 1, (unsigned int)j, fp);
686280304Sjkim    }
687280304Sjkim    fwrite(end, 1, strlen(end), fp);
688280304Sjkim}
68955714Skris
690280304Sjkim/*
691280304Sjkim * int size: should always be > ~ 60; I actually ignore this parameter :-)
692280304Sjkim */
69355714Skrisint uufread(unsigned char *out, int size, unsigned int num, FILE *fp)
694280304Sjkim{
695280304Sjkim    int i, j, tot;
696280304Sjkim    static int done = 0;
697280304Sjkim    static int valid = 0;
698280304Sjkim    static int start = 1;
69955714Skris
700280304Sjkim    if (start) {
701280304Sjkim        for (;;) {
702280304Sjkim            b[0] = '\0';
703280304Sjkim            fgets((char *)b, 300, fp);
704280304Sjkim            if (b[0] == '\0') {
705280304Sjkim                fprintf(stderr, "no 'begin' found in uuencoded input\n");
706280304Sjkim                return (-1);
707280304Sjkim            }
708280304Sjkim            if (strncmp((char *)b, "begin ", 6) == 0)
709280304Sjkim                break;
710280304Sjkim        }
711280304Sjkim        start = 0;
712280304Sjkim    }
713280304Sjkim    if (done)
714280304Sjkim        return (0);
715280304Sjkim    tot = 0;
716280304Sjkim    if (valid) {
717280304Sjkim        memcpy(out, bb, (unsigned int)valid);
718280304Sjkim        tot = valid;
719280304Sjkim        valid = 0;
720280304Sjkim    }
721280304Sjkim    for (;;) {
722280304Sjkim        b[0] = '\0';
723280304Sjkim        fgets((char *)b, 300, fp);
724280304Sjkim        if (b[0] == '\0')
725280304Sjkim            break;
726280304Sjkim        i = strlen((char *)b);
727280304Sjkim        if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd')) {
728280304Sjkim            done = 1;
729280304Sjkim            while (!feof(fp)) {
730280304Sjkim                fgets((char *)b, 300, fp);
731280304Sjkim            }
732280304Sjkim            break;
733280304Sjkim        }
734280304Sjkim        i = uudecode(b, i, bb);
735280304Sjkim        if (i < 0)
736280304Sjkim            break;
737280304Sjkim        if ((i + tot + 8) > num) {
738280304Sjkim            /* num to copy to make it a multiple of 8 */
739280304Sjkim            j = (num / 8 * 8) - tot - 8;
740280304Sjkim            memcpy(&(out[tot]), bb, (unsigned int)j);
741280304Sjkim            tot += j;
742280304Sjkim            memcpy(bb, &(bb[j]), (unsigned int)i - j);
743280304Sjkim            valid = i - j;
744280304Sjkim            break;
745280304Sjkim        }
746280304Sjkim        memcpy(&(out[tot]), bb, (unsigned int)i);
747280304Sjkim        tot += i;
748280304Sjkim    }
749280304Sjkim    return (tot);
750280304Sjkim}
75155714Skris
75255714Skris#define ccc2l(c,l)      (l =((DES_LONG)(*((c)++)))<<16, \
753280304Sjkim                         l|=((DES_LONG)(*((c)++)))<< 8, \
754280304Sjkim                         l|=((DES_LONG)(*((c)++))))
75555714Skris
75655714Skris#define l2ccc(l,c)      (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
75755714Skris                    *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
75855714Skris                    *((c)++)=(unsigned char)(((l)    )&0xff))
75955714Skris
76055714Skrisint uuencode(unsigned char *in, int num, unsigned char *out)
761280304Sjkim{
762280304Sjkim    int j, i, n, tot = 0;
763280304Sjkim    DES_LONG l;
764280304Sjkim    register unsigned char *p;
765280304Sjkim    p = out;
76655714Skris
767280304Sjkim    for (j = 0; j < num; j += 45) {
768280304Sjkim        if (j + 45 > num)
769280304Sjkim            i = (num - j);
770280304Sjkim        else
771280304Sjkim            i = 45;
772280304Sjkim        *(p++) = i + ' ';
773280304Sjkim        for (n = 0; n < i; n += 3) {
774280304Sjkim            ccc2l(in, l);
775280304Sjkim            *(p++) = ((l >> 18) & 0x3f) + ' ';
776280304Sjkim            *(p++) = ((l >> 12) & 0x3f) + ' ';
777280304Sjkim            *(p++) = ((l >> 6) & 0x3f) + ' ';
778280304Sjkim            *(p++) = ((l) & 0x3f) + ' ';
779280304Sjkim            tot += 4;
780280304Sjkim        }
781280304Sjkim        *(p++) = '\n';
782280304Sjkim        tot += 2;
783280304Sjkim    }
784280304Sjkim    *p = '\0';
785280304Sjkim    l = 0;
786280304Sjkim    return (tot);
787280304Sjkim}
78855714Skris
78955714Skrisint uudecode(unsigned char *in, int num, unsigned char *out)
790280304Sjkim{
791280304Sjkim    int j, i, k;
792280304Sjkim    unsigned int n = 0, space = 0;
793280304Sjkim    DES_LONG l;
794280304Sjkim    DES_LONG w, x, y, z;
795280304Sjkim    unsigned int blank = (unsigned int)'\n' - ' ';
79655714Skris
797280304Sjkim    for (j = 0; j < num;) {
798280304Sjkim        n = *(in++) - ' ';
799280304Sjkim        if (n == blank) {
800280304Sjkim            n = 0;
801280304Sjkim            in--;
802280304Sjkim        }
803280304Sjkim        if (n > 60) {
804280304Sjkim            fprintf(stderr, "uuencoded line length too long\n");
805280304Sjkim            return (-1);
806280304Sjkim        }
807280304Sjkim        j++;
80855714Skris
809280304Sjkim        for (i = 0; i < n; j += 4, i += 3) {
810280304Sjkim            /*
811280304Sjkim             * the following is for cases where spaces are removed from
812280304Sjkim             * lines.
813280304Sjkim             */
814280304Sjkim            if (space) {
815280304Sjkim                w = x = y = z = 0;
816280304Sjkim            } else {
817280304Sjkim                w = *(in++) - ' ';
818280304Sjkim                x = *(in++) - ' ';
819280304Sjkim                y = *(in++) - ' ';
820280304Sjkim                z = *(in++) - ' ';
821280304Sjkim            }
822280304Sjkim            if ((w > 63) || (x > 63) || (y > 63) || (z > 63)) {
823280304Sjkim                k = 0;
824280304Sjkim                if (w == blank)
825280304Sjkim                    k = 1;
826280304Sjkim                if (x == blank)
827280304Sjkim                    k = 2;
828280304Sjkim                if (y == blank)
829280304Sjkim                    k = 3;
830280304Sjkim                if (z == blank)
831280304Sjkim                    k = 4;
832280304Sjkim                space = 1;
833280304Sjkim                switch (k) {
834280304Sjkim                case 1:
835280304Sjkim                    w = 0;
836280304Sjkim                    in--;
837280304Sjkim                case 2:
838280304Sjkim                    x = 0;
839280304Sjkim                    in--;
840280304Sjkim                case 3:
841280304Sjkim                    y = 0;
842280304Sjkim                    in--;
843280304Sjkim                case 4:
844280304Sjkim                    z = 0;
845280304Sjkim                    in--;
846280304Sjkim                    break;
847280304Sjkim                case 0:
848280304Sjkim                    space = 0;
849280304Sjkim                    fprintf(stderr, "bad uuencoded data values\n");
850280304Sjkim                    w = x = y = z = 0;
851280304Sjkim                    return (-1);
852280304Sjkim                    break;
853280304Sjkim                }
854280304Sjkim            }
855280304Sjkim            l = (w << 18) | (x << 12) | (y << 6) | (z);
856280304Sjkim            l2ccc(l, out);
857280304Sjkim        }
858280304Sjkim        if (*(in++) != '\n') {
859280304Sjkim            fprintf(stderr, "missing nl in uuencoded line\n");
860280304Sjkim            w = x = y = z = 0;
861280304Sjkim            return (-1);
862280304Sjkim        }
863280304Sjkim        j++;
864280304Sjkim    }
865280304Sjkim    *out = '\0';
866280304Sjkim    w = x = y = z = 0;
867280304Sjkim    return (n);
868280304Sjkim}
869