2 Copyright (c) 1995-1998 by Cisco systems, Inc.
4 Permission to use, copy, modify, and distribute this software for
5 any purpose and without fee is hereby granted, provided that this
6 copyright and permission notice appear on all copies of the
7 software and supporting documentation, the name of Cisco Systems,
8 Inc. not be used in advertising or publicity pertaining to
9 distribution of the program without specific prior permission, and
10 notice be given in supporting documentation that modification,
11 copying and distribution is by permission of Cisco Systems, Inc.
13 Cisco Systems, Inc. makes no representations about the suitability
14 of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
15 IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16 WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS FOR A PARTICULAR PURPOSE.
24 #include <netinet/in.h> /* for ntohl() */
35 * create_md5_hash(): create an md5 hash of the "session_id", "the user's
36 * key", "the version number", the "sequence number", and an optional
37 * 16 bytes of data (a previously calculated hash). If not present, this
38 * should be NULL pointer.
40 * Write resulting hash into the array pointed to by "hash".
42 * The caller must allocate sufficient space for the resulting hash
43 * (which is 16 bytes long). The resulting hash can safely be used as
44 * input to another call to create_md5_hash, as its contents are copied
45 * before the new hash is generated.
50 static void create_md5_hash TAC_ARGS((int session_id, const char *key, unsigned version, unsigned seq_no, u_char *prev_hash, u_char *hash));
53 create_md5_hash(session_id, key, version, seq_no, prev_hash, hash)
56 unsigned version; /* promoted "u_char" type */
57 unsigned seq_no; /* promoted "u_char" type */
61 u_char *md_stream, *mdp;
64 u_char version_uchar = version;
65 u_char seq_no_uchar = seq_no;
67 md_len = sizeof(session_id) + strlen(key) + sizeof(version_uchar) +
73 mdp = md_stream = (u_char *) tac_malloc(md_len);
74 bcopy(&session_id, mdp, sizeof(session_id));
75 mdp += sizeof(session_id);
77 bcopy(key, mdp, strlen(key));
80 bcopy(&version_uchar, mdp, sizeof(version_uchar));
81 mdp += sizeof(version_uchar);
83 bcopy(&seq_no_uchar, mdp, sizeof(seq_no_uchar));
84 mdp += sizeof(seq_no_uchar);
87 bcopy(prev_hash, mdp, MD5_LEN);
91 MD5Update(&mdcontext, md_stream, md_len);
92 MD5Final(hash, &mdcontext);
98 * Overwrite input data with en/decrypted version by generating an MD5 hash and
99 * xor'ing data with it.
101 * When more than 16 bytes of hash is needed, the MD5 hash is performed
102 * again with the same values as before, but with the previous hash value
103 * appended to the MD5 input stream.
105 * Return 0 on success, -1 on failure.
108 int md5_xor TAC_ARGS((HDR *hdr, u_char *data, const char *key));
111 md5_xor(hdr, data, key)
117 u_char hash[MD5_LEN]; /* the md5 hash */
118 u_char last_hash[MD5_LEN]; /* the last hash we generated */
119 u_char *prev_hashp = (u_char *) NULL; /* pointer to last created
126 data_len = ntohl(hdr->datalength);
127 session_id = hdr->session_id; /* always in network order for hashing */
128 version = hdr->version;
129 seq_no = hdr->seq_no;
134 for (i = 0; i < data_len; i += 16) {
136 create_md5_hash(session_id, key, version, seq_no, prev_hashp, hash);
138 if (debug & DEBUG_MD5_HASH_FLAG) {
142 "hash: session_id=%u, key=%s, version=%d, seq_no=%d",
143 session_id, key, version, seq_no);
145 report(LOG_DEBUG, "prev_hash:");
146 for (k = 0; k < MD5_LEN; k++)
147 report(LOG_DEBUG, "0x%x", prev_hashp[k]);
149 report(LOG_DEBUG, "no prev. hash");
152 report(LOG_DEBUG, "hash: ");
153 for (k = 0; k < MD5_LEN; k++)
154 report(LOG_DEBUG, "0x%x", hash[k]);
156 bcopy(hash, last_hash, MD5_LEN);
157 prev_hashp = last_hash;
159 for (j = 0; j < 16; j++) {
161 if ((i + j) >= data_len) {
162 hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR)
163 ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
166 if (debug & DEBUG_XOR_FLAG) {
168 "data[%d] = 0x%x, xor'ed with hash[%d] = 0x%x -> 0x%x\n",
173 data[i + j] ^ hash[j]);
175 data[i + j] ^= hash[j];
178 hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR)
179 ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;