NXP / fsl_phy_mcr20a

Fork of fsl_phy_mcr20a by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RNG.cpp Source File

RNG.cpp

00001 /*!
00002 * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * \file RNG.c
00006 * RNG implementation file for the ARM CORTEX-M4 processor
00007 *
00008 * Redistribution and use in source and binary forms, with or without modification,
00009 * are permitted provided that the following conditions are met:
00010 *
00011 * o Redistributions of source code must retain the above copyright notice, this list
00012 *   of conditions and the following disclaimer.
00013 *
00014 * o Redistributions in binary form must reproduce the above copyright notice, this
00015 *   list of conditions and the following disclaimer in the documentation and/or
00016 *   other materials provided with the distribution.
00017 *
00018 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
00019 *   contributors may be used to endorse or promote products derived from this
00020 *   software without specific prior written permission.
00021 *
00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00024 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00026 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00029 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 
00035 #include "RNG_Interface.h"
00036 #include "fsl_device_registers.h"
00037 #include "fsl_clock_manager.h"
00038 //#include "SecLib.h"
00039 #include "FunctionLib.h "
00040 
00041 #if (gSecLib_HWSupport_d == gSecLib_MMCAUSupport_d)
00042 //#include "mmcau_interface.h"
00043 #endif
00044 
00045 #ifndef gRNG_UsePhyRngForInitialSeed_d
00046 #define gRNG_UsePhyRngForInitialSeed_d 0
00047 #endif
00048 
00049 #if (gRNG_HWSupport_d == gRNG_NoHWSupport_d)
00050   uint32_t mRandomNumber;
00051 
00052   #if gRNG_UsePhyRngForInitialSeed_d
00053   extern void PhyGetRandomNo(uint32_t *pRandomNo);
00054   #endif
00055 #endif
00056 
00057 /************************************************************************************
00058 *************************************************************************************
00059 * Private macros
00060 *************************************************************************************
00061 ************************************************************************************/
00062 #define mPRNG_NoOfBits_c      (160)
00063 #define mPRNG_NoOfBytes_c     (mPRNG_NoOfBits_c/8)
00064 #define mPRNG_NoOfLongWords_c (mPRNG_NoOfBits_c/32)
00065 
00066 /************************************************************************************
00067 *************************************************************************************
00068 * Private memory declarations
00069 *************************************************************************************
00070 ************************************************************************************/
00071 static uint32_t XKEY[mPRNG_NoOfLongWords_c];
00072 static uint32_t mPRNG_Requests = gRngMaxRequests_d;
00073 
00074 /************************************************************************************
00075 *************************************************************************************
00076 * Public functions
00077 *************************************************************************************
00078 ************************************************************************************/
00079 
00080 /******************************************************************************
00081  * Name: RNG_Init()
00082  * Description: Initialize the RNG HW module
00083  * Parameter(s): -
00084  * Return: Status of the RNG module
00085  ******************************************************************************/
00086 uint8_t RNG_Init(void)
00087 {
00088 #if gRNG_HWSupport_d == gRNG_RNGAHWSupport_d
00089     CLOCK_SYS_EnableRngaClock(0);
00090     /* Mask Interrupts and start RNG */
00091     RNG_CR = RNG_CR_INTM_MASK | RNG_CR_HA_MASK | RNG_CR_GO_MASK;
00092 
00093 #elif gRNG_HWSupport_d == gRNG_RNGBHWSupport_d
00094     CLOCK_SYS_EnableRngbClock(0);
00095     /* Execute a SW Reset */
00096     RNG_CMD |= RNG_CMD_SR_MASK;
00097 
00098     /* Mask Interrupts */
00099     RNG_CR = RNG_CR_MASKDONE_MASK | RNG_CR_MASKERR_MASK;
00100 
00101     /* Start Self Test and Seed Generation */
00102     RNG_CMD = RNG_CMD_ST_MASK | RNG_CMD_GS_MASK;
00103 
00104     /* Wait for Self Test and Seed Generation to be done*/
00105     while (RNG_CMD & (RNG_CMD_ST_MASK | RNG_CMD_GS_MASK));
00106 
00107     /* Enable RNG Auto-Reseed */
00108     RNG_CR |= RNG_CR_AR_MASK;
00109 
00110     /* Check for Errors */
00111     if ( RNG_SR & RNG_SR_ERR_MASK )
00112     {
00113         return (uint8_t)(RNG_ESR);
00114     }
00115 #elif gRNG_HWSupport_d == gRNG_TRNGHWSupport_d
00116 //    uint32_t temp;
00117 //
00118 //    SIM_SCGC6 |= SIM_SCGC6_TRNG_MASK;
00119 //
00120 //    /* Reset TRNG registers to default values */
00121 //    HW_TRNG_RTMCTL_WR(gTRNG_BaseAddr_c, BM_TRNG_RTMCTL_RST_DEF | BM_TRNG_RTMCTL_PRGM);
00122 //
00123 //    /* Enable Entropy Valid IRQ */
00124 //    //disallow device to sleep, allow device to sleep in ISR 
00125 //    //HW_TRNG_SA_TRNG_INT_MASK_SET(gTRNG_BaseAddr_c, BM_TRNG_SA_TRNG_INT_MASK_SA_TRNG_SBS_ENTROPY_VALID);
00126 //
00127 //    /* Set TRNG in Run mode, and enable entropy read access */
00128 //    temp = HW_TRNG_RTMCTL_RD(gTRNG_BaseAddr_c);
00129 //    temp &= ~(BM_TRNG_RTMCTL_PRGM | BM_TRNG_RTMCTL_ERR);
00130 //    temp |= BM_TRNG_RTMCTL_TRNG_ACC;
00131 //    HW_TRNG_RTMCTL_WR(gTRNG_BaseAddr_c, temp);
00132 #else
00133     #if gRNG_UsePhyRngForInitialSeed_d
00134     PhyGetRandomNo(&mRandomNumber);
00135     #else
00136     mRandomNumber = HW_SIM_UIDL_RD(SIM_BASE);
00137     #endif
00138 #endif /* gRNG_HwSupport_d == 1 */
00139 
00140     /* Init Successfull */
00141     return gRngSuccess_d;
00142 }
00143 
00144 /******************************************************************************
00145  * Name: RNG_HwGetRandomNo()
00146  * Description: Read a random number from the HW RNG module
00147  * Parameter(s): [OUT] pRandomNo - pointer to location where the RN will be stored
00148  * Return: status of the RNG module
00149  ******************************************************************************/
00150 #if (gRNG_HWSupport_d != gRNG_NoHWSupport_d)
00151 static uint8_t RNG_HwGetRandomNo(uint32_t* pRandomNo)
00152 {
00153 #if gRNG_HWSupport_d == gRNG_RNGAHWSupport_d
00154     /* If output register is empty, wait for a new random number */
00155     while ( ((RNG_SR & RNG_SR_OREG_LVL_MASK) >> RNG_SR_OREG_LVL_SHIFT) == 0 );
00156 
00157     /* Copy the output of RNG module */
00158     *pRandomNo = RNG_OR;
00159 
00160 #elif gRNG_HWSupport_d == gRNG_RNGBHWSupport_d
00161     /* Check for Errors */
00162     if ( RNG_SR & RNG_SR_ERR_MASK )
00163         return (uint8_t)(RNG_ESR);
00164 
00165     /* If output FIFO is empty, wait for a new random number */
00166     while (((RNG_SR & RNG_SR_FIFO_LVL_MASK) >> RNG_SR_FIFO_LVL_SHIFT) == 0 );
00167 
00168     /* Copy the output of RNG module */
00169     *pRandomNo = RNG_OUT;
00170 
00171 #elif gRNG_HWSupport_d == gRNG_TRNGHWSupport_d
00172     static uint8_t entropyIdx = 0;
00173     
00174     /* wait for entropy to be generated or for an error */
00175     while( !(HW_TRNG_RTMCTL_RD(gTRNG_BaseAddr_c) & (BM_TRNG_RTMCTL_ENT_VAL | BM_TRNG_RTMCTL_ERR)) );
00176     
00177     if( HW_TRNG_RTMCTL_RD(gTRNG_BaseAddr_c) & BM_TRNG_RTMCTL_ERR )
00178         return gRngInternalError_d;
00179 
00180     *pRandomNo = HW_TRNG_RTENTan_RD(gTRNG_BaseAddr_c, entropyIdx);
00181     if( ++entropyIdx == 16 )
00182     {
00183         entropyIdx = 0;
00184         //disallow device to sleep
00185     }
00186 #endif
00187 
00188     return gRngSuccess_d;
00189 }
00190 #endif /* gRNG_HwSupport_d */
00191 
00192 
00193 /******************************************************************************
00194  * Name: RNG_GetRandomNo()
00195  * Description: Read a random number from RNG module or from 802.15.4 PHY
00196  * Parameter(s): [OUT] pRandomNo - pointer to location where the RN will be stored
00197  * Return: none
00198  ******************************************************************************/
00199 void RNG_GetRandomNo(uint32_t* pRandomNo)
00200 {
00201     /* Check for NULL pointers */
00202     if (NULL == pRandomNo)
00203         return;
00204 
00205 #if (gRNG_HWSupport_d == gRNG_NoHWSupport_d)
00206     mRandomNumber = (mRandomNumber * 6075) + 1283;
00207     FLib_MemCpy(pRandomNo, &mRandomNumber, sizeof(uint32_t));    
00208 #else
00209     (void)RNG_HwGetRandomNo(pRandomNo);
00210 #endif
00211 }
00212 
00213 /******************************************************************************
00214  * Name: RNG_SetPseudoRandomNoSeed()
00215  * Description: Initialize seed for the PRNG algorithm.
00216  * Parameter(s):
00217  *      pSeed - pointer to a buffer containing 20 bytes (160 bits).
00218  *             Can be set using the RNG_GetRandomNo() function.
00219  * Return: None
00220  ******************************************************************************/
00221 void RNG_SetPseudoRandomNoSeed(uint8_t* pSeed)
00222 {
00223     mPRNG_Requests = 1;
00224     FLib_MemCpy( XKEY, pSeed, mPRNG_NoOfBytes_c );
00225 }
00226 
00227 #if 0
00228 /******************************************************************************
00229  * Name: RNG_GetRandomNo()
00230  *
00231  * Description: Pseudo Random Number Generator (PRNG) implementation
00232  *              according to NIST FIPS Publication 186-2, APPENDIX 3
00233  *
00234  * Let x be the signer's private key.  The following may be used to generate m values of x:
00235  *   Step 1. Choose a new, secret value for the seed-key, XKEY.
00236  *   Step 2. In hexadecimal notation let
00237  *     t = 67452301 EFCDAB89 98BADCFE 10325476 C3D2E1F0.
00238  *     This is the initial value for H0 || H1 || H2 || H3 || H4 in the SHS.
00239  *   Step 3. For j = 0 to m - 1 do
00240  *     a. XSEEDj = optional user input.
00241  *     b. XVAL = (XKEY + XSEEDj) mod 2^b
00242  *     c. xj = G(t,XVAL) mod q
00243  *     d. XKEY = (1 + XKEY + xj) mod 2^b
00244  *
00245  * Parameter(s):
00246  *      pOut - pointer to the output buffer
00247  *      outBytes - the number of bytes to be copyed (1-20)
00248  *      pXSEED - optional user SEED. Should be NULL if not used.
00249  *
00250  * Return: The number of bytes copied or -1 if reseed is needed
00251  ******************************************************************************/
00252 int16_t RNG_GetPseudoRandomNo(uint8_t* pOut, uint8_t outBytes, uint8_t* pXSEED)
00253 {
00254     uint32_t i;
00255     sha1Context_t ctx;
00256 
00257     if (mPRNG_Requests == gRngMaxRequests_d)
00258         return -1;
00259 
00260     mPRNG_Requests++;
00261 
00262     /* a. XSEEDj = optional user input. */
00263     if (pXSEED)
00264     {
00265         /* b. XVAL = (XKEY + XSEEDj) mod 2^b */
00266         for (i=0; i<mPRNG_NoOfBytes_c; i++)
00267         {
00268             ctx.buffer[i] = ((uint8_t*)XKEY)[i] + pXSEED[i];
00269         }
00270     }
00271     else
00272     {
00273         for (i=0; i<mPRNG_NoOfBytes_c; i++)
00274         {
00275             ctx.buffer[i] = ((uint8_t*)XKEY)[i];
00276         }
00277     }
00278 
00279     /* c. xj = G(t,XVAL) mod q
00280     ***************************/
00281     SHA1_Hash(&ctx, ctx.buffer, mPRNG_NoOfBytes_c);
00282 
00283     /* d. XKEY = (1 + XKEY + xj) mod 2^b */
00284     XKEY[0] += 1;
00285     for (i=0; i<mPRNG_NoOfLongWords_c; i++)
00286     {
00287         XKEY[i] += ctx.hash[i];
00288     }
00289 
00290     /* Check if the length provided exceeds the output data size */
00291     if (outBytes > mPRNG_NoOfBytes_c)
00292     {
00293         outBytes = mPRNG_NoOfBytes_c;
00294     }
00295 
00296     /* Copy the generated number */
00297     for (i=0; i < outBytes; i++)
00298     {
00299         pOut[i] = ((uint8_t*)ctx.hash)[i];
00300     }
00301 
00302     return outBytes;
00303 }
00304 #endif
00305 
00306 /********************************** EOF ***************************************/