summaryrefslogtreecommitdiff
path: root/sys/src/libsec/port/aesXCBmac.c
blob: 6f17f87dbd8bf4a0cc1ab594fda87cd2cee7df6d (plain)
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
#include "os.h"
#include <libsec.h>

/*
 * AES-XCBC-MAC-96 message authentication, per rfc3566.
 */
static uchar basekey[3][16] = {
	{
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	},
	{
	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
	},
	{
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
	},
};

void
setupAESXCBCstate(AESstate *s)		/* was setupmac96 */
{
	int i, j;
	uint q[16 / sizeof(uint)];
	uchar *p;

	assert(s->keybytes == 16);
	for(i = 0; i < 3; i++)
		aes_encrypt(s->ekey, s->rounds, basekey[i],
			s->mackey + AESbsize*i);

	p = s->mackey;
	memset(q, 0, AESbsize);

	/*
	 * put the in the right endian.  once figured, probably better
	 * to use some fcall macros.
	 * keys for encryption in local endianness for the algorithm...
	 * only key1 is used for encryption;
	 * BUG!!: I think this is what I got wrong.
	 */
	for(i = 0; i < 16 / sizeof(uint); i ++){
		for(j = 0; j < sizeof(uint); j++)
			q[i] |= p[sizeof(uint)-j-1] << 8*j;
		p += sizeof(uint);
	}
	memmove(s->mackey, q, 16);
}

/*
 * Not dealing with > 128-bit keys, not dealing with strange corner cases like
 * empty message.  Should be fine for AES-XCBC-MAC-96.
 */
uchar*
aesXCBCmac(uchar *p, int len, AESstate *s)
{
	uchar *p2, *ip, *eip, *mackey;
	uchar q[AESbsize];

	assert(s->keybytes == 16);	/* more complicated for bigger */
	memset(s->ivec, 0, AESbsize);	/* E[0] is 0+ */

	for(; len > AESbsize; len -= AESbsize){
		memmove(q, p, AESbsize);
		p2 = q;
		ip = s->ivec;
		for(eip = ip + AESbsize; ip < eip; )
			*p2++ ^= *ip++;
		aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
		p += AESbsize;
	}
	/* the last one */

	memmove(q, p, len);
	p2 = q+len;
	if(len == AESbsize)
		mackey = s->mackey + AESbsize;	/* k2 */
	else{
		mackey = s->mackey+2*AESbsize;	/* k3 */
		*p2++ = 1 << 7;			/* padding */
		len = AESbsize - len - 1;
		memset(p2, 0, len);
	}

	ip = s->ivec;
	p2 = q;
	for(eip = ip + AESbsize; ip < eip; )
		*p2++ ^= *ip++ ^ *mackey++;
	aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
	return s->ivec;			/* only the 12 bytes leftmost */
}