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 * create_md5_hash(): create an md5 hash of the "session_id", "the user's
25 * key", "the version number", the "sequence number", and an optional
26 * 16 bytes of data (a previously calculated hash). If not present, this
27 * should be NULL pointer.
29 * Write resulting hash into the array pointed to by "hash".
31 * The caller must allocate sufficient space for the resulting hash
32 * (which is 16 bytes long). The resulting hash can safely be used as
33 * input to another call to create_md5_hash, as its contents are copied
34 * before the new hash is generated.
40 create_md5_hash(session_id, key, version, seq_no, prev_hash, hash)
48 u_char *md_stream, *mdp;
52 md_len = sizeof(session_id) + strlen(key) + sizeof(version) +
58 mdp = md_stream = (u_char *) tac_malloc(md_len);
59 bcopy(&session_id, mdp, sizeof(session_id));
60 mdp += sizeof(session_id);
62 bcopy(key, mdp, strlen(key));
65 bcopy(&version, mdp, sizeof(version));
66 mdp += sizeof(version);
68 bcopy(&seq_no, mdp, sizeof(seq_no));
69 mdp += sizeof(seq_no);
72 bcopy(prev_hash, mdp, MD5_LEN);
76 MD5Update(&mdcontext, md_stream, md_len);
77 MD5Final(hash, &mdcontext);
83 * Overwrite input data with en/decrypted version by generating an MD5 hash and
84 * xor'ing data with it.
86 * When more than 16 bytes of hash is needed, the MD5 hash is performed
87 * again with the same values as before, but with the previous hash value
88 * appended to the MD5 input stream.
90 * Return 0 on success, -1 on failure.
93 md5_xor(hdr, data, key)
99 u_char hash[MD5_LEN]; /* the md5 hash */
100 u_char last_hash[MD5_LEN]; /* the last hash we generated */
101 u_char *prev_hashp = (u_char *) NULL; /* pointer to last created
108 data_len = ntohl(hdr->datalength);
109 session_id = hdr->session_id; /* always in network order for hashing */
110 version = hdr->version;
111 seq_no = hdr->seq_no;
116 for (i = 0; i < data_len; i += 16) {
118 create_md5_hash(session_id, key, version, seq_no, prev_hashp, hash);
120 if (debug & DEBUG_MD5_HASH_FLAG) {
124 "hash: session_id=%u, key=%s, version=%d, seq_no=%d",
125 session_id, key, version, seq_no);
127 report(LOG_DEBUG, "prev_hash:");
128 for (k = 0; k < MD5_LEN; k++)
129 report(LOG_DEBUG, "0x%x", prev_hashp[k]);
131 report(LOG_DEBUG, "no prev. hash");
134 report(LOG_DEBUG, "hash: ");
135 for (k = 0; k < MD5_LEN; k++)
136 report(LOG_DEBUG, "0x%x", hash[k]);
138 bcopy(hash, last_hash, MD5_LEN);
139 prev_hashp = last_hash;
141 for (j = 0; j < 16; j++) {
143 if ((i + j) >= data_len) {
144 hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR)
145 ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
148 if (debug & DEBUG_XOR_FLAG) {
150 "data[%d] = 0x%x, xor'ed with hash[%d] = 0x%x -> 0x%x\n",
155 data[i + j] ^ hash[j]);
157 data[i + j] ^= hash[j];
160 hdr->encryption = (hdr->encryption == TAC_PLUS_CLEAR)
161 ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;