From 03a91dc7729cbc3ec446273b0491c06541500de4 Mon Sep 17 00:00:00 2001 From: Mark Eichin Date: Thu, 3 Nov 1994 23:31:51 +0000 Subject: [PATCH] * pcbc_encrypt.c: moved from f_pcbc.c in lib/crypto/des, and inlined proper des.h to avoid confusion in names. * Makefile.in: add -I to CFLAGS to get f_tables.h from lib/crypto/des as well. this shouldn't have been in lib/crypto/des in the first place, and the old version here was nonportable. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4626 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/des425/ChangeLog | 7 + src/lib/des425/Makefile.in | 2 +- src/lib/des425/pcbc_encrypt.c | 471 +++++++++++++++++----------------- 3 files changed, 239 insertions(+), 241 deletions(-) diff --git a/src/lib/des425/ChangeLog b/src/lib/des425/ChangeLog index d2fc93f3d..cf76d7637 100644 --- a/src/lib/des425/ChangeLog +++ b/src/lib/des425/ChangeLog @@ -1,3 +1,10 @@ +Thu Nov 3 18:29:10 1994 Mark Eichin (eichin@cygnus.com) + + * pcbc_encrypt.c: moved from f_pcbc.c in lib/crypto/des, and + inlined proper des.h to avoid confusion in names. + * Makefile.in: add -I to CFLAGS to get f_tables.h from + lib/crypto/des as well. + Wed Oct 26 14:23:36 1994 (tytso@rsx-11) * Makefile.in (check): diff --git a/src/lib/des425/Makefile.in b/src/lib/des425/Makefile.in index 389a379a7..650c8dded 100644 --- a/src/lib/des425/Makefile.in +++ b/src/lib/des425/Makefile.in @@ -1,4 +1,4 @@ -CFLAGS = $(CCOPTS) $(DEFS) +CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../crypto/des LDFLAGS = -g all:: $(OBJS) diff --git a/src/lib/des425/pcbc_encrypt.c b/src/lib/des425/pcbc_encrypt.c index 00d9644ee..45de20bc0 100644 --- a/src/lib/des425/pcbc_encrypt.c +++ b/src/lib/des425/pcbc_encrypt.c @@ -1,261 +1,252 @@ /* * lib/des425/pcbc_encrypt.c - * - * Copyright 1985, 1986, 1987, 1988,1990 by the Massachusetts Institute - * of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * - * These routines perform encryption and decryption using the DES - * private key algorithm, or else a subset of it-- fewer inner loops. - * ( AUTH_DES_ITER defaults to 16, may be less) - * - * Under U.S. law, this software may not be exported outside the US - * without license from the U.S. Commerce department. - * - * The key schedule is passed as an arg, as well as the cleartext or - * ciphertext. The cleartext and ciphertext should be in host order. - * - * These routines form the library interface to the des facilities. - * - * spm 8/85 MIT project athena */ - -#include -#include "des.h" - -extern int mit_des_debug; -extern int mit_des_debug_print(); - /* - * pcbc_encrypt is an "error propagation chaining" encrypt operation - * for DES, similar to CBC, but that, on encryption, "xor"s the - * plaintext of block N with the ciphertext resulting from block N, - * then "xor"s that result with the plaintext of block N+1 prior to - * encrypting block N+1. (decryption the appropriate inverse. This - * "pcbc" mode propagates a single bit error anywhere in either the - * cleartext or ciphertext chain all the way through to the end. In - * contrast, CBC mode limits a single bit error in the ciphertext to - * affect only the current (8byte) block and the subsequent block. - * - * performs pcbc error-propagation chaining operation by xor-ing block - * N+1 with both the plaintext (block N) and the ciphertext from block - * N. Either encrypts from cleartext to ciphertext, if encrypt != 0 - * or decrypts from ciphertext to cleartext, if encrypt == 0 - * - * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not - * enough space was provided, your program will get trashed. - * - * For encryption, the cleartext string is null padded, at the end, to - * an integral multiple of eight bytes. - * - * For decryption, the ciphertext will be used in integral multiples - * of 8 bytes, but only the first "length" bytes returned into the - * cleartext. - * - * This is NOT a standard mode of operation. + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. */ -int -des_pcbc_encrypt(in,out,length,key,iv,encrypt) - mit_des_cblock *in; /* >= length bytes of inputtext */ - mit_des_cblock *out; /* >= length bytes of outputtext */ - register long length; /* in bytes */ - int encrypt; /* 0 ==> decrypt, else encrypt */ - des_key_schedule key; /* precomputed key schedule */ - mit_des_cblock *iv; /* 8 bytes of ivec */ -{ - register unsigned long *input = (unsigned long *) in; - register unsigned long *output = (unsigned long *) out; - register unsigned long *ivec = (unsigned long *) iv; +/* + * des_pcbc_encrypt.c - encrypt a string of characters in error propagation mode + */ - unsigned long i,j; - static unsigned long t_input[2]; - static unsigned long t_output[2]; - static unsigned char *t_in_p; - static unsigned long xor_0, xor_1; +/* + * copy of include/des.h to avoid collision with local one + */ +#include +#include - t_in_p = (unsigned char *) t_input; - if (encrypt) { -#ifdef MUSTALIGN - if ((long) ivec & 3) { - memcpy((char *)&xor_0, (char *)ivec++,sizeof(xor_0)); - memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1)); - } - else +#ifndef KRB_INT32 +#define KRB_INT32 long #endif - { - xor_0 = *ivec++; - xor_1 = *ivec; - } - - for (i = 0; length > 0; i++, length -= 8) { - /* get input */ -#ifdef MUSTALIGN - if ((long) input & 3) { - memcpy((char *)&t_input[0], (char *)input, sizeof(t_input[0])); - memcpy((char *)&t_input[1], (char *)(input+1),sizeof(t_input[1])); - } - else +#ifndef KRB_UINT32 +#define KRB_UINT32 unsigned KRB_INT32 #endif - { - t_input[0] = *input; - t_input[1] = *(input+1); - } - - /* zero pad */ - if (length < 8) { - for (j = length; j <= 7; j++) - *(t_in_p+j)= 0; - } -#ifdef DEBUG - if (mit_des_debug) - mit_des_debug_print("clear",length,t_input[0],t_input[1]); +typedef unsigned char des_cblock[8]; /* crypto-block size */ +/* Key schedule */ +typedef struct des_ks_struct { union { KRB_INT32 pad; des_cblock _;} __; } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#ifndef NCOMPAT +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define key_sched des_key_sched +#define cbc_encrypt des_cbc_encrypt +#define cbc_cksum des_cbc_cksum +#define C_Block_print des_cblock_print +#define quad_cksum des_quad_cksum +typedef struct des_ks_struct bit_64; #endif - /* do the xor for cbc into the temp */ - t_input[0] ^= xor_0 ; - t_input[1] ^= xor_1 ; - /* encrypt */ - (void) des_ecb_encrypt(t_input,t_output,key,encrypt); - /* - * We want to XOR with both the plaintext and ciphertext - * of the previous block, before we write the output, in - * case both input and output are the same space. - */ -#ifdef MUSTALIGN - if ((long) input & 3) { - memcpy((char *)&xor_0, (char *)input++, sizeof(xor_0)); - xor_0 ^= t_output[0]; - memcpy((char *)&xor_1, (char *)input++, sizeof(xor_1)); - xor_1 ^= t_output[1]; - } - else -#endif - { - xor_0 = *input++ ^ t_output[0]; - xor_1 = *input++ ^ t_output[1]; - } - - - /* copy temp output and save it for cbc */ -#ifdef MUSTALIGN - if ((long) output & 3) { - memcpy((char *)output++, (char *)&t_output[0], - sizeof(t_output[0])); - memcpy((char *)output++, (char *)&t_output[1], - sizeof(t_output[1])); - } - else -#endif - { - *output++ = t_output[0]; - *output++ = t_output[1]; - } +#define des_cblock_print(x) des_cblock_print_file(x, stdout) -#ifdef DEBUG - if (mit_des_debug) { - mit_des_debug_print("xor'ed",i,t_input[0],t_input[1]); - mit_des_debug_print("cipher",i,t_output[0],t_output[1]); - } -#endif - } - t_output[0] = 0; - t_output[1] = 0; - xor_0 = 0; - xor_1 = 0; - return 0; - } +#include "f_tables.h" - else { - /* decrypt */ -#ifdef MUSTALIGN - if ((long) ivec & 3) { - memcpy((char *)&xor_0, (char *)ivec++,sizeof(xor_0)); - memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1)); - } - else -#endif - { - xor_0 = *ivec++; - xor_1 = *ivec; +/* + * des_pcbc_encrypt - {en,de}crypt a stream in PCBC mode + */ +int +des_pcbc_encrypt(in, out, length, schedule, ivec, encrypt) + des_cblock *in; + des_cblock *out; + long length; + des_key_schedule schedule; + des_cblock ivec; + int encrypt; +{ + register unsigned KRB_INT32 left, right; + register unsigned KRB_INT32 temp; + register unsigned KRB_INT32 *kp; + register unsigned char *ip, *op; + + /* + * Copy the key pointer, just once + */ + kp = (unsigned KRB_INT32 *)schedule; + + /* + * Deal with encryption and decryption separately. + */ + if (encrypt) { + register unsigned KRB_INT32 plainl; + register unsigned KRB_INT32 plainr; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = (unsigned char *)in; + op = (unsigned char *)out; + while (length > 0) { + /* + * Get block of input. If the length is + * greater than 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length > 8) { + GET_HALF_BLOCK(plainl, ip); + GET_HALF_BLOCK(plainr, ip); + left ^= plainl; + right ^= plainr; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. We know this is the + * last block, though, so we don't have + * to save the plain text. + */ + ip += (int) length; + switch(length) { + case 8: + right ^= *(--ip) & 0xff; + case 7: + right ^= (*(--ip) & 0xff) << 8; + case 6: + right ^= (*(--ip) & 0xff) << 16; + case 5: + right ^= (*(--ip) & 0xff) << 24; + case 4: + left ^= *(--ip) & 0xff; + case 3: + left ^= (*(--ip) & 0xff) << 8; + case 2: + left ^= (*(--ip) & 0xff) << 16; + case 1: + left ^= (*(--ip) & 0xff) << 24; + break; + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, temp, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Xor with the old plain text + */ + left ^= plainl; + right ^= plainr; + } + } else { + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + unsigned KRB_INT32 ocipherl, ocipherr; + unsigned KRB_INT32 cipherl, cipherr; + + if (length <= 0) + return 0; + + /* + * Prime the old cipher with ivec. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + ip = (unsigned char *)in; + op = (unsigned char *)out; + for (;;) { /* check done inside loop */ + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, temp, kp); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + if (length > 8) { + length -= 8; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + /* + * Save current cipher block here + */ + ocipherl = cipherl ^ left; + ocipherr = cipherr ^ right; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: + *(--op) = right & 0xff; + case 7: + *(--op) = (right >> 8) & 0xff; + case 6: + *(--op) = (right >> 16) & 0xff; + case 5: + *(--op) = (right >> 24) & 0xff; + case 4: + *(--op) = left & 0xff; + case 3: + *(--op) = (left >> 8) & 0xff; + case 2: + *(--op) = (left >> 16) & 0xff; + case 1: + *(--op) = (left >> 24) & 0xff; + break; + } + break; /* we're done */ + } + } } - for (i = 0; length > 0; i++, length -= 8) { - /* get input */ -#ifdef MUSTALIGN - if ((long) input & 3) { - memcpy((char *)&t_input[0],(char *)input++,sizeof(t_input[0])); - memcpy((char *)&t_input[1],(char *)input++,sizeof(t_input[1])); - } - else -#endif - { - t_input[0] = *input++; - t_input[1] = *input++; - } - - /* no padding for decrypt */ -#ifdef DEBUG - if (mit_des_debug) - mit_des_debug_print("cipher",i,t_input[0],t_input[1]); -#else -#ifdef lint - i = i; -#endif -#endif - /* encrypt */ - (void) des_ecb_encrypt(t_input,t_output,key,encrypt); -#ifdef DEBUG - if (mit_des_debug) - mit_des_debug_print("out pre xor",i,t_output[0],t_output[1]); -#endif - /* do the xor for cbc into the output */ - t_output[0] ^= xor_0 ; - t_output[1] ^= xor_1 ; - /* copy temp output */ -#ifdef MUSTALIGN - if ((long) output & 3) { - memcpy((char *)output++, (char *)&t_output[0], - sizeof(t_output[0])); - memcpy((char *)output++, (char *)&t_output[1], - sizeof(t_output[1])); - } - else -#endif - { - *output++ = t_output[0]; - *output++ = t_output[1]; - } - - /* save xor value for next round */ - xor_0 = t_output[0] ^ t_input[0]; - xor_1 = t_output[1] ^ t_input[1]; - -#ifdef DEBUG - if (mit_des_debug) - mit_des_debug_print("clear",i,t_output[0],t_output[1]); -#endif - } + /* + * Done, return nothing. + */ return 0; - } } -- 2.26.2