1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
#include <config.h>

#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>

#include <glib.h>

#include "skey.h"
#include "skeyutil.h"
#include "sha1.h"


#define HTONDIGEST(x) { \
      x[0] = htonl(x[0]); \
      x[1] = htonl(x[1]); \
      x[2] = htonl(x[2]); \
      x[3] = htonl(x[3]); \
      x[4] = htonl(x[4]); }

#ifdef WORDS_BIGENDIAN
/*
 * Note: this code is harmless on little-endian machines.
 */
static void byteReverse(unsigned char *buf, unsigned longs)
{
	guint32 t;
	do
	{
		t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
		    ((unsigned) buf[1] << 8 | buf[0]);
		*(guint32 *) buf = t;
		buf += 4;
	}
	while (--longs);
}
#endif


int SHA1Keycrunch(char *result, const char *seed, const char *passphrase)
{
	char *buf;
	gsize len;
	GChecksum *checksum;
	guint8 digest[20];
	gsize digest_len = sizeof (digest);
	guint32 *results;

	len = strlen(seed) + strlen(passphrase);
	if ((buf = (char *)g_try_malloc(len+1)) == NULL)
		return -1;

	strcpy(buf, seed);
	skey_lowcase(buf);
	strcat(buf, passphrase);
	skey_sevenbit(buf);

	checksum = g_checksum_new (G_CHECKSUM_SHA1);
	g_checksum_update (checksum, (const guchar *) buf, len);
	g_free(buf);

	g_checksum_get_digest (checksum, digest, &digest_len);
	g_assert (digest_len == 20);

#ifndef WORDS_BIGENDIAN
	results = (guint32 *) digest;
	HTONDIGEST(results);
#else
	byteReverse((unsigned char *)digest, 5);
#endif

	results = (guint32 *) digest;
	results[0] ^= results[2];
	results[1] ^= results[3];
	results[0] ^= results[4];

	memcpy((void *)result, (void *)results, SKEY_SIZE);

	g_checksum_free (checksum);

	return 0;
}

void SHA1SKey(char *x)
{
	GChecksum *checksum;
	guint8 digest[20];
	gsize digest_len = sizeof (digest);
	guint32 *results;

	checksum = g_checksum_new (G_CHECKSUM_SHA1);
	g_checksum_update (checksum, (const guchar *) x, SKEY_SIZE);
	g_checksum_get_digest (checksum, digest, &digest_len);
	g_assert (digest_len == 20);

	results = (guint32 *) digest;
#ifndef WORDS_BIGENDIAN
	HTONDIGEST(results);
#else
	byteReverse((unsigned char *)digest, 5);
#endif

	results[0] ^= results[2];
	results[1] ^= results[3];
	results[0] ^= results[4];

	memcpy((void *)x, (void *)results, SKEY_SIZE);

	g_checksum_free (checksum);
}