Вы находитесь на странице: 1из 18

Badger Message Authentication Code,

Algorithm Specification

May 12, 2005

White Paper, Version 1.0

CRYPTICO A/S
Fruebjergvej 3
2100 Copenhagen
Denmark
info@cryptico.com
Cryptico A/S Badger MAC, Algorithm Specification

Copyright Notice

c 2003-2005 Cryptico A/S. All rights reserved. All title and copyrights in and to this document
Copyright °
are owned by Cryptico A/S and/or its suppliers. Any commercial use or redistribution of this document is not
allowed without the prior written consent of Cryptico A/S. Non-commercial redistribution of this document is
allowed provided that the document is redistributed in its entirety and that this legal notice is not removed or
altered in any way. Cryptico A/S shall not in any way be liable for any use of the document. This document
is provided “as is” without any express or implied warranty for its contents.
Some or all of the work described or mentioned in this document may be patented or patent pending. All title
and intellectual property rights in and to the work, including, but not limited to, patent rights and copyrights,
are owned by Cryptico A/S and/or its suppliers. For further information on licensing terms and conditions,
please contact Cryptico at info@cryptico.com.
Cryptico, CryptiCore, the Cryptico logo and “Re-thinking encryption” are trademarks of Cryptico A/S.

2
Cryptico A/S Badger MAC, Algorithm Specification

1 Introduction

This document describes the Badger Message Authentication Code (MAC), including the key
setup and IV setup schemes. It furthermore describes the Application Programming Interface
(API) of the C example source code presented in Appendix A. Appendix B presents some
test vectors.
The Badger source code and a test program are available in a zip-file at www.cryptico.com.

1.1 Notation

In the following, p will denote the prime number 232 −5. We define Zp to be the set {0, . . . , p−1}
and {0, 1}n to be the set {0, . . . , 2n − 1} (for any positive integer n). By +n , we mean addition
modulo 2n , while + and · denote standard addition and multiplication over the integers. Given
a 2n-bit string x, we denote its least significant n bits by L(x) and its most significant n bits
by U (x). 0n is the binary string consisting of n zeroes. By M , we denote the message to be
hashed, and |M | denotes its length in bits. Mmax is the largest possible input message.
When the stream cipher Rabbit is used in algorithmic descriptions, the following pseudo-code
function calls are used:
• RabbitKeySetup(K): Initializes Rabbit with the 128-bit key K.
• RabbitIVSetup(N ): Initializes Rabbit with the 64-bit nonce N .
• RabbitNextbit(n): Returns n bits of pseudorandom output.

1.2 Byte order

By a||b, we denote the concatenation of the two bitstrings a and b. For n-byte values, the
least significant byte (LSByte) is written to the right, e.g. if a has n bytes, we have a =
an || . . . ||a1 . In particular, if a and b are n-byte values, then a||b results in the byte order
an || . . . ||a1 ||bn || . . . ||b1 .
This byte order corresponds to the natural byte order of little endian processors. Likewise,
the C code found in appendix A is written for little endian machines. For a big endian, byte
order has to be swapped where appropriate.

2 The Badger Algorithm

The Badger message authentication code processes a message of length up to 264 − 1 bit into
an authentication tag of length u · 32 bit, where u (1 ≤ u ≤ 5) can be chosen by the user
according to the security needs1 . The value u defines the number of parallel hash trees within
Badger. The algorithm uses a 128-bit key, and the number of messages to be processed under
this key is limited to 264 .
In order to run the Badger algorithm under a given key, the key setup has to be run just once.
The resulting internal state of the MAC can be saved for use with any other message that is
to be processed later. For every message, two steps have to be executed: In the processing
phase, the data is hashed onto a 64-bit string, and in the finalize phase, this string is
transformed into the desired MAC tag.
1
Note that larger values for u are also possible, but they do not contribute further to the security of the
MAC.

3
Cryptico A/S Badger MAC, Algorithm Specification

2.1 Key Setup


Badger uses the Rabbit stream cipher to initialize the internal state. For each of its u parallel
hash trees, Badger requires 6 finalize keys from Zp (for the finalize phase) and v level keys
from {0, 1}64 (for the processing phase), where v = max{1, dlog2 |Mmax |e − 6}. These are
generated as described in figure 1.

RabbitKeySetup(K)
words used = 0

// Assign 32-bit values to finalize keys


for j = 1 to 6:
for i = 1 to u:
final key[j][i] = RabbitNextbit(32)
words used++

// Test whether they are in Zp


for j = 1 to 6:
for i = 1 to u:
while(final key[j][i] ≥ p)
final key[j][i] = RabbitNextbit(32)
words used++

// Empty buffer
while(words used mod 4 6= 0):
discard RabbitNextbit(32)
words used++

// Assign 64-bit values to level keys


for j = 1 to v:
for i = 1 to u:
level key[j][i] = RabbitNextbit(64)

Fig. 1. Pseudo-code of the key setup

2.2 Processing Phase


The processing phase uses a core function h : {0, 1}64 × {0, 1}128 → {0, 1}64 , which hashes a
128-bit string m2 ||m1 under a 64-bit key k to a 64-bit string h(k, m2 , m1 ) as follows:

h(k, m2 , m1 ) = (L(m1 ) +32 L(k)) · (U (m1 ) +32 U (k)) +64 m2 .

Using this function and denoting level key[j][i] by kji , the processing of a message can
proceed as described in figure 2.

2.3 Finalization Phase


The finalization phase requires the Rabbit stream cipher, this time using both key setup
and IV setup. In most applications, a new IV is used for every tag that is to be generated.

4
Cryptico A/S Badger MAC, Algorithm Specification

L = |M |
if L = 0
M1 = . . . = Mu = 0
Go to finalization
r = L mod 64
if r 6= 0:
M = 064−r ||M
for i = 1 to u:
Mi = M
v 0 = max{1, dlog2 Le − 6}
for j = 1 to v 0 :
divide M i into 64-bit blocks, M i = mit || . . . ||mi1
if t is even:
M i = h(kji , mit , mit−1 )|| . . . ||h(kji , mi2 , mi1 )
else:
M i = mit ||h(kji , mit−1 , mit−2 )|| . . . ||h(kji , mi2 , mi1 )

Fig. 2. Pseudo-code of the processing phase

Denoting the finalization key final key[j][i] by Kji , the overall finalization phase can be
described as in figure 3.

RabbitKeySetup(K)
RabbitIVSetup(N )
for i = 1 to u:
Qi = 07 ||L||M i
divide³ Qi into 27-bit i i i
´ blocks , Q = q5 || . . . ||q1
5
Si = i i i
P
j=1 qj Kj + K6 mod p
S = S u || . . . ||S 1
S = S⊕ RabbitNextbit(u · 32)
return S

Fig. 3. Pseudo-code of the finalization phase

5
Cryptico A/S Badger MAC, Algorithm Specification

3 The Badger API

The API of the Badger source code, provided in Appendix A, consists of four functions:
badger key setup, badger init, badger process, and badger finalize mac. All four func-
tions return the value 0 if the function call was successful and -1 if an error occurred. The key
material needed by the algorithm is kept in an instance of the badger key instance struc-
ture. Current state information obtained through previous processing of data, e.g., number of
bits processed, is kept in an instance of badger mac instance. Both of these structures are
defined in badger.h.

3.1 Key setup

int badger_key_setup(badger_key_instance *p_key_instance,


const cc_byte *p_key, size_t key_size)

Generates the key material needed for processing of the data to be authenticated and puts it
into the key instance. badger key setup is invoked every time the key is changed. However,
it is not necessary to call it for every message to be authenticated.

• p key instance: Pointer to the key instance used to hold the key material.
• p key: Pointer to the key to be used for generating the key material.
• key size: Size of the key in bytes. The size must be 16 bytes.

3.2 Initialize

void badger_init(badger_mac_instance *p_mac_instance)

Used to initialize the MAC instance. Must be used before processing a new message.

• p mac instance: Pointer to the MAC instance used for this data authentication.

3.3 Process data

badger_process(const badger_key_instance *p_key_instance,


badger_mac_instance *p_mac_instance,
const cc_byte *p_data, size_t data_size)

The process function is called to do the intermediate processing of the data to be authen-
ticated. Processing of a message can be done either by calling badger process once, with
p data pointing to the full message, or by calling it several times, with the respective p data
pointing to successive substrings of the message (see example in section 4). It is, however,
still required that the data is processed in the proper order.

• p key instance: Pointer to the key instance.


• p mac instance: Pointer to the MAC instance.
• p data: Pointer to the first byte of data to be processed.
• data size: Number of bytes to be processed.

6
Cryptico A/S Badger MAC, Algorithm Specification

3.4 Finalize MAC


int badger_finalize_mac(const badger_key_instance *p_key_instance,
badger_mac_instance *p_mac_instance, const cc_byte *p_iv,
size_t iv_size, cc_byte *p_mac, size_t mac_size)

Finalizes computation of the MAC value. The MAC value is written at the address pointed
to by p mac. The value of mac size has to be a multiple of 4, and the memory required to
store the MAC value must be allocated by the caller in advance.

• p key instance: Pointer to the key instance.


• p mac instance: Pointer to the MAC instance.
• p iv: Pointer to the initialization vector to be used for finalization.
• iv size: Size in bytes of initialization vector. The size must be 8 bytes.
• p mac: Pointer to destination for the calculated MAC value.
• mac size: Size in bytes of the MAC value. The size must be 4 bytes per tree, with the
number of trees being defined by the constant BADGER NO OF TREES in badger.h.

4 Coding Examples

The following presents some simple examples of the use of Badger.

Authentication of a single set of data can be performed as follows:


badger_key_instance key_instance;
badger_mac_instance mac_instance;
cc_byte p_key[16] = {...};
cc_byte p_iv[8] = {...};
cc_byte p_mac[16];

/* ... */

/* Set up the key instance, process the message, and produce the MAC value */
badger_key_setup(&key_instance, p_key, 16);
badger_init(&mac_instance);
badger_process(&key_instance, &mac_instance, p_data, data_size);
badger_finalize_mac(&key_instance, &mac_instance, p_iv, 8, p_mac, 16);

/* ... */

In some applications it may be necessary to process the data in parts. The example be-
low produces the same MAC value as above, assuming that data size1 + data size2 =
data size:
badger_key_instance key_instance;
badger_mac_instance mac_instance;
cc_byte p_key[16] = {...};
cc_byte p_iv[8] = {...};

7
Cryptico A/S Badger MAC, Algorithm Specification

cc_byte p_mac[16];

/* ... */

/* Set up the key instance, process the message and produce the MAC value */
badger_key_setup(&key_instance, p_key, 16);
badger_init(&mac_instance);
badger_process(&key_instance, &mac_instance, p_data, data_size1);
badger_process(&key_instance, &mac_instance,
p_data + data_size1, data_size2);
badger_finalize_mac(&key_instance, &mac_instance, p_iv, 8, p_mac, 16);

/* ... */

When computing MAC values for several sets of data using the same set of key material, a
unique IV should be applied for each set of data. The IV does not have to be secret and
can, for instance, simply be a counter value or a block/package number. The procedure can
be performed as follows:
badger_key_instance key_instance;
badger_mac_instance mac_instance;
cc_byte p_key[16] = {...};
cc_byte p_iv1[8] = {...};
cc_byte p_iv2[8] = {...};
cc_byte p_mac1[16], p_mac2[16];

/* ... */

/* Set up the key instance */


badger_key_setup(&key_instance, p_key, 16);

/* ... */

/* Process input and compute MAC value for the first set of data */
badger_init(&mac_instance);
badger_process(&key_instance, &mac_instance, p_data1, data_size1);
badger_finalize_mac(&key_instance, &mac_instance, p_iv1, 8, p_mac1, 16);

/* ... */

/* Process input and produce MAC value for the second set of data */
badger_init(&mac_instance);
badger_process(&key_instance, &mac_instance, p_data2, data_size2);
badger_finalize_mac(&key_instance, &mac_instance, p_iv2, 8, p_mac2, 16);

8
Cryptico A/S Badger MAC, Algorithm Specification

A ANSI C Source Code

This appendix presents the ANSI C source code for Badger. The API and the arguments to
the functions are described in section 3.

badger.h
Below the badger.h header file is listed:
/******************************************************************************/
/* File name: badger.h */
/*----------------------------------------------------------------------------*/
/* Header file for reference C version of the Badger MAC function. */
/* */
/* For further documentation, see "Badger Message Authentication Code, */
/* Algorithm Specification" which can be found at http://www.cryptico.com/. */
/* */
/* This source code is for little-endian processors (e.g. x86). */
/*----------------------------------------------------------------------------*/
/* Copyright (C) Cryptico A/S. All rights reserved. */
/* */
/* YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. */
/* */
/* This software is developed by Cryptico A/S and/or its suppliers. */
/* All title and intellectual property rights in and to the software, */
/* including but not limited to patent rights and copyrights, are owned by */
/* Cryptico A/S and/or its suppliers. */
/* */
/* The software may be used solely for non-commercial purposes */
/* without the prior written consent of Cryptico A/S. For further */
/* information on licensing terms and conditions please contact Cryptico A/S */
/* at info@cryptico.com */
/* */
/* Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" are */
/* either trademarks or registered trademarks of Cryptico A/S. */
/* */
/* Cryptico A/S shall not in any way be liable for any use of this software. */
/* The software is provided "as is" without any express or implied warranty. */
/* */
/******************************************************************************/

/******************************************************************************/
/* USAGE OF DEFINES: */
/*----------------------------------------------------------------------------*/
/* BADGER_NO_OF_TREES: Number of parallel trees. */
/* MAC tag size [bytes] = 4 * no_of_trees */
/* Minimum value: 1 */
/*----------------------------------------------------------------------------*/
/* BADGER_NO_OF_LEVELS: Maximum number of levels in each tree. */
/* Max. message size [bytes] = 8 * 2^no_of_levels */
/* Allowed values: 2 - 58 (even numbers only) */
/* Overall maximum message size: 2^61-1 bytes. */
/******************************************************************************/

#ifndef _BADGER_H
#define _BADGER_H

9
Cryptico A/S Badger MAC, Algorithm Specification

/* We need definitions and functions from the Rabbit stream cipher */


#include "rabbit.h"

/* -------------------------------------------------------------------------- */

/* See above for documentation */


#define BADGER_NO_OF_LEVELS 58
#define BADGER_NO_OF_TREES 4

/* -------------------------------------------------------------------------- */

/* Type declaration of 64-bit unsigned integer */


#if defined(_MSC_VER) /* Microsoft Visual C++ and Intel C++ compilers */
typedef unsigned __int64 cc_uint64;
#elif defined(__GNUC__) /* GNU compilers */
typedef unsigned long long int cc_uint64;
#else /* Unknown compiler */
#error You must define the unsigned 64-bit integer type for your compiler here.
#endif

/* -------------------------------------------------------------------------- */

/* Structure to store key material */


typedef struct
{
cc_uint64 level_key[BADGER_NO_OF_LEVELS][BADGER_NO_OF_TREES];
cc_uint32 final_key[6][BADGER_NO_OF_TREES];
rabbit_instance rabbit_master_instance;
} badger_key_instance;

/* Structure to store internal state */


typedef struct
{
cc_uint64 tree_buffer[BADGER_NO_OF_LEVELS][BADGER_NO_OF_TREES];
cc_uint64 bit_count;
cc_byte buffer[16];
cc_uint32 buffer_index;
} badger_mac_instance;

/* -------------------------------------------------------------------------- */

#ifdef __cplusplus
extern "C" {
#endif

/* All function calls return zero on success */


int badger_key_setup(badger_key_instance *p_key_instance,
const cc_byte *p_key, size_t key_size);

void badger_init(badger_mac_instance *p_mac_instance);

int badger_process(const badger_key_instance *p_key_instance,


badger_mac_instance *p_mac_instance,
const cc_byte *p_data, size_t data_size);

10
Cryptico A/S Badger MAC, Algorithm Specification

int badger_finalize_mac(const badger_key_instance *p_key_instance,


badger_mac_instance *p_mac_instance, const cc_byte *p_iv,
size_t iv_size, cc_byte *p_mac, size_t mac_size);

#ifdef __cplusplus
}
#endif

/* -------------------------------------------------------------------------- */

#endif

badger.c
Below the badger.c file is listed:
/******************************************************************************/
/* File name: badger.c */
/*----------------------------------------------------------------------------*/
/* Source file for reference C version of the Badger MAC function. */
/* */
/* For further documentation, see "Badger Message Authentication Code, */
/* Algorithm Specification" which can be found at http://www.cryptico.com/. */
/* */
/* This source code is for little-endian processors (e.g. x86). */
/*----------------------------------------------------------------------------*/
/* Copyright (C) Cryptico A/S. All rights reserved. */
/* */
/* YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. */
/* */
/* This software is developed by Cryptico A/S and/or its suppliers. */
/* All title and intellectual property rights in and to the software, */
/* including but not limited to patent rights and copyrights, are owned by */
/* Cryptico A/S and/or its suppliers. */
/* */
/* The software may be used solely for non-commercial purposes */
/* without the prior written consent of Cryptico A/S. For further */
/* information on licensing terms and conditions please contact Cryptico A/S */
/* at info@cryptico.com */
/* */
/* Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" are */
/* either trademarks or registered trademarks of Cryptico A/S. */
/* */
/* Cryptico A/S shall not in any way be liable for any use of this software. */
/* The software is provided "as is" without any express or implied warranty. */
/* */
/******************************************************************************/

#include "badger.h"

/* -------------------------------------------------------------------------- */

/* Hash two blocks and propagate the result recursively through the tree */
static void badger_hash_node(const cc_uint64 *p_mac_key, cc_uint64 *p_mac_buffer,
cc_uint64 buf_mask, const cc_uint64 *p_left, const cc_uint64 *p_right)
{
/* Temporary variables */
cc_uint32 t1, t2;
cc_uint64 t3;

11
Cryptico A/S Badger MAC, Algorithm Specification

/* Hash */
t1 = *((cc_uint32*)p_mac_key+0) + *((cc_uint32*)p_left+0);
t2 = *((cc_uint32*)p_mac_key+1) + *((cc_uint32*)p_left+1);
t3 = (cc_uint64)t1 * (cc_uint64)t2 + *p_right;

/* If the buffer at this level contains a result already... */


if (buf_mask&1)
/* Hash next level */
badger_hash_node(p_mac_key+BADGER_NO_OF_TREES,
p_mac_buffer+BADGER_NO_OF_TREES, buf_mask>>1, p_mac_buffer, &t3);
else
/* Save the result in the buffer */
*p_mac_buffer = t3;
}

/* -------------------------------------------------------------------------- */

/* Initialize the key instance */


int badger_key_setup(badger_key_instance *p_key_instance,
const cc_byte *p_key, size_t key_size)
{
/* Temporary variables */
int i, j, res;
rabbit_instance prng_inst;
cc_uint32 spare_final_key[4];
int spare_final_key_index = 4;

/* Cipher key setup */


res = rabbit_key_setup(&prng_inst, p_key, key_size);
if (res)
return res;

/* Copy cipher instance */


for (i=0; i<(sizeof(rabbit_instance)>>2); i++)
*((int*)&p_key_instance->rabbit_master_instance+i) = *((int*)&prng_inst+i);

/* Generate Final Keys */


/* If the number of trees is even... */
if (!(BADGER_NO_OF_TREES&1))
{
/* Generate key material */
res = rabbit_prng(&prng_inst, (cc_byte*)&p_key_instance->final_key[0][0],
4*6*BADGER_NO_OF_TREES);
if (res)
return res;
}
else
{
/* Generate key material (except the last 8 bytes) */
res = rabbit_prng(&prng_inst, (cc_byte*)&p_key_instance->final_key[0][0],
4*6*BADGER_NO_OF_TREES-8);
if (res)
return res;

/* Generate 16 bytes of pseudo-random data for the spare key buffer */


res = rabbit_prng(&prng_inst, (cc_byte*)spare_final_key, 16);

12
Cryptico A/S Badger MAC, Algorithm Specification

if (res)
return res;

/* Move key material to the last 8 bytes */


*(cc_uint32*)((cc_byte*)&p_key_instance->final_key[0][0]+
4*6*BADGER_NO_OF_TREES-8) = spare_final_key[0];
*(cc_uint32*)((cc_byte*)&p_key_instance->final_key[0][0]+
4*6*BADGER_NO_OF_TREES-4) = spare_final_key[1];
spare_final_key_index = 2;
}

/* Make sure all Final Keys are less than 2^32-5 */


/* For all final keys... */
for (j=0; j<6; j++)
for (i=0; i<BADGER_NO_OF_TREES; i++)
/* As long as the key is invalid... */
while (p_key_instance->final_key[j][i] >= 0xFFFFFFFB)
{
/* If the buffer with spare key material is empty... */
if (spare_final_key_index == 4)
{
/* Generate 16 bytes new key material */
res = rabbit_prng(&prng_inst, (cc_byte*)spare_final_key, 16);
if (res)
return res;

/* Mark the buffer as full */


spare_final_key_index = 0;
}

/* Assign a new key */


p_key_instance->final_key[j][i] = spare_final_key[spare_final_key_index++];
}

/* Generate Level Keys */


res = rabbit_prng(&prng_inst, (cc_byte*)&p_key_instance->level_key[0][0],
8*BADGER_NO_OF_LEVELS*BADGER_NO_OF_TREES);

return res;
}

/* -------------------------------------------------------------------------- */

/* Reset the MAC instance */


void badger_init(badger_mac_instance *p_mac_instance)
{
/* Reset the state by setting bit_counter and buffer_index to zero */
p_mac_instance->bit_count = 0;
p_mac_instance->buffer_index = 0;
}

/* -------------------------------------------------------------------------- */

/* Process data */
int badger_process(const badger_key_instance *p_key_instance,
badger_mac_instance *p_mac_instance,
const cc_byte *p_data, size_t data_size)

13
Cryptico A/S Badger MAC, Algorithm Specification

{
/* Temporary variables */
int i;

/* If attempting to process more than 2^61-1 bytes then return error */


if ((cc_uint64)data_size > (0x1FFFFFFFFFFFFFFF - (p_mac_instance->bit_count>>3)))
return -1;

/* If the buffer is not empty, try to fill it */


if (p_mac_instance->buffer_index > 0)
while ((data_size > 0) && (p_mac_instance->buffer_index < 16))
{
p_mac_instance->buffer[p_mac_instance->buffer_index++] = *(p_data++);
data_size--;
}

/* If the buffer is full, hash it */


if (p_mac_instance->buffer_index == 16)
{
for (i=0; i<BADGER_NO_OF_TREES; i++)
badger_hash_node(&p_key_instance->level_key[0][i], &p_mac_instance->tree_buffer[0][i],
p_mac_instance->bit_count>>7, (cc_uint64*)p_mac_instance->buffer,
(cc_uint64*)(p_mac_instance->buffer+8));
p_mac_instance->bit_count += 128;
p_mac_instance->buffer_index = 0;
}

/* While there are more full blocks to hash... */


while (data_size >= 16)
{
for (i=0; i<BADGER_NO_OF_TREES; i++)
badger_hash_node(&p_key_instance->level_key[0][i], &p_mac_instance->tree_buffer[0][i],
p_mac_instance->bit_count>>7, (cc_uint64*)p_data,
(cc_uint64*)(p_data+8));
p_data += 16;
data_size -= 16;
p_mac_instance->bit_count += 128;
}

/* If there is a partial incomplete block left, put it in the buffer */


while (data_size)
{
p_mac_instance->buffer[p_mac_instance->buffer_index++] = *(p_data++);
data_size--;
}

return 0;
}

/* -------------------------------------------------------------------------- */

/* Create the MAC tag */


int badger_finalize_mac(const badger_key_instance *p_key_instance,
badger_mac_instance *p_mac_instance, const cc_byte *p_iv,
size_t iv_size, cc_byte *p_mac, size_t mac_size)
{
/* Temporary variables */

14
Cryptico A/S Badger MAC, Algorithm Specification

int i, res, right_filled;


cc_uint32 low, high, r, t1, t2;
cc_uint64 buf_mask, *p_left, t, right[BADGER_NO_OF_TREES];
const cc_uint64 *p_mac_key;
rabbit_instance encr_inst;

/* Check if mac_size is correct */


if (mac_size != BADGER_NO_OF_TREES*4)
return -1;

/* Initialize variables */
buf_mask = p_mac_instance->bit_count >> 7;
p_left = &p_mac_instance->tree_buffer[0][0];
p_mac_key = &p_key_instance->level_key[1][0];
right_filled = 0;

/* Update bit_count variable */


p_mac_instance->bit_count += 8*p_mac_instance->buffer_index;

/* If the buffer contains data... */


if (p_mac_instance->buffer_index > 0)
{
/* If the buffer contains 8 bytes or less... */
if (p_mac_instance->buffer_index <= 8)
{
/* Append zeroes to fill the 8-byte block */
while (p_mac_instance->buffer_index<8)
p_mac_instance->buffer[p_mac_instance->buffer_index++] = 0;

/* Copy the 8-byte block into each position of the right[] array */
for (i=0; i<BADGER_NO_OF_TREES; i++)
right[i] = *(cc_uint64*)p_mac_instance->buffer;
}
else
/* Else the buffer contains between 9 and 15 bytes... */
{
/* Append zeroes to fill the block */
while (p_mac_instance->buffer_index<16)
p_mac_instance->buffer[p_mac_instance->buffer_index++] = 0;

/* Process the block */


for (i=0; i<BADGER_NO_OF_TREES; i++)
{
t1 = *((cc_uint32*)(&p_key_instance->level_key[0][i])+0) +
*((cc_uint32*)p_mac_instance->buffer+0);
t2 = *((cc_uint32*)(&p_key_instance->level_key[0][i])+1) +
*((cc_uint32*)p_mac_instance->buffer+1);
right[i] = (cc_uint64)t1 * (cc_uint64)t2 +
*((cc_uint64*)p_mac_instance->buffer+1);
}
}
right_filled = 1;
}

/* If nothing has been processed... */


if (!buf_mask && !p_mac_instance->buffer_index)
{

15
Cryptico A/S Badger MAC, Algorithm Specification

/* Fill temporary result buffer with zeroes */


for (i=0; i<BADGER_NO_OF_TREES; i++)
right[i] = 0;
}
else
{
/* Find the first full buffer and copy its content into the right[] array */
while (!right_filled)
{
if (buf_mask&1)
{
for (i=0; i<BADGER_NO_OF_TREES; i++)
right[i] = *(p_left+i);
right_filled = 1;
}

p_left += BADGER_NO_OF_TREES;
p_mac_key += BADGER_NO_OF_TREES;
buf_mask >>= 1;
}

/* Finish tree */
while (buf_mask)
{
/* If the buffer at this level is full... */
if (buf_mask&1)
{
/* Hash this level in all trees */
for (i=0; i<BADGER_NO_OF_TREES; i++)
{
t1 = *((cc_uint32*)p_mac_key+0) + *((cc_uint32*)p_left+0);
t2 = *((cc_uint32*)p_mac_key+1) + *((cc_uint32*)p_left+1);
right[i] += (cc_uint64)t1 * (cc_uint64)t2;
p_mac_key++;
p_left++;
}
}
else
{
/* Correct pointers to point at next level */
p_left += BADGER_NO_OF_TREES;
p_mac_key += BADGER_NO_OF_TREES;
}
/* Correct buf_mask to represent remaining levels */
buf_mask >>= 1;
}
}

for (i=0; i<BADGER_NO_OF_TREES; i++)


{
/* Hashing of the result (to make it 32-bit) */
/* The length is appended to the result of the tree hashing and the */
/* result is divided into 27-bit pieces and processed */
t = (cc_uint64)p_key_instance->final_key[0][i] *
(right[i] & 0x07FFFFFF);
t += (cc_uint64)p_key_instance->final_key[1][i] *
((right[i] >> 27) & 0x07FFFFFF);

16
Cryptico A/S Badger MAC, Algorithm Specification

t += (cc_uint64)p_key_instance->final_key[2][i] *
((right[i] >> 54) |
((p_mac_instance->bit_count & 0x0001FFFF) << 10));
t += (cc_uint64)p_key_instance->final_key[3][i] *
((p_mac_instance->bit_count >> 17) & 0x07FFFFFF);
t += (cc_uint64)p_key_instance->final_key[4][i] *
(p_mac_instance->bit_count >> 44);
t += (cc_uint64)p_key_instance->final_key[5][i];

/* mod p32 */
low = (cc_uint32)(t&0xFFFFFFFF);
high = (cc_uint32)(t>>32);
r = low + 5*high;
if ((low > r) || (r > 0xFFFFFFFA)) /* Note: both conditions will never */
r -= 0xFFFFFFFB; /* be met at the same time. */

/* Save the result in the output buffers */


*(cc_uint32*)(p_mac+4*i) = r;
}

/* Cipher IV setup */
res = rabbit_iv_setup(&(p_key_instance->rabbit_master_instance), &encr_inst, p_iv, iv_size);
if (res)
return res;

/* Encrypt the result */


res = rabbit_cipher(&encr_inst, p_mac, p_mac, mac_size);

return res;
}

/* -------------------------------------------------------------------------- */

17
Cryptico A/S Badger MAC, Algorithm Specification

B Testing

Below some test vectors are presented. A program testing the keys, IV’s and the corresponding
output is included in the zip-file available from www.cryptico.com. It does also contain test
vectors for larger messages. The keys and outputs are presented byte-wise. The leftmost byte
of key is K [7..0] .

key = [00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f]

iv = [00 01 02 03 04 05 06 07]

msg0 = []
mac0 = [54 6D 3A 85 F8 CB FA D9 E0 58 50 58 2C AC 3D E4]

msg1 = [00]
mac1 = [5F AA AB 85 AC BE 04 48 1D D6 34 D0 FA D9 FA FA]

msg2 = [01]
mac2 = [47 EA 18 A1 99 AE 07 31 7C A5 AC C9 37 2F 55 85]

msg3 = [00 01 02 03 04 05 06 07 08]


mac3 = [F7 02 3D 65 CF 66 69 23 47 A0 8B 5F 93 55 84 27]

msg4[0] = [00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05]


msg4[1] = [06 07 08 09 00 01 02 03 04 05 06]
mac4 = [39 37 0F 67 99 7B 03 21 58 2B 1F 2C 76 68 E6 39]

18