Here's a tentative Nettle interface for umac. Comments appreciated.
I'll be traveling over the weekend, more or less offline, so I may not respond until Tuesday or so.
Regards, /Niels
/* umac.h * * UMAC message authentication code (RFC-4418). */
/* nettle, low-level cryptographics library * * Copyright (C) 2013 Niels Möller * * The nettle library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The nettle library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the nettle library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02111-1301, USA. */
#ifndef NETTLE_UMAC_H_INCLUDED #define NETTLE_UMAC_H_INCLUDED
#ifdef __cplusplus extern "C" { #endif
#define UMAC_BLOCK_SIZE 1024 #define UMAC_KEY_SIZE 16
/* Subkeys and state for UMAC with tag size 32*n bits. */ #define _UMAC_STATE(n) \ uint32_t l1_key[UMAC_BLOCK_SIZE/4 + 4*((n)-1)]; \ /* Keys in 32-bit pieces, low first */ \ uint32_t p64_key[2*(n)]; \ uint32_t p128_key[4*(n)]; \ uint64_t l3_key1[8*(n)]; \ uint32_t l3_key2[(n)]; \ /* AES cipher for encrypting the nonce */ \ struct aes_ctx pdf_key; \ /* Buffer l1 output for one block */ \ uint64_t l1_out[(n)]; \ /* For both poly64-hashing and poly128 hashing */ \ uint64_t poly_state[2*(n)];
struct umac_buffer { unsigned blocks; unsigned pos; uint8_t buffer[UMAC_BLOCK_SIZE]; }
struct umac32_ctx { _UMAC_STATE(1); /* Input to the pdf_key, zero-padded and low bits cleared. */ uint8_t nonce[AES_BLOCK_SIZE]; int nonce_low; /* Low bits, plus some flag for the pad cache. */ /* Previous padding block */ uint8_t pad_cache[AES_BLOCK_SIZE];
struct umac_buffer buffer; };
struct umac64_ctx { _UMAC_STATE(2); /* Input to the pdf_key, zero-padded and low bits cleared. */ uint8_t nonce[AES_BLOCK_SIZE]; int nonce_low; /* Low bits, plus some flag for the pad cache. */ /* Previous padding block */ uint8_t pad_cache[AES_BLOCK_SIZE];
struct umac_buffer buffer; };
struct umac96_ctx { _UMAC_STATE(3); /* Input to the pdf_key, zero-padded if needed. */ uint8_t nonce[AES_BLOCK_SIZE];
struct umac_buffer buffer; };
struct umac128_ctx { _UMAC_STATE(4); /* Input to the pdf_key, zero-padded if needed. */ uint8_t nonce[AES_BLOCK_SIZE];
struct umac_buffer buffer; };
/* The _set_key function initialize the nonce to zero. */ void umac32_set_key (struct umac32_ctx *ctx, const uint8_t *key); void umac64_set_key (struct umac64_ctx *ctx, const uint8_t *key); void umac96_set_key (struct umac96_ctx *ctx, const uint8_t *key); void umac128_set_key (struct umac128_ctx *ctx, const uint8_t *key);
/* Optional, if not used, messages get incrementing nonces starting from zero. */ void umac32_set_nonce (struct umac32_ctx *ctx, unsigned nonce_length, const uint8_t *nonce); void umac64_set_nonce (struct umac64_ctx *ctx, unsigned nonce_length, const uint8_t *nonce); void umac96_set_nonce (struct umac96_ctx *ctx, unsigned nonce_length, const uint8_t *nonce); void umac128_set_nonce (struct umac128_ctx *ctx, unsigned nonce_length, const uint8_t *nonce);
void umac32_update (struct umac32_ctx *ctx, unsigned length, const uint8_t *data); void umac64_update (struct umac64_ctx *ctx, unsigned length, const uint8_t *data); void umac96_update (struct umac96_ctx *ctx, unsigned length, const uint8_t *data); void umac128_update (struct umac128_ctx *ctx, unsigned length, const uint8_t *data);
/* The _digest functions increment the nonce */ void umac32_digest (struct umac32_ctx *ctx, unsigned length, uint8_t *digest); void umac64_digest (struct umac64_ctx *ctx, unsigned length, uint8_t *digest); void umac96_digest (struct umac96_ctx *ctx, unsigned length, uint8_t *digest); void umac128_digest (struct umac128_ctx *ctx, unsigned length, uint8_t *digest);
/* Internal functions */ #define _UMAC_POLY64_BLOCKS 16384
uint64_t _umac_nh (const uint32_t *key, unsigned length, const uint8_t *msg);
/* Equivalent to
for (i = 0; i < n; i++) out[i] = _umac_nh (key + 4*i, length, msg);
but processing input only once. */ void _umac_nh_n (uint64_t *out, unsigned n, const uint32_t *key, unsigned length, const uint8_t *msg);
/* Returns y*k + m (mod p), including "marker" processing. Return value is *not* in canonical representation, and must be normalized before the output is used. */ uint64_t _umac_poly64 (uint32_t kh, uint32_t kl, uint64_t y, uint64_t m);
void _umac_poly128 (const uint32_t *k, uint32_t *y, uint64_t mh, uint64_t ml);
uint32_t _umac_l3 (const uint64_t *key_1, uint32_t key_2, const uint64_t *m);
#ifdef __cplusplus } #endif
#endif /* NETTLE_UMAC_H_INCLUDED */