/*
 * Copyright (c) 2003-2016
 * Distributed Systems Software.  All rights reserved.
 * See the file BN-LICENSE for redistribution information.
 *
 * $Id: sha3.h 2885 2016-05-16 23:48:04Z brachman $
 */

#ifndef _BN_SHA3_
#define _BN_SHA3_

#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>

#ifndef MAYBE_UNUSED
#define MAYBE_UNUSED    __attribute__ ((__unused__))
#endif

/* Return a pointer to space for one OBJ. */
#define ALLOC(OBJ)          ((OBJ *) malloc(sizeof(OBJ)))

/* Return a pointer to space for a vector of N objects, each an OBJ. */
#define ALLOC_N(OBJ, N)     ((OBJ *) malloc(sizeof(OBJ) * (N)))

typedef enum {
  DIGEST_SHA3_224      = 0,
  DIGEST_SHA3_256      = 1,
  DIGEST_SHA3_384      = 2,
  DIGEST_SHA3_512      = 3,
  DIGEST_INVALID       = -1
} Digest_alg;

enum {
  SHA3_MAX_PERMUTATION_SIZE = 25,
  SHA3_MAX_RATE_IN_QWORDS   = 24,
  SHA3_NUMBER_OF_ROUNDS     = 24,
  SHA3_MAX_DIGEST_SIZE      = (512 / 8)
};

typedef struct Digest_tab {
  const char *name;             /* Canonical name. */
  Digest_alg alg;               /* Unique internal digest algorithm ID. */
  unsigned int block_size;      /* Internal block size, in bytes. */
  unsigned int digest_size;     /* Digest (output) size, in bytes. */
  unsigned int flags;           /* Implementation and purpose descriptors. */
} Digest_tab;

/* Context for a SHA-3 family hash function. */
typedef struct SHA3_ctx {
  Digest_tab *dt;
  unsigned int rate;
  size_t digest_bits;                           /* Output length, in bits. */
  uint64_t hash[SHA3_MAX_PERMUTATION_SIZE];     /* State: 1600 bits. */
  uint64_t message[SHA3_MAX_RATE_IN_QWORDS];    /* 1536-bits for leftovers. */
  unsigned int rest;                            /* Bytes in message[]. */
  unsigned int block_size;                      /* Message block size. */
  unsigned int bit_padding;
} SHA3_ctx;

#define LE_DEC64(X)			lendian_dec64(&X)
#define ROTL64(QWORD, N)	((QWORD) << (N) ^ ((QWORD) >> (64 - (N))))
#define IS_ALIGNED_64(P)	(0 == (7 & ((const char *) (P) - (const char *) 0)))

#define SHA3_MUST_FINALIZE	0x40000000
#define SHA3_FINALIZED		0x80000000

extern SHA3_ctx *sha3_init(Digest_alg alg, SHA3_ctx *octx,
						   unsigned int *digest_size);
extern SHA3_ctx *sha3_init_by_name(const char *digest_name, SHA3_ctx *octx,
								   unsigned int *digest_size);

extern void crypto_keccak_init(SHA3_ctx *ctx, unsigned int nbits);
extern void sha3_update(SHA3_ctx *ctx, const unsigned char *msg, size_t size);
extern void sha3_update_bits(SHA3_ctx *ctx, const unsigned char *msg,
							 unsigned int nbits);
extern void sha3_final(SHA3_ctx *ctx, unsigned char *result);
extern int sha3(Digest_alg alg, const unsigned char *msg, int msglen,
				unsigned char *result, unsigned int *digest_size);
extern int sha3_by_name(const char *digest_name, const unsigned char *msg,
						int msglen, unsigned char *result,
						unsigned int *digest_size);
extern int sha3_bits(Digest_alg alg, const unsigned char *msg,
					 unsigned int nbits, unsigned char *result,
					 unsigned int *digest_size);
extern Digest_tab *sha3_lookup_digest_by_name(const char *digest_name);
extern Digest_tab *sha3_lookup_digest_by_algorithm(Digest_alg alg);
extern unsigned int sha3_lookup_digest_size(const char *digest_name);

#endif
