/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* lib/crypto/builtin/des/f_cksum.c */ /* * Copyright (C) 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. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * 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. */ /* DES implementation donated by Dennis Ferguson */ /* * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode */ #include "des_int.h" #include "f_tables.h" /* * This routine performs DES cipher-block-chaining checksum operation, * a.k.a. Message Authentication Code. It ALWAYS encrypts from input * to a single 64 bit output MAC checksum. * * The key schedule is passed as an arg, as well as the cleartext or * ciphertext. The cleartext and ciphertext should be in host order. * * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was * provided, your program will get trashed. * * The input is null padded, at the end (highest addr), to an integral * multiple of eight bytes. */ unsigned long mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, unsigned long length, const mit_des_key_schedule schedule, const krb5_octet *ivec) { unsigned DES_INT32 left, right; const unsigned DES_INT32 *kp; const unsigned char *ip; unsigned char *op; DES_INT32 len; /* * Initialize left and right with the contents of the initial * vector. */ ip = ivec; GET_HALF_BLOCK(left, ip); GET_HALF_BLOCK(right, ip); /* * Suitably initialized, now work the length down 8 bytes * at a time. */ ip = in; len = length; while (len > 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 (len >= 8) { unsigned DES_INT32 temp; GET_HALF_BLOCK(temp, ip); left ^= temp; GET_HALF_BLOCK(temp, ip); right ^= temp; len -= 8; } else { /* * Oh, shoot. We need to pad the * end with zeroes. Work backwards * to do this. */ ip += (int) len; switch(len) { 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; break; } len = 0; } /* * Encrypt what we have */ kp = (const unsigned DES_INT32 *)schedule; DES_DO_ENCRYPT(left, right, kp); } /* * Done. Left and right have the checksum. Put it into * the output. */ op = out; PUT_HALF_BLOCK(left, op); PUT_HALF_BLOCK(right, op); /* * Return right. I'll bet the MIT code returns this * inconsistantly (with the low order byte of the checksum * not always in the low order byte of the DES_INT32). We won't. */ return right & 0xFFFFFFFFUL; }