]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/des/des.c
Run util/openssl-format-source -v -c .
[thirdparty/openssl.git] / crypto / des / des.c
CommitLineData
d02b48c6 1/* crypto/des/des.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
ae5c8664 8 *
d02b48c6
RE
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
ae5c8664 15 *
d02b48c6
RE
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
ae5c8664 22 *
d02b48c6
RE
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
ae5c8664 37 * 4. If you include any Windows specific code (or a derivative thereof) from
d02b48c6
RE
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
ae5c8664 40 *
d02b48c6
RE
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
ae5c8664 52 *
d02b48c6
RE
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <stdlib.h>
48b83a25 61#include <string.h>
e766a681 62#include <openssl/opensslconf.h>
bc36ee62 63#ifndef OPENSSL_SYS_MSDOS
ae5c8664
MC
64# ifndef OPENSSL_SYS_VMS
65# include OPENSSL_UNISTD
66# else /* OPENSSL_SYS_VMS */
67# ifdef __DECC
68# include <unistd.h>
69# else /* not __DECC */
70# include <math.h>
71# endif /* __DECC */
72# endif /* OPENSSL_SYS_VMS */
73#else /* OPENSSL_SYS_MSDOS */
74# include <io.h>
d02b48c6
RE
75#endif
76
77#include <time.h>
78#include "des_ver.h"
79
bc36ee62 80#ifdef OPENSSL_SYS_VMS
ae5c8664
MC
81# include <types.h>
82# include <stat.h>
d02b48c6 83#else
ae5c8664
MC
84# ifndef _IRIX
85# include <sys/types.h>
86# endif
87# include <sys/stat.h>
d02b48c6 88#endif
ec577822 89#include <openssl/des.h>
cfa3747b 90#include <openssl/rand.h>
2ed2d151 91#include <openssl/ui_compat.h>
d02b48c6 92
d02b48c6
RE
93void usage(void);
94void doencryption(void);
95int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
96void uufwriteEnd(FILE *fp);
ae5c8664
MC
97int uufread(unsigned char *out, int size, unsigned int num, FILE *fp);
98int uuencode(unsigned char *in, int num, unsigned char *out);
99int uudecode(unsigned char *in, int num, unsigned char *out);
100void DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length,
101 DES_key_schedule sk1, DES_key_schedule sk2,
102 DES_cblock *ivec1, DES_cblock *ivec2, int enc);
bc36ee62 103#ifdef OPENSSL_SYS_VMS
ae5c8664 104# define EXIT(a) exit(a&0x10000000L)
d02b48c6 105#else
ae5c8664 106# define EXIT(a) exit(a)
d02b48c6
RE
107#endif
108
109#define BUFSIZE (8*1024)
110#define VERIFY 1
ae5c8664
MC
111#define KEYSIZ 8
112#define KEYSIZB 1024 /* should hit tty line limit first :-) */
113char key[KEYSIZB + 1];
114int do_encrypt, longk = 0;
115FILE *DES_IN, *DES_OUT, *CKSUM_OUT;
d02b48c6
RE
116char uuname[200];
117unsigned char uubuf[50];
ae5c8664
MC
118int uubufnum = 0;
119#define INUUBUFN (45*100)
120#define OUTUUBUF (65*100)
d02b48c6
RE
121unsigned char b[OUTUUBUF];
122unsigned char bb[300];
ae5c8664 123DES_cblock cksum = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
d02b48c6 124
ae5c8664
MC
125char cksumname[200] = "";
126
127int vflag, cflag, eflag, dflag, kflag, bflag, fflag, sflag, uflag, flag3,
128 hflag, error;
d02b48c6 129
6b691a5c 130int main(int argc, char **argv)
ae5c8664
MC
131{
132 int i;
133 struct stat ins, outs;
134 char *p;
135 char *in = NULL, *out = NULL;
136
137 vflag = cflag = eflag = dflag = kflag = hflag = bflag = fflag = sflag =
138 uflag = flag3 = 0;
139 error = 0;
140 memset(key, 0, sizeof(key));
141
142 for (i = 1; i < argc; i++) {
143 p = argv[i];
144 if ((p[0] == '-') && (p[1] != '\0')) {
145 p++;
146 while (*p) {
147 switch (*(p++)) {
148 case '3':
149 flag3 = 1;
150 longk = 1;
151 break;
152 case 'c':
153 cflag = 1;
154 strncpy(cksumname, p, 200);
155 cksumname[sizeof(cksumname) - 1] = '\0';
156 p += strlen(cksumname);
157 break;
158 case 'C':
159 cflag = 1;
160 longk = 1;
161 strncpy(cksumname, p, 200);
162 cksumname[sizeof(cksumname) - 1] = '\0';
163 p += strlen(cksumname);
164 break;
165 case 'e':
166 eflag = 1;
167 break;
168 case 'v':
169 vflag = 1;
170 break;
171 case 'E':
172 eflag = 1;
173 longk = 1;
174 break;
175 case 'd':
176 dflag = 1;
177 break;
178 case 'D':
179 dflag = 1;
180 longk = 1;
181 break;
182 case 'b':
183 bflag = 1;
184 break;
185 case 'f':
186 fflag = 1;
187 break;
188 case 's':
189 sflag = 1;
190 break;
191 case 'u':
192 uflag = 1;
193 strncpy(uuname, p, 200);
194 uuname[sizeof(uuname) - 1] = '\0';
195 p += strlen(uuname);
196 break;
197 case 'h':
198 hflag = 1;
199 break;
200 case 'k':
201 kflag = 1;
202 if ((i + 1) == argc) {
203 fputs("must have a key with the -k option\n", stderr);
204 error = 1;
205 } else {
206 int j;
207
208 i++;
209 strncpy(key, argv[i], KEYSIZB);
210 for (j = strlen(argv[i]) - 1; j >= 0; j--)
211 argv[i][j] = '\0';
212 }
213 break;
214 default:
215 fprintf(stderr, "'%c' unknown flag\n", p[-1]);
216 error = 1;
217 break;
218 }
219 }
220 } else {
221 if (in == NULL)
222 in = argv[i];
223 else if (out == NULL)
224 out = argv[i];
225 else
226 error = 1;
227 }
228 }
229 if (error)
230 usage();
231 /*-
232 * We either
233 * do checksum or
234 * do encrypt or
235 * do decrypt or
236 * do decrypt then ckecksum or
237 * do checksum then encrypt
238 */
239 if (((eflag + dflag) == 1) || cflag) {
240 if (eflag)
241 do_encrypt = DES_ENCRYPT;
242 if (dflag)
243 do_encrypt = DES_DECRYPT;
244 } else {
245 if (vflag) {
246#ifndef _Windows
247 fprintf(stderr, "des(1) built with %s\n", libdes_version);
248#endif
249 EXIT(1);
250 } else
251 usage();
252 }
253
254#ifndef _Windows
255 if (vflag)
256 fprintf(stderr, "des(1) built with %s\n", libdes_version);
257#endif
258 if ((in != NULL) && (out != NULL) &&
bc36ee62 259#ifndef OPENSSL_SYS_MSDOS
ae5c8664
MC
260 (stat(in, &ins) != -1) &&
261 (stat(out, &outs) != -1) &&
262 (ins.st_dev == outs.st_dev) && (ins.st_ino == outs.st_ino))
263#else /* OPENSSL_SYS_MSDOS */
264 (strcmp(in, out) == 0))
d02b48c6 265#endif
ae5c8664
MC
266 {
267 fputs("input and output file are the same\n", stderr);
268 EXIT(3);
269 }
270
271 if (!kflag)
272 if (des_read_pw_string
273 (key, KEYSIZB + 1, "Enter key:", eflag ? VERIFY : 0)) {
274 fputs("password error\n", stderr);
275 EXIT(2);
276 }
277
278 if (in == NULL)
279 DES_IN = stdin;
280 else if ((DES_IN = fopen(in, "r")) == NULL) {
281 perror("opening input file");
282 EXIT(4);
283 }
284
285 CKSUM_OUT = stdout;
286 if (out == NULL) {
287 DES_OUT = stdout;
288 CKSUM_OUT = stderr;
289 } else if ((DES_OUT = fopen(out, "w")) == NULL) {
290 perror("opening output file");
291 EXIT(5);
292 }
bc36ee62 293#ifdef OPENSSL_SYS_MSDOS
ae5c8664
MC
294 /* This should set the file to binary mode. */
295 {
296# include <fcntl.h>
297 if (!(uflag && dflag))
298 setmode(fileno(DES_IN), O_BINARY);
299 if (!(uflag && eflag))
300 setmode(fileno(DES_OUT), O_BINARY);
301 }
d02b48c6
RE
302#endif
303
ae5c8664
MC
304 doencryption();
305 fclose(DES_IN);
306 fclose(DES_OUT);
307 EXIT(0);
308}
d02b48c6 309
6b691a5c 310void usage(void)
ae5c8664
MC
311{
312 char **u;
313 static const char *Usage[] = {
314 "des <options> [input-file [output-file]]",
315 "options:",
316 "-v : des(1) version number",
317 "-e : encrypt using SunOS compatible user key to DES key conversion.",
318 "-E : encrypt ",
319 "-d : decrypt using SunOS compatible user key to DES key conversion.",
320 "-D : decrypt ",
321 "-c[ckname] : generate a cbc_cksum using SunOS compatible user key to",
322 " DES key conversion and output to ckname (stdout default,",
323 " stderr if data being output on stdout). The checksum is",
324 " generated before encryption and after decryption if used",
325 " in conjunction with -[eEdD].",
326 "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].",
327 "-k key : use key 'key'",
328 "-h : the key that is entered will be a hexadecimal number",
329 " that is used directly as the des key",
330 "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]",
331 " (uuname is the filename to put in the uuencode header).",
332 "-b : encrypt using DES in ecb encryption mode, the default is cbc mode.",
333 "-3 : encrypt using triple DES encryption. This uses 2 keys",
334 " generated from the input key. If the input key is less",
335 " than 8 characters long, this is equivalent to normal",
336 " encryption. Default is triple cbc, -b makes it triple ecb.",
337 NULL
338 };
339 for (u = (char **)Usage; *u; u++) {
340 fputs(*u, stderr);
341 fputc('\n', stderr);
342 }
343
344 EXIT(1);
345}
d02b48c6 346
6b691a5c 347void doencryption(void)
ae5c8664 348{
d02b48c6 349#ifdef _LIBC
ae5c8664 350 extern unsigned long time();
d02b48c6
RE
351#endif
352
ae5c8664
MC
353 register int i;
354 DES_key_schedule ks, ks2;
355 DES_cblock iv, iv2;
356 char *p;
357 int num = 0, j, k, l, rem, ll, len, last, ex = 0;
358 DES_cblock kk, k2;
359 FILE *O;
360 int Exit = 0;
bc36ee62 361#ifndef OPENSSL_SYS_MSDOS
ae5c8664 362 static unsigned char buf[BUFSIZE + 8], obuf[BUFSIZE + 8];
d02b48c6 363#else
ae5c8664
MC
364 static unsigned char *buf = NULL, *obuf = NULL;
365
366 if (buf == NULL) {
367 if (((buf = OPENSSL_malloc(BUFSIZE + 8)) == NULL) ||
368 ((obuf = OPENSSL_malloc(BUFSIZE + 8)) == NULL)) {
369 fputs("Not enough memory\n", stderr);
370 Exit = 10;
371 goto problems;
372 }
373 }
d02b48c6
RE
374#endif
375
ae5c8664
MC
376 if (hflag) {
377 j = (flag3 ? 16 : 8);
378 p = key;
379 for (i = 0; i < j; i++) {
380 k = 0;
381 if ((*p <= '9') && (*p >= '0'))
382 k = (*p - '0') << 4;
383 else if ((*p <= 'f') && (*p >= 'a'))
384 k = (*p - 'a' + 10) << 4;
385 else if ((*p <= 'F') && (*p >= 'A'))
386 k = (*p - 'A' + 10) << 4;
387 else {
388 fputs("Bad hex key\n", stderr);
389 Exit = 9;
390 goto problems;
391 }
392 p++;
393 if ((*p <= '9') && (*p >= '0'))
394 k |= (*p - '0');
395 else if ((*p <= 'f') && (*p >= 'a'))
396 k |= (*p - 'a' + 10);
397 else if ((*p <= 'F') && (*p >= 'A'))
398 k |= (*p - 'A' + 10);
399 else {
400 fputs("Bad hex key\n", stderr);
401 Exit = 9;
402 goto problems;
403 }
404 p++;
405 if (i < 8)
406 kk[i] = k;
407 else
408 k2[i - 8] = k;
409 }
410 DES_set_key_unchecked(&k2, &ks2);
411 OPENSSL_cleanse(k2, sizeof(k2));
412 } else if (longk || flag3) {
413 if (flag3) {
414 DES_string_to_2keys(key, &kk, &k2);
415 DES_set_key_unchecked(&k2, &ks2);
416 OPENSSL_cleanse(k2, sizeof(k2));
417 } else
418 DES_string_to_key(key, &kk);
419 } else
420 for (i = 0; i < KEYSIZ; i++) {
421 l = 0;
422 k = key[i];
423 for (j = 0; j < 8; j++) {
424 if (k & 1)
425 l++;
426 k >>= 1;
427 }
428 if (l & 1)
429 kk[i] = key[i] & 0x7f;
430 else
431 kk[i] = key[i] | 0x80;
432 }
433
434 DES_set_key_unchecked(&kk, &ks);
435 OPENSSL_cleanse(key, sizeof(key));
436 OPENSSL_cleanse(kk, sizeof(kk));
437 /* woops - A bug that does not showup under unix :-( */
438 memset(iv, 0, sizeof(iv));
439 memset(iv2, 0, sizeof(iv2));
440
441 l = 1;
442 rem = 0;
443 /* first read */
444 if (eflag || (!dflag && cflag)) {
445 for (;;) {
446 num = l = fread(&(buf[rem]), 1, BUFSIZE, DES_IN);
447 l += rem;
448 num += rem;
449 if (l < 0) {
450 perror("read error");
451 Exit = 6;
452 goto problems;
453 }
454
455 rem = l % 8;
456 len = l - rem;
457 if (feof(DES_IN)) {
458 for (i = 7 - rem; i > 0; i--)
459 RAND_pseudo_bytes(buf + l++, 1);
460 buf[l++] = rem;
461 ex = 1;
462 len += rem;
463 } else
464 l -= rem;
465
466 if (cflag) {
467 DES_cbc_cksum(buf, &cksum, (long)len, &ks, &cksum);
468 if (!eflag) {
469 if (feof(DES_IN))
470 break;
471 else
472 continue;
473 }
474 }
475
476 if (bflag && !flag3)
477 for (i = 0; i < l; i += 8)
478 DES_ecb_encrypt((DES_cblock *)&(buf[i]),
479 (DES_cblock *)&(obuf[i]),
480 &ks, do_encrypt);
481 else if (flag3 && bflag)
482 for (i = 0; i < l; i += 8)
483 DES_ecb2_encrypt((DES_cblock *)&(buf[i]),
484 (DES_cblock *)&(obuf[i]),
485 &ks, &ks2, do_encrypt);
486 else if (flag3 && !bflag) {
487 char tmpbuf[8];
488
489 if (rem)
490 memcpy(tmpbuf, &(buf[l]), (unsigned int)rem);
491 DES_3cbc_encrypt((DES_cblock *)buf, (DES_cblock *)obuf,
492 (long)l, ks, ks2, &iv, &iv2, do_encrypt);
493 if (rem)
494 memcpy(&(buf[l]), tmpbuf, (unsigned int)rem);
495 } else {
496 DES_cbc_encrypt(buf, obuf, (long)l, &ks, &iv, do_encrypt);
497 if (l >= 8)
498 memcpy(iv, &(obuf[l - 8]), 8);
499 }
500 if (rem)
501 memcpy(buf, &(buf[l]), (unsigned int)rem);
502
503 i = 0;
504 while (i < l) {
505 if (uflag)
506 j = uufwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
507 else
508 j = fwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
509 if (j == -1) {
510 perror("Write error");
511 Exit = 7;
512 goto problems;
513 }
514 i += j;
515 }
516 if (feof(DES_IN)) {
517 if (uflag)
518 uufwriteEnd(DES_OUT);
519 break;
520 }
521 }
522 } else { /* decrypt */
523
524 ex = 1;
525 for (;;) {
526 if (ex) {
527 if (uflag)
528 l = uufread(buf, 1, BUFSIZE, DES_IN);
529 else
530 l = fread(buf, 1, BUFSIZE, DES_IN);
531 ex = 0;
532 rem = l % 8;
533 l -= rem;
534 }
535 if (l < 0) {
536 perror("read error");
537 Exit = 6;
538 goto problems;
539 }
540
541 if (bflag && !flag3)
542 for (i = 0; i < l; i += 8)
543 DES_ecb_encrypt((DES_cblock *)&(buf[i]),
544 (DES_cblock *)&(obuf[i]),
545 &ks, do_encrypt);
546 else if (flag3 && bflag)
547 for (i = 0; i < l; i += 8)
548 DES_ecb2_encrypt((DES_cblock *)&(buf[i]),
549 (DES_cblock *)&(obuf[i]),
550 &ks, &ks2, do_encrypt);
551 else if (flag3 && !bflag) {
552 DES_3cbc_encrypt((DES_cblock *)buf, (DES_cblock *)obuf,
553 (long)l, ks, ks2, &iv, &iv2, do_encrypt);
554 } else {
555 DES_cbc_encrypt(buf, obuf, (long)l, &ks, &iv, do_encrypt);
556 if (l >= 8)
557 memcpy(iv, &(buf[l - 8]), 8);
558 }
559
560 if (uflag)
561 ll = uufread(&(buf[rem]), 1, BUFSIZE, DES_IN);
562 else
563 ll = fread(&(buf[rem]), 1, BUFSIZE, DES_IN);
564 ll += rem;
565 rem = ll % 8;
566 ll -= rem;
567 if (feof(DES_IN) && (ll == 0)) {
568 last = obuf[l - 1];
569
570 if ((last > 7) || (last < 0)) {
571 fputs("The file was not decrypted correctly.\n", stderr);
572 Exit = 8;
573 last = 0;
574 }
575 l = l - 8 + last;
576 }
577 i = 0;
578 if (cflag)
579 DES_cbc_cksum(obuf,
580 (DES_cblock *)cksum, (long)l / 8 * 8, &ks,
581 (DES_cblock *)cksum);
582 while (i != l) {
583 j = fwrite(obuf, 1, (unsigned int)l - i, DES_OUT);
584 if (j == -1) {
585 perror("Write error");
586 Exit = 7;
587 goto problems;
588 }
589 i += j;
590 }
591 l = ll;
592 if ((l == 0) && feof(DES_IN))
593 break;
594 }
595 }
596 if (cflag) {
597 l = 0;
598 if (cksumname[0] != '\0') {
599 if ((O = fopen(cksumname, "w")) != NULL) {
600 CKSUM_OUT = O;
601 l = 1;
602 }
603 }
604 for (i = 0; i < 8; i++)
605 fprintf(CKSUM_OUT, "%02X", cksum[i]);
606 fprintf(CKSUM_OUT, "\n");
607 if (l)
608 fclose(CKSUM_OUT);
609 }
610 problems:
611 OPENSSL_cleanse(buf, sizeof(buf));
612 OPENSSL_cleanse(obuf, sizeof(obuf));
613 OPENSSL_cleanse(&ks, sizeof(ks));
614 OPENSSL_cleanse(&ks2, sizeof(ks2));
615 OPENSSL_cleanse(iv, sizeof(iv));
616 OPENSSL_cleanse(iv2, sizeof(iv2));
617 OPENSSL_cleanse(kk, sizeof(kk));
618 OPENSSL_cleanse(k2, sizeof(k2));
619 OPENSSL_cleanse(uubuf, sizeof(uubuf));
620 OPENSSL_cleanse(b, sizeof(b));
621 OPENSSL_cleanse(bb, sizeof(bb));
622 OPENSSL_cleanse(cksum, sizeof(cksum));
623 if (Exit)
624 EXIT(Exit);
625}
d02b48c6 626
6b691a5c
UM
627/* We ignore this parameter but it should be > ~50 I believe */
628int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp)
ae5c8664
MC
629{
630 int i, j, left, rem, ret = num;
631 static int start = 1;
632
633 if (start) {
634 fprintf(fp, "begin 600 %s\n",
635 (uuname[0] == '\0') ? "text.d" : uuname);
636 start = 0;
637 }
638
639 if (uubufnum) {
640 if (uubufnum + num < 45) {
641 memcpy(&(uubuf[uubufnum]), data, (unsigned int)num);
642 uubufnum += num;
643 return (num);
644 } else {
645 i = 45 - uubufnum;
646 memcpy(&(uubuf[uubufnum]), data, (unsigned int)i);
647 j = uuencode((unsigned char *)uubuf, 45, b);
648 fwrite(b, 1, (unsigned int)j, fp);
649 uubufnum = 0;
650 data += i;
651 num -= i;
652 }
653 }
654
655 for (i = 0; i < (((int)num) - INUUBUFN); i += INUUBUFN) {
656 j = uuencode(&(data[i]), INUUBUFN, b);
657 fwrite(b, 1, (unsigned int)j, fp);
658 }
659 rem = (num - i) % 45;
660 left = (num - i - rem);
661 if (left) {
662 j = uuencode(&(data[i]), left, b);
663 fwrite(b, 1, (unsigned int)j, fp);
664 i += left;
665 }
666 if (i != num) {
667 memcpy(uubuf, &(data[i]), (unsigned int)rem);
668 uubufnum = rem;
669 }
670 return (ret);
671}
d02b48c6 672
6b691a5c 673void uufwriteEnd(FILE *fp)
ae5c8664
MC
674{
675 int j;
676 static const char *end = " \nend\n";
677
678 if (uubufnum != 0) {
679 uubuf[uubufnum] = '\0';
680 uubuf[uubufnum + 1] = '\0';
681 uubuf[uubufnum + 2] = '\0';
682 j = uuencode(uubuf, uubufnum, b);
683 fwrite(b, 1, (unsigned int)j, fp);
684 }
685 fwrite(end, 1, strlen(end), fp);
686}
687
688/*
689 * int size: should always be > ~ 60; I actually ignore this parameter :-)
690 */
6b691a5c 691int uufread(unsigned char *out, int size, unsigned int num, FILE *fp)
ae5c8664
MC
692{
693 int i, j, tot;
694 static int done = 0;
695 static int valid = 0;
696 static int start = 1;
697
698 if (start) {
699 for (;;) {
700 b[0] = '\0';
701 fgets((char *)b, 300, fp);
702 if (b[0] == '\0') {
703 fprintf(stderr, "no 'begin' found in uuencoded input\n");
704 return (-1);
705 }
706 if (strncmp((char *)b, "begin ", 6) == 0)
707 break;
708 }
709 start = 0;
710 }
711 if (done)
712 return (0);
713 tot = 0;
714 if (valid) {
715 memcpy(out, bb, (unsigned int)valid);
716 tot = valid;
717 valid = 0;
718 }
719 for (;;) {
720 b[0] = '\0';
721 fgets((char *)b, 300, fp);
722 if (b[0] == '\0')
723 break;
724 i = strlen((char *)b);
725 if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd')) {
726 done = 1;
727 while (!feof(fp)) {
728 fgets((char *)b, 300, fp);
729 }
730 break;
731 }
732 i = uudecode(b, i, bb);
733 if (i < 0)
734 break;
735 if ((i + tot + 8) > num) {
736 /* num to copy to make it a multiple of 8 */
737 j = (num / 8 * 8) - tot - 8;
738 memcpy(&(out[tot]), bb, (unsigned int)j);
739 tot += j;
740 memcpy(bb, &(bb[j]), (unsigned int)i - j);
741 valid = i - j;
742 break;
743 }
744 memcpy(&(out[tot]), bb, (unsigned int)i);
745 tot += i;
746 }
747 return (tot);
748}
d02b48c6
RE
749
750#define ccc2l(c,l) (l =((DES_LONG)(*((c)++)))<<16, \
ae5c8664
MC
751 l|=((DES_LONG)(*((c)++)))<< 8, \
752 l|=((DES_LONG)(*((c)++))))
d02b48c6
RE
753
754#define l2ccc(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
755 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
756 *((c)++)=(unsigned char)(((l) )&0xff))
757
6b691a5c 758int uuencode(unsigned char *in, int num, unsigned char *out)
ae5c8664
MC
759{
760 int j, i, n, tot = 0;
761 DES_LONG l;
762 register unsigned char *p;
763 p = out;
764
765 for (j = 0; j < num; j += 45) {
766 if (j + 45 > num)
767 i = (num - j);
768 else
769 i = 45;
770 *(p++) = i + ' ';
771 for (n = 0; n < i; n += 3) {
772 ccc2l(in, l);
773 *(p++) = ((l >> 18) & 0x3f) + ' ';
774 *(p++) = ((l >> 12) & 0x3f) + ' ';
775 *(p++) = ((l >> 6) & 0x3f) + ' ';
776 *(p++) = ((l) & 0x3f) + ' ';
777 tot += 4;
778 }
779 *(p++) = '\n';
780 tot += 2;
781 }
782 *p = '\0';
783 l = 0;
784 return (tot);
785}
d02b48c6 786
6b691a5c 787int uudecode(unsigned char *in, int num, unsigned char *out)
ae5c8664
MC
788{
789 int j, i, k;
790 unsigned int n = 0, space = 0;
791 DES_LONG l;
792 DES_LONG w, x, y, z;
793 unsigned int blank = (unsigned int)'\n' - ' ';
794
795 for (j = 0; j < num;) {
796 n = *(in++) - ' ';
797 if (n == blank) {
798 n = 0;
799 in--;
800 }
801 if (n > 60) {
802 fprintf(stderr, "uuencoded line length too long\n");
803 return (-1);
804 }
805 j++;
806
807 for (i = 0; i < n; j += 4, i += 3) {
808 /*
809 * the following is for cases where spaces are removed from
810 * lines.
811 */
812 if (space) {
813 w = x = y = z = 0;
814 } else {
815 w = *(in++) - ' ';
816 x = *(in++) - ' ';
817 y = *(in++) - ' ';
818 z = *(in++) - ' ';
819 }
820 if ((w > 63) || (x > 63) || (y > 63) || (z > 63)) {
821 k = 0;
822 if (w == blank)
823 k = 1;
824 if (x == blank)
825 k = 2;
826 if (y == blank)
827 k = 3;
828 if (z == blank)
829 k = 4;
830 space = 1;
831 switch (k) {
832 case 1:
833 w = 0;
834 in--;
835 case 2:
836 x = 0;
837 in--;
838 case 3:
839 y = 0;
840 in--;
841 case 4:
842 z = 0;
843 in--;
844 break;
845 case 0:
846 space = 0;
847 fprintf(stderr, "bad uuencoded data values\n");
848 w = x = y = z = 0;
849 return (-1);
850 break;
851 }
852 }
853 l = (w << 18) | (x << 12) | (y << 6) | (z);
854 l2ccc(l, out);
855 }
856 if (*(in++) != '\n') {
857 fprintf(stderr, "missing nl in uuencoded line\n");
858 w = x = y = z = 0;
859 return (-1);
860 }
861 j++;
862 }
863 *out = '\0';
864 w = x = y = z = 0;
865 return (n);
866}