/*- * Copyright 2021 John-Mark Gurney. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include "stm32f1xx.h" #include "stm32f1xx_hal.h" #include #include #include #define NBYTESENTROPY (256 / 8) #define DEFINE_RNG_SAVE 1 #if DEFINE_RNG_SAVE const rng_word_t rng_save[roundup(NBYTESENTROPY, sizeof(rng_word_t)) / sizeof(rng_word_t)] __attribute__ ((section (".savestate"))); #endif static void strobe_rng_init(void) { /* * Seed RNG * Seed w/ saved state. */ strobe_seed_prng((uint8_t *)rng_save, sizeof rng_save); /* * On first boot, SRAM is uninitialized and randomness from * it is used. * * Note: This depends upon sbrk pointing to uinitalized SRAM. */ strobe_seed_prng(sbrk(0), 2*1024); } SYSINIT_VF(rng_init, SI_SUB_HAL, SI_ORDER_LAST, strobe_rng_init); uint32_t times[20]; static void analog_seed_rng(void) { ADC_HandleTypeDef ah; ADC_ChannelConfTypeDef chanconf; uint16_t v; int timespos; int i; /* Enable ADC1 Clock */ __HAL_RCC_ADC1_CLK_ENABLE(); /* Configure */ ah = (ADC_HandleTypeDef){ .Instance = ADC1, .Init.DataAlign = ADC_DATAALIGN_RIGHT, .Init.ScanConvMode = ADC_SCAN_DISABLE, .Init.ContinuousConvMode = DISABLE, .Init.NbrOfConversion = 1, .Init.DiscontinuousConvMode = DISABLE, .Init.NbrOfDiscConversion = 1, .Init.ExternalTrigConv = ADC_SOFTWARE_START, }; HAL_ADC_Init(&ah); chanconf = (ADC_ChannelConfTypeDef){ .Rank = ADC_REGULAR_RANK_1, .Channel = ADC_CHANNEL_TEMPSENSOR, /* temp sensor */ .SamplingTime = ADC_SAMPLETIME_71CYCLES_5, }; HAL_ADC_ConfigChannel(&ah, &chanconf); HAL_Delay(1); timespos = 0; /* Capture */ for (i = 0; i < 256 / 2; i++) { times[timespos++] = HAL_GetTick(); timespos %= sizeof times / sizeof *times; /* * Capture some ADC data. If pin is floating, 0xfff * happens frequently, if pin is grounded, 0 happens * frequently, filter these values out. */ do { HAL_ADC_Start(&ah); HAL_ADC_PollForConversion(&ah, 1); v = HAL_ADC_GetValue(&ah); } while (v == 0 || v == 0xfff); strobe_seed_prng((uint8_t *)&v, sizeof v); } /* Deinit */ HAL_ADC_DeInit(&ah); } SYSINIT_VF(analog_seed_rng, SI_SUB_HAL, SI_ORDER_LAST, analog_seed_rng); static void strobe_rng_save(void) { rng_word_t tmp[sizeof rng_save / sizeof(rng_word_t)]; int r; /* * Save entropy for next reset. */ r = strobe_randomize((uint8_t *)tmp, sizeof tmp); (void)r; doflash(rng_save, tmp, sizeof(rng_save)); } SYSINIT_VF(rng_save, SI_SUB_LAST, SI_ORDER_LAST, strobe_rng_save);