From e9883f16460e4e81377144c59112fa528fb26811 Mon Sep 17 00:00:00 2001 From: Richard Basch Date: Tue, 28 Nov 1995 01:09:19 +0000 Subject: [PATCH] Triple-DES support routines git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7127 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/des/d3_cbc.c | 200 ++++++++++++++++++++++++++++++++ src/lib/crypto/des/d3_ecb.c | 48 ++++++++ src/lib/crypto/des/d3_kysched.c | 55 +++++++++ src/lib/crypto/des/d3_procky.c | 59 ++++++++++ src/lib/crypto/des/d3_rndky.c | 51 ++++++++ src/lib/crypto/des/d3_str2ky.c | 118 +++++++++++++++++++ src/lib/crypto/des/u_nfold.c | 106 +++++++++++++++++ 7 files changed, 637 insertions(+) create mode 100644 src/lib/crypto/des/d3_cbc.c create mode 100644 src/lib/crypto/des/d3_ecb.c create mode 100644 src/lib/crypto/des/d3_kysched.c create mode 100644 src/lib/crypto/des/d3_procky.c create mode 100644 src/lib/crypto/des/d3_rndky.c create mode 100644 src/lib/crypto/des/d3_str2ky.c create mode 100644 src/lib/crypto/des/u_nfold.c diff --git a/src/lib/crypto/des/d3_cbc.c b/src/lib/crypto/des/d3_cbc.c new file mode 100644 index 000000000..4509c2e17 --- /dev/null +++ b/src/lib/crypto/des/d3_cbc.c @@ -0,0 +1,200 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "des.h" +#include "des_int.h" +#include "f_tables.h" + +/* + * Triple-DES CBC encryption mode. + */ + +int +mit_des3_cbc_encrypt(in, out, length, ks1, ks2, ks3, ivec, encrypt) + const mit_des_cblock FAR *in; + mit_des_cblock FAR *out; + long length; + mit_des_key_schedule ks1, ks2, ks3; + mit_des_cblock ivec; + int encrypt; +{ + register unsigned KRB_INT32 left, right; + register unsigned KRB_INT32 temp; + register unsigned KRB_INT32 *kp1, *kp2, *kp3; + register unsigned char *ip, *op; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp1 = (unsigned KRB_INT32 *)ks1; + kp2 = (unsigned KRB_INT32 *)ks2; + kp3 = (unsigned KRB_INT32 *)ks3; + + /* + * Deal with encryption and decryption separately. + */ + if (encrypt) { + /* + * 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 more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length >= 8) { + left ^= ((*ip++) & FF_UINT32) << 24; + left ^= ((*ip++) & FF_UINT32) << 16; + left ^= ((*ip++) & FF_UINT32) << 8; + left ^= (*ip++) & FF_UINT32; + right ^= ((*ip++) & FF_UINT32) << 24; + right ^= ((*ip++) & FF_UINT32) << 16; + right ^= ((*ip++) & FF_UINT32) << 8; + right ^= (*ip++) & FF_UINT32; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) length; + switch(length) { + case 7: right ^= (*(--ip) & FF_UINT32) << 8; + case 6: right ^= (*(--ip) & FF_UINT32) << 16; + case 5: right ^= (*(--ip) & FF_UINT32) << 24; + case 4: left ^= *(--ip) & FF_UINT32; + case 3: left ^= (*(--ip) & FF_UINT32) << 8; + case 2: left ^= (*(--ip) & FF_UINT32) << 16; + case 1: left ^= (*(--ip) & FF_UINT32) << 24; + + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, temp, kp1); + DES_DO_DECRYPT(left, right, temp, kp2); + DES_DO_ENCRYPT(left, right, temp, kp3); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + } + } 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, kp3); + DES_DO_ENCRYPT(left, right, temp, kp2); + DES_DO_DECRYPT(left, right, temp, kp1); + + /* + * 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; + ocipherr = cipherr; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: *(--op) = (unsigned char) (right & 0xff); + case 7: *(--op) = (unsigned char) ((right >> 8) & 0xff); + case 6: *(--op) = (unsigned char) ((right >> 16) & 0xff); + case 5: *(--op) = (unsigned char) ((right >> 24) & 0xff); + case 4: *(--op) = (unsigned char) (left & 0xff); + case 3: *(--op) = (unsigned char) ((left >> 8) & 0xff); + case 2: *(--op) = (unsigned char) ((left >> 16) & 0xff); + case 1: *(--op) = (unsigned char) ((left >> 24) & 0xff); + } + break; /* we're done */ + } + } + } + + /* + * Done, return nothing. + */ + return 0; +} diff --git a/src/lib/crypto/des/d3_ecb.c b/src/lib/crypto/des/d3_ecb.c new file mode 100644 index 000000000..a51898fd9 --- /dev/null +++ b/src/lib/crypto/des/d3_ecb.c @@ -0,0 +1,48 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "des.h" +#include "des_int.h" +#include "f_tables.h" + +/* + * Triple-DES ECB encryption mode. + */ + +int +mit_des3_ecb_encrypt(in, out, sched1, sched2, sched3, encrypt) + const mit_des_cblock FAR *in; + mit_des_cblock FAR *out; + mit_des_key_schedule sched1, sched2, sched3; + int encrypt; +{ + if (encrypt) { + mit_des_ecb_encrypt(in, out, sched1, encrypt); + mit_des_ecb_encrypt(out, out, sched2, !encrypt); + mit_des_ecb_encrypt(out, out, sched3, encrypt); + } else { + mit_des_ecb_encrypt(in, out, sched3, encrypt); + mit_des_ecb_encrypt(out, out, sched2, !encrypt); + mit_des_ecb_encrypt(out, out, sched1, encrypt); + } + return 0; +} diff --git a/src/lib/crypto/des/d3_kysched.c b/src/lib/crypto/des/d3_kysched.c new file mode 100644 index 000000000..efd91c44b --- /dev/null +++ b/src/lib/crypto/des/d3_kysched.c @@ -0,0 +1,55 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "k5-int.h" +#include "des_int.h" + +int +mit_des3_key_sched(key,key_sched) + mit_des3_cblock key; + mit_des3_key_schedule key_sched; +{ + mit_des_cblock *k = (mit_des_cblock *)key; + mit_des_key_schedule *schedule = (mit_des_key_schedule *)key_sched; + + make_key_sched(k[0],schedule[0]); + make_key_sched(k[1],schedule[1]); + make_key_sched(k[2],schedule[2]); + + if (!mit_des_check_key_parity(k[0])) /* bad parity --> return -1 */ + return(-1); + if (mit_des_is_weak_key(k[0])) + return(-2); + + if (!mit_des_check_key_parity(k[1])) + return(-1); + if (mit_des_is_weak_key(k[1])) + return(-2); + + if (!mit_des_check_key_parity(k[2])) + return(-1); + if (mit_des_is_weak_key(k[2])) + return(-2); + + /* if key was good, return 0 */ + return 0; +} diff --git a/src/lib/crypto/des/d3_procky.c b/src/lib/crypto/des/d3_procky.c new file mode 100644 index 000000000..1e50dd9fd --- /dev/null +++ b/src/lib/crypto/des/d3_procky.c @@ -0,0 +1,59 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "k5-int.h" +#include "des_int.h" + +krb5_error_code +mit_des3_process_key (eblock, keyblock) + krb5_encrypt_block * eblock; + const krb5_keyblock * keyblock; +{ + struct mit_des_ks_struct *schedule; /* pointer to key schedules */ + + if (keyblock->enctype != ENCTYPE_DES3_CBC_MD5) + return KRB5_PROG_ETYPE_NOSUPP; + + if (keyblock->length != sizeof (mit_des3_cblock)) + return KRB5_BAD_KEYSIZE; + + if ( !(schedule = (struct mit_des_ks_struct *) malloc(3*sizeof(mit_des_key_schedule))) ) + return ENOMEM; +#define cleanup() { free( (char *) schedule); } + + switch (mit_des3_key_sched (*(mit_des3_cblock *)keyblock->contents, + *(mit_des3_key_schedule *)schedule)) { + case -1: + cleanup(); + return KRB5DES_BAD_KEYPAR; + + case -2: + cleanup(); + return KRB5DES_WEAK_KEY; + } + + eblock->key = (krb5_keyblock *) keyblock; + eblock->priv = (krb5_pointer) schedule; + eblock->priv_size = (krb5_int32) 3*sizeof(mit_des_key_schedule); + + return 0; +} diff --git a/src/lib/crypto/des/d3_rndky.c b/src/lib/crypto/des/d3_rndky.c new file mode 100644 index 000000000..5edcf4d32 --- /dev/null +++ b/src/lib/crypto/des/d3_rndky.c @@ -0,0 +1,51 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "k5-int.h" +#include "des_int.h" + +krb5_error_code +mit_des3_random_key (eblock, seed, keyblock) + const krb5_encrypt_block * eblock; + krb5_pointer seed; + krb5_keyblock ** keyblock; +{ + krb5_keyblock *randkey; + + if (!(randkey = (krb5_keyblock *)malloc(sizeof(*randkey)))) + return ENOMEM; + if (!(randkey->contents=(krb5_octet *)malloc(sizeof(mit_des3_cblock)))) { + krb5_xfree(randkey); + return ENOMEM; + } + randkey->magic = KV5M_KEYBLOCK; + randkey->length = sizeof(mit_des3_cblock); + randkey->enctype = eblock->crypto_entry->proto_enctype; + mit_des_new_random_key(*(mit_des_cblock *)randkey->contents, + (mit_des_random_key_seed *) seed); + mit_des_new_random_key(*((mit_des_cblock *)randkey->contents + 1), + (mit_des_random_key_seed *) seed); + mit_des_new_random_key(*((mit_des_cblock *)randkey->contents + 2), + (mit_des_random_key_seed *) seed); + *keyblock = randkey; + return 0; +} diff --git a/src/lib/crypto/des/d3_str2ky.c b/src/lib/crypto/des/d3_str2ky.c new file mode 100644 index 000000000..5f4d7a050 --- /dev/null +++ b/src/lib/crypto/des/d3_str2ky.c @@ -0,0 +1,118 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "k5-int.h" +#include "des_int.h" + +/* + * Triple-DES string-to-key algorithm + * + * 1. Concatenate the input string and salt, and pad with zeroes until + * it is at least 24 bits, and a multiple of eight. + * 2. Fanfold the bits into a 24 bytes of key information (3 DES keys). + * 3. Use the three DES keys to perform a triple CBC encryption and return + * the last 24 bytes (similar to the MAC computation for DES in FIPS 81). + * + * This routine assumes that the triple CBC checksum will do the appropriate + * padding and that its return value will be 24 bytes. + */ + +static mit_des_cblock zero_ivec = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +krb5_error_code +mit_des3_string_to_key (eblock, keyblock, data, salt) +const krb5_encrypt_block FAR * eblock; +krb5_keyblock FAR * keyblock; +const krb5_data FAR * data; +const krb5_data FAR * salt; +{ + register char *str, *copystr; + register mit_des_cblock *key; + register int j; + + register long length; + mit_des3_key_schedule ks; + krb5_enctype enctype = eblock->crypto_entry->proto_enctype; + + if (enctype == ENCTYPE_DES3_CBC_MD5) + keyblock->length = sizeof(mit_des3_cblock); + else + return (KRB5_PROG_ETYPE_NOSUPP); + + if ( !(keyblock->contents = (krb5_octet *)malloc(keyblock->length)) ) + return(ENOMEM); + + keyblock->magic = KV5M_KEYBLOCK; + keyblock->enctype = enctype; + key = (mit_des_cblock *)keyblock->contents; + + if (salt) + length = data->length + salt->length; + else + length = data->length; + + if (length < keyblock->length) + length = keyblock->length; + + copystr = malloc((size_t) length); + if (!copystr) { + free(keyblock->contents); + keyblock->contents = 0; + return ENOMEM; + } + + memset(copystr, 0, length); + memcpy(copystr, (char *) data->data, data->length); + if (salt) + memcpy(copystr + data->length, (char *)salt->data, salt->length); + + /* n-fold into des3 key */ + if (mit_des_n_fold(copystr, length, keyblock->contents, keyblock->length)) + return EINVAL; + + /* fix key parity */ + for (j = 0; j < keyblock->length/sizeof(mit_des_cblock); j++) + mit_des_fixup_key_parity(*((mit_des_cblock *)key+j)); + + /* Now, CBC encrypt with itself */ + (void) mit_des3_key_sched(*((mit_des3_cblock *)key), ks); + (void) mit_des3_cbc_encrypt((mit_des_cblock *)key, + (mit_des_cblock *)key, + keyblock->length, + ((mit_des_key_schedule *)ks)[0], + ((mit_des_key_schedule *)ks)[1], + ((mit_des_key_schedule *)ks)[2], + zero_ivec, TRUE); + + /* erase key_sked */ + memset((char *)ks, 0, sizeof(ks)); + + /* clean & free the input string */ + memset(copystr, 0, (size_t) length); + krb5_xfree(copystr); + + /* now fix up key parity again */ + for (j = 0; j < keyblock->length/sizeof(mit_des_cblock); j++) + mit_des_fixup_key_parity(*((mit_des_cblock *)key+j)); + + return 0; +} diff --git a/src/lib/crypto/des/u_nfold.c b/src/lib/crypto/des/u_nfold.c new file mode 100644 index 000000000..3dd919962 --- /dev/null +++ b/src/lib/crypto/des/u_nfold.c @@ -0,0 +1,106 @@ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * + * N-folding algorithm + * Described in "A Better Key Schedule for DES-like Ciphers" + * by Uri Blumenthal and Steven M. Bellovin + * based on the work done by Lars Knudsen. + * + * To n-fold a number X, replicate the input value X to a length that is + * the least common multiple of n and the length of X. Before each + * repetition, the input value is rotated to the right by 13 bit positions. + * The successive n-bit chunks are added together using 1's complement + * addition (addition with end-around carry) to yield a n-bit result. + * + * The algorithm here assumes that the input and output are padded to + * octet boundaries (8-bit multiple). + */ + +#include "k5-int.h" +#include + +#define ROTATE_VALUE 13 + +krb5_error_code +mit_des_n_fold(inbuf, inlen, outbuf, outlen) + krb5_octet *inbuf; + size_t inlen; + krb5_octet *outbuf; + size_t outlen; +{ + register int bytes; + register krb5_octet *tempbuf; + + if (inbuf == (krb5_octet *)NULL) + return EINVAL; + if (outbuf == (krb5_octet *)NULL) + return EINVAL; + + tempbuf = (krb5_octet *)malloc(inlen); + if (tempbuf == (krb5_octet *)NULL) + return ENOMEM; + + memset(outbuf, 0, outlen); + bytes = 0; + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + + do { + int i, j; + register unsigned int k; + + if ((bytes % inlen) == 0) { + /* Rotate input */ + k = ((bytes/inlen) * ROTATE_VALUE) % (inlen*8); + + for (j = (k+7)/8; j < inlen + (k/7)/8; j++) + tempbuf[j % inlen] = + (inbuf[((8*j-k)/8)%inlen] & (((1<<(8-(k&7)))-1) <<(k&7))) + + (inbuf[((8*j-k)/8 + 1)%inlen] >> (8-(k&7))); + } + + + i = min(outlen - (bytes % outlen), inlen - (bytes % inlen)); + + j = i; + k = 0; + while (j--) { + k = outbuf[(bytes+j) % outlen] + tempbuf[(bytes+j) % inlen] + k; + outbuf[(bytes+j) % outlen] = k & 0xff; + k >>= 8; + } + + j = outlen-1; + while (k) { + assert(j >= 0); + k += outbuf[j]; + outbuf[j--] = k & 0xff; + k >>= 8; + } + + bytes += i; + } while (((bytes % inlen) == 0) && ((bytes % outlen) == 0)); + + return 0; +} -- 2.26.2