]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libsec/port/aesXCBmac.c
libsec: implement SPKI fingerprinting for okCertificate()
[plan9front.git] / sys / src / libsec / port / aesXCBmac.c
1 #include "os.h"
2 #include <libsec.h>
3
4 /*
5  * AES-XCBC-MAC-96 message authentication, per rfc3566.
6  */
7 static uchar basekey[3][16] = {
8         {
9         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
10         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
11         },
12         {
13         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
14         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
15         },
16         {
17         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
18         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
19         },
20 };
21
22 void
23 setupAESXCBCstate(AESstate *s)          /* was setupmac96 */
24 {
25         int i, j;
26         uint q[16 / sizeof(uint)];
27         uchar *p;
28
29         assert(s->keybytes == 16);
30         for(i = 0; i < 3; i++)
31                 aes_encrypt(s->ekey, s->rounds, basekey[i],
32                         s->mackey + AESbsize*i);
33
34         p = s->mackey;
35         memset(q, 0, AESbsize);
36
37         /*
38          * put the in the right endian.  once figured, probably better
39          * to use some fcall macros.
40          * keys for encryption in local endianness for the algorithm...
41          * only key1 is used for encryption;
42          * BUG!!: I think this is what I got wrong.
43          */
44         for(i = 0; i < 16 / sizeof(uint); i ++){
45                 for(j = 0; j < sizeof(uint); j++)
46                         q[i] |= p[sizeof(uint)-j-1] << 8*j;
47                 p += sizeof(uint);
48         }
49         memmove(s->mackey, q, 16);
50 }
51
52 /*
53  * Not dealing with > 128-bit keys, not dealing with strange corner cases like
54  * empty message.  Should be fine for AES-XCBC-MAC-96.
55  */
56 uchar*
57 aesXCBCmac(uchar *p, int len, AESstate *s)
58 {
59         uchar *p2, *ip, *eip, *mackey;
60         uchar q[AESbsize];
61
62         assert(s->keybytes == 16);      /* more complicated for bigger */
63         memset(s->ivec, 0, AESbsize);   /* E[0] is 0+ */
64
65         for(; len > AESbsize; len -= AESbsize){
66                 memmove(q, p, AESbsize);
67                 p2 = q;
68                 ip = s->ivec;
69                 for(eip = ip + AESbsize; ip < eip; )
70                         *p2++ ^= *ip++;
71                 aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
72                 p += AESbsize;
73         }
74         /* the last one */
75
76         memmove(q, p, len);
77         p2 = q+len;
78         if(len == AESbsize)
79                 mackey = s->mackey + AESbsize;  /* k2 */
80         else{
81                 mackey = s->mackey+2*AESbsize;  /* k3 */
82                 *p2++ = 1 << 7;                 /* padding */
83                 len = AESbsize - len - 1;
84                 memset(p2, 0, len);
85         }
86
87         ip = s->ivec;
88         p2 = q;
89         for(eip = ip + AESbsize; ip < eip; )
90                 *p2++ ^= *ip++ ^ *mackey++;
91         aes_encrypt((ulong *)s->mackey, s->rounds, q, s->ivec);
92         return s->ivec;                 /* only the 12 bytes leftmost */
93 }