/*
 * authencrypt - compute and encrypt the mac field in an NTP packet
 */
#include "ntp_stdlib.h"

/*
 * For our purposes an NTP packet looks like:
 *
 *	a variable amount of encrypted data, multiple of 8 bytes, followed by:
 *	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;

int
DESauthencrypt(keyno, pkt, length)
	u_long keyno;
	U_LONG *pkt;
	int length;	/* length of encrypted portion of packet */
{
	register U_LONG *pd;
	register int i;
	register u_char *keys;
	register int len;
	U_LONG work[2];

	authencryptions++;

	if (keyno == 0) {
		keys = DESzeroekeys;
	} else {
		if (keyno != cache_keyid) {
			authkeyuncached++;
			if (!authhavekey(keyno)) {
				authnokey++;
				return 0;
			}
		}
		keys = DEScache_ekeys;
	}

	/*
	 * Do the encryption.  Work our way forward in the packet, eight
	 * bytes at a time, encrypting as we go.  Note that the byte order
	 * issues are handled by the DES routine itself
	 */
	pd = pkt;
	work[0] = work[1] = 0;
	len = length / sizeof(U_LONG);

	for (i = (len/2); i > 0; i--) {
		work[0] ^= *pd++;
		work[1] ^= *pd++;
		DESauth_des(work, keys);
	}

	if (len & 0x1) {
		work[0] ^= *pd++;
		DESauth_des(work, keys);
	}

	/*
	 * Space past the keyid and stick the result back in the mac field
	 */
	pd += NOCRYPT_LONGS;
	*pd++ = work[0];
	*pd = work[1];

	return 4 + BLOCK_OCTETS;	/* return size of key and MAC  */
}
