/** * @brief Handles RNG interrupt request. * @note In the case of a clock error, the RNG is no more able to generate * random numbers because the PLL48CLK clock is not correct. User has * to check that the clock controller is correctly configured to provide * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_FLAG(). * The clock error has no impact on the previously generated * random numbers, and the RNG_DR register contents can be used. * @note In the case of a seed error, the generation of random numbers is * interrupted as long as the SECS bit is '1'. If a number is * available in the RNG_DR register, it must not be used because it may * not have enough entropy. In this case, it is recommended to clear the * SEIS bit using __HAL_RNG_CLEAR_FLAG(), then disable and enable * the RNG peripheral to reinitialize and restart the RNG. * @param hrng: pointer to a RNG_HandleTypeDef structure that contains * the configuration information for RNG. * @retval None */ void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng) { /* RNG clock error interrupt occurred */ if(__HAL_RNG_GET_FLAG(hrng, RNG_IT_CEI) != RESET) { HAL_RNG_ErrorCallback(hrng); /* Clear the clock error flag */ __HAL_RNG_CLEAR_FLAG(hrng, RNG_IT_CEI); /* Change RNG peripheral state */ hrng->State = HAL_RNG_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hrng); } /* RNG seed error interrupt occurred */ if(__HAL_RNG_GET_FLAG(hrng, RNG_IT_SEI) != RESET) { HAL_RNG_ErrorCallback(hrng); /* Clear the seed error flag */ __HAL_RNG_CLEAR_FLAG(hrng, RNG_IT_SEI); /* Change RNG peripheral state */ hrng->State = HAL_RNG_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hrng); } /* Check RNG data ready flag */ if(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) != RESET) { /* Data Ready callback */ HAL_RNG_ReadyCallback(hrng); /* Change RNG peripheral state */ hrng->State = HAL_RNG_STATE_READY; /* Clear the RNG Data Ready flag */ __HAL_RNG_CLEAR_FLAG(hrng, RNG_FLAG_DRDY); /* Process Unlocked */ __HAL_UNLOCK(hrng); } }
/** * @brief Returns a 32-bit random number. * @note Each time the random number data is read the RNG_FLAG_DRDY flag * is automatically cleared. * @param hrng: pointer to a RNG_HandleTypeDef structure that contains * the configuration information for RNG. * @retval 32-bit random number */ uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng) { uint32_t random32bit = 0; uint32_t tickstart = 0; /* Process Locked */ __HAL_LOCK(hrng); /* Get tick */ tickstart = HAL_GetTick(); /* Check if data register contains valid random data */ while(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET) { if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } /* Get a 32bit Random number */ random32bit = hrng->Instance->DR; /* Process Unlocked */ __HAL_UNLOCK(hrng); /* Return the 32 bit random number */ return random32bit; }
/** mbedtls_hardware_poll * @brief Get len bytes of entropy from the hardware RNG. * @param data pointer will be NULL * @param output pointer to the random generated bytes buffer * @param len input is the requested length of bytes to be generated * @param olen is the pointer to the length of bytes effectively generated * @returns 0 if the generation went well. -1 in case of error */ int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen ) { int ret; ((void) data); /* RNG Peripheral clock enable */ __HAL_RCC_RNG_CLK_ENABLE(); /* Initialize RNG instance */ RngHandle.Instance = RNG; HAL_RNG_Init(&RngHandle); /* Get Random byte */ for( uint32_t i = 0; i < len; i++ ){ rng_get_byte( output + i ); } *olen = len; /* Just be extra sure that we didn't do it wrong */ if( ( __HAL_RNG_GET_FLAG(&RngHandle, (RNG_FLAG_CECS|RNG_FLAG_SECS)) ) != 0 ) { ret = -1; } else { ret = 0; } /*Disable the RNG peripheral */ HAL_RNG_DeInit(&RngHandle); /* RNG Peripheral clock disable - assume we're the only users of RNG */ __HAL_RCC_RNG_CLK_DISABLE(); return( ret ); }
HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit) { uint32_t tickstart = 0; HAL_StatusTypeDef status = HAL_OK; /* Process Locked */ __HAL_LOCK(hrng); /* Check RNG peripheral state */ if(hrng->State == HAL_RNG_STATE_READY) { /* Change RNG peripheral state */ hrng->State = HAL_RNG_STATE_BUSY; /* Get tick */ tickstart = HAL_GetTick(); /* Check if data register contains valid random data */ while(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET) { if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE) { hrng->State = HAL_RNG_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hrng); return HAL_TIMEOUT; } } /* Get a 32bit Random number */ hrng->RandomNumber = hrng->Instance->DR; *random32bit = hrng->RandomNumber; hrng->State = HAL_RNG_STATE_READY; } else { status = HAL_ERROR; } /* Process Unlocked */ __HAL_UNLOCK(hrng); return status; }
/** * @brief Returns a random number. * @param arg not used * @param output random number * @param output_len random number length * @retval 0 */ int RandVal(void* arg, unsigned char *output, size_t output_len) { uint32_t nbrng = 0; uint8_t offset = 0; nbrng = output_len; while(nbrng > 0) { /* Wait until random number is ready */ while(__HAL_RNG_GET_FLAG(&RngHandle, RNG_FLAG_DRDY)== RESET); /* Get the random number */ *(output + offset) = HAL_RNG_GetRandomNumber(&RngHandle) && 0xFFFFFF00; offset++; nbrng --; } /* Return the random number */ return(0); }