|
|
1.1 ! root 1: /* ! 2: * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/des/RCS/pcbc_encrypt.c,v $ ! 3: * $Author: jtkohl $ ! 4: * ! 5: * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute ! 6: * of Technology. ! 7: * ! 8: * For copying and distribution information, please see the file ! 9: * <mit-copyright.h>. ! 10: * ! 11: * These routines perform encryption and decryption using the DES ! 12: * private key algorithm, or else a subset of it-- fewer inner loops. ! 13: * ( AUTH_DES_ITER defaults to 16, may be less) ! 14: * ! 15: * Under U.S. law, this software may not be exported outside the US ! 16: * without license from the U.S. Commerce department. ! 17: * ! 18: * The key schedule is passed as an arg, as well as the cleartext or ! 19: * ciphertext. The cleartext and ciphertext should be in host order. ! 20: * ! 21: * These routines form the library interface to the des facilities. ! 22: * ! 23: * spm 8/85 MIT project athena ! 24: */ ! 25: ! 26: #ifndef lint ! 27: static char rcsid_pcbc_encrypt_c[] = ! 28: "$Id: pcbc_encrypt.c,v 4.11 90/01/02 13:46:30 jtkohl Exp $"; ! 29: #endif lint ! 30: ! 31: #include <mit-copyright.h> ! 32: #include <stdio.h> ! 33: #include <des.h> ! 34: #include "des_internal.h" ! 35: ! 36: extern int des_debug; ! 37: extern int des_debug_print(); ! 38: ! 39: /* ! 40: * pcbc_encrypt is an "error propagation chaining" encrypt operation ! 41: * for DES, similar to CBC, but that, on encryption, "xor"s the ! 42: * plaintext of block N with the ciphertext resulting from block N, ! 43: * then "xor"s that result with the plaintext of block N+1 prior to ! 44: * encrypting block N+1. (decryption the appropriate inverse. This ! 45: * "pcbc" mode propagates a single bit error anywhere in either the ! 46: * cleartext or ciphertext chain all the way through to the end. In ! 47: * contrast, CBC mode limits a single bit error in the ciphertext to ! 48: * affect only the current (8byte) block and the subsequent block. ! 49: * ! 50: * performs pcbc error-propagation chaining operation by xor-ing block ! 51: * N+1 with both the plaintext (block N) and the ciphertext from block ! 52: * N. Either encrypts from cleartext to ciphertext, if encrypt != 0 ! 53: * or decrypts from ciphertext to cleartext, if encrypt == 0 ! 54: * ! 55: * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not ! 56: * enough space was provided, your program will get trashed. ! 57: * ! 58: * For encryption, the cleartext string is null padded, at the end, to ! 59: * an integral multiple of eight bytes. ! 60: * ! 61: * For decryption, the ciphertext will be used in integral multiples ! 62: * of 8 bytes, but only the first "length" bytes returned into the ! 63: * cleartext. ! 64: * ! 65: * This is NOT a standard mode of operation. ! 66: * ! 67: */ ! 68: ! 69: int ! 70: des_pcbc_encrypt(in,out,length,key,iv,encrypt) ! 71: des_cblock *in; /* >= length bytes of inputtext */ ! 72: des_cblock *out; /* >= length bytes of outputtext */ ! 73: register long length; /* in bytes */ ! 74: int encrypt; /* 0 ==> decrypt, else encrypt */ ! 75: des_key_schedule key; /* precomputed key schedule */ ! 76: des_cblock *iv; /* 8 bytes of ivec */ ! 77: { ! 78: register unsigned long *input = (unsigned long *) in; ! 79: register unsigned long *output = (unsigned long *) out; ! 80: register unsigned long *ivec = (unsigned long *) iv; ! 81: ! 82: unsigned long i,j; ! 83: static unsigned long t_input[2]; ! 84: static unsigned long t_output[2]; ! 85: static unsigned char *t_in_p; ! 86: static unsigned long xor_0, xor_1; ! 87: ! 88: t_in_p = (unsigned char *) t_input; ! 89: if (encrypt) { ! 90: #ifdef MUSTALIGN ! 91: if ((long) ivec & 3) { ! 92: bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0)); ! 93: bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1)); ! 94: } ! 95: else ! 96: #endif ! 97: { ! 98: xor_0 = *ivec++; ! 99: xor_1 = *ivec; ! 100: } ! 101: ! 102: for (i = 0; length > 0; i++, length -= 8) { ! 103: /* get input */ ! 104: #ifdef MUSTALIGN ! 105: if ((long) input & 3) { ! 106: bcopy((char *)input,(char *)&t_input[0],sizeof(t_input[0])); ! 107: bcopy((char *)(input+1),(char *)&t_input[1],sizeof(t_input[1])); ! 108: } ! 109: else ! 110: #endif ! 111: { ! 112: t_input[0] = *input; ! 113: t_input[1] = *(input+1); ! 114: } ! 115: ! 116: /* zero pad */ ! 117: if (length < 8) { ! 118: for (j = length; j <= 7; j++) ! 119: *(t_in_p+j)= 0; ! 120: } ! 121: ! 122: #ifdef DEBUG ! 123: if (des_debug) ! 124: des_debug_print("clear",length,t_input[0],t_input[1]); ! 125: #endif ! 126: /* do the xor for cbc into the temp */ ! 127: t_input[0] ^= xor_0 ; ! 128: t_input[1] ^= xor_1 ; ! 129: /* encrypt */ ! 130: (void) des_ecb_encrypt(t_input,t_output,key,encrypt); ! 131: ! 132: /* ! 133: * We want to XOR with both the plaintext and ciphertext ! 134: * of the previous block, before we write the output, in ! 135: * case both input and output are the same space. ! 136: */ ! 137: #ifdef MUSTALIGN ! 138: if ((long) input & 3) { ! 139: bcopy((char *)input++,(char *)&xor_0,sizeof(xor_0)); ! 140: xor_0 ^= t_output[0]; ! 141: bcopy((char *)input++,(char *)&xor_1,sizeof(xor_1)); ! 142: xor_1 ^= t_output[1]; ! 143: } ! 144: else ! 145: #endif ! 146: { ! 147: xor_0 = *input++ ^ t_output[0]; ! 148: xor_1 = *input++ ^ t_output[1]; ! 149: } ! 150: ! 151: ! 152: /* copy temp output and save it for cbc */ ! 153: #ifdef MUSTALIGN ! 154: if ((long) output & 3) { ! 155: bcopy((char *)&t_output[0],(char *)output++, ! 156: sizeof(t_output[0])); ! 157: bcopy((char *)&t_output[1],(char *)output++, ! 158: sizeof(t_output[1])); ! 159: } ! 160: else ! 161: #endif ! 162: { ! 163: *output++ = t_output[0]; ! 164: *output++ = t_output[1]; ! 165: } ! 166: ! 167: #ifdef DEBUG ! 168: if (des_debug) { ! 169: des_debug_print("xor'ed",i,t_input[0],t_input[1]); ! 170: des_debug_print("cipher",i,t_output[0],t_output[1]); ! 171: } ! 172: #endif ! 173: } ! 174: t_output[0] = 0; ! 175: t_output[1] = 0; ! 176: xor_0 = 0; ! 177: xor_1 = 0; ! 178: return 0; ! 179: } ! 180: ! 181: else { ! 182: /* decrypt */ ! 183: #ifdef MUSTALIGN ! 184: if ((long) ivec & 3) { ! 185: bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0)); ! 186: bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1)); ! 187: } ! 188: else ! 189: #endif ! 190: { ! 191: xor_0 = *ivec++; ! 192: xor_1 = *ivec; ! 193: } ! 194: ! 195: for (i = 0; length > 0; i++, length -= 8) { ! 196: /* get input */ ! 197: #ifdef MUSTALIGN ! 198: if ((long) input & 3) { ! 199: bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0])); ! 200: bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[1])); ! 201: } ! 202: else ! 203: #endif ! 204: { ! 205: t_input[0] = *input++; ! 206: t_input[1] = *input++; ! 207: } ! 208: ! 209: /* no padding for decrypt */ ! 210: #ifdef DEBUG ! 211: if (des_debug) ! 212: des_debug_print("cipher",i,t_input[0],t_input[1]); ! 213: #else ! 214: #ifdef lint ! 215: i = i; ! 216: #endif ! 217: #endif ! 218: /* encrypt */ ! 219: (void) des_ecb_encrypt(t_input,t_output,key,encrypt); ! 220: #ifdef DEBUG ! 221: if (des_debug) ! 222: des_debug_print("out pre xor",i,t_output[0],t_output[1]); ! 223: #endif ! 224: /* do the xor for cbc into the output */ ! 225: t_output[0] ^= xor_0 ; ! 226: t_output[1] ^= xor_1 ; ! 227: /* copy temp output */ ! 228: #ifdef MUSTALIGN ! 229: if ((long) output & 3) { ! 230: bcopy((char *)&t_output[0],(char *)output++, ! 231: sizeof(t_output[0])); ! 232: bcopy((char *)&t_output[1],(char *)output++, ! 233: sizeof(t_output[1])); ! 234: } ! 235: else ! 236: #endif ! 237: { ! 238: *output++ = t_output[0]; ! 239: *output++ = t_output[1]; ! 240: } ! 241: ! 242: /* save xor value for next round */ ! 243: xor_0 = t_output[0] ^ t_input[0]; ! 244: xor_1 = t_output[1] ^ t_input[1]; ! 245: ! 246: #ifdef DEBUG ! 247: if (des_debug) ! 248: des_debug_print("clear",i,t_output[0],t_output[1]); ! 249: #endif ! 250: } ! 251: return 0; ! 252: } ! 253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.