/************************************************************************************************
    Project 1: Application of SIMD and VLIW architectures of Analog Devices
               DSP in SHA-1, SHA-256 and AES-Rijndael cryptographic algorithms
    Project 2: Application of SIMD and VLIW architectures of Analog Devices
               DSP in SHA-384, SHA-512 and AES-Rijndael key-expansion
               cryptographic algorithms   
   Supervisor: Assoc. Prof. Milos Drutarovsky
    File Name: sha.h
Last Modified: 3-V-2003
       Author: Anton Karabinos (Project 2), Roman Ploskon (Project 1),
               Department of Electronics and Multimedia Communications,
               Technical University of Kosice
      Version: 1.01
  Description: SHA-1, SHA-256, SHA-384, SHA-512 - Header file
     Platform: ADSP-21160 SHARC

Function's Description:
=======================
void SHA1_Init_Message_Digest (unsigned int dm *Message_Digest)

  - Initializes content of pointed buffer (message digest)
    + This must be performed before computing the message digest
    + Buffer must be an array of SHA1_DIGEST_SIZE words
      (word is SHA_WORD_SIZE-bit wide)


void SHA256_Init_Message_Digest (unsigned int dm *Message_Digest)

  - Initializes content of pointed buffer (message digest)
    + This must be performed before computing the message digest
    + Buffer must be an array of SHA256_DIGEST_SIZE words
      (word is SHA_WORD_SIZE-bit wide)


void SHA1_Process_Block (unsigned int dm *Block,
                         unsigned int dm *Message_Digest)

  - Processes a block = input buffer
  - Block is address of buffer (block) to be processed
    + Block must be an array of SHA1_256_BLOCK_SIZE words
      (word is SHA_WORD_SIZE-bit wide)
  - Message_Digest is address of the output buffer, where will be stored
    the result (message digest)
    + Message digest must be an array of SHA1_DIGEST_SIZE words
      (word is SHA_WORD_SIZE-wide)


void SHA256_Process_Block (unsigned int dm *Block,
                           unsigned int dm *Message_Digest)

  - Processes a block = input buffer
  - Block is address of buffer (block) to be processed
    + Block must be an array of SHA1_256_BLOCK_SIZE words
      (word is SHA_WORD_SIZE-bit wide)
  - Message_Digest is address of the output buffer, where will be stored
    the result (message digest)
    + Message digest must be an array of SHA256_DIGEST_SIZE words
      (word is SHA_WORD_SIZE-bit wide)


void SHA1_256_Process_Last_Block (unsigned int dm *Block,
                                  size_t dm LastBlock_Length,
                                  size_t dm Message_Length_HI,
                                  size_t dm Message_Length_LO,
                                  void (*SHA_Process_Block) (unsigned int dm *Block,
                                                             unsigned int dm *Message_Digest),
                                  unsigned int dm *Message_Digest)

  - Processes a last block
  - Block is address of buffer (last block) to be processed
    + Last block must be an array of SHA1_256_BLOCK_SIZE words
      (word is SHA_WORD_SIZE-bit wide)
  - LastBlock_Length is effective length of last block (length of user's data in last block)
    + LastBlock_Length is in range <1, SHA1_256_BLOCK_SIZE * SHA_WORD_SIZE> [bits]
    + Remaining bits (bits after user's bits) do not need to be cleared
  - Message_Length_HI is high word of message length
  - Message_Length_LO is low word of message length
    + If message length is <= SHA1_256_BLOCK_SIZE * SHA_WORD_SIZE
      then you have to call only function SHA1_256_Process_Last_Block
      (You can not call function SHA1_Process_Block or SHA256_Process_Block)
  - SHA_Process_Block is pointer to function used to process block
    + SHA1:   SHA_Process_Block = &SHA1_Process_Block
    + SHA256: SHA_Process_Block = &SHA256_Process_Block
  - Message_Digest is address of the output buffer, where will be stored
    the result (message digest)
    + SHA1:   Message digest must be an array of SHA1_DIGEST_SIZE words
              (word is SHA_WORD_SIZE-bit wide)
    + SHA256: Message digest must be an array of SHA256_DIGEST_SIZE words
              (word is SHA_WORD_SIZE-bit wide)


void SHA512_384_1024bit_Block (unsigned int dm *Block,
                               unsigned int dm *Hash_Constant);

  - function for hash 1024 bits block
  - input parameter is pointer to input buffer and pointer to hash constants dedicated to hashed
    block
  - the constant must be arrangement by this rule: high 32 bits | low 32 bits
  - at the end of computation the input hash constant is replaced by new computed hash constant,
    by this rule:  high 32 bits | low 32 bits of hash constant
  - function empty input buffer after computation


void SHA512_384_Last_Block(unsigned int dm *Block,
                       unsigned int dm *Hash_Constant,
                       size_t dm Block_Length,
                       unsigned int dm *Message_Length,
                       unsigned int dm Digest_Length);

  - function for hash last blok of message
  - input parameters are pointer to input blok, pointer to hash constant dedicated to hashed
    block, length of this blok, pointer to entire message length and the lenght of message
    digest.
    Each length must be defined in bits!
  - the constant must be arrangement by this rule: high 32 bits | low 32 bits
  - the length of message must be arrangement by this rule:
    | 127 - 96bits | 95 - 64 bits | 63 - 32 bits | 31 - 0 bits  | of message length
  - the Digest_length can take this to value:
    512 if SHA-512 is computed
    384 if SHA-384 is computed
  - after executing this function the input hash constant is replaced by message digest, by this 
    rule: high 32-bits | low 32-bit of message digest
  - function empty input buffer after computation


void SHA512_384_Init (unsigned int dm *Hash_Constant,
                      unsigned int dm Digest_Length);

  - function for initializing hash constant at the begin of hash process 
  - input parameter is pointer where the init hash constant will be stored
  - the Digest_Length can take this to value:
    512 if SHA-512 is computed
    384 if SHA-384 is computed

************************************************************************************************/

#ifndef _SHA_H
#define _SHA_H

#include 

#define SHA_WORD_SIZE                32
#define SHA1_256_BLOCK_SIZE          16   /* SHA-1, SHA-256: Block length is 16*32=512 bit */
#define SHA1_256_BLOCK_LENGTH        SHA1_256_BLOCK_SIZE * SHA_WORD_SIZE
#define SHA1_256_LENGTH_SIZE         2    /* SHA-1, SHA-256: Message length is 2*32=64-bit */
#define SHA1_DIGEST_SIZE             5    /* SHA-1: Message digest is 5*32=160 bit */
#define SHA256_DIGEST_SIZE           8    /* SHA-256: Message digest is 8*32=256 bit */

#define SHA384_512_BLOCK_SIZE        32   /* SHA-384, SHA-512: Block length is 32*32=1024 bit */
#define SHA384_512_BLOCK_LENGTH      SHA384_512_BLOCK_SIZE * SHA_WORD_SIZE
#define SHA384_512_LENGTH_SIZE       4    /* SHA-384, SHA-512: Message length is 4*32=128-bit */
#define SHA384_DIGEST_SIZE           12   /* SHA-384: Message digest is 12*32=384 bit */
#define SHA512_DIGEST_SIZE           16   /* SHA-512: Message digest is 16*32=512 bit */
/* SHA384: For declaration of message digest array use SHA512_DIGEST_SIZE !
   SHA384_DIGEST_SIZE use only for reading first items from declared bigger array. */


void SHA1_Init_Message_Digest (unsigned int dm *Message_Digest);

void SHA256_Init_Message_Digest (unsigned int dm *Message_Digest);

void SHA1_Process_Block (unsigned int dm *Block,
                         unsigned int dm *Message_Digest);

void SHA256_Process_Block (unsigned int dm *Block,
                           unsigned int dm *Message_Digest);

void SHA1_256_Process_Last_Block (unsigned int dm *Block,
                                  size_t dm LastBlock_Length,
                                  size_t dm Message_Length_HI,
                                  size_t dm Message_Length_LO,
                                  void (*SHA_Process_Block) (unsigned int dm *Block,
                                                             unsigned int dm *Message_Digest),
                                  unsigned int dm *Message_Digest);

void SHA512_384_1024bit_Block (unsigned int dm *Block,
                               unsigned int dm *Hash_Constant);

void SHA512_384_Last_Block(unsigned int dm *Block,
                           unsigned int dm *Hash_Constant,
                           size_t dm Block_Length,
                           unsigned int dm *Message_Length,
                           unsigned int dm Digest_Length);

void SHA512_384_Init (unsigned int dm *Hash_Constant,
                      unsigned int dm Digest_Length);

#endif  /* _SHA_H */