Logo Search packages:      
Sourcecode: tac-plus version File versions  Download package

encrypt.c

/* 
   Copyright (c) 1995-2000 by Cisco systems, Inc.

   Permission to use, copy, modify, and distribute modified and
   unmodified copies of this software for any purpose and without fee is
   hereby granted, provided that (a) this copyright and permission notice
   appear on all copies of the software and supporting documentation, (b)
   the name of Cisco Systems, Inc. not be used in advertising or
   publicity pertaining to distribution of the program without specific
   prior permission, and (c) notice be given in supporting documentation
   that use, modification, copying and distribution is by permission of
   Cisco Systems, Inc.

   Cisco Systems, Inc. makes no representations about the suitability
   of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
   IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
   WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS FOR A PARTICULAR PURPOSE.
*/

#include "tac_plus.h"
#include "md5.h"

/*
 * create_md5_hash(): create an md5 hash of the "session_id", "the user's
 * key", "the version number", the "sequence number", and an optional
 * 16 bytes of data (a previously calculated hash). If not present, this
 * should be NULL pointer.
 *
 * Write resulting hash into the array pointed to by "hash".
 *
 * The caller must allocate sufficient space for the resulting hash
 * (which is 16 bytes long). The resulting hash can safely be used as
 * input to another call to create_md5_hash, as its contents are copied
 * before the new hash is generated.
 *
 *
 */

void
create_md5_hash(session_id, key, version, seq_no, prev_hash, hash)
int session_id;
char *key;
u_char version;
u_char seq_no;
u_char *prev_hash;
u_char *hash;
{
    u_char *md_stream, *mdp;
    int md_len;
    MD5_CTX mdcontext;

    md_len = sizeof(session_id) + strlen(key) + sizeof(version) +
      sizeof(seq_no);

    if (prev_hash) {
      md_len += MD5_LEN;
    }
    mdp = md_stream = (u_char *) tac_malloc(md_len);
    bcopy(&session_id, mdp, sizeof(session_id));
    mdp += sizeof(session_id);

    bcopy(key, mdp, strlen(key));
    mdp += strlen(key);

    bcopy(&version, mdp, sizeof(version));
    mdp += sizeof(version);

    bcopy(&seq_no, mdp, sizeof(seq_no));
    mdp += sizeof(seq_no);

    if (prev_hash) {
      bcopy(prev_hash, mdp, MD5_LEN);
      mdp += MD5_LEN;
    }
    MD5Init(&mdcontext);
    MD5Update(&mdcontext, md_stream, md_len);
    MD5Final(hash, &mdcontext);
    free(md_stream);
    return;
}

/*
 * Overwrite input data with en/decrypted version by generating an MD5 hash and
 * xor'ing data with it.
 *
 * When more than 16 bytes of hash is needed, the MD5 hash is performed
 * again with the same values as before, but with the previous hash value
 * appended to the MD5 input stream.
 *
 * Return 0 on success, -1 on failure.
 */

md5_xor(hdr, data, key)
HDR *hdr;
u_char *data;
char *key;
{
    int i, j;
    u_char hash[MD5_LEN];     /* the md5 hash */
    u_char last_hash[MD5_LEN];      /* the last hash we generated */
    u_char *prev_hashp = (u_char *) NULL; /* pointer to last created
                                     * hash */
    int data_len;
    int session_id;
    u_char version;
    u_char seq_no;

    data_len = ntohl(hdr->datalength);
    session_id = hdr->session_id; /* always in network order for hashing */
    version = hdr->version;
    seq_no = hdr->seq_no;

    if (!key)
      return (0);

    for (i = 0; i < data_len; i += 16) {

      create_md5_hash(session_id, key, version, seq_no, prev_hashp, hash);

      if (debug & DEBUG_MD5_HASH_FLAG) {
          int k;

          report(LOG_DEBUG, 
               "hash: session_id=%u, key=%s, version=%d, seq_no=%d",
               session_id, key, version, seq_no);
          if (prev_hashp) {
            report(LOG_DEBUG, "prev_hash:");
            for (k = 0; k < MD5_LEN; k++)
                report(LOG_DEBUG, "0x%x", prev_hashp[k]);
          } else {
            report(LOG_DEBUG, "no prev. hash");
          }

          report(LOG_DEBUG, "hash: ");
          for (k = 0; k < MD5_LEN; k++)
            report(LOG_DEBUG, "0x%x", hash[k]);
      }                 /* debug */
      bcopy(hash, last_hash, MD5_LEN);
      prev_hashp = last_hash;

      for (j = 0; j < 16; j++) {

          if ((i + j) >= data_len) {
            hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR) 
                ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
            return (0);
          }
          if (debug & DEBUG_XOR_FLAG) {
            report(LOG_DEBUG,
               "data[%d] = 0x%x, xor'ed with hash[%d] = 0x%x -> 0x%x\n",
                   i + j,
                   data[i + j],
                   j,
                   hash[j],
                   data[i + j] ^ hash[j]);
          }             /* debug */
          data[i + j] ^= hash[j];
      }
    }
    hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR) 
      ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
    return (0);
}

Generated by  Doxygen 1.6.0   Back to index