text: /**************************** usha.c ***************************/
  /***************** See RFC NNNN for details. *******************/
  /* Copyright (c) 2010 IETF Trust and the persons identified as */
  /* authors of the code.  All rights reserved.                  */
  /* See sha.h for terms of use and redistribution.              */
  
  /*
   *  Description:
   *     This file implements a unified interface to the SHA algorithms.
   */
  
  #include "crypto/sha.h"
  
  /*
   *  USHAReset
   *
   *  Description:
   *      This function will initialize the SHA Context in preparation
   *      for computing a new SHA message digest.
   *
   *  Parameters:
   *      context: [in/out]
   *          The context to reset.
   *      whichSha: [in]
   *          Selects which SHA reset to call
   *
   *  Returns:
   *      sha Error Code.
   *
   */
  int USHAReset(USHAContext *context, enum SHAversion whichSha)
  {
    if (!context) return shaNull;
    context->whichSha = whichSha;
    switch (whichSha) {
      case SHA1:   return SHA1Reset((SHA1Context*)&context->ctx);
      case SHA224: return SHA224Reset((SHA224Context*)&context->ctx);
      case SHA256: return SHA256Reset((SHA256Context*)&context->ctx);
      case SHA384: return SHA384Reset((SHA384Context*)&context->ctx);
      case SHA512: return SHA512Reset((SHA512Context*)&context->ctx);
      default: return shaBadParam;
    }
  }
  
  /*
   *  USHAInput
   *
   *  Description:
   *      This function accepts an array of octets as the next portion
   *      of the message.
   *
   *  Parameters:
   *      context: [in/out]
   *          The SHA context to update
   *      message_array: [in]
   *          An array of octets representing the next portion of
   *          the message.
   *      length: [in]
   *          The length of the message in message_array
   *
   *  Returns:
   *      sha Error Code.
   *
   */
  int USHAInput(USHAContext *context,
                const uint8_t *bytes, unsigned int bytecount)
  {
    if (!context) return shaNull;
    switch (context->whichSha) {
      case SHA1:
        return SHA1Input((SHA1Context*)&context->ctx, bytes,
                         bytecount);
      case SHA224:
        return SHA224Input((SHA224Context*)&context->ctx, bytes,
            bytecount);
      case SHA256:
        return SHA256Input((SHA256Context*)&context->ctx, bytes,
            bytecount);
      case SHA384:
        return SHA384Input((SHA384Context*)&context->ctx, bytes,
            bytecount);
      case SHA512:
        return SHA512Input((SHA512Context*)&context->ctx, bytes,
            bytecount);
      default: return shaBadParam;
    }
  }
  
  /*
   * USHAFinalBits
   *
   * Description:
   *   This function will add in any final bits of the message.
   *
   * Parameters:
   *   context: [in/out]
   *     The SHA context to update
   *   message_bits: [in]
   *     The final bits of the message, in the upper portion of the
   *     byte. (Use 0b###00000 instead of 0b00000### to input the
   *     three bits ###.)
   *   length: [in]
   *     The number of bits in message_bits, between 1 and 7.
   *
   * Returns:
   *   sha Error Code.
   */
  int USHAFinalBits(USHAContext *context,
                    uint8_t bits, unsigned int bit_count)
  {
    if (!context) return shaNull;
    switch (context->whichSha) {
      case SHA1:
        return SHA1FinalBits((SHA1Context*)&context->ctx, bits,
                             bit_count);
      case SHA224:
        return SHA224FinalBits((SHA224Context*)&context->ctx, bits,
            bit_count);
      case SHA256:
        return SHA256FinalBits((SHA256Context*)&context->ctx, bits,
            bit_count);
      case SHA384:
        return SHA384FinalBits((SHA384Context*)&context->ctx, bits,
            bit_count);
      case SHA512:
        return SHA512FinalBits((SHA512Context*)&context->ctx, bits,
            bit_count);
      default: return shaBadParam;
    }
  }
  
  /*
   * USHAResult
   *
   * Description:
   *   This function will return the message digest of the appropriate
   *   bit size, as returned by USHAHashSizeBits(whichSHA) for the
   *   'whichSHA' value used in the preceeding call to USHAReset,
   *   into the Message_Digest array provided by the caller.
   *
   * Parameters:
   *   context: [in/out]
   *     The context to use to calculate the SHA-1 hash.
   *   Message_Digest: [out]
   *     Where the digest is returned.
   *
   * Returns:
   *   sha Error Code.
   *
   */
  int USHAResult(USHAContext *context,
                 uint8_t Message_Digest[USHAMaxHashSize])
  {
    if (!context) return shaNull;
    switch (context->whichSha) {
      case SHA1:
        return SHA1Result((SHA1Context*)&context->ctx, Message_Digest);
      case SHA224:
        return SHA224Result((SHA224Context*)&context->ctx,
                            Message_Digest);
      case SHA256:
        return SHA256Result((SHA256Context*)&context->ctx,
                            Message_Digest);
      case SHA384:
        return SHA384Result((SHA384Context*)&context->ctx,
                            Message_Digest);
      case SHA512:
        return SHA512Result((SHA512Context*)&context->ctx,
                            Message_Digest);
      default: return shaBadParam;
    }
  }
  
  /*
   * USHABlockSize
   *
   * Description:
   *   This function will return the blocksize for the given SHA
   *   algorithm.
   *
   * Parameters:
   *   whichSha:
   *     which SHA algorithm to query
   *
   * Returns:
   *   block size
   *
   */
  int USHABlockSize(enum SHAversion whichSha)
  {
    switch (whichSha) {
      case SHA1:   return SHA1_Message_Block_Size;
      case SHA224: return SHA224_Message_Block_Size;
      case SHA256: return SHA256_Message_Block_Size;
      case SHA384: return SHA384_Message_Block_Size;
      default:
      case SHA512: return SHA512_Message_Block_Size;
    }
  }
  
  /*
   * USHAHashSize
   *
   * Description:
   *   This function will return the hashsize for the given SHA
   *   algorithm.
   *
   * Parameters:
   *   whichSha:
   *     which SHA algorithm to query
   *
   * Returns:
   *   hash size
   *
   */
  int USHAHashSize(enum SHAversion whichSha)
  {
    switch (whichSha) {
      case SHA1:   return SHA1HashSize;
      case SHA224: return SHA224HashSize;
      case SHA256: return SHA256HashSize;
      case SHA384: return SHA384HashSize;
      default:
      case SHA512: return SHA512HashSize;
    }
  }
  
  /*
   * USHAHashSizeBits
   *
   * Description:
   *   This function will return the hashsize for the given SHA
   *   algorithm, expressed in bits.
   *
   * Parameters:
   *   whichSha:
   *     which SHA algorithm to query
   *
   * Returns:
   *   hash size in bits
   *
   */
  int USHAHashSizeBits(enum SHAversion whichSha)
  {
    switch (whichSha) {
      case SHA1:   return SHA1HashSizeBits;
      case SHA224: return SHA224HashSizeBits;
      case SHA256: return SHA256HashSizeBits;
      case SHA384: return SHA384HashSizeBits;
      default:
      case SHA512: return SHA512HashSizeBits;
    }
  }
  
  /*
   * USHAHashName
   *
   * Description:
   *   This function will return the name of the given SHA algorithm
   *   as a string.
   *
   * Parameters:
   *   whichSha:
   *     which SHA algorithm to query
   *
   * Returns:
   *   character string with the name in it
   *
   */
  const char *USHAHashName(enum SHAversion whichSha)
  {
    switch (whichSha) {
      case SHA1:   return "SHA1";
      case SHA224: return "SHA224";
      case SHA256: return "SHA256";
      case SHA384: return "SHA384";
      default:
      case SHA512: return "SHA512";
    }
  }
  