How to generate a random REAL number using STM32 MCM?

I am working on a project with MCM MCM STM32F103E cortex-m3 in microvision keil development environment.
I need to generate random numbers for some purpose, but I don't want to use the pseudo-random numbers that the standard C ++ libraries generate, so I need a way to generate REAL random numbers using hardware functions, but I don't know how I can do that.
Any ideas? (I am a software engineer, not an electronic engineer, so please describe it simply: P)

+3


source to share


4 answers


As stated, the chip has no hardware RNG.

But you can roll yourself. The usual approach is to measure jitter between INDEPENDENT clocks. Independent means that the two clocks are supported by different Christians or RC generators and are not derived from them.

I would use:

  • SysTick Timer / Counter derived from system clock (MHz range)
  • One of the kHz RC oscillators


Tune the counter on the kHz RC oscillator to interrupt several times per second. In the interrupt handler, you read the current value of the SysTick counter. Whether the SysTick is used for other purposes (scheduling), the lower 5 or so bits are necessarily unpredictable.

To get random numbers from this use a regular pseudo-RNG. Use the entropy collected above to unpredictably mutate the internal state of a pseudo-RNG. To generate keys, don't read all the bits at once, but allow a couple of mutations.

The attacks on this are obvious: if an attacker can measure or control an RC oscillator with a frequency of up to MHz, the accuracy of randomness will disappear. If you are worried about this, use a smart card or other security coprocessor.

+4


source


This is an old question I just came across, but I want to answer because I don't find other answers that are satisfying.

"I need random numbers to generate RSA keys."

This means that the PRNG routine (too often mistakenly called RNG, my homepage) is UNACCEPTABLE and does not guarantee the required security.



An external true RNG is acceptable, but the most graceful answer is to upgrade to an STM32F2xx or STM32F4xx microcontroller, which has a built-in TRUE random number generator designed for just such applications. For development, I suppose you could use thr F1 and any PRNG, but the temptation there would be "it works, let it ship" before using a real RNG by sending a faulty product when the component is RIGHT (of course ST F4, and I think there are also F2 chips, since before this question was asked).

This answer may not be acceptable for non-technical reasons (the chip was already listed, the OP did not have any access to the required functions), but whoever chose the chip had to choose it based on what built-in peripherals and functions are required for the application.

+8


source


The F1 series doesn't seem to have an RNG (random number generator), so your only options are to use pseudo-randoms, or to ask for external input (some consider, for example, a random movement of a human hand). You often get better pseudo randoms by using some kind of crypto library instead of the standard C ++ libraries.

+4


source


There is another method I found and tested that works quite well. It can generate true random 32bit numbers, I've never tested how fast it can, it can take a few milliseconds per number. Here's how it's done:

  • Read the noisy internal temperature at the fastest rate to generate the most ADC noise.
  • Run values ​​through a hardware CRC generator available for most (all?) STM32 chips

Repeat a few times, I found that 8 times gives a pretty good randomness. I checked for randomness by sorting the output values ​​in ascending order and plotting them in excel, with good random numbers that generate a straight line, bad randomness or "accumulation" of certain numbers is immediately visible. Here is the code for STM32F03:

uint32_t getTrueRandomNumber(void) {

ADC_InitTypeDef ADC_InitStructure;

//enable ADC1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

// Initialize ADC 14MHz RC
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
RCC_HSI14Cmd(ENABLE);
while (!RCC_GetFlagStatus(RCC_FLAG_HSI14RDY))
    ;

ADC_DeInit(ADC1);
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO; //default
ADC_Init(ADC1, &ADC_InitStructure);

//enable internal channel
ADC_TempSensorCmd(ENABLE);

// Enable ADCperipheral
ADC_Cmd(ADC1, ENABLE);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN) == RESET)
    ;

ADC1->CHSELR = 0; //no channel selected
//Convert the ADC1 temperature sensor, user shortest sample time to generate most noise
ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_1_5Cycles);

// Enable CRC clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);

uint8_t i;
for (i = 0; i < 8; i++) {
    //Start ADC1 Software Conversion
    ADC_StartOfConversion(ADC1);
    //wait for conversion complete
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) {
    }

    CRC_CalcCRC(ADC_GetConversionValue(ADC1));
    //clear EOC flag
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}

//disable ADC1 to save power
ADC_Cmd(ADC1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);

return CRC_CalcCRC(0xBADA55E5);

      

}

+2


source







All Articles