/* $OpenBSD: umac.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */
/* -----------------------------------------------------------------------
*
* umac.c -- C Implementation UMAC Message Authentication
*
* Version 0.93b of rfc4418.txt -- 2006 July 18
*
* For a full description of UMAC message authentication see the UMAC
* world-wide-web page at http://www.cs.ucdavis.edu/~rogaway/umac
* Please report bugs and suggestions to the UMAC webpage.
*
* Copyright (c) 1999-2006 Ted Krovetz
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and with or without fee, is hereby
* granted provided that the above copyright notice appears in all copies
* and in supporting documentation, and that the name of the copyright
* holder not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
*
* Comments should be directed to Ted Krovetz (tdk@acm.org)
*
* ---------------------------------------------------------------------- */
/* ////////////////////// IMPORTANT NOTES /////////////////////////////////
*
* 1) This version does not work properly on messages larger than 16MB
*
* 2) If you set the switch to use SSE2, then all data must be 16-byte
* aligned
*
* 3) When calling the function umac(), it is assumed that msg is in
* a writable buffer of length divisible by 32 bytes. The message itself
* does not have to fill the entire buffer, but bytes beyond msg may be
* zeroed.
*
* 4) Three free AES implementations are supported by this implementation of
* UMAC. Paulo Barreto's version is in the public domain and can be found
* at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ (search for
* "Barreto"). The only two files needed are rijndael-alg-fst.c and
* rijndael-alg-fst.h. Brian Gladman's version is distributed with the GNU
* Public lisence at http://fp.gladman.plus.com/AES/index.htm. It
* includes a fast IA-32 assembly version. The OpenSSL crypo library is
* the third.
*
* 5) With FORCE_C_ONLY flags set to 0, incorrect results are sometimes
* produced under gcc with optimizations set -O3 or higher. Dunno why.
*
/////////////////////////////////////////////////////////////////////// */
/* ---------------------------------------------------------------------- */
/* --- User Switches ---------------------------------------------------- */
/* ---------------------------------------------------------------------- */
#ifndef UMAC_OUTPUT_LEN
#define UMAC_OUTPUT_LEN 8 /* Alowable: 4, 8, 12, 16 */
#endif
#if UMAC_OUTPUT_LEN != 4 && UMAC_OUTPUT_LEN != 8 && \
UMAC_OUTPUT_LEN != 12 && UMAC_OUTPUT_LEN != 16
# error UMAC_OUTPUT_LEN must be defined to 4, 8, 12 or 16
#endif
/* #define FORCE_C_ONLY 1 ANSI C and 64-bit integers req'd */
/* #define AES_IMPLEMENTAION 1 1 = OpenSSL, 2 = Barreto, 3 = Gladman */
/* #define SSE2 0 Is SSE2 is available? */
/* #define RUN_TESTS 0 Run basic correctness/speed tests */
/* #define UMAC_AE_SUPPORT 0 Enable auhthenticated encrytion */
/* ---------------------------------------------------------------------- */
/* -- Global Includes --------------------------------------------------- */
/* ---------------------------------------------------------------------- */
#include "includes.h"
#include <sys/types.h>
#include "xmalloc.h"
#include "umac.h"
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
/* ---------------------------------------------------------------------- */
/* --- Primitive Data Types --- */
/* ---------------------------------------------------------------------- */
/* The following assumptions may need change on your system */
typedef u_int8_t UINT8; /* 1 byte */
typedef u_int16_t UINT16; /* 2 byte */
typedef u_int32_t UINT32; /* 4 byte */
typedef u_int64_t UINT64; /* 8 bytes */
typedef unsigned int UWORD; /* Register */
/* ---------------------------------------------------------------------- */
/* --- Constants -------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
#define UMAC_KEY_LEN 16 /* UMAC takes 16 bytes of external key */
/* Message "words" are read from memory in an endian-specific manner. */
/* For this implementation to behave correctly, __LITTLE_ENDIAN__ must */
/* be set true if the host computer is little-endian. */
#if BYTE_ORDER == LITTLE_ENDIAN
#define __LITTLE_ENDIAN__ 1
#else
#define __LITTLE_ENDIAN__ 0
#endif
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ----- Architecture Specific ------------------------------------------ */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ----- Primitive Routines --------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* --- 32-bit by 32-bit to 64-bit Multiplication ------------------------ */
/* ---------------------------------------------------------------------- */
#define MUL64(a,b) ((UINT64)((UINT64)(UINT32)(a) * (UINT64)(UINT32)(b)))
/* ---------------------------------------------------------------------- */
/* --- Endian Conversion --- Forcing assembly