11899Swollman/*- 21899Swollman * Copyright (c) 1991, 1993 31899Swollman * The Regents of the University of California. All rights reserved. 41899Swollman * 51899Swollman * This code is derived from software contributed to Berkeley by 61899Swollman * Matt Bishop of Dartmouth College. 71899Swollman * 81899Swollman * The United States Government has rights in this work pursuant 91899Swollman * to contract no. NAG 2-680 between the National Aeronautics and 101899Swollman * Space Administration and Dartmouth College. 111899Swollman * 121899Swollman * Redistribution and use in source and binary forms, with or without 131899Swollman * modification, are permitted provided that the following conditions 141899Swollman * are met: 151899Swollman * 1. Redistributions of source code must retain the above copyright 161899Swollman * notice, this list of conditions and the following disclaimer. 171899Swollman * 2. Redistributions in binary form must reproduce the above copyright 181899Swollman * notice, this list of conditions and the following disclaimer in the 191899Swollman * documentation and/or other materials provided with the distribution. 201899Swollman * 3. All advertising materials mentioning features or use of this software 211899Swollman * must display the following acknowledgement: 221899Swollman * This product includes software developed by the University of 231899Swollman * California, Berkeley and its contributors. 241899Swollman * 4. Neither the name of the University nor the names of its contributors 251899Swollman * may be used to endorse or promote products derived from this software 261899Swollman * without specific prior written permission. 271899Swollman * 281899Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 291899Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 301899Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 311899Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 321899Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 331899Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 341899Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351899Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 361899Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 371899Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 381899Swollman * SUCH DAMAGE. 391899Swollman */ 401899Swollman 411899Swollman#ifndef lint 42115718Smarkmstatic const char copyright[] = 431899Swollman"@(#) Copyright (c) 1991, 1993\n\ 441899Swollman The Regents of the University of California. All rights reserved.\n"; 451899Swollman#endif /* not lint */ 461899Swollman 471899Swollman#ifndef lint 4863248Speter#if 0 491899Swollmanstatic char sccsid[] = "@(#)bdes.c 8.1 (Berkeley) 6/6/93"; 5063248Speter#endif 511899Swollman#endif /* not lint */ 521899Swollman 531899Swollman/* 541899Swollman * BDES -- DES encryption package for Berkeley Software Distribution 4.4 551899Swollman * options: 561899Swollman * -a key is in ASCII 571899Swollman * -b use ECB (electronic code book) mode 581899Swollman * -d invert (decrypt) input 591899Swollman * -f b use b-bit CFB (cipher feedback) mode 601899Swollman * -F b use b-bit CFB (cipher feedback) alternative mode 611899Swollman * -k key use key as the cryptographic key 621899Swollman * -m b generate a MAC of length b 631899Swollman * -o b use b-bit OFB (output feedback) mode 641899Swollman * -p don't reset the parity bit 651899Swollman * -v v use v as the initialization vector (ignored for ECB) 661899Swollman * note: the last character of the last block is the integer indicating 671899Swollman * how many characters of that block are to be output 681899Swollman * 691899Swollman * Author: Matt Bishop 701899Swollman * Department of Mathematics and Computer Science 711899Swollman * Dartmouth College 721899Swollman * Hanover, NH 03755 731899Swollman * Email: Matt.Bishop@dartmouth.edu 741899Swollman * ...!decvax!dartvax!Matt.Bishop 751899Swollman * 761899Swollman * See Technical Report PCS-TR91-158, Department of Mathematics and Computer 771899Swollman * Science, Dartmouth College, for a detailed description of the implemen- 781899Swollman * tation and differences between it and Sun's. The DES is described in 791899Swollman * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page 801899Swollman * or the technical report for a complete reference). 811899Swollman */ 821899Swollman 83115718Smarkm#include <sys/cdefs.h> 84115718Smarkm__FBSDID("$FreeBSD: releng/10.3/secure/usr.bin/bdes/bdes.c 198856 2009-11-03 18:40:42Z jhb $"); 85115718Smarkm 86115718Smarkm#include <sys/types.h> 87115718Smarkm 88115718Smarkm#include <ctype.h> 89115718Smarkm#include <err.h> 901899Swollman#include <errno.h> 911899Swollman#include <stdio.h> 921899Swollman#include <stdlib.h> 931899Swollman#include <string.h> 94115718Smarkm#include <unistd.h> 951899Swollman 96115718Smarkm#include <openssl/des.h> 97115718Smarkm 981899Swollman/* 991899Swollman * BSD and System V systems offer special library calls that do 1001899Swollman * block moves and fills, so if possible we take advantage of them 1011899Swollman */ 1021899Swollman#define MEMCPY(dest,src,len) bcopy((src),(dest),(len)) 1031899Swollman#define MEMZERO(dest,len) bzero((dest),(len)) 1041899Swollman 105115718Smarkm#define DES_XFORM(buf) \ 106115718Smarkm DES_ecb_encrypt(buf, buf, &schedule, \ 107115718Smarkm mode == MODE_ENCRYPT ? DES_ENCRYPT : DES_DECRYPT); 1081899Swollman 1091899Swollman/* 1101899Swollman * this does an error-checking write 1111899Swollman */ 1121899Swollman#define READ(buf, n) fread(buf, sizeof(char), n, stdin) 1131899Swollman#define WRITE(buf,n) \ 1141899Swollman if (fwrite(buf, sizeof(char), n, stdout) != n) \ 115115718Smarkm warnx("fwrite error at %d", n); 1161899Swollman 1171899Swollman/* 1181899Swollman * global variables and related macros 1191899Swollman */ 1201899Swollman#define KEY_DEFAULT 0 /* interpret radix of key from key */ 1211899Swollman#define KEY_ASCII 1 /* key is in ASCII characters */ 1221899Swollmanint keybase = KEY_DEFAULT; /* how to interpret the key */ 1231899Swollman 1241899Swollmanenum { /* encrypt, decrypt, authenticate */ 1251899Swollman MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE 1261899Swollman} mode = MODE_ENCRYPT; 127115718Smarkm 1281899Swollmanenum { /* ecb, cbc, cfb, cfba, ofb? */ 1291899Swollman ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA 1301899Swollman} alg = ALG_CBC; 1311899Swollman 132115718SmarkmDES_cblock ivec; /* initialization vector */ 133115718Smarkm 1341899Swollmanchar bits[] = { /* used to extract bits from a char */ 1351899Swollman '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' 1361899Swollman}; 137115718Smarkm 1381899Swollmanint inverse; /* 0 to encrypt, 1 to decrypt */ 1391899Swollmanint macbits = -1; /* number of bits in authentication */ 1401899Swollmanint fbbits = -1; /* number of feedback bits */ 1411899Swollmanint pflag; /* 1 to preserve parity bits */ 1421899Swollman 143115718SmarkmDES_key_schedule schedule; /* expanded DES key */ 144115718Smarkm 145115718Smarkmstatic void ecbenc(void); 146115718Smarkmstatic void ecbdec(void); 147115718Smarkmstatic void cbcenc(void); 148115718Smarkmstatic void cbcdec(void); 149115718Smarkmstatic void cfbenc(void); 150115718Smarkmstatic void cfbdec(void); 151115718Smarkmstatic void cfbaenc(void); 152115718Smarkmstatic void cfbadec(void); 153115718Smarkmstatic void ofbenc(void); 154115718Smarkmstatic void ofbdec(void); 155115718Smarkm 156115718Smarkmstatic void cbcauth(void); 157115718Smarkmstatic void cfbauth(void); 158115718Smarkm 159115718Smarkmstatic void cvtkey(DES_cblock, char *); 160115718Smarkmstatic int setbits(char *, int); 161115718Smarkmstatic void makekey(DES_cblock *); 162115718Smarkmstatic int tobinhex(char, int); 163115718Smarkm 164115718Smarkmstatic void usage(void); 165115718Smarkm 166115718Smarkmint 167140394Sddsmain(int argc, char *argv[]) 1681899Swollman{ 1691899Swollman extern char *optarg; /* argument to option if any */ 170115718Smarkm int i; /* counter in a for loop */ 171115718Smarkm char *p; /* used to obtain the key */ 172115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 173198856Sjhb int kflag; /* command-line encryption key */ 1741899Swollman 175140394Sdds setproctitle("-"); /* Hide command-line arguments */ 1761899Swollman 177198856Sjhb /* initialize the initialization vector */ 1781899Swollman MEMZERO(ivec, 8); 1791899Swollman 1801899Swollman /* process the argument list */ 1811899Swollman kflag = 0; 182176407Sru while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1) 1831899Swollman switch(i) { 1841899Swollman case 'a': /* key is ASCII */ 1851899Swollman keybase = KEY_ASCII; 1861899Swollman break; 1871899Swollman case 'b': /* use ECB mode */ 1881899Swollman alg = ALG_ECB; 1891899Swollman break; 1901899Swollman case 'd': /* decrypt */ 1911899Swollman mode = MODE_DECRYPT; 1921899Swollman break; 1931899Swollman case 'F': /* use alternative CFB mode */ 1941899Swollman alg = ALG_CFBA; 1951899Swollman if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0) 196115718Smarkm errx(1, "-F: number must be 1-56 inclusive"); 1971899Swollman else if (fbbits == -1) 198115718Smarkm errx(1, "-F: number must be a multiple of 7"); 1991899Swollman break; 2001899Swollman case 'f': /* use CFB mode */ 2011899Swollman alg = ALG_CFB; 2021899Swollman if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) 203115718Smarkm errx(1, "-f: number must be 1-64 inclusive"); 2041899Swollman else if (fbbits == -1) 205115718Smarkm errx(1, "-f: number must be a multiple of 8"); 2061899Swollman break; 2071899Swollman case 'k': /* encryption key */ 2081899Swollman kflag = 1; 209115718Smarkm cvtkey(msgbuf, optarg); 2101899Swollman break; 2111899Swollman case 'm': /* number of bits for MACing */ 2121899Swollman mode = MODE_AUTHENTICATE; 2131899Swollman if ((macbits = setbits(optarg, 1)) > 64) 214115718Smarkm errx(1, "-m: number must be 0-64 inclusive"); 2151899Swollman break; 2161899Swollman case 'o': /* use OFB mode */ 2171899Swollman alg = ALG_OFB; 2181899Swollman if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) 219115718Smarkm errx(1, "-o: number must be 1-64 inclusive"); 2201899Swollman else if (fbbits == -1) 221115718Smarkm errx(1, "-o: number must be a multiple of 8"); 2221899Swollman break; 2231899Swollman case 'p': /* preserve parity bits */ 2241899Swollman pflag = 1; 2251899Swollman break; 2261899Swollman case 'v': /* set initialization vector */ 227115718Smarkm cvtkey(ivec, optarg); 2281899Swollman break; 2291899Swollman default: /* error */ 2301899Swollman usage(); 2311899Swollman } 2321899Swollman 2331899Swollman if (!kflag) { 2341899Swollman /* 2351899Swollman * if the key's not ASCII, assume it is 2361899Swollman */ 2371899Swollman keybase = KEY_ASCII; 2381899Swollman /* 2391899Swollman * get the key 2401899Swollman */ 2411899Swollman p = getpass("Enter key: "); 2421899Swollman /* 2431899Swollman * copy it, nul-padded, into the key area 2441899Swollman */ 245115718Smarkm cvtkey(msgbuf, p); 2461899Swollman } 2471899Swollman 248115718Smarkm makekey(&msgbuf); 2491899Swollman inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT; 2501899Swollman 2511899Swollman switch(alg) { 2521899Swollman case ALG_CBC: 2531899Swollman switch(mode) { 2541899Swollman case MODE_AUTHENTICATE: /* authenticate using CBC mode */ 2551899Swollman cbcauth(); 2561899Swollman break; 2571899Swollman case MODE_DECRYPT: /* decrypt using CBC mode */ 2581899Swollman cbcdec(); 2591899Swollman break; 2601899Swollman case MODE_ENCRYPT: /* encrypt using CBC mode */ 2611899Swollman cbcenc(); 2621899Swollman break; 2631899Swollman } 2641899Swollman break; 2651899Swollman case ALG_CFB: 2661899Swollman switch(mode) { 2671899Swollman case MODE_AUTHENTICATE: /* authenticate using CFB mode */ 2681899Swollman cfbauth(); 2691899Swollman break; 2701899Swollman case MODE_DECRYPT: /* decrypt using CFB mode */ 2711899Swollman cfbdec(); 2721899Swollman break; 2731899Swollman case MODE_ENCRYPT: /* encrypt using CFB mode */ 2741899Swollman cfbenc(); 2751899Swollman break; 2761899Swollman } 2771899Swollman break; 2781899Swollman case ALG_CFBA: 2791899Swollman switch(mode) { 2801899Swollman case MODE_AUTHENTICATE: /* authenticate using CFBA mode */ 281115718Smarkm errx(1, "can't authenticate with CFBA mode"); 2821899Swollman break; 2831899Swollman case MODE_DECRYPT: /* decrypt using CFBA mode */ 2841899Swollman cfbadec(); 2851899Swollman break; 2861899Swollman case MODE_ENCRYPT: /* encrypt using CFBA mode */ 2871899Swollman cfbaenc(); 2881899Swollman break; 2891899Swollman } 2901899Swollman break; 2911899Swollman case ALG_ECB: 2921899Swollman switch(mode) { 2931899Swollman case MODE_AUTHENTICATE: /* authenticate using ECB mode */ 294115718Smarkm errx(1, "can't authenticate with ECB mode"); 2951899Swollman break; 2961899Swollman case MODE_DECRYPT: /* decrypt using ECB mode */ 2971899Swollman ecbdec(); 2981899Swollman break; 2991899Swollman case MODE_ENCRYPT: /* encrypt using ECB mode */ 3001899Swollman ecbenc(); 3011899Swollman break; 3021899Swollman } 3031899Swollman break; 3041899Swollman case ALG_OFB: 3051899Swollman switch(mode) { 3061899Swollman case MODE_AUTHENTICATE: /* authenticate using OFB mode */ 307115718Smarkm errx(1, "can't authenticate with OFB mode"); 3081899Swollman break; 3091899Swollman case MODE_DECRYPT: /* decrypt using OFB mode */ 3101899Swollman ofbdec(); 3111899Swollman break; 3121899Swollman case MODE_ENCRYPT: /* encrypt using OFB mode */ 3131899Swollman ofbenc(); 3141899Swollman break; 3151899Swollman } 3161899Swollman break; 3171899Swollman } 318115718Smarkm return (0); 3191899Swollman} 3201899Swollman 3211899Swollman/* 3221899Swollman * map a hex character to an integer 3231899Swollman */ 324115718Smarkmstatic int 325115718Smarkmtobinhex(char c, int radix) 3261899Swollman{ 3271899Swollman switch(c) { 3281899Swollman case '0': return(0x0); 3291899Swollman case '1': return(0x1); 3301899Swollman case '2': return(radix > 2 ? 0x2 : -1); 3311899Swollman case '3': return(radix > 3 ? 0x3 : -1); 3321899Swollman case '4': return(radix > 4 ? 0x4 : -1); 3331899Swollman case '5': return(radix > 5 ? 0x5 : -1); 3341899Swollman case '6': return(radix > 6 ? 0x6 : -1); 3351899Swollman case '7': return(radix > 7 ? 0x7 : -1); 3361899Swollman case '8': return(radix > 8 ? 0x8 : -1); 3371899Swollman case '9': return(radix > 9 ? 0x9 : -1); 3381899Swollman case 'A': case 'a': return(radix > 10 ? 0xa : -1); 3391899Swollman case 'B': case 'b': return(radix > 11 ? 0xb : -1); 3401899Swollman case 'C': case 'c': return(radix > 12 ? 0xc : -1); 3411899Swollman case 'D': case 'd': return(radix > 13 ? 0xd : -1); 3421899Swollman case 'E': case 'e': return(radix > 14 ? 0xe : -1); 3431899Swollman case 'F': case 'f': return(radix > 15 ? 0xf : -1); 3441899Swollman } 3451899Swollman /* 3461899Swollman * invalid character 3471899Swollman */ 3481899Swollman return(-1); 3491899Swollman} 3501899Swollman 3511899Swollman/* 3521899Swollman * convert the key to a bit pattern 3531899Swollman */ 354115718Smarkmstatic void 355115718Smarkmcvtkey(DES_cblock obuf, char *ibuf) 3561899Swollman{ 357115718Smarkm int i, j; /* counter in a for loop */ 3581899Swollman int nbuf[64]; /* used for hex/key translation */ 3591899Swollman 3601899Swollman /* 3611899Swollman * just switch on the key base 3621899Swollman */ 3631899Swollman switch(keybase) { 3641899Swollman case KEY_ASCII: /* ascii to integer */ 3651899Swollman (void)strncpy(obuf, ibuf, 8); 3661899Swollman return; 3671899Swollman case KEY_DEFAULT: /* tell from context */ 3681899Swollman /* 3691899Swollman * leading '0x' or '0X' == hex key 3701899Swollman */ 3711899Swollman if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) { 3721899Swollman ibuf = &ibuf[2]; 3731899Swollman /* 3741899Swollman * now translate it, bombing on any illegal hex digit 3751899Swollman */ 3761899Swollman for (i = 0; ibuf[i] && i < 16; i++) 3771899Swollman if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1) 378115718Smarkm warnx("bad hex digit in key"); 3791899Swollman while (i < 16) 3801899Swollman nbuf[i++] = 0; 3811899Swollman for (i = 0; i < 8; i++) 3821899Swollman obuf[i] = 3831899Swollman ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf); 3841899Swollman /* preserve parity bits */ 3851899Swollman pflag = 1; 3861899Swollman return; 3871899Swollman } 3881899Swollman /* 3891899Swollman * leading '0b' or '0B' == binary key 3901899Swollman */ 3911899Swollman if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) { 3921899Swollman ibuf = &ibuf[2]; 3931899Swollman /* 3941899Swollman * now translate it, bombing on any illegal binary digit 3951899Swollman */ 3961899Swollman for (i = 0; ibuf[i] && i < 16; i++) 3971899Swollman if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1) 398115718Smarkm warnx("bad binary digit in key"); 3991899Swollman while (i < 64) 4001899Swollman nbuf[i++] = 0; 4011899Swollman for (i = 0; i < 8; i++) 4021899Swollman for (j = 0; j < 8; j++) 4031899Swollman obuf[i] = (obuf[i]<<1)|nbuf[8*i+j]; 4041899Swollman /* preserve parity bits */ 4051899Swollman pflag = 1; 4061899Swollman return; 4071899Swollman } 4081899Swollman /* 4091899Swollman * no special leader -- ASCII 4101899Swollman */ 4111899Swollman (void)strncpy(obuf, ibuf, 8); 4121899Swollman } 4131899Swollman} 4141899Swollman 4151899Swollman/* 4161899Swollman * convert an ASCII string into a decimal number: 4171899Swollman * 1. must be between 0 and 64 inclusive 4181899Swollman * 2. must be a valid decimal number 4191899Swollman * 3. must be a multiple of mult 4201899Swollman */ 421115718Smarkmstatic int 422115718Smarkmsetbits(char *s, int mult) 4231899Swollman{ 424115718Smarkm char *p; /* pointer in a for loop */ 425115718Smarkm int n = 0; /* the integer collected */ 4261899Swollman 4271899Swollman /* 4281899Swollman * skip white space 4291899Swollman */ 4301899Swollman while (isspace(*s)) 4311899Swollman s++; 4321899Swollman /* 4331899Swollman * get the integer 4341899Swollman */ 4351899Swollman for (p = s; *p; p++) { 4361899Swollman if (isdigit(*p)) 4371899Swollman n = n * 10 + *p - '0'; 4381899Swollman else { 439115718Smarkm warnx("bad decimal digit in MAC length"); 4401899Swollman } 4411899Swollman } 4421899Swollman /* 4431899Swollman * be sure it's a multiple of mult 4441899Swollman */ 4451899Swollman return((n % mult != 0) ? -1 : n); 4461899Swollman} 4471899Swollman 4481899Swollman/***************** 4491899Swollman * DES FUNCTIONS * 4501899Swollman *****************/ 4511899Swollman/* 4521899Swollman * This sets the DES key and (if you're using the deszip version) 4531899Swollman * the direction of the transformation. This uses the Sun 4541899Swollman * to map the 64-bit key onto the 56 bits that the key schedule 4551899Swollman * generation routines use: the old way, which just uses the user- 4561899Swollman * supplied 64 bits as is, and the new way, which resets the parity 4571899Swollman * bit to be the same as the low-order bit in each character. The 4581899Swollman * new way generates a greater variety of key schedules, since many 4591899Swollman * systems set the parity (high) bit of each character to 0, and the 4601899Swollman * DES ignores the low order bit of each character. 4611899Swollman */ 462115718Smarkmstatic void 463115718Smarkmmakekey(DES_cblock *buf) 4641899Swollman{ 465115718Smarkm int i, j; /* counter in a for loop */ 466115718Smarkm int par; /* parity counter */ 4671899Swollman 4681899Swollman /* 4691899Swollman * if the parity is not preserved, flip it 4701899Swollman */ 4711899Swollman if (!pflag) { 4721899Swollman for (i = 0; i < 8; i++) { 4731899Swollman par = 0; 4741899Swollman for (j = 1; j < 8; j++) 475115718Smarkm if ((bits[j] & (*buf)[i]) != 0) 4761899Swollman par++; 477115718Smarkm if ((par & 0x01) == 0x01) 478115718Smarkm (*buf)[i] &= 0x7f; 4791899Swollman else 480115718Smarkm (*buf)[i] = ((*buf)[i] & 0x7f) | 0x80; 4811899Swollman } 4821899Swollman } 4831899Swollman 484115718Smarkm DES_set_odd_parity(buf); 485115718Smarkm DES_set_key(buf, &schedule); 4861899Swollman} 4871899Swollman 4881899Swollman/* 4891899Swollman * This encrypts using the Electronic Code Book mode of DES 4901899Swollman */ 491115718Smarkmstatic void 492115718Smarkmecbenc(void) 4931899Swollman{ 494115718Smarkm int n; /* number of bytes actually read */ 495115718Smarkm int bn; /* block number */ 496115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 4971899Swollman 498115718Smarkm for (bn = 0; (n = READ(msgbuf, 8)) == 8; bn++) { 4991899Swollman /* 5001899Swollman * do the transformation 5011899Swollman */ 502115718Smarkm DES_XFORM(&msgbuf); 503115718Smarkm WRITE(&msgbuf, 8); 5041899Swollman } 5051899Swollman /* 50646064Skris * at EOF or last block -- in either case, the last byte contains 5071899Swollman * the character representation of the number of bytes in it 5081899Swollman */ 5091899Swollman bn++; 510115718Smarkm MEMZERO(&msgbuf[n], 8 - n); 511115718Smarkm msgbuf[7] = n; 512115718Smarkm DES_XFORM(&msgbuf); 513115718Smarkm WRITE(&msgbuf, 8); 5141899Swollman 5151899Swollman} 5161899Swollman 5171899Swollman/* 5181899Swollman * This decrypts using the Electronic Code Book mode of DES 5191899Swollman */ 520115718Smarkmstatic void 521115718Smarkmecbdec(void) 5221899Swollman{ 523115718Smarkm int n; /* number of bytes actually read */ 524115718Smarkm int c; /* used to test for EOF */ 525115718Smarkm int bn; /* block number */ 526115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 5271899Swollman 528115718Smarkm for (bn = 1; (n = READ(msgbuf, 8)) == 8; bn++) { 5291899Swollman /* 5301899Swollman * do the transformation 5311899Swollman */ 532115718Smarkm DES_XFORM(&msgbuf); 5331899Swollman /* 5341899Swollman * if the last one, handle it specially 5351899Swollman */ 5361899Swollman if ((c = getchar()) == EOF) { 537115718Smarkm n = msgbuf[7]; 5381899Swollman if (n < 0 || n > 7) 539115718Smarkm warnx("decryption failed (block corrupt) at %d", 540115718Smarkm bn); 5411899Swollman } 5421899Swollman else 5431899Swollman (void)ungetc(c, stdin); 544115718Smarkm WRITE(msgbuf, n); 5451899Swollman } 5461899Swollman if (n > 0) 547115718Smarkm warnx("decryption failed (incomplete block) at %d", bn); 5481899Swollman} 5491899Swollman 5501899Swollman/* 5511899Swollman * This encrypts using the Cipher Block Chaining mode of DES 5521899Swollman */ 553115718Smarkmstatic void 554115718Smarkmcbcenc(void) 5551899Swollman{ 556115718Smarkm int n; /* number of bytes actually read */ 557115718Smarkm int bn; /* block number */ 558115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 5591899Swollman 5601899Swollman /* 5611899Swollman * do the transformation 5621899Swollman */ 563115718Smarkm for (bn = 1; (n = READ(msgbuf, 8)) == 8; bn++) { 5641899Swollman for (n = 0; n < 8; n++) 565115718Smarkm msgbuf[n] ^= ivec[n]; 566115718Smarkm DES_XFORM(&msgbuf); 567115718Smarkm MEMCPY(ivec, msgbuf, 8); 568115718Smarkm WRITE(msgbuf, 8); 5691899Swollman } 5701899Swollman /* 5711899Swollman * at EOF or last block -- in either case, the last byte contains 5721899Swollman * the character representation of the number of bytes in it 5731899Swollman */ 5741899Swollman bn++; 575115718Smarkm MEMZERO(&msgbuf[n], 8 - n); 576115718Smarkm msgbuf[7] = n; 5771899Swollman for (n = 0; n < 8; n++) 578115718Smarkm msgbuf[n] ^= ivec[n]; 579115718Smarkm DES_XFORM(&msgbuf); 580115718Smarkm WRITE(msgbuf, 8); 5811899Swollman 5821899Swollman} 5831899Swollman 5841899Swollman/* 5851899Swollman * This decrypts using the Cipher Block Chaining mode of DES 5861899Swollman */ 587115718Smarkmstatic void 588115718Smarkmcbcdec(void) 5891899Swollman{ 590115718Smarkm int n; /* number of bytes actually read */ 591115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 592115718Smarkm DES_cblock ibuf; /* temp buffer for initialization vector */ 593115718Smarkm int c; /* used to test for EOF */ 594115718Smarkm int bn; /* block number */ 5951899Swollman 596115718Smarkm for (bn = 0; (n = READ(msgbuf, 8)) == 8; bn++) { 5971899Swollman /* 5981899Swollman * do the transformation 5991899Swollman */ 600115718Smarkm MEMCPY(ibuf, msgbuf, 8); 601115718Smarkm DES_XFORM(&msgbuf); 6021899Swollman for (c = 0; c < 8; c++) 603115718Smarkm msgbuf[c] ^= ivec[c]; 604115718Smarkm MEMCPY(ivec, ibuf, 8); 6051899Swollman /* 6061899Swollman * if the last one, handle it specially 6071899Swollman */ 6081899Swollman if ((c = getchar()) == EOF) { 609115718Smarkm n = msgbuf[7]; 6101899Swollman if (n < 0 || n > 7) 611115718Smarkm warnx("decryption failed (block corrupt) at %d", 612115718Smarkm bn); 6131899Swollman } 6141899Swollman else 6151899Swollman (void)ungetc(c, stdin); 616115718Smarkm WRITE(msgbuf, n); 6171899Swollman } 6181899Swollman if (n > 0) 619115718Smarkm warnx("decryption failed (incomplete block) at %d", bn); 6201899Swollman} 6211899Swollman 6221899Swollman/* 6231899Swollman * This authenticates using the Cipher Block Chaining mode of DES 6241899Swollman */ 625115718Smarkmstatic void 626115718Smarkmcbcauth(void) 6271899Swollman{ 628115718Smarkm int n, j; /* number of bytes actually read */ 629115718Smarkm DES_cblock msgbuf; /* I/O buffer */ 630115718Smarkm DES_cblock encbuf; /* encryption buffer */ 6311899Swollman 6321899Swollman /* 6331899Swollman * do the transformation 6341899Swollman * note we DISCARD the encrypted block; 6351899Swollman * we only care about the last one 6361899Swollman */ 637115718Smarkm while ((n = READ(msgbuf, 8)) == 8) { 6381899Swollman for (n = 0; n < 8; n++) 639115718Smarkm encbuf[n] = msgbuf[n] ^ ivec[n]; 640115718Smarkm DES_XFORM(&encbuf); 641115718Smarkm MEMCPY(ivec, encbuf, 8); 6421899Swollman } 6431899Swollman /* 6441899Swollman * now compute the last one, right padding with '\0' if need be 6451899Swollman */ 6461899Swollman if (n > 0) { 647115718Smarkm MEMZERO(&msgbuf[n], 8 - n); 6481899Swollman for (n = 0; n < 8; n++) 649115718Smarkm encbuf[n] = msgbuf[n] ^ ivec[n]; 650115718Smarkm DES_XFORM(&encbuf); 6511899Swollman } 6521899Swollman /* 6531899Swollman * drop the bits 6541899Swollman * we write chars until fewer than 7 bits, 6551899Swollman * and then pad the last one with 0 bits 6561899Swollman */ 6571899Swollman for (n = 0; macbits > 7; n++, macbits -= 8) 658115718Smarkm (void)putchar(encbuf[n]); 6591899Swollman if (macbits > 0) { 660115718Smarkm msgbuf[0] = 0x00; 6611899Swollman for (j = 0; j < macbits; j++) 662115718Smarkm msgbuf[0] |= encbuf[n] & bits[j]; 663115718Smarkm (void)putchar(msgbuf[0]); 6641899Swollman } 6651899Swollman} 6661899Swollman 6671899Swollman/* 6681899Swollman * This encrypts using the Cipher FeedBack mode of DES 6691899Swollman */ 670115718Smarkmstatic void 671115718Smarkmcfbenc(void) 6721899Swollman{ 673115718Smarkm int n; /* number of bytes actually read */ 674115718Smarkm int nbytes; /* number of bytes to read */ 675115718Smarkm int bn; /* block number */ 6761899Swollman char ibuf[8]; /* input buffer */ 677115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 6781899Swollman 6791899Swollman /* 6801899Swollman * do things in bytes, not bits 6811899Swollman */ 6821899Swollman nbytes = fbbits / 8; 6831899Swollman /* 6841899Swollman * do the transformation 6851899Swollman */ 6861899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 687115718Smarkm MEMCPY(msgbuf, ivec, 8); 688115718Smarkm DES_XFORM(&msgbuf); 6891899Swollman for (n = 0; n < 8 - nbytes; n++) 690115718Smarkm ivec[n] = ivec[n+nbytes]; 6911899Swollman for (n = 0; n < nbytes; n++) 692115718Smarkm ivec[8 - nbytes + n] = ibuf[n] ^ msgbuf[n]; 693115718Smarkm WRITE(&ivec[8 - nbytes], nbytes); 6941899Swollman } 6951899Swollman /* 6961899Swollman * at EOF or last block -- in either case, the last byte contains 6971899Swollman * the character representation of the number of bytes in it 6981899Swollman */ 6991899Swollman bn++; 7001899Swollman MEMZERO(&ibuf[n], nbytes - n); 7011899Swollman ibuf[nbytes - 1] = n; 702115718Smarkm MEMCPY(msgbuf, ivec, 8); 703115718Smarkm DES_XFORM(&msgbuf); 7041899Swollman for (n = 0; n < nbytes; n++) 705115718Smarkm ibuf[n] ^= msgbuf[n]; 7061899Swollman WRITE(ibuf, nbytes); 7071899Swollman} 7081899Swollman 7091899Swollman/* 7101899Swollman * This decrypts using the Cipher Block Chaining mode of DES 7111899Swollman */ 712115718Smarkmstatic void 713115718Smarkmcfbdec(void) 7141899Swollman{ 715115718Smarkm int n; /* number of bytes actually read */ 716115718Smarkm int c; /* used to test for EOF */ 717115718Smarkm int nbytes; /* number of bytes to read */ 718115718Smarkm int bn; /* block number */ 7191899Swollman char ibuf[8]; /* input buffer */ 7201899Swollman char obuf[8]; /* output buffer */ 721115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 7221899Swollman 7231899Swollman /* 7241899Swollman * do things in bytes, not bits 7251899Swollman */ 7261899Swollman nbytes = fbbits / 8; 7271899Swollman /* 7281899Swollman * do the transformation 7291899Swollman */ 7301899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 731115718Smarkm MEMCPY(msgbuf, ivec, 8); 732115718Smarkm DES_XFORM(&msgbuf); 7331899Swollman for (c = 0; c < 8 - nbytes; c++) 734115718Smarkm ivec[c] = ivec[c + nbytes]; 7351899Swollman for (c = 0; c < nbytes; c++) { 736115718Smarkm ivec[8 - nbytes + c] = ibuf[c]; 737115718Smarkm obuf[c] = ibuf[c] ^ msgbuf[c]; 7381899Swollman } 7391899Swollman /* 7401899Swollman * if the last one, handle it specially 7411899Swollman */ 7421899Swollman if ((c = getchar()) == EOF) { 7431899Swollman n = obuf[nbytes-1]; 7441899Swollman if (n < 0 || n > nbytes-1) 745115718Smarkm warnx("decryption failed (block corrupt) at %d", 746115718Smarkm bn); 7471899Swollman } 7481899Swollman else 7491899Swollman (void)ungetc(c, stdin); 7501899Swollman WRITE(obuf, n); 7511899Swollman } 7521899Swollman if (n > 0) 753115718Smarkm warnx("decryption failed (incomplete block) at %d", bn); 7541899Swollman} 7551899Swollman 7561899Swollman/* 7571899Swollman * This encrypts using the alternative Cipher FeedBack mode of DES 7581899Swollman */ 759115718Smarkmstatic void 760115718Smarkmcfbaenc(void) 7611899Swollman{ 762115718Smarkm int n; /* number of bytes actually read */ 763115718Smarkm int nbytes; /* number of bytes to read */ 764115718Smarkm int bn; /* block number */ 7651899Swollman char ibuf[8]; /* input buffer */ 7661899Swollman char obuf[8]; /* output buffer */ 767115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 7681899Swollman 7691899Swollman /* 7701899Swollman * do things in bytes, not bits 7711899Swollman */ 7721899Swollman nbytes = fbbits / 7; 7731899Swollman /* 7741899Swollman * do the transformation 7751899Swollman */ 7761899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 777115718Smarkm MEMCPY(msgbuf, ivec, 8); 778115718Smarkm DES_XFORM(&msgbuf); 7791899Swollman for (n = 0; n < 8 - nbytes; n++) 780115718Smarkm ivec[n] = ivec[n + nbytes]; 7811899Swollman for (n = 0; n < nbytes; n++) 782115718Smarkm ivec[8 - nbytes + n] = (ibuf[n] ^ msgbuf[n]) | 0x80; 7831899Swollman for (n = 0; n < nbytes; n++) 784115718Smarkm obuf[n] = ivec[8 - nbytes + n] & 0x7f; 7851899Swollman WRITE(obuf, nbytes); 7861899Swollman } 7871899Swollman /* 7881899Swollman * at EOF or last block -- in either case, the last byte contains 7891899Swollman * the character representation of the number of bytes in it 7901899Swollman */ 7911899Swollman bn++; 7921899Swollman MEMZERO(&ibuf[n], nbytes - n); 7931899Swollman ibuf[nbytes - 1] = ('0' + n)|0200; 794115718Smarkm MEMCPY(msgbuf, ivec, 8); 795115718Smarkm DES_XFORM(&msgbuf); 7961899Swollman for (n = 0; n < nbytes; n++) 797115718Smarkm ibuf[n] ^= msgbuf[n]; 7981899Swollman WRITE(ibuf, nbytes); 7991899Swollman} 8001899Swollman 8011899Swollman/* 8021899Swollman * This decrypts using the alternative Cipher Block Chaining mode of DES 8031899Swollman */ 804115718Smarkmstatic void 805115718Smarkmcfbadec(void) 8061899Swollman{ 807115718Smarkm int n; /* number of bytes actually read */ 808115718Smarkm int c; /* used to test for EOF */ 809115718Smarkm int nbytes; /* number of bytes to read */ 810115718Smarkm int bn; /* block number */ 8111899Swollman char ibuf[8]; /* input buffer */ 8121899Swollman char obuf[8]; /* output buffer */ 813115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 8141899Swollman 8151899Swollman /* 8161899Swollman * do things in bytes, not bits 8171899Swollman */ 8181899Swollman nbytes = fbbits / 7; 8191899Swollman /* 8201899Swollman * do the transformation 8211899Swollman */ 8221899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 823115718Smarkm MEMCPY(msgbuf, ivec, 8); 824115718Smarkm DES_XFORM(&msgbuf); 8251899Swollman for (c = 0; c < 8 - nbytes; c++) 826115718Smarkm ivec[c] = ivec[c + nbytes]; 8271899Swollman for (c = 0; c < nbytes; c++) { 828115718Smarkm ivec[8 - nbytes + c] = ibuf[c] | 0x80; 829115718Smarkm obuf[c] = (ibuf[c] ^ msgbuf[c]) & 0x7f; 8301899Swollman } 8311899Swollman /* 8321899Swollman * if the last one, handle it specially 8331899Swollman */ 8341899Swollman if ((c = getchar()) == EOF) { 8351899Swollman if ((n = (obuf[nbytes-1] - '0')) < 0 8361899Swollman || n > nbytes-1) 837115718Smarkm warnx("decryption failed (block corrupt) at %d", 838115718Smarkm bn); 8391899Swollman } 8401899Swollman else 8411899Swollman (void)ungetc(c, stdin); 8421899Swollman WRITE(obuf, n); 8431899Swollman } 8441899Swollman if (n > 0) 845115718Smarkm warnx("decryption failed (incomplete block) at %d", bn); 8461899Swollman} 8471899Swollman 8481899Swollman 8491899Swollman/* 8501899Swollman * This encrypts using the Output FeedBack mode of DES 8511899Swollman */ 852115718Smarkmstatic void 853115718Smarkmofbenc(void) 8541899Swollman{ 855115718Smarkm int n; /* number of bytes actually read */ 856115718Smarkm int c; /* used to test for EOF */ 857115718Smarkm int nbytes; /* number of bytes to read */ 858115718Smarkm int bn; /* block number */ 8591899Swollman char ibuf[8]; /* input buffer */ 8601899Swollman char obuf[8]; /* output buffer */ 861115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 8621899Swollman 8631899Swollman /* 8641899Swollman * do things in bytes, not bits 8651899Swollman */ 8661899Swollman nbytes = fbbits / 8; 8671899Swollman /* 8681899Swollman * do the transformation 8691899Swollman */ 8701899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 871115718Smarkm MEMCPY(msgbuf, ivec, 8); 872115718Smarkm DES_XFORM(&msgbuf); 8731899Swollman for (n = 0; n < 8 - nbytes; n++) 874115718Smarkm ivec[n] = ivec[n + nbytes]; 8751899Swollman for (n = 0; n < nbytes; n++) { 876115718Smarkm ivec[8 - nbytes + n] = msgbuf[n]; 877115718Smarkm obuf[n] = ibuf[n] ^ msgbuf[n]; 8781899Swollman } 8791899Swollman WRITE(obuf, nbytes); 8801899Swollman } 8811899Swollman /* 8821899Swollman * at EOF or last block -- in either case, the last byte contains 8831899Swollman * the character representation of the number of bytes in it 8841899Swollman */ 8851899Swollman bn++; 8861899Swollman MEMZERO(&ibuf[n], nbytes - n); 8871899Swollman ibuf[nbytes - 1] = n; 888115718Smarkm MEMCPY(msgbuf, ivec, 8); 889115718Smarkm DES_XFORM(&msgbuf); 8901899Swollman for (c = 0; c < nbytes; c++) 891115718Smarkm ibuf[c] ^= msgbuf[c]; 8921899Swollman WRITE(ibuf, nbytes); 8931899Swollman} 8941899Swollman 8951899Swollman/* 8961899Swollman * This decrypts using the Output Block Chaining mode of DES 8971899Swollman */ 898115718Smarkmstatic void 899115718Smarkmofbdec(void) 9001899Swollman{ 901115718Smarkm int n; /* number of bytes actually read */ 902115718Smarkm int c; /* used to test for EOF */ 903115718Smarkm int nbytes; /* number of bytes to read */ 904115718Smarkm int bn; /* block number */ 9051899Swollman char ibuf[8]; /* input buffer */ 9061899Swollman char obuf[8]; /* output buffer */ 907115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 9081899Swollman 9091899Swollman /* 9101899Swollman * do things in bytes, not bits 9111899Swollman */ 9121899Swollman nbytes = fbbits / 8; 9131899Swollman /* 9141899Swollman * do the transformation 9151899Swollman */ 9161899Swollman for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) { 917115718Smarkm MEMCPY(msgbuf, ivec, 8); 918115718Smarkm DES_XFORM(&msgbuf); 9191899Swollman for (c = 0; c < 8 - nbytes; c++) 920115718Smarkm ivec[c] = ivec[c + nbytes]; 9211899Swollman for (c = 0; c < nbytes; c++) { 922115718Smarkm ivec[8 - nbytes + c] = msgbuf[c]; 923115718Smarkm obuf[c] = ibuf[c] ^ msgbuf[c]; 9241899Swollman } 9251899Swollman /* 9261899Swollman * if the last one, handle it specially 9271899Swollman */ 9281899Swollman if ((c = getchar()) == EOF) { 9291899Swollman n = obuf[nbytes-1]; 9301899Swollman if (n < 0 || n > nbytes-1) 931115718Smarkm warnx("decryption failed (block corrupt) at %d", 932115718Smarkm bn); 9331899Swollman } 9341899Swollman else 9351899Swollman (void)ungetc(c, stdin); 9361899Swollman /* 9371899Swollman * dump it 9381899Swollman */ 9391899Swollman WRITE(obuf, n); 9401899Swollman } 9411899Swollman if (n > 0) 942115718Smarkm warnx("decryption failed (incomplete block) at %d", bn); 9431899Swollman} 9441899Swollman 9451899Swollman/* 9461899Swollman * This authenticates using the Cipher FeedBack mode of DES 9471899Swollman */ 948115718Smarkmstatic void 949115718Smarkmcfbauth(void) 9501899Swollman{ 951115718Smarkm int n, j; /* number of bytes actually read */ 952115718Smarkm int nbytes; /* number of bytes to read */ 9531899Swollman char ibuf[8]; /* input buffer */ 954115718Smarkm DES_cblock msgbuf; /* encryption buffer */ 9551899Swollman 9561899Swollman /* 9571899Swollman * do things in bytes, not bits 9581899Swollman */ 9591899Swollman nbytes = fbbits / 8; 9601899Swollman /* 9611899Swollman * do the transformation 9621899Swollman */ 9631899Swollman while ((n = READ(ibuf, nbytes)) == nbytes) { 964115718Smarkm MEMCPY(msgbuf, ivec, 8); 965115718Smarkm DES_XFORM(&msgbuf); 9661899Swollman for (n = 0; n < 8 - nbytes; n++) 967115718Smarkm ivec[n] = ivec[n + nbytes]; 9681899Swollman for (n = 0; n < nbytes; n++) 969115718Smarkm ivec[8 - nbytes + n] = ibuf[n] ^ msgbuf[n]; 9701899Swollman } 9711899Swollman /* 9721899Swollman * at EOF or last block -- in either case, the last byte contains 9731899Swollman * the character representation of the number of bytes in it 9741899Swollman */ 9751899Swollman MEMZERO(&ibuf[n], nbytes - n); 9761899Swollman ibuf[nbytes - 1] = '0' + n; 977115718Smarkm MEMCPY(msgbuf, ivec, 8); 978115718Smarkm DES_XFORM(&msgbuf); 9791899Swollman for (n = 0; n < nbytes; n++) 980115718Smarkm ibuf[n] ^= msgbuf[n]; 9811899Swollman /* 9821899Swollman * drop the bits 9831899Swollman * we write chars until fewer than 7 bits, 9841899Swollman * and then pad the last one with 0 bits 9851899Swollman */ 9861899Swollman for (n = 0; macbits > 7; n++, macbits -= 8) 987115718Smarkm (void)putchar(msgbuf[n]); 9881899Swollman if (macbits > 0) { 989115718Smarkm msgbuf[0] = 0x00; 9901899Swollman for (j = 0; j < macbits; j++) 991115718Smarkm msgbuf[0] |= msgbuf[n] & bits[j]; 992115718Smarkm (void)putchar(msgbuf[0]); 9931899Swollman } 9941899Swollman} 9951899Swollman 9961899Swollman/* 9971899Swollman * message about usage 9981899Swollman */ 999115718Smarkmstatic void 1000115718Smarkmusage(void) 10011899Swollman{ 10028871Srgrimes (void)fprintf(stderr, "%s\n", 1003141651Sru"usage: bdes [-abdp] [-F N] [-f N] [-k key] [-m N] [-o N] [-v vector]"); 10041899Swollman exit(1); 10051899Swollman} 1006