116Salm/* cbc.c: This file contains the encryption routines for the ed line editor */ 216Salm/*- 31057Salm * Copyright (c) 1993 The Regents of the University of California. 416Salm * All rights reserved. 516Salm * 61057Salm * Copyright (c) 1993 Andrew Moore, Talke Studio. 71057Salm * All rights reserved. 816Salm * 916Salm * Redistribution and use in source and binary forms, with or without 1016Salm * modification, are permitted provided that the following conditions 1116Salm * are met: 1216Salm * 1. Redistributions of source code must retain the above copyright 1316Salm * notice, this list of conditions and the following disclaimer. 1416Salm * 2. Redistributions in binary form must reproduce the above copyright 1516Salm * notice, this list of conditions and the following disclaimer in the 1616Salm * documentation and/or other materials provided with the distribution. 1716Salm * 4. Neither the name of the University nor the names of its contributors 1816Salm * may be used to endorse or promote products derived from this software 1916Salm * without specific prior written permission. 2016Salm * 2116Salm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2216Salm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2316Salm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2416Salm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2516Salm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2616Salm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2716Salm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2816Salm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2916Salm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3016Salm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3116Salm * SUCH DAMAGE. 3216Salm */ 3316Salm 3499109Sobrien#include <sys/cdefs.h> 3599109Sobrien__FBSDID("$FreeBSD$"); 3616Salm 371057Salm#include <sys/types.h> 3816Salm#include <errno.h> 3916Salm#include <pwd.h> 4027963Ssteve#ifdef DES 4127963Ssteve#include <time.h> 42115717Smarkm#include <openssl/des.h> 43115717Smarkm#define ED_DES_INCLUDES 4427963Ssteve#endif 4516Salm 4616Salm#include "ed.h" 4716Salm 481057Salm 4916Salm/* 5016Salm * BSD and System V systems offer special library calls that do 511057Salm * block move_liness and fills, so if possible we take advantage of them 5216Salm */ 5316Salm#define MEMCPY(dest,src,len) memcpy((dest),(src),(len)) 5416Salm#define MEMZERO(dest,len) memset((dest), 0, (len)) 5516Salm 5616Salm/* Hide the calls to the primitive encryption routines. */ 57101093Smarkm#define DES_XFORM(buf) \ 58115717Smarkm DES_ecb_encrypt(buf, buf, &schedule, \ 59115717Smarkm inverse ? DES_DECRYPT : DES_ENCRYPT); 6016Salm 6116Salm/* 6216Salm * read/write - no error checking 6316Salm */ 6416Salm#define READ(buf, n, fp) fread(buf, sizeof(char), n, fp) 6516Salm#define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp) 6616Salm 6716Salm/* 6816Salm * global variables and related macros 6916Salm */ 7016Salm 7116Salmenum { /* encrypt, decrypt, authenticate */ 7216Salm MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE 7316Salm} mode = MODE_ENCRYPT; 7416Salm 75115777Sjhay#ifdef DES 76115717SmarkmDES_cblock ivec; /* initialization vector */ 77115717SmarkmDES_cblock pvec; /* padding vector */ 78115777Sjhay#endif 79115717Smarkm 8016Salmchar bits[] = { /* used to extract bits from a char */ 8116Salm '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' 8216Salm}; 83115717Smarkm 8416Salmint pflag; /* 1 to preserve parity bits */ 8516Salm 86115777Sjhay#ifdef DES 87115717SmarkmDES_key_schedule schedule; /* expanded DES key */ 88115777Sjhay#endif 89115717Smarkm 901057Salmunsigned char des_buf[8]; /* shared buffer for get_des_char/put_des_char */ 911057Salmint des_ct = 0; /* count for get_des_char/put_des_char */ 921057Salmint des_n = 0; /* index for put_des_char/get_des_char */ 9316Salm 941057Salm/* init_des_cipher: initialize DES */ 9516Salmvoid 9690109Simpinit_des_cipher(void) 9716Salm{ 9816Salm#ifdef DES 9916Salm int i; 10016Salm 10116Salm des_ct = des_n = 0; 10216Salm 1037165Sjoerg /* initialize the initialization vector */ 10416Salm MEMZERO(ivec, 8); 10516Salm 10646684Skris /* initialize the padding vector */ 10716Salm for (i = 0; i < 8; i++) 108115717Smarkm pvec[i] = (char) (arc4random() % 256); 10916Salm#endif 11016Salm} 11116Salm 11216Salm 1131057Salm/* get_des_char: return next char in an encrypted file */ 1141057Salmint 11590109Simpget_des_char(FILE *fp) 11616Salm{ 11716Salm#ifdef DES 11816Salm if (des_n >= des_ct) { 11916Salm des_n = 0; 1201057Salm des_ct = cbc_decode(des_buf, fp); 12116Salm } 12216Salm return (des_ct > 0) ? des_buf[des_n++] : EOF; 1237165Sjoerg#else 1247165Sjoerg return (getc(fp)); 12516Salm#endif 12616Salm} 12716Salm 12816Salm 1291057Salm/* put_des_char: write a char to an encrypted file; return char written */ 1301057Salmint 13190109Simpput_des_char(int c, FILE *fp) 13216Salm{ 13316Salm#ifdef DES 13416Salm if (des_n == sizeof des_buf) { 1351057Salm des_ct = cbc_encode(des_buf, des_n, fp); 13616Salm des_n = 0; 13716Salm } 13816Salm return (des_ct >= 0) ? (des_buf[des_n++] = c) : EOF; 1397165Sjoerg#else 1407165Sjoerg return (fputc(c, fp)); 14116Salm#endif 14216Salm} 14316Salm 14416Salm 1451057Salm/* flush_des_file: flush an encrypted file's output; return status */ 1461057Salmint 14790109Simpflush_des_file(FILE *fp) 14816Salm{ 14916Salm#ifdef DES 15016Salm if (des_n == sizeof des_buf) { 1511057Salm des_ct = cbc_encode(des_buf, des_n, fp); 15216Salm des_n = 0; 15316Salm } 1541057Salm return (des_ct >= 0 && cbc_encode(des_buf, des_n, fp) >= 0) ? 0 : EOF; 1557165Sjoerg#else 1567165Sjoerg return (fflush(fp)); 15716Salm#endif 15816Salm} 15916Salm 16016Salm#ifdef DES 16116Salm/* 16216Salm * get keyword from tty or stdin 16316Salm */ 1641057Salmint 16590109Simpget_keyword(void) 16616Salm{ 16781220Smike char *p; /* used to obtain the key */ 168115717Smarkm DES_cblock msgbuf; /* I/O buffer */ 16916Salm 17016Salm /* 17116Salm * get the key 17216Salm */ 17316Salm if (*(p = getpass("Enter key: "))) { 17416Salm 17516Salm /* 17616Salm * copy it, nul-padded, into the key area 17716Salm */ 178115717Smarkm expand_des_key(msgbuf, p); 17916Salm MEMZERO(p, _PASSWORD_LEN); 180115717Smarkm set_des_key(&msgbuf); 18116Salm MEMZERO(msgbuf, sizeof msgbuf); 18216Salm return 1; 18316Salm } 18416Salm return 0; 18516Salm} 18616Salm 18716Salm 18816Salm/* 18916Salm * print a warning message and, possibly, terminate 19016Salm */ 19116Salmvoid 19290109Simpdes_error(const char *s) 19316Salm{ 19481220Smike errmsg = s ? s : strerror(errno); 19516Salm} 19616Salm 19716Salm/* 19816Salm * map a hex character to an integer 19916Salm */ 2001057Salmint 20190109Simphex_to_binary(int c, int radix) 20216Salm{ 20316Salm switch(c) { 20416Salm case '0': return(0x0); 20516Salm case '1': return(0x1); 20616Salm case '2': return(radix > 2 ? 0x2 : -1); 20716Salm case '3': return(radix > 3 ? 0x3 : -1); 20816Salm case '4': return(radix > 4 ? 0x4 : -1); 20916Salm case '5': return(radix > 5 ? 0x5 : -1); 21016Salm case '6': return(radix > 6 ? 0x6 : -1); 21116Salm case '7': return(radix > 7 ? 0x7 : -1); 21216Salm case '8': return(radix > 8 ? 0x8 : -1); 21316Salm case '9': return(radix > 9 ? 0x9 : -1); 21416Salm case 'A': case 'a': return(radix > 10 ? 0xa : -1); 21516Salm case 'B': case 'b': return(radix > 11 ? 0xb : -1); 21616Salm case 'C': case 'c': return(radix > 12 ? 0xc : -1); 21716Salm case 'D': case 'd': return(radix > 13 ? 0xd : -1); 21816Salm case 'E': case 'e': return(radix > 14 ? 0xe : -1); 21916Salm case 'F': case 'f': return(radix > 15 ? 0xf : -1); 22016Salm } 22116Salm /* 22216Salm * invalid character 22316Salm */ 22416Salm return(-1); 22516Salm} 22616Salm 22716Salm/* 22816Salm * convert the key to a bit pattern 22990109Simp * obuf bit pattern 23090109Simp * kbuf the key itself 23116Salm */ 23216Salmvoid 23390109Simpexpand_des_key(char *obuf, char *kbuf) 23416Salm{ 23581220Smike int i, j; /* counter in a for loop */ 23616Salm int nbuf[64]; /* used for hex/key translation */ 23716Salm 23816Salm /* 23916Salm * leading '0x' or '0X' == hex key 24016Salm */ 24181220Smike if (kbuf[0] == '0' && (kbuf[1] == 'x' || kbuf[1] == 'X')) { 24281220Smike kbuf = &kbuf[2]; 24316Salm /* 24416Salm * now translate it, bombing on any illegal hex digit 24516Salm */ 24681220Smike for (i = 0; kbuf[i] && i < 16; i++) 24781220Smike if ((nbuf[i] = hex_to_binary((int) kbuf[i], 16)) == -1) 2481057Salm des_error("bad hex digit in key"); 24916Salm while (i < 16) 25016Salm nbuf[i++] = 0; 25116Salm for (i = 0; i < 8; i++) 25216Salm obuf[i] = 25316Salm ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf); 25416Salm /* preserve parity bits */ 25516Salm pflag = 1; 25616Salm return; 25716Salm } 25816Salm /* 25916Salm * leading '0b' or '0B' == binary key 26016Salm */ 26181220Smike if (kbuf[0] == '0' && (kbuf[1] == 'b' || kbuf[1] == 'B')) { 26281220Smike kbuf = &kbuf[2]; 26316Salm /* 26416Salm * now translate it, bombing on any illegal binary digit 26516Salm */ 26681220Smike for (i = 0; kbuf[i] && i < 16; i++) 26781220Smike if ((nbuf[i] = hex_to_binary((int) kbuf[i], 2)) == -1) 2681057Salm des_error("bad binary digit in key"); 26916Salm while (i < 64) 27016Salm nbuf[i++] = 0; 27116Salm for (i = 0; i < 8; i++) 27216Salm for (j = 0; j < 8; j++) 27316Salm obuf[i] = (obuf[i]<<1)|nbuf[8*i+j]; 27416Salm /* preserve parity bits */ 27516Salm pflag = 1; 27616Salm return; 27716Salm } 27816Salm /* 27916Salm * no special leader -- ASCII 28016Salm */ 28181220Smike (void)strncpy(obuf, kbuf, 8); 28216Salm} 28316Salm 28416Salm/***************** 28516Salm * DES FUNCTIONS * 28616Salm *****************/ 28716Salm/* 28816Salm * This sets the DES key and (if you're using the deszip version) 28916Salm * the direction of the transformation. This uses the Sun 29016Salm * to map the 64-bit key onto the 56 bits that the key schedule 29116Salm * generation routines use: the old way, which just uses the user- 29216Salm * supplied 64 bits as is, and the new way, which resets the parity 29316Salm * bit to be the same as the low-order bit in each character. The 29416Salm * new way generates a greater variety of key schedules, since many 29516Salm * systems set the parity (high) bit of each character to 0, and the 29616Salm * DES ignores the low order bit of each character. 29716Salm */ 29816Salmvoid 299115717Smarkmset_des_key(DES_cblock *buf) /* key block */ 30016Salm{ 30181220Smike int i, j; /* counter in a for loop */ 30281220Smike int par; /* parity counter */ 30316Salm 30416Salm /* 30516Salm * if the parity is not preserved, flip it 30616Salm */ 30716Salm if (!pflag) { 30816Salm for (i = 0; i < 8; i++) { 30916Salm par = 0; 31016Salm for (j = 1; j < 8; j++) 311115717Smarkm if ((bits[j] & (*buf)[i]) != 0) 31216Salm par++; 313115717Smarkm if ((par & 0x01) == 0x01) 314115717Smarkm (*buf)[i] &= 0x7f; 31516Salm else 316115717Smarkm (*buf)[i] = ((*buf)[i] & 0x7f) | 0x80; 31716Salm } 31816Salm } 31916Salm 320115717Smarkm DES_set_odd_parity(buf); 321115717Smarkm DES_set_key(buf, &schedule); 32216Salm} 32316Salm 32416Salm 32516Salm/* 32616Salm * This encrypts using the Cipher Block Chaining mode of DES 32716Salm */ 3281057Salmint 329101093Smarkmcbc_encode(unsigned char *msgbuf, int n, FILE *fp) 33016Salm{ 33116Salm int inverse = 0; /* 0 to encrypt, 1 to decrypt */ 33216Salm 33316Salm /* 33416Salm * do the transformation 33516Salm */ 33616Salm if (n == 8) { 33716Salm for (n = 0; n < 8; n++) 338115717Smarkm msgbuf[n] ^= ivec[n]; 339115717Smarkm DES_XFORM((DES_cblock *)msgbuf); 340115717Smarkm MEMCPY(ivec, msgbuf, 8); 341115717Smarkm return WRITE(msgbuf, 8, fp); 34216Salm } 34316Salm /* 34416Salm * at EOF or last block -- in either case, the last byte contains 34516Salm * the character representation of the number of bytes in it 34616Salm */ 34716Salm/* 34816Salm MEMZERO(msgbuf + n, 8 - n); 34916Salm*/ 35016Salm /* 35116Salm * Pad the last block randomly 35216Salm */ 353115717Smarkm (void)MEMCPY(msgbuf + n, pvec, 8 - n); 354115717Smarkm msgbuf[7] = n; 35516Salm for (n = 0; n < 8; n++) 356115717Smarkm msgbuf[n] ^= ivec[n]; 357115717Smarkm DES_XFORM((DES_cblock *)msgbuf); 358115717Smarkm return WRITE(msgbuf, 8, fp); 35916Salm} 36016Salm 36116Salm/* 36216Salm * This decrypts using the Cipher Block Chaining mode of DES 36390109Simp * msgbuf I/O buffer 36490109Simp * fp input file descriptor 36516Salm */ 3661057Salmint 367101093Smarkmcbc_decode(unsigned char *msgbuf, FILE *fp) 36816Salm{ 369115717Smarkm DES_cblock tbuf; /* temp buffer for initialization vector */ 37081220Smike int n; /* number of bytes actually read */ 37181220Smike int c; /* used to test for EOF */ 37216Salm int inverse = 1; /* 0 to encrypt, 1 to decrypt */ 37316Salm 374115717Smarkm if ((n = READ(msgbuf, 8, fp)) == 8) { 37516Salm /* 37616Salm * do the transformation 37716Salm */ 378115717Smarkm MEMCPY(tbuf, msgbuf, 8); 379115717Smarkm DES_XFORM((DES_cblock *)msgbuf); 38016Salm for (c = 0; c < 8; c++) 381115717Smarkm msgbuf[c] ^= ivec[c]; 382115717Smarkm MEMCPY(ivec, tbuf, 8); 38316Salm /* 38416Salm * if the last one, handle it specially 38516Salm */ 38616Salm if ((c = fgetc(fp)) == EOF) { 387115717Smarkm n = msgbuf[7]; 38816Salm if (n < 0 || n > 7) { 3891057Salm des_error("decryption failed (block corrupted)"); 39016Salm return EOF; 39116Salm } 39216Salm } else 39316Salm (void)ungetc(c, fp); 39416Salm return n; 39516Salm } 39616Salm if (n > 0) 3971057Salm des_error("decryption failed (incomplete block)"); 39816Salm else if (n < 0) 3991057Salm des_error("cannot read file"); 40016Salm return EOF; 40116Salm} 40216Salm#endif /* DES */ 403