/* * auth12crypt.c - routines to support two stage NTP encryption */ #include "ntp_stdlib.h" /* * For our purposes an NTP packet looks like: * * a variable amount of encrypted data, multiple of 8 bytes, which * is encrypted in pass 1, followed by: * an 8 byte chunk of data which is encrypted in pass 2 * NOCRYPT_OCTETS worth of unencrypted data, followed by: * BLOCK_OCTETS worth of ciphered checksum. */ #define NOCRYPT_OCTETS 4 #define BLOCK_OCTETS 8 #define NOCRYPT_LONGS ((NOCRYPT_OCTETS)/sizeof(U_LONG)) #define BLOCK_LONGS ((BLOCK_OCTETS)/sizeof(U_LONG)) /* * Imported from the key data base module */ extern u_long cache_keyid; /* cached key ID */ extern u_char DEScache_ekeys[]; /* cached decryption keys */ extern u_char DESzeroekeys[]; /* zero key decryption keys */ /* * Stat counters, from the database module */ extern U_LONG authencryptions; extern U_LONG authkeyuncached; extern U_LONG authnokey; /* * auth1crypt - do the first stage of a two stage encryption */ void DESauth1crypt(keyno, pkt, length) u_long keyno; U_LONG *pkt; int length; /* length of all encrypted data */ { register U_LONG *pd; register int i; register u_char *keys; U_LONG work[2]; authencryptions++; if (keyno == 0) { keys = DESzeroekeys; } else { if (keyno != cache_keyid) { authkeyuncached++; if (!authhavekey(keyno)) { authnokey++; return; } } keys = DEScache_ekeys; } /* * Do the first five encryptions. Stick the intermediate result * in the mac field. The sixth encryption must wait until the * caller freezes a transmit time stamp, and will be done in stage 2. */ pd = pkt; work[0] = work[1] = 0; for (i = (length/BLOCK_OCTETS - 1); i > 0; i--) { work[0] ^= *pd++; work[1] ^= *pd++; DESauth_des(work, keys); } /* * Space to the end of the packet and stick the intermediate * result in the mac field. */ pd += BLOCK_LONGS + NOCRYPT_LONGS; *pd++ = work[0]; *pd = work[1]; } /* * auth2crypt - do the second stage of a two stage encryption */ int DESauth2crypt(keyno, pkt, length) u_long keyno; U_LONG *pkt; int length; /* total length of encrypted area */ { register U_LONG *pd; register u_char *keys; /* * Skip the key check. The call to the first stage should * have got it. */ if (keyno == 0) keys = DESzeroekeys; else keys = DEScache_ekeys; /* * The mac currently should hold the results of the first `n' * encryptions. We xor in the last block in data section and * do the final encryption in place. * * Get a pointer to the MAC block. XOR in the last two words of * the data area. Call the encryption routine. */ pd = pkt + (length/sizeof(U_LONG)) + NOCRYPT_LONGS; *pd ^= *(pd - NOCRYPT_LONGS - 2); *(pd + 1) ^= *(pd - NOCRYPT_LONGS - 1); DESauth_des(pd, keys); return 4 + 8; /* return size of key number and MAC */ }