summaryrefslogtreecommitdiff
path: root/sys/src/libsec/port/aesXCBmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/src/libsec/port/aesXCBmac.c')
-rw-r--r--sys/src/libsec/port/aesXCBmac.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/sys/src/libsec/port/aesXCBmac.c b/sys/src/libsec/port/aesXCBmac.c
new file mode 100644
index 000000000..6f17f87db
--- /dev/null
+++ b/sys/src/libsec/port/aesXCBmac.c
@@ -0,0 +1,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 */
+}