/*
* Convert character string to 56-bit DES key, contained in 8 bytes
* (including parity):
* - Strip leading and trailing white space; compress multiple spaces
* - compute MD5 hash
* - extract 7 bit pieces into bytes
* - compute parity
*
* The algorithm specifier must be 16 bytes long.
*/

#include "netfone.h"

#ifdef CRYPTO

#define MAX_KEY 256

#define MD_CTX struct MD5Context
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final

void string_DES_key(LPSTR key, LPBYTE dk, char algorithm[16])
{
	LPSTR s, d;
	char c[MAX_KEY + 1], cw[MAX_KEY + 1];
	int seen_white = 0;
	unsigned char digest[16];
	MD_CTX context;
	unsigned char des_key[8];
	
	/* white space trimming, conversion and compression */
	for (s = key, d = c; *s && ((d - (LPSTR) c) < MAX_KEY); s++) {
		if (isspace(*s)) {
			seen_white = 1;
		}
		else {
			if (seen_white) {
				seen_white = 0;
				if (d != c) *d++ = ' ';
			}
			*d++ = tolower(*s);
		}
	}
	*d = '\0';
	
	/* extract algorithm specifier, if any */
	strcpy(algorithm, "DES-CBC");
	if ((s = _fstrchr(c, '/')) && s - key < 16) {
		*s = '\0';
		s++; /* skip slash */
		for (d = c; *d; d++) {
			*d = toupper(*d);
		}
		strcpy(algorithm, c);
	} else {
		s = c;
	}
	
	/* compute MD5 hash */
	MDInit(&context);
	_fstrcpy(cw, s);
	MDUpdate(&context, (unsigned char *) cw, _fstrlen(cw));
	MDFinal(digest, &context);
	
	/* extract 8 7-bit bytes */
	des_key[0] = (digest[0] & 0xfe) >> 1;
	des_key[1] = ((digest[0] & 0x01) << 6) | ((digest[1] & 0xfc) >> 2);
	des_key[2] = ((digest[1] & 0x03) << 5) | ((digest[2] & 0xf8) >> 3);
	des_key[3] = ((digest[2] & 0x07) << 4) | ((digest[3] & 0xf0) >> 4);
	des_key[4] = ((digest[3] & 0x0f) << 3) | ((digest[4] & 0xe0) >> 5);
	des_key[5] = ((digest[4] & 0x1f) << 2) | ((digest[5] & 0xc0) >> 6);
	des_key[6] = ((digest[5] & 0x3f) << 1) | ((digest[6] & 0x80) >> 7);
	des_key[7] = digest[6] & 0x0f;
	
	/* compute parity */
	des_set_odd_parity((des_cblock *) des_key);
	_fmemcpy(dk, des_key, 8);
}
#endif
