| /* crypto/des/des.c */ |
| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| * All rights reserved. |
| * |
| * This package is an SSL implementation written |
| * by Eric Young (eay@cryptsoft.com). |
| * The implementation was written so as to conform with Netscapes SSL. |
| * |
| * This library is free for commercial and non-commercial use as long as |
| * the following conditions are aheared to. The following conditions |
| * apply to all code found in this distribution, be it the RC4, RSA, |
| * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
| * included with this distribution is covered by the same copyright terms |
| * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
| * |
| * Copyright remains Eric Young's, and as such any Copyright notices in |
| * the code are not to be removed. |
| * If this package is used in a product, Eric Young should be given attribution |
| * as the author of the parts of the library used. |
| * This can be in the form of a textual message at program startup or |
| * in documentation (online or textual) provided with the package. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * "This product includes cryptographic software written by |
| * Eric Young (eay@cryptsoft.com)" |
| * The word 'cryptographic' can be left out if the rouines from the library |
| * being used are not cryptographic related :-). |
| * 4. If you include any Windows specific code (or a derivative thereof) from |
| * the apps directory (application code) you must include an acknowledgement: |
| * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
| * |
| * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * |
| * The licence and distribution terms for any publically available version or |
| * derivative of this code cannot be changed. i.e. this code cannot simply be |
| * copied and put under another distribution licence |
| * [including the GNU Public Licence.] |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <openssl/opensslconf.h> |
| #ifndef OPENSSL_SYS_MSDOS |
| #ifndef OPENSSL_SYS_VMS |
| #include OPENSSL_UNISTD |
| #else /* OPENSSL_SYS_VMS */ |
| #ifdef __DECC |
| #include <unistd.h> |
| #else /* not __DECC */ |
| #include <math.h> |
| #endif /* __DECC */ |
| #endif /* OPENSSL_SYS_VMS */ |
| #else /* OPENSSL_SYS_MSDOS */ |
| #include <io.h> |
| #endif |
| |
| #include <time.h> |
| #include "des_ver.h" |
| |
| #ifdef OPENSSL_SYS_VMS |
| #include <types.h> |
| #include <stat.h> |
| #else |
| #ifndef _IRIX |
| #include <sys/types.h> |
| #endif |
| #include <sys/stat.h> |
| #endif |
| #include <openssl/des.h> |
| #include <openssl/rand.h> |
| #include <openssl/ui_compat.h> |
| |
| void usage(void); |
| void doencryption(void); |
| int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp); |
| void uufwriteEnd(FILE *fp); |
| int uufread(unsigned char *out,int size,unsigned int num,FILE *fp); |
| int uuencode(unsigned char *in,int num,unsigned char *out); |
| int uudecode(unsigned char *in,int num,unsigned char *out); |
| void DES_3cbc_encrypt(DES_cblock *input,DES_cblock *output,long length, |
| DES_key_schedule sk1,DES_key_schedule sk2, |
| DES_cblock *ivec1,DES_cblock *ivec2,int enc); |
| #ifdef OPENSSL_SYS_VMS |
| #define EXIT(a) exit(a&0x10000000L) |
| #else |
| #define EXIT(a) exit(a) |
| #endif |
| |
| #define BUFSIZE (8*1024) |
| #define VERIFY 1 |
| #define KEYSIZ 8 |
| #define KEYSIZB 1024 /* should hit tty line limit first :-) */ |
| char key[KEYSIZB+1]; |
| int do_encrypt,longk=0; |
| FILE *DES_IN,*DES_OUT,*CKSUM_OUT; |
| char uuname[200]; |
| unsigned char uubuf[50]; |
| int uubufnum=0; |
| #define INUUBUFN (45*100) |
| #define OUTUUBUF (65*100) |
| unsigned char b[OUTUUBUF]; |
| unsigned char bb[300]; |
| DES_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; |
| char cksumname[200]=""; |
| |
| int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error; |
| |
| int main(int argc, char **argv) |
| { |
| int i; |
| struct stat ins,outs; |
| char *p; |
| char *in=NULL,*out=NULL; |
| |
| vflag=cflag=eflag=dflag=kflag=hflag=bflag=fflag=sflag=uflag=flag3=0; |
| error=0; |
| memset(key,0,sizeof(key)); |
| |
| for (i=1; i<argc; i++) |
| { |
| p=argv[i]; |
| if ((p[0] == '-') && (p[1] != '\0')) |
| { |
| p++; |
| while (*p) |
| { |
| switch (*(p++)) |
| { |
| case '3': |
| flag3=1; |
| longk=1; |
| break; |
| case 'c': |
| cflag=1; |
| strncpy(cksumname,p,200); |
| cksumname[sizeof(cksumname)-1]='\0'; |
| p+=strlen(cksumname); |
| break; |
| case 'C': |
| cflag=1; |
| longk=1; |
| strncpy(cksumname,p,200); |
| cksumname[sizeof(cksumname)-1]='\0'; |
| p+=strlen(cksumname); |
| break; |
| case 'e': |
| eflag=1; |
| break; |
| case 'v': |
| vflag=1; |
| break; |
| case 'E': |
| eflag=1; |
| longk=1; |
| break; |
| case 'd': |
| dflag=1; |
| break; |
| case 'D': |
| dflag=1; |
| longk=1; |
| break; |
| case 'b': |
| bflag=1; |
| break; |
| case 'f': |
| fflag=1; |
| break; |
| case 's': |
| sflag=1; |
| break; |
| case 'u': |
| uflag=1; |
| strncpy(uuname,p,200); |
| uuname[sizeof(uuname)-1]='\0'; |
| p+=strlen(uuname); |
| break; |
| case 'h': |
| hflag=1; |
| break; |
| case 'k': |
| kflag=1; |
| if ((i+1) == argc) |
| { |
| fputs("must have a key with the -k option\n",stderr); |
| error=1; |
| } |
| else |
| { |
| int j; |
| |
| i++; |
| strncpy(key,argv[i],KEYSIZB); |
| for (j=strlen(argv[i])-1; j>=0; j--) |
| argv[i][j]='\0'; |
| } |
| break; |
| default: |
| fprintf(stderr,"'%c' unknown flag\n",p[-1]); |
| error=1; |
| break; |
| } |
| } |
| } |
| else |
| { |
| if (in == NULL) |
| in=argv[i]; |
| else if (out == NULL) |
| out=argv[i]; |
| else |
| error=1; |
| } |
| } |
| if (error) usage(); |
| /* We either |
| * do checksum or |
| * do encrypt or |
| * do decrypt or |
| * do decrypt then ckecksum or |
| * do checksum then encrypt |
| */ |
| if (((eflag+dflag) == 1) || cflag) |
| { |
| if (eflag) do_encrypt=DES_ENCRYPT; |
| if (dflag) do_encrypt=DES_DECRYPT; |
| } |
| else |
| { |
| if (vflag) |
| { |
| #ifndef _Windows |
| fprintf(stderr,"des(1) built with %s\n",libdes_version); |
| #endif |
| EXIT(1); |
| } |
| else usage(); |
| } |
| |
| #ifndef _Windows |
| if (vflag) fprintf(stderr,"des(1) built with %s\n",libdes_version); |
| #endif |
| if ( (in != NULL) && |
| (out != NULL) && |
| #ifndef OPENSSL_SYS_MSDOS |
| (stat(in,&ins) != -1) && |
| (stat(out,&outs) != -1) && |
| (ins.st_dev == outs.st_dev) && |
| (ins.st_ino == outs.st_ino)) |
| #else /* OPENSSL_SYS_MSDOS */ |
| (strcmp(in,out) == 0)) |
| #endif |
| { |
| fputs("input and output file are the same\n",stderr); |
| EXIT(3); |
| } |
| |
| if (!kflag) |
| if (des_read_pw_string(key,KEYSIZB+1,"Enter key:",eflag?VERIFY:0)) |
| { |
| fputs("password error\n",stderr); |
| EXIT(2); |
| } |
| |
| if (in == NULL) |
| DES_IN=stdin; |
| else if ((DES_IN=fopen(in,"r")) == NULL) |
| { |
| perror("opening input file"); |
| EXIT(4); |
| } |
| |
| CKSUM_OUT=stdout; |
| if (out == NULL) |
| { |
| DES_OUT=stdout; |
| CKSUM_OUT=stderr; |
| } |
| else if ((DES_OUT=fopen(out,"w")) == NULL) |
| { |
| perror("opening output file"); |
| EXIT(5); |
| } |
| |
| #ifdef OPENSSL_SYS_MSDOS |
| /* This should set the file to binary mode. */ |
| { |
| #include <fcntl.h> |
| if (!(uflag && dflag)) |
| setmode(fileno(DES_IN),O_BINARY); |
| if (!(uflag && eflag)) |
| setmode(fileno(DES_OUT),O_BINARY); |
| } |
| #endif |
| |
| doencryption(); |
| fclose(DES_IN); |
| fclose(DES_OUT); |
| EXIT(0); |
| } |
| |
| void usage(void) |
| { |
| char **u; |
| static const char *Usage[]={ |
| "des <options> [input-file [output-file]]", |
| "options:", |
| "-v : des(1) version number", |
| "-e : encrypt using SunOS compatible user key to DES key conversion.", |
| "-E : encrypt ", |
| "-d : decrypt using SunOS compatible user key to DES key conversion.", |
| "-D : decrypt ", |
| "-c[ckname] : generate a cbc_cksum using SunOS compatible user key to", |
| " DES key conversion and output to ckname (stdout default,", |
| " stderr if data being output on stdout). The checksum is", |
| " generated before encryption and after decryption if used", |
| " in conjunction with -[eEdD].", |
| "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].", |
| "-k key : use key 'key'", |
| "-h : the key that is entered will be a hexadecimal number", |
| " that is used directly as the des key", |
| "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]", |
| " (uuname is the filename to put in the uuencode header).", |
| "-b : encrypt using DES in ecb encryption mode, the default is cbc mode.", |
| "-3 : encrypt using triple DES encryption. This uses 2 keys", |
| " generated from the input key. If the input key is less", |
| " than 8 characters long, this is equivalent to normal", |
| " encryption. Default is triple cbc, -b makes it triple ecb.", |
| NULL |
| }; |
| for (u=(char **)Usage; *u; u++) |
| { |
| fputs(*u,stderr); |
| fputc('\n',stderr); |
| } |
| |
| EXIT(1); |
| } |
| |
| void doencryption(void) |
| { |
| #ifdef _LIBC |
| extern unsigned long time(); |
| #endif |
| |
| register int i; |
| DES_key_schedule ks,ks2; |
| DES_cblock iv,iv2; |
| char *p; |
| int num=0,j,k,l,rem,ll,len,last,ex=0; |
| DES_cblock kk,k2; |
| FILE *O; |
| int Exit=0; |
| #ifndef OPENSSL_SYS_MSDOS |
| static unsigned char buf[BUFSIZE+8],obuf[BUFSIZE+8]; |
| #else |
| static unsigned char *buf=NULL,*obuf=NULL; |
| |
| if (buf == NULL) |
| { |
| if ( (( buf=OPENSSL_malloc(BUFSIZE+8)) == NULL) || |
| ((obuf=OPENSSL_malloc(BUFSIZE+8)) == NULL)) |
| { |
| fputs("Not enough memory\n",stderr); |
| Exit=10; |
| goto problems; |
| } |
| } |
| #endif |
| |
| if (hflag) |
| { |
| j=(flag3?16:8); |
| p=key; |
| for (i=0; i<j; i++) |
| { |
| k=0; |
| if ((*p <= '9') && (*p >= '0')) |
| k=(*p-'0')<<4; |
| else if ((*p <= 'f') && (*p >= 'a')) |
| k=(*p-'a'+10)<<4; |
| else if ((*p <= 'F') && (*p >= 'A')) |
| k=(*p-'A'+10)<<4; |
| else |
| { |
| fputs("Bad hex key\n",stderr); |
| Exit=9; |
| goto problems; |
| } |
| p++; |
| if ((*p <= '9') && (*p >= '0')) |
| k|=(*p-'0'); |
| else if ((*p <= 'f') && (*p >= 'a')) |
| k|=(*p-'a'+10); |
| else if ((*p <= 'F') && (*p >= 'A')) |
| k|=(*p-'A'+10); |
| else |
| { |
| fputs("Bad hex key\n",stderr); |
| Exit=9; |
| goto problems; |
| } |
| p++; |
| if (i < 8) |
| kk[i]=k; |
| else |
| k2[i-8]=k; |
| } |
| DES_set_key_unchecked(&k2,&ks2); |
| OPENSSL_cleanse(k2,sizeof(k2)); |
| } |
| else if (longk || flag3) |
| { |
| if (flag3) |
| { |
| DES_string_to_2keys(key,&kk,&k2); |
| DES_set_key_unchecked(&k2,&ks2); |
| OPENSSL_cleanse(k2,sizeof(k2)); |
| } |
| else |
| DES_string_to_key(key,&kk); |
| } |
| else |
| for (i=0; i<KEYSIZ; i++) |
| { |
| l=0; |
| k=key[i]; |
| for (j=0; j<8; j++) |
| { |
| if (k&1) l++; |
| k>>=1; |
| } |
| if (l & 1) |
| kk[i]=key[i]&0x7f; |
| else |
| kk[i]=key[i]|0x80; |
| } |
| |
| DES_set_key_unchecked(&kk,&ks); |
| OPENSSL_cleanse(key,sizeof(key)); |
| OPENSSL_cleanse(kk,sizeof(kk)); |
| /* woops - A bug that does not showup under unix :-( */ |
| memset(iv,0,sizeof(iv)); |
| memset(iv2,0,sizeof(iv2)); |
| |
| l=1; |
| rem=0; |
| /* first read */ |
| if (eflag || (!dflag && cflag)) |
| { |
| for (;;) |
| { |
| num=l=fread(&(buf[rem]),1,BUFSIZE,DES_IN); |
| l+=rem; |
| num+=rem; |
| if (l < 0) |
| { |
| perror("read error"); |
| Exit=6; |
| goto problems; |
| } |
| |
| rem=l%8; |
| len=l-rem; |
| if (feof(DES_IN)) |
| { |
| for (i=7-rem; i>0; i--) |
| RAND_pseudo_bytes(buf + l++, 1); |
| buf[l++]=rem; |
| ex=1; |
| len+=rem; |
| } |
| else |
| l-=rem; |
| |
| if (cflag) |
| { |
| DES_cbc_cksum(buf,&cksum, |
| (long)len,&ks,&cksum); |
| if (!eflag) |
| { |
| if (feof(DES_IN)) break; |
| else continue; |
| } |
| } |
| |
| if (bflag && !flag3) |
| for (i=0; i<l; i+=8) |
| DES_ecb_encrypt( |
| (DES_cblock *)&(buf[i]), |
| (DES_cblock *)&(obuf[i]), |
| &ks,do_encrypt); |
| else if (flag3 && bflag) |
| for (i=0; i<l; i+=8) |
| DES_ecb2_encrypt( |
| (DES_cblock *)&(buf[i]), |
| (DES_cblock *)&(obuf[i]), |
| &ks,&ks2,do_encrypt); |
| else if (flag3 && !bflag) |
| { |
| char tmpbuf[8]; |
| |
| if (rem) memcpy(tmpbuf,&(buf[l]), |
| (unsigned int)rem); |
| DES_3cbc_encrypt( |
| (DES_cblock *)buf,(DES_cblock *)obuf, |
| (long)l,ks,ks2,&iv, |
| &iv2,do_encrypt); |
| if (rem) memcpy(&(buf[l]),tmpbuf, |
| (unsigned int)rem); |
| } |
| else |
| { |
| DES_cbc_encrypt( |
| buf,obuf, |
| (long)l,&ks,&iv,do_encrypt); |
| if (l >= 8) memcpy(iv,&(obuf[l-8]),8); |
| } |
| if (rem) memcpy(buf,&(buf[l]),(unsigned int)rem); |
| |
| i=0; |
| while (i < l) |
| { |
| if (uflag) |
| j=uufwrite(obuf,1,(unsigned int)l-i, |
| DES_OUT); |
| else |
| j=fwrite(obuf,1,(unsigned int)l-i, |
| DES_OUT); |
| if (j == -1) |
| { |
| perror("Write error"); |
| Exit=7; |
| goto problems; |
| } |
| i+=j; |
| } |
| if (feof(DES_IN)) |
| { |
| if (uflag) uufwriteEnd(DES_OUT); |
| break; |
| } |
| } |
| } |
| else /* decrypt */ |
| { |
| ex=1; |
| for (;;) |
| { |
| if (ex) { |
| if (uflag) |
| l=uufread(buf,1,BUFSIZE,DES_IN); |
| else |
| l=fread(buf,1,BUFSIZE,DES_IN); |
| ex=0; |
| rem=l%8; |
| l-=rem; |
| } |
| if (l < 0) |
| { |
| perror("read error"); |
| Exit=6; |
| goto problems; |
| } |
| |
| if (bflag && !flag3) |
| for (i=0; i<l; i+=8) |
| DES_ecb_encrypt( |
| (DES_cblock *)&(buf[i]), |
| (DES_cblock *)&(obuf[i]), |
| &ks,do_encrypt); |
| else if (flag3 && bflag) |
| for (i=0; i<l; i+=8) |
| DES_ecb2_encrypt( |
| (DES_cblock *)&(buf[i]), |
| (DES_cblock *)&(obuf[i]), |
| &ks,&ks2,do_encrypt); |
| else if (flag3 && !bflag) |
| { |
| DES_3cbc_encrypt( |
| (DES_cblock *)buf,(DES_cblock *)obuf, |
| (long)l,ks,ks2,&iv, |
| &iv2,do_encrypt); |
| } |
| else |
| { |
| DES_cbc_encrypt( |
| buf,obuf, |
| (long)l,&ks,&iv,do_encrypt); |
| if (l >= 8) memcpy(iv,&(buf[l-8]),8); |
| } |
| |
| if (uflag) |
| ll=uufread(&(buf[rem]),1,BUFSIZE,DES_IN); |
| else |
| ll=fread(&(buf[rem]),1,BUFSIZE,DES_IN); |
| ll+=rem; |
| rem=ll%8; |
| ll-=rem; |
| if (feof(DES_IN) && (ll == 0)) |
| { |
| last=obuf[l-1]; |
| |
| if ((last > 7) || (last < 0)) |
| { |
| fputs("The file was not decrypted correctly.\n", |
| stderr); |
| Exit=8; |
| last=0; |
| } |
| l=l-8+last; |
| } |
| i=0; |
| if (cflag) DES_cbc_cksum(obuf, |
| (DES_cblock *)cksum,(long)l/8*8,&ks, |
| (DES_cblock *)cksum); |
| while (i != l) |
| { |
| j=fwrite(obuf,1,(unsigned int)l-i,DES_OUT); |
| if (j == -1) |
| { |
| perror("Write error"); |
| Exit=7; |
| goto problems; |
| } |
| i+=j; |
| } |
| l=ll; |
| if ((l == 0) && feof(DES_IN)) break; |
| } |
| } |
| if (cflag) |
| { |
| l=0; |
| if (cksumname[0] != '\0') |
| { |
| if ((O=fopen(cksumname,"w")) != NULL) |
| { |
| CKSUM_OUT=O; |
| l=1; |
| } |
| } |
| for (i=0; i<8; i++) |
| fprintf(CKSUM_OUT,"%02X",cksum[i]); |
| fprintf(CKSUM_OUT,"\n"); |
| if (l) fclose(CKSUM_OUT); |
| } |
| problems: |
| OPENSSL_cleanse(buf,sizeof(buf)); |
| OPENSSL_cleanse(obuf,sizeof(obuf)); |
| OPENSSL_cleanse(&ks,sizeof(ks)); |
| OPENSSL_cleanse(&ks2,sizeof(ks2)); |
| OPENSSL_cleanse(iv,sizeof(iv)); |
| OPENSSL_cleanse(iv2,sizeof(iv2)); |
| OPENSSL_cleanse(kk,sizeof(kk)); |
| OPENSSL_cleanse(k2,sizeof(k2)); |
| OPENSSL_cleanse(uubuf,sizeof(uubuf)); |
| OPENSSL_cleanse(b,sizeof(b)); |
| OPENSSL_cleanse(bb,sizeof(bb)); |
| OPENSSL_cleanse(cksum,sizeof(cksum)); |
| if (Exit) EXIT(Exit); |
| } |
| |
| /* We ignore this parameter but it should be > ~50 I believe */ |
| int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp) |
| { |
| int i,j,left,rem,ret=num; |
| static int start=1; |
| |
| if (start) |
| { |
| fprintf(fp,"begin 600 %s\n", |
| (uuname[0] == '\0')?"text.d":uuname); |
| start=0; |
| } |
| |
| if (uubufnum) |
| { |
| if (uubufnum+num < 45) |
| { |
| memcpy(&(uubuf[uubufnum]),data,(unsigned int)num); |
| uubufnum+=num; |
| return(num); |
| } |
| else |
| { |
| i=45-uubufnum; |
| memcpy(&(uubuf[uubufnum]),data,(unsigned int)i); |
| j=uuencode((unsigned char *)uubuf,45,b); |
| fwrite(b,1,(unsigned int)j,fp); |
| uubufnum=0; |
| data+=i; |
| num-=i; |
| } |
| } |
| |
| for (i=0; i<(((int)num)-INUUBUFN); i+=INUUBUFN) |
| { |
| j=uuencode(&(data[i]),INUUBUFN,b); |
| fwrite(b,1,(unsigned int)j,fp); |
| } |
| rem=(num-i)%45; |
| left=(num-i-rem); |
| if (left) |
| { |
| j=uuencode(&(data[i]),left,b); |
| fwrite(b,1,(unsigned int)j,fp); |
| i+=left; |
| } |
| if (i != num) |
| { |
| memcpy(uubuf,&(data[i]),(unsigned int)rem); |
| uubufnum=rem; |
| } |
| return(ret); |
| } |
| |
| void uufwriteEnd(FILE *fp) |
| { |
| int j; |
| static const char *end=" \nend\n"; |
| |
| if (uubufnum != 0) |
| { |
| uubuf[uubufnum]='\0'; |
| uubuf[uubufnum+1]='\0'; |
| uubuf[uubufnum+2]='\0'; |
| j=uuencode(uubuf,uubufnum,b); |
| fwrite(b,1,(unsigned int)j,fp); |
| } |
| fwrite(end,1,strlen(end),fp); |
| } |
| |
| /* int size: should always be > ~ 60; I actually ignore this parameter :-) */ |
| int uufread(unsigned char *out, int size, unsigned int num, FILE *fp) |
| { |
| int i,j,tot; |
| static int done=0; |
| static int valid=0; |
| static int start=1; |
| |
| if (start) |
| { |
| for (;;) |
| { |
| b[0]='\0'; |
| fgets((char *)b,300,fp); |
| if (b[0] == '\0') |
| { |
| fprintf(stderr,"no 'begin' found in uuencoded input\n"); |
| return(-1); |
| } |
| if (strncmp((char *)b,"begin ",6) == 0) break; |
| } |
| start=0; |
| } |
| if (done) return(0); |
| tot=0; |
| if (valid) |
| { |
| memcpy(out,bb,(unsigned int)valid); |
| tot=valid; |
| valid=0; |
| } |
| for (;;) |
| { |
| b[0]='\0'; |
| fgets((char *)b,300,fp); |
| if (b[0] == '\0') break; |
| i=strlen((char *)b); |
| if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd')) |
| { |
| done=1; |
| while (!feof(fp)) |
| { |
| fgets((char *)b,300,fp); |
| } |
| break; |
| } |
| i=uudecode(b,i,bb); |
| if (i < 0) break; |
| if ((i+tot+8) > num) |
| { |
| /* num to copy to make it a multiple of 8 */ |
| j=(num/8*8)-tot-8; |
| memcpy(&(out[tot]),bb,(unsigned int)j); |
| tot+=j; |
| memcpy(bb,&(bb[j]),(unsigned int)i-j); |
| valid=i-j; |
| break; |
| } |
| memcpy(&(out[tot]),bb,(unsigned int)i); |
| tot+=i; |
| } |
| return(tot); |
| } |
| |
| #define ccc2l(c,l) (l =((DES_LONG)(*((c)++)))<<16, \ |
| l|=((DES_LONG)(*((c)++)))<< 8, \ |
| l|=((DES_LONG)(*((c)++)))) |
| |
| #define l2ccc(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \ |
| *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ |
| *((c)++)=(unsigned char)(((l) )&0xff)) |
| |
| |
| int uuencode(unsigned char *in, int num, unsigned char *out) |
| { |
| int j,i,n,tot=0; |
| DES_LONG l; |
| register unsigned char *p; |
| p=out; |
| |
| for (j=0; j<num; j+=45) |
| { |
| if (j+45 > num) |
| i=(num-j); |
| else i=45; |
| *(p++)=i+' '; |
| for (n=0; n<i; n+=3) |
| { |
| ccc2l(in,l); |
| *(p++)=((l>>18)&0x3f)+' '; |
| *(p++)=((l>>12)&0x3f)+' '; |
| *(p++)=((l>> 6)&0x3f)+' '; |
| *(p++)=((l )&0x3f)+' '; |
| tot+=4; |
| } |
| *(p++)='\n'; |
| tot+=2; |
| } |
| *p='\0'; |
| l=0; |
| return(tot); |
| } |
| |
| int uudecode(unsigned char *in, int num, unsigned char *out) |
| { |
| int j,i,k; |
| unsigned int n=0,space=0; |
| DES_LONG l; |
| DES_LONG w,x,y,z; |
| unsigned int blank=(unsigned int)'\n'-' '; |
| |
| for (j=0; j<num; ) |
| { |
| n= *(in++)-' '; |
| if (n == blank) |
| { |
| n=0; |
| in--; |
| } |
| if (n > 60) |
| { |
| fprintf(stderr,"uuencoded line length too long\n"); |
| return(-1); |
| } |
| j++; |
| |
| for (i=0; i<n; j+=4,i+=3) |
| { |
| /* the following is for cases where spaces are |
| * removed from lines. |
| */ |
| if (space) |
| { |
| w=x=y=z=0; |
| } |
| else |
| { |
| w= *(in++)-' '; |
| x= *(in++)-' '; |
| y= *(in++)-' '; |
| z= *(in++)-' '; |
| } |
| if ((w > 63) || (x > 63) || (y > 63) || (z > 63)) |
| { |
| k=0; |
| if (w == blank) k=1; |
| if (x == blank) k=2; |
| if (y == blank) k=3; |
| if (z == blank) k=4; |
| space=1; |
| switch (k) { |
| case 1: w=0; in--; |
| case 2: x=0; in--; |
| case 3: y=0; in--; |
| case 4: z=0; in--; |
| break; |
| case 0: |
| space=0; |
| fprintf(stderr,"bad uuencoded data values\n"); |
| w=x=y=z=0; |
| return(-1); |
| break; |
| } |
| } |
| l=(w<<18)|(x<<12)|(y<< 6)|(z ); |
| l2ccc(l,out); |
| } |
| if (*(in++) != '\n') |
| { |
| fprintf(stderr,"missing nl in uuencoded line\n"); |
| w=x=y=z=0; |
| return(-1); |
| } |
| j++; |
| } |
| *out='\0'; |
| w=x=y=z=0; |
| return(n); |
| } |