cbc.c

     1	/* cbc.c: This file contains the encryption routines for the ed line editor */
     2	/*-
     3	 * Copyright (c) 1993 The Regents of the University of California.
     4	 * All rights reserved.
     5	 *
     6	 * Copyright (c) 1993 Andrew Moore, Talke Studio.
     7	 * All rights reserved.
     8	 *
     9	 * Redistribution and use in source and binary forms, with or without
    10	 * modification, are permitted provided that the following conditions
    11	 * are met:
    12	 * 1. Redistributions of source code must retain the above copyright
    13	 *    notice, this list of conditions and the following disclaimer.
    14	 * 2. Redistributions in binary form must reproduce the above copyright
    15	 *    notice, this list of conditions and the following disclaimer in the
    16	 *    documentation and/or other materials provided with the distribution.
    17	 * 4. Neither the name of the University nor the names of its contributors
    18	 *    may be used to endorse or promote products derived from this software
    19	 *    without specific prior written permission.
    20	 *
    21	 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    22	 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    23	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    24	 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    25	 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    26	 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    27	 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    28	 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    29	 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    30	 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    31	 * SUCH DAMAGE.
    32	 */
    33	
    34	#include <sys/cdefs.h>
    35	__FBSDID("$FreeBSD: src/bin/ed/cbc.c,v 1.20 2004/04/06 20:06:47 markm Exp $");
    36	
    37	#include <sys/types.h>
    38	#include <errno.h>
    39	#include <pwd.h>
    40	#ifdef DES
    41	#include <time.h>
    42	#include <openssl/des.h>
    43	#define ED_DES_INCLUDES
    44	#endif
    45	
    46	#include "ed.h"
    47	
    48	
    49	/*
    50	 * BSD and System V systems offer special library calls that do
    51	 * block move_liness and fills, so if possible we take advantage of them
    52	 */
    53	#define	MEMCPY(dest,src,len)	memcpy((dest),(src),(len))
    54	#define	MEMZERO(dest,len)	memset((dest), 0, (len))
    55	
    56	/* Hide the calls to the primitive encryption routines. */
    57	#define	DES_XFORM(buf)							\
    58			DES_ecb_encrypt(buf, buf, &schedule, 			\
    59			    inverse ? DES_DECRYPT : DES_ENCRYPT);
    60	
    61	/*
    62	 * read/write - no error checking
    63	 */
    64	#define	READ(buf, n, fp)	fread(buf, sizeof(char), n, fp)
    65	#define WRITE(buf, n, fp)	fwrite(buf, sizeof(char), n, fp)
    66	
    67	/*
    68	 * global variables and related macros
    69	 */
    70	
    71	enum { 					/* encrypt, decrypt, authenticate */
    72		MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
    73	} mode = MODE_ENCRYPT;
    74	
    75	#ifdef DES
    76	DES_cblock ivec;			/* initialization vector */
    77	DES_cblock pvec;			/* padding vector */
    78	#endif
    79	
    80	char bits[] = {				/* used to extract bits from a char */
    81		'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
    82	};
    83	
    84	int pflag;				/* 1 to preserve parity bits */
    85	
    86	#ifdef DES
    87	DES_key_schedule schedule;		/* expanded DES key */
    88	#endif
    89	
    90	unsigned char des_buf[8];	/* shared buffer for get_des_char/put_des_char */
    91	int des_ct = 0;			/* count for get_des_char/put_des_char */
    92	int des_n = 0;			/* index for put_des_char/get_des_char */
    93	
    94	/* init_des_cipher: initialize DES */
    95	void
    96	init_des_cipher(void)
    97	{
    98	#ifdef DES
    99		int i;
   100	
   101		des_ct = des_n = 0;
   102	
   103		/* initialize the initialization vector */
   104		MEMZERO(ivec, 8);
   105	
   106		/* initialize the padding vector */
   107		for (i = 0; i < 8; i++)
   108			pvec[i] = (char) (arc4random() % 256);
   109	#endif
   110	}
   111	
   112	
   113	/* get_des_char: return next char in an encrypted file */
   114	int
   115	get_des_char(FILE *fp)
   116	{
   117	#ifdef DES
   118		if (des_n >= des_ct) {
   119			des_n = 0;
   120			des_ct = cbc_decode(des_buf, fp);
   121		}
   122		return (des_ct > 0) ? des_buf[des_n++] : EOF;
   123	#else
   124		return (getc(fp));
   125	#endif
   126	}
   127	
   128	
   129	/* put_des_char: write a char to an encrypted file; return char written */
   130	int
   131	put_des_char(int c, FILE *fp)
   132	{
   133	#ifdef DES
   134		if (des_n == sizeof des_buf) {
   135			des_ct = cbc_encode(des_buf, des_n, fp);
   136			des_n = 0;
   137		}
   138		return (des_ct >= 0) ? (des_buf[des_n++] = c) : EOF;
   139	#else
   140		return (fputc(c, fp));
   141	#endif
   142	}
   143	
   144	
   145	/* flush_des_file: flush an encrypted file's output; return status */
   146	int
   147	flush_des_file(FILE *fp)
   148	{
   149	#ifdef DES
   150		if (des_n == sizeof des_buf) {
   151			des_ct = cbc_encode(des_buf, des_n, fp);
   152			des_n = 0;
   153		}
   154		return (des_ct >= 0 && cbc_encode(des_buf, des_n, fp) >= 0) ? 0 : EOF;
   155	#else
   156		return (fflush(fp));
   157	#endif
   158	}
   159	
   160	#ifdef DES
   161	/*
   162	 * get keyword from tty or stdin
   163	 */
   164	int
   165	get_keyword(void)
   166	{
   167		char *p;			/* used to obtain the key */
   168		DES_cblock msgbuf;		/* I/O buffer */
   169	
   170		/*
   171		 * get the key
   172		 */
   173		if (*(p = getpass("Enter key: "))) {
   174	
   175			/*
   176			 * copy it, nul-padded, into the key area
   177			 */
   178			expand_des_key(msgbuf, p);
   179			MEMZERO(p, _PASSWORD_LEN);
   180			set_des_key(&msgbuf);
   181			MEMZERO(msgbuf, sizeof msgbuf);
   182			return 1;
   183		}
   184		return 0;
   185	}
   186	
   187	
   188	/*
   189	 * print a warning message and, possibly, terminate
   190	 */
   191	void
   192	des_error(const char *s)
   193	{
   194		errmsg = s ? s : strerror(errno);
   195	}
   196	
   197	/*
   198	 * map a hex character to an integer
   199	 */
   200	int
   201	hex_to_binary(int c, int radix)
   202	{
   203		switch(c) {
   204		case '0':		return(0x0);
   205		case '1':		return(0x1);
   206		case '2':		return(radix > 2 ? 0x2 : -1);
   207		case '3':		return(radix > 3 ? 0x3 : -1);
   208		case '4':		return(radix > 4 ? 0x4 : -1);
   209		case '5':		return(radix > 5 ? 0x5 : -1);
   210		case '6':		return(radix > 6 ? 0x6 : -1);
   211		case '7':		return(radix > 7 ? 0x7 : -1);
   212		case '8':		return(radix > 8 ? 0x8 : -1);
   213		case '9':		return(radix > 9 ? 0x9 : -1);
   214		case 'A': case 'a':	return(radix > 10 ? 0xa : -1);
   215		case 'B': case 'b':	return(radix > 11 ? 0xb : -1);
   216		case 'C': case 'c':	return(radix > 12 ? 0xc : -1);
   217		case 'D': case 'd':	return(radix > 13 ? 0xd : -1);
   218		case 'E': case 'e':	return(radix > 14 ? 0xe : -1);
   219		case 'F': case 'f':	return(radix > 15 ? 0xf : -1);
   220		}
   221		/*
   222		 * invalid character
   223		 */
   224		return(-1);
   225	}
   226	
   227	/*
   228	 * convert the key to a bit pattern
   229	 *	obuf		bit pattern
   230	 *	kbuf		the key itself
   231	 */
   232	void
   233	expand_des_key(char *obuf, char *kbuf)
   234	{
   235		int i, j;			/* counter in a for loop */
   236		int nbuf[64];			/* used for hex/key translation */
   237	
   238		/*
   239		 * leading '0x' or '0X' == hex key
   240		 */
   241		if (kbuf[0] == '0' && (kbuf[1] == 'x' || kbuf[1] == 'X')) {
   242			kbuf = &kbuf[2];
   243			/*
   244			 * now translate it, bombing on any illegal hex digit
   245			 */
   246			for (i = 0; kbuf[i] && i < 16; i++)
   247				if ((nbuf[i] = hex_to_binary((int) kbuf[i], 16)) == -1)
   248					des_error("bad hex digit in key");
   249			while (i < 16)
   250				nbuf[i++] = 0;
   251			for (i = 0; i < 8; i++)
   252				obuf[i] =
   253				    ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
   254			/* preserve parity bits */
   255			pflag = 1;
   256			return;
   257		}
   258		/*
   259		 * leading '0b' or '0B' == binary key
   260		 */
   261		if (kbuf[0] == '0' && (kbuf[1] == 'b' || kbuf[1] == 'B')) {
   262			kbuf = &kbuf[2];
   263			/*
   264			 * now translate it, bombing on any illegal binary digit
   265			 */
   266			for (i = 0; kbuf[i] && i < 16; i++)
   267				if ((nbuf[i] = hex_to_binary((int) kbuf[i], 2)) == -1)
   268					des_error("bad binary digit in key");
   269			while (i < 64)
   270				nbuf[i++] = 0;
   271			for (i = 0; i < 8; i++)
   272				for (j = 0; j < 8; j++)
   273					obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
   274			/* preserve parity bits */
   275			pflag = 1;
   276			return;
   277		}
   278		/*
   279		 * no special leader -- ASCII
   280		 */
   281		(void)strncpy(obuf, kbuf, 8);
   282	}
   283	
   284	/*****************
   285	 * DES FUNCTIONS *
   286	 *****************/
   287	/*
   288	 * This sets the DES key and (if you're using the deszip version)
   289	 * the direction of the transformation.  This uses the Sun
   290	 * to map the 64-bit key onto the 56 bits that the key schedule
   291	 * generation routines use: the old way, which just uses the user-
   292	 * supplied 64 bits as is, and the new way, which resets the parity
   293	 * bit to be the same as the low-order bit in each character.  The
   294	 * new way generates a greater variety of key schedules, since many
   295	 * systems set the parity (high) bit of each character to 0, and the
   296	 * DES ignores the low order bit of each character.
   297	 */
   298	void
   299	set_des_key(DES_cblock *buf)			/* key block */
   300	{
   301		int i, j;				/* counter in a for loop */
   302		int par;				/* parity counter */
   303	
   304		/*
   305		 * if the parity is not preserved, flip it
   306		 */
   307		if (!pflag) {
   308			for (i = 0; i < 8; i++) {
   309				par = 0;
   310				for (j = 1; j < 8; j++)
   311					if ((bits[j] & (*buf)[i]) != 0)
   312						par++;
   313				if ((par & 0x01) == 0x01)
   314					(*buf)[i] &= 0x7f;
   315				else
   316					(*buf)[i] = ((*buf)[i] & 0x7f) | 0x80;
   317			}
   318		}
   319	
   320		DES_set_odd_parity(buf);
   321		DES_set_key(buf, &schedule);
   322	}
   323	
   324	
   325	/*
   326	 * This encrypts using the Cipher Block Chaining mode of DES
   327	 */
   328	int
   329	cbc_encode(unsigned char *msgbuf, int n, FILE *fp)
   330	{
   331		int inverse = 0;	/* 0 to encrypt, 1 to decrypt */
   332	
   333		/*
   334		 * do the transformation
   335		 */
   336		if (n == 8) {
   337			for (n = 0; n < 8; n++)
   338				msgbuf[n] ^= ivec[n];
   339			DES_XFORM((DES_cblock *)msgbuf);
   340			MEMCPY(ivec, msgbuf, 8);
   341			return WRITE(msgbuf, 8, fp);
   342		}
   343		/*
   344		 * at EOF or last block -- in either case, the last byte contains
   345		 * the character representation of the number of bytes in it
   346		 */
   347	/*
   348		MEMZERO(msgbuf +  n, 8 - n);
   349	*/
   350		/*
   351		 *  Pad the last block randomly
   352		 */
   353		(void)MEMCPY(msgbuf + n, pvec, 8 - n);
   354		msgbuf[7] = n;
   355		for (n = 0; n < 8; n++)
   356			msgbuf[n] ^= ivec[n];
   357		DES_XFORM((DES_cblock *)msgbuf);
   358		return WRITE(msgbuf, 8, fp);
   359	}
   360	
   361	/*
   362	 * This decrypts using the Cipher Block Chaining mode of DES
   363	 *	msgbuf	I/O buffer
   364	 *	fp	input file descriptor
   365	 */
   366	int
   367	cbc_decode(unsigned char *msgbuf, FILE *fp)
   368	{
   369		DES_cblock tbuf;	/* temp buffer for initialization vector */
   370		int n;			/* number of bytes actually read */
   371		int c;			/* used to test for EOF */
   372		int inverse = 1;	/* 0 to encrypt, 1 to decrypt */
   373	
   374		if ((n = READ(msgbuf, 8, fp)) == 8) {
   375			/*
   376			 * do the transformation
   377			 */
   378			MEMCPY(tbuf, msgbuf, 8);
   379			DES_XFORM((DES_cblock *)msgbuf);
   380			for (c = 0; c < 8; c++)
   381				msgbuf[c] ^= ivec[c];
   382			MEMCPY(ivec, tbuf, 8);
   383			/*
   384			 * if the last one, handle it specially
   385			 */
   386			if ((c = fgetc(fp)) == EOF) {
   387				n = msgbuf[7];
   388				if (n < 0 || n > 7) {
   389					des_error("decryption failed (block corrupted)");
   390					return EOF;
   391				}
   392			} else
   393				(void)ungetc(c, fp);
   394			return n;
   395		}
   396		if (n > 0)
   397			des_error("decryption failed (incomplete block)");
   398		else if (n < 0)
   399			des_error("cannot read file");
   400		return EOF;
   401	}
   402	#endif	/* DES */

Generated by GNU Enscript 1.6.6.