/**
 * @brief  Compute the HASH SHA1 digest.
 * @param  Input: pointer to the Input buffer to be treated.
 * @param  Ilen: length of the Input buffer.
 * @param  Output: the returned digest
 * @retval An ErrorStatus enumeration value:
 *          - SUCCESS: digest computation done
 *          - ERROR: digest computation failed
 */
ErrorStatus HASH_SHA1(uint8_t *Input, uint32_t Ilen, uint8_t Output[20]) {
    HASH_InitTypeDef SHA1_HASH_InitStructure;
    HASH_MsgDigest SHA1_MessageDigest;
    __IO uint16_t nbvalidbitsdata = 0;
    uint32_t i = 0;
    __IO uint32_t counter = 0;
    uint32_t busystatus = 0;
    ErrorStatus status = SUCCESS;
    uint32_t inputaddr = (uint32_t) Input;
    uint32_t outputaddr = (uint32_t) Output;

    /* Number of valid bits in last word of the Input data */
    nbvalidbitsdata = 8 * (Ilen % 4);

    /* HASH peripheral initialization */
    HASH_DeInit();

    /* HASH Configuration */
    SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
    SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
    SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
    HASH_Init(&SHA1_HASH_InitStructure);

    /* Configure the number of valid bits in last word of the data */
    HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);

    /* Write the Input block in the IN FIFO */
    for (i = 0; i < Ilen; i += 4) {
        HASH_DataIn(*(uint32_t*) inputaddr);
        inputaddr += 4;
    }

    /* Start the HASH processor */
    HASH_StartDigest();

    /* wait until the Busy flag is RESET */
    do {
        busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
        counter++;
    } while ((counter != SHA1BUSY_TIMEOUT) && (busystatus != RESET));

    if (busystatus != RESET) {
        status = ERROR;
    } else {
        /* Read the message digest */
        HASH_GetDigest(&SHA1_MessageDigest);
        *(uint32_t*) (outputaddr) = __REV(SHA1_MessageDigest.Data[0]);
        outputaddr += 4;
        *(uint32_t*) (outputaddr) = __REV(SHA1_MessageDigest.Data[1]);
        outputaddr += 4;
        *(uint32_t*) (outputaddr) = __REV(SHA1_MessageDigest.Data[2]);
        outputaddr += 4;
        *(uint32_t*) (outputaddr) = __REV(SHA1_MessageDigest.Data[3]);
        outputaddr += 4;
        *(uint32_t*) (outputaddr) = __REV(SHA1_MessageDigest.Data[4]);
    }
    return status;
}
Example #2
0
/**
  * @brief  HASH MD5 Digest computation (using DMA for data transfer) 
  * @note   DMA2 stream7 channel2 is used to transfer data from memory
  *         (MessageToHash[] array) to HASH Peripheral (the INPUT data register).
  * @param  None
  * @retval None
  */
static void HASH_MD5_DMA(void)
{
  HASH_InitTypeDef HASH_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;

  /* HASH Configuration */
  HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
  HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HASH;
  HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
  HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
  HASH_Init(&HASH_InitStructure);

  /*DMA Configuration*/
  DMA_DeInit(DMA2_Stream7);
  DMA_InitStructure.DMA_Channel = DMA_Channel_2;
  DMA_InitStructure.DMA_PeripheralBaseAddr = HASH_DIN_REG_ADDR;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)MessageToHash;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = SIZE_MSG_TO_HASH_IN_WORDS;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  /* Configure the DMA Stream */
  DMA_Init(DMA2_Stream7, &DMA_InitStructure);

  /* Enable HASH DMA */
  HASH_DMACmd(ENABLE);

  /* Enable DMA2 Transfer */
  DMA_Cmd(DMA2_Stream7, ENABLE);

  /* Note :  When the DMA is enabled, it provides the information to the hash 
             processor when it is transferring the last data word. Then the 
             padding and digest computation are performed automatically as if 
             DCAL had been written to 1.*/

  /* wait until DMA Transfer completed */
  while (DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) == RESET);

  /* wait until the Busy flag is RESET */
  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);

  /* Get the MD5 Digest */
  HASH_GetDigest(&MsgDigest);
}
Example #3
0
/**
  * @brief  Compute the HMAC MD5 digest.
  * @param  Key: pointer to the Key used for HMAC.
  * @param  Keylen: length of the Key used for HMAC.
  * @param  Input: pointer to the Input buffer to be treated.
  * @param  Ilen: length of the Input buffer.
  * @param  Output: the returned digest  
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: digest computation done
  *          - ERROR: digest computation failed
  */
ErrorStatus HMAC_MD5(uint8_t *Key, uint32_t Keylen, uint8_t *Input, 
                     uint32_t Ilen, uint8_t Output[16])
{
  HASH_InitTypeDef MD5_HASH_InitStructure;
  HASH_MsgDigest MD5_MessageDigest;
  __IO uint16_t nbvalidbitsdata = 0;
  __IO uint16_t nbvalidbitskey = 0;
  uint32_t i = 0;
  __IO uint32_t counter = 0;
  uint32_t busystatus = 0;
  ErrorStatus status = SUCCESS;
  uint32_t keyaddr    = (uint32_t)Key;
  uint32_t inputaddr  = (uint32_t)Input;
  uint32_t outputaddr = (uint32_t)Output;

  /* Number of valid bits in last word of the Input data */
  nbvalidbitsdata = 8 * (Ilen % 4);

  /* Number of valid bits in last word of the Key */
  nbvalidbitskey = 8 * (Keylen % 4);
   
  /* HASH peripheral initialization */
  HASH_DeInit();

  /* HASH Configuration */
  MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
  MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
  MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
  if(Keylen > 64)
  {
    /* HMAC long Key */
    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
  }
  else
  {
    /* HMAC short Key */
    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
  }
  HASH_Init(&MD5_HASH_InitStructure);

  /* Configure the number of valid bits in last word of the Key */
  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);

  /* Write the Key */
  for(i=0; i<Keylen; i+=4)
  {
    HASH_DataIn(*(uint32_t*)keyaddr);
    keyaddr+=4;
  }
  
  /* Start the HASH processor */
  HASH_StartDigest();

  /* wait until the Busy flag is RESET */
  do
  {
    busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
    counter++;
  }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));

  if (busystatus != RESET)
  {
     status = ERROR;
  }
  else
  {
    /* Configure the number of valid bits in last word of the Input data */
    HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);

    /* Write the Input block in the IN FIFO */
    for(i=0; i<Ilen; i+=4)
    {
      HASH_DataIn(*(uint32_t*)inputaddr);
      inputaddr+=4;
    }

    /* Start the HASH processor */
    HASH_StartDigest();

    /* wait until the Busy flag is RESET */
    counter =0;
    do
    {
       busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
       counter++;
    }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));

    if (busystatus != RESET)
    {
      status = ERROR;
    }
    else
    {  
      /* Configure the number of valid bits in last word of the Key */
      HASH_SetLastWordValidBitsNbr(nbvalidbitskey);

      /* Write the Key */
      keyaddr = (uint32_t)Key;
      for(i=0; i<Keylen; i+=4)
      {
        HASH_DataIn(*(uint32_t*)keyaddr);
        keyaddr+=4;
      }
  
       /* Start the HASH processor */
       HASH_StartDigest();

       /* wait until the Busy flag is RESET */
       counter =0;
       do
       {
          busystatus = HASH_GetFlagStatus(HASH_FLAG_BUSY);
          counter++;
      }while ((counter != MD5BUSY_TIMEOUT) && (busystatus != RESET));

      if (busystatus != RESET)
      {
         status = ERROR;
      }
      else
      {
         /* Read the message digest */
         HASH_GetDigest(&MD5_MessageDigest);
         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[0]);
         outputaddr+=4;
         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[1]);
         outputaddr+=4;
         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[2]);
         outputaddr+=4;
         *(uint32_t*)(outputaddr)  = __REV(MD5_MessageDigest.Data[3]);
      }
    }
  }
  return status;  
}