1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #define CC_PAL_LOG_CUR_COMPONENT HOST_LOG_MASK_SECURE_BOOT
8 
9 #include "rsa_pki_pka.h"
10 #include "rsa_bsv.h"
11 #include "secureboot_stage_defs.h"
12 
13 
14 /************************ Defines ******************************/
15 
16 /************************ Enums ********************************/
17 
18 /************************ Typedefs  ****************************/
19 
20 /************************ Structs  ******************************/
21 
22 /************************ Public Variables **********************/
23 /* SRAM address used for the PKA */
24 const uint32_t g_SramPkaAddr = 0;
25 
26 /************************ Public Functions ******************************/
27 
28 #ifdef PKA_DEBUG
29   uint8_t tempRes[268];
30 #endif
31 
32 /* ***************************************************************************** */
33 /* *********      RSA PKI PKA initialisation functions and macros      ********* */
34 /* ***************************************************************************** */
35 
36 /***********      PkaSetRegsSizesTab function      **********************/
37 /**
38  * @brief This function initializes the PKA registers sizes table.
39  *
40  *      The function sets sizes table as follows:
41  *            -  tab[0] = MaxSizeBits; //maximal size, usually this is exact modulus size in bits
42  *            -  tab[1] = Extended size with extra bits, aligned to big words.
43  *            -  other entrie,
44         uint32_t  Xs = PKA_SIZE_ENTRY_NOT_USED, means - not used.
45  *
46  * @param[in] opSizeInBits - Size of PKA operations (modulus) in bits. The value must be in interval
47  *                          from defined Min. to Max. size bits.
48  * @param[in] regSizeInPkaWords - Sise of registers in PKA big words (e.g. 128-bit words).
49  *
50  * @return - no return value
51  *
52  */
RSA_PKA_SetRegsSizesTab(uint32_t opSizeInBits,int32_t regSizeInPkaWords,unsigned long virtualHwBaseAddr)53 void RSA_PKA_SetRegsSizesTab( uint32_t     opSizeInBits,
54                   int32_t      regSizeInPkaWords,
55                   unsigned long  virtualHwBaseAddr)
56 {
57     /* LOCAL DECLARATIONS */
58 
59     uint32_t  i;
60 
61     /* FUNCTION LOGIC */
62 
63     /* Set exact op. size */
64     SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, PKA_L0), opSizeInBits);
65     /* Set register size (with extra bits) aligned to PKA big words */
66     SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, PKA_L0) + 4,
67                   regSizeInPkaWords*RSA_PKA_BIG_WORD_SIZE_IN_BITS);
68 
69     /* remaining entries set to PKA_SIZE_ENTRY_NOT_USED for debugging goals */
70     for (i = 2; i < RSA_PKA_MAX_COUNT_OF_REGS_SIZES; i++) {
71         SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, PKA_L0) + 4*i, PKA_SIZE_ENTRY_NOT_USED);
72     }
73 
74     return;
75 
76 } /* END of the finction  PkaSetRegsSizesTab */
77 
78 
79 /***********      PkaSetRegsMapTab function      **********************/
80 /**
81  * @brief This function initializes the PKA registers sizes table.
82  *
83  *   The function checks input parameters and sets the physical memory registers mapping-table
84  *   according to parameters, passed by the user:
85  *     - start address of register 0 is the start address of PKA data registers memory
86  *       PKA_SRAM_REGS_MEM_OFFSET_WORDS (defined in pka_hw_defs.h file);
87  *     - special registers are set as follows: N=0,NP=1,T0=30,T1=31;
88  *     - all registers have the same size, equalled to given size;
89  *
90  * @param[in] countOfRegs  - The count of registeres, requirred by the user.
91  * @param[in] regSizeInPkaWords - Sise of registers in PKA big words (e.g. 128-bit words).
92  * @param[in] virtualHwBaseAddr - cc base address
93  *
94  * @return - no return value
95  *
96  */
RSA_PKA_SetRegsMapTab(int32_t countOfRegs,int32_t regSizeInPkaWords,unsigned long virtualHwBaseAddr)97 void RSA_PKA_SetRegsMapTab(int32_t   countOfRegs,
98                int32_t   regSizeInPkaWords,
99                unsigned long  virtualHwBaseAddr)
100 {
101     /* LOCAL DECLARATIONS */
102 
103     uint32_t  currentAddr;
104     int32_t i;
105 
106     /* FUNCTION LOGIC */
107     /* start addres of PKA mem. */
108     currentAddr = RSA_PKA_SRAM_REGS_MEM_OFFSET_WORDS;
109 
110     /* set addresses of the user requested registers (excluding T0,T1) */
111     for (i = 0; i < countOfRegs-2; i++) {
112                 SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, MEMORY_MAP0) +
113                                       i*sizeof(uint32_t), currentAddr);
114                 currentAddr += regSizeInPkaWords*RSA_PKA_BIG_WORD_SIZE_IN_32_BIT_WORDS;
115     }
116     /* set addresses of 2 temp registers: T0=30, T1=31 */
117     SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, MEMORY_MAP0) + 30*sizeof(uint32_t), currentAddr);
118     SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, MEMORY_MAP0) + 31*sizeof(uint32_t),
119                   currentAddr + regSizeInPkaWords*RSA_PKA_BIG_WORD_SIZE_IN_32_BIT_WORDS);
120 
121     /* set default virtual addresses of N,NP,T0,T1 registers into N_NP_T0_T1_Reg */
122     SB_HAL_WRITE_REGISTER(SB_REG_ADDR(virtualHwBaseAddr, N_NP_T0_T1_ADDR),
123                   (uint32_t)RSA_HW_PKI_PKA_N_NP_T0_T1_REG_DEFAULT_VAL);
124 
125     return;
126 
127 }  /* END of the finction  PkaSetRegsMapTab */
128 
129 
130 /***********      PkaInitPka function      **********************/
131 /**
132  * @brief This function initializes the PKA engine.
133  *
134  *    The function performs the following:
135  *      - initializes the PKA_SizesTable, PKA_MappingTable and special register
136  *        N_NP_T0_T1 according to user passed register sizes, registers mapping
137  *        and default N_NP_T0_T1 value.
138  *
139  *    The function calls the PkaSetRegsSizesTab  and PkaSetRegsMapTab
140  *    functions and sets N_NP_T0_T1 value into N_NP_T0_T1 register.
141  *    Notes:
142  *            - See remarks to PkaSetRegsSizesTab and PkaSetRegsMapTab functions.
143  *            - The function allocates one additional word for each register if it is needed for extra bits.
144  *
145  * @return CCError_t - On success CC_OK is returned, on failure an error code:
146  *                       PKA_REGISTER_SIZES_ERROR
147  *                       PKA_ENTRIES_COUNT_ERROR
148  *                       PKA_NOT_ENOUGH_MEMORY_ERROR
149  *
150  */
RSA_PKA_InitPka(uint32_t opSizeInBits,uint32_t regsCount,unsigned long virtualHwBaseAddr)151 void RSA_PKA_InitPka( uint32_t   opSizeInBits,          /*in - modulus size in bits*/
152               uint32_t   regsCount,             /*in*/
153               unsigned long  virtualHwBaseAddr) /*in*/
154 {
155 
156     /* LOCAL DECLARATIONS */
157 
158     uint32_t  regSizeInPkaWords;
159 
160     /*     enabling the PKA clocks      */
161     SB_HAL_WRITE_REGISTER( SB_REG_ADDR(virtualHwBaseAddr, PKA_CLK_ENABLE), 0x1UL );
162 
163     /* minimal needed regs size */
164     regSizeInPkaWords = GET_FULL_OP_SIZE_PKA_WORDS(opSizeInBits);
165 
166 
167     /* setting the PKA registers mapping table */
168     /*-----------------------------------------*/
169     RSA_PKA_SetRegsMapTab(regsCount, regSizeInPkaWords, virtualHwBaseAddr);
170 
171     /* setting the PKA registers sizes table   */
172     /*-----------------------------------------*/
173     RSA_PKA_SetRegsSizesTab(opSizeInBits, regSizeInPkaWords, virtualHwBaseAddr);
174 
175     /* ......  End of function ...... */
176     return;
177 
178 }
179 
180 
181 /***********      RSA_HW_PKI_PKA_FinishPKA function      **********************/
182 /**
183  * @brief This function ends the PKA engine session and disables PKA clocks.
184  *
185  * @param[in] virtualHwBaseAddr -  Virtual HW base address, passed by user.
186  *
187  * @return - no return parameters.
188  *
189  */
RSA_HW_PKI_PKA_FinishPKA(unsigned long virtualHwBaseAddr)190  void RSA_HW_PKI_PKA_FinishPKA( unsigned long virtualHwBaseAddr /*in*/ )
191  {
192 
193    /* FUNCTION LOGIC */
194 
195    /* close PKA clocks */
196    SB_HAL_WRITE_REGISTER( SB_REG_ADDR(virtualHwBaseAddr, PKA_CLK_ENABLE), 0x0UL );
197 
198  }
199 
200 
201 
202 /*******************************************************************************/
203 /************    RSA PKI PKA mathmatic functions and macros     ****************/
204 /*******************************************************************************/
205 
206 
207 /***********    PkaDbgExecOperation (with virtual pointers)     ******************/
208 /**
209  * @brief This function executes any allowed PKA mathematic operation according to
210  *        user passed Opcode.
211  *
212  *        The function receives code of operation, virtual pointers to PKI registers
213  *        (sequence number), for arguments and result, and operates PKA machine by writing
214  *        full operation code into OPCODE register. Then the function calls macros for
215  *        waiting the PKA pipe ready signal.
216  *        If opcode is illegal or one of operands is illegal, the function returns an
217  *        error code defined in llf_pki_error.h file.
218  *
219  *        The user don't call this function directly. For user convenience, in llf_pki.h file  are
220  *        given some macros for calling this function according to each performed operation.
221  *
222  *     NOTES:
223  *       -  Before executing modular operations, the modulus must be set into N=r0 register of PKA.
224  *       -  Before modular multiplication and exponentiation must be calculated and set into NP=r1
225  *          register the Barrett modulus tag NP = 2**(sizeN+132) / N.
226  *       -  In operations with immediate operands (IsImmediate bit = 1), the operand value (5-bit)
227  *          is treated as sign-extended. That means: low 4 bits are treated as unsigned operand
228  *          value in range 0-15 and bit 5 is a sign (with extension to all high bits of register,
229  *          in which the full operand shall be set).
230  *       -  In shift operations the 5-bits shift operand is treated as unsigned value in range 0-31
231  *          (count of shifts is equaled to shift operand value + 1).
232  *       -  The LMul operation gives the low half of multiplication result of length equaled to
233  *          operation size. The leading not significant bits of the operands and result (including
234  *          the the extra word) must be zeroed.
235  *       -  The HMul operation gives the high half of multiplication result plus one high word of low
236  *          half of full multiplication result. Therefore this result is by one word large, than
237  *          operation size. The leading not significant bits of the operands and result,
238  *          including extra word must be zeroed.
239  *       -  The ModInv operation calculates Res = 1/OpB mod N for odd modulus. Operand A is ignored.
240  *          In case of even modulus the function returns an error. Therefore in this case
241  *          (also for odd modulus) the user may call the PkaExecFullModInv function.
242  *
243  * @param[in] Opcode   - The operation code according HW PKA definitions. Valid values: 0 - max Opcode.
244  * @param[in] LenID    - ID of the length of operands according to register sizes table
245  *                       (means the number of entry in the table). Valid values: 0...7.
246  * @param[in] IsAImmed - If IsAImmed = 1, then operand A treated as immediate value, else -
247  *                       as virtual register pointer. Valid values: 0,1.
248  * @param[in] OpA      - Operand A: an immediate value or virtual register pointer, according to IsAImmed
249  *                       IsAImmed parameter. Valid values: 0 <= OpA <= 31.
250  * @param[in] IsBImmed - If IsBImmed = 1, then operand B treated as immediate value, else -
251  *                       as virtual register pointer. Valid values: 0,1.
252  * @param[in] OpB      - Operand B: an immediate value or virtual register pointer, according to IsAImmed
253  *                       IsBImmed parameter. Valid values: 0 <= OpA <= 31.
254  * @param[in] ResDiscard -  If ResDiscard = 1, then result is discarded.
255  * @param[in] Res        - Virtual register pointer for result data.
256  *                         Valid values: 0 <= Res <= 31. Value Res = RES_DISCARD means result must be discarded.
257  * @param[in] Tag        - The user defined value (Tag <= 31), used for indication goals.
258  *
259  *
260  * @return CCError_t - On success CC_OK is returned, on failure an error code:
261  *                       PKA_ILLEGAL_OPCODE_ERROR
262  *                       PKA_ILLEGAL_OPERAND_LEN_ERROR
263  *                       PKA_ILLEGAL_OPERAND_TYPE_ERROR
264  *                       PKA_ILLEGAL_OPERAND_ERROR
265  *                       PKA_INVERSION_NOT_EXISTS_ERROR
266  */
267 
268 
_RSA_PKA_ExecOperation(uint32_t Opcode,uint8_t LenID,uint8_t IsAImmed,int8_t OpA,uint8_t IsBImmed,int8_t OpB,uint8_t ResDiscard,int8_t Res,uint8_t Tag,unsigned long virtualHwBaseAddr)269 CCError_t _RSA_PKA_ExecOperation( uint32_t      Opcode,      /*in*/
270                 uint8_t       LenID,         /*in*/
271                 uint8_t       IsAImmed,      /*in*/
272                 int8_t        OpA,       /*in*/
273                 uint8_t       IsBImmed,      /*in*/
274                 int8_t        OpB,       /*in*/
275                 uint8_t       ResDiscard,    /*in*/
276                 int8_t        Res,       /*in*/
277                 uint8_t       Tag,       /*in*/
278                     unsigned long      virtualHwBaseAddr)
279 {
280 
281     /* LOCAL DECLARATIONS */
282 
283     /* error identification */
284     CCError_t Error = CC_OK;
285 
286     /* full Operation Code word */
287     uint32_t FullOpCode;
288 
289     /* FUNCTION LOGIC */
290 
291     /* if Res == RES_DISCARD , then result is discarded */
292     if (Res == (int8_t)RES_DISCARD) {
293         ResDiscard = 1;
294         Res = 0;
295     }
296 
297 
298     /*************************************************/
299     /*      main PKI operation of this function      */
300     /*************************************************/
301 
302     FullOpCode = RSA_PKA_FullOpCode(Opcode, LenID, IsAImmed, OpA, IsBImmed, OpB, ResDiscard, Res, Tag);
303     RSA_PKA_WAIT_ON_PKA_PIPE_READY(virtualHwBaseAddr);
304     SB_HAL_WRITE_REGISTER( SB_REG_ADDR(virtualHwBaseAddr, OPCODE), FullOpCode);
305 
306 
307     /*************************************************/
308     /* finishing operations for different cases      */
309     /*************************************************/
310 
311     return Error;
312 
313 } /* END OF function PkaDbgExecOperation */
314 
315 
316 /***********      PkaCopyDataIntoPkaReg function      **********************/
317 /**
318 * @brief This function  copies source data into PKA register .
319 *
320 *        Assumings: - PKA is initialized.
321 *                   - Length of extended (by word) registers is placed into LenID entry of
322 *                     sizes table.
323 *                   - If the extra word of register must be cleared also the user must
324 *                     set LenID according to extended register size
325 *
326 * @param[in] dstReg       - Virtual address (number) of destination register.
327 * @param[in] LenId        - ID of entry of regsSizesTable, defining full register length,
328 *                           aligned to PKA word.
329 * @param[in] src_ptr      - Pointer to source buffer.
330 * @param[in] sizeWords    - Data size in words.
331 *
332 * @return - no return parameters.
333 *
334 */
RSA_HW_PKI_PKA_CopyDataIntoPkaReg(uint32_t dstReg,uint32_t LenID,const uint32_t * src_ptr,uint32_t sizeWords,unsigned long virtualHwBaseAddr)335 void RSA_HW_PKI_PKA_CopyDataIntoPkaReg(uint32_t    dstReg,    /*out*/
336                        uint32_t    LenID,     /*in*/
337                        const  uint32_t  *src_ptr, /*in*/
338                        uint32_t    sizeWords,  /*in*/
339                        unsigned long  virtualHwBaseAddr)
340 {
341 
342     /* LOCAL DECLARATIONS */
343 
344 
345     /* current register address and size */
346     uint32_t  currAddr;
347     uint32_t  regSizeWords;
348 
349 
350     /* FUNCTION LOGIC */
351 
352     /* copy data from src buffer into PKA register with 0-padding  *
353     *  in the last PKA-word                       */
354 
355     RSA_PKA_WAIT_ON_PKA_DONE(virtualHwBaseAddr);
356         /* register size in 32-bits words */
357     RSA_PKA_ReadRegSize(regSizeWords, LenID, virtualHwBaseAddr);/*temporary in Bits*/
358     regSizeWords = CALC_FULL_32BIT_WORDS(regSizeWords);
359 
360         currAddr = RSA_PKA_GetRegAddress(dstReg, virtualHwBaseAddr);
361         RSA_HW_PKI_HW_LOAD_BLOCK_TO_PKA_MEM(virtualHwBaseAddr, currAddr, src_ptr, sizeWords);
362 
363         /* zeroe not significant high words of the register */
364         if (regSizeWords > sizeWords){
365                 currAddr = currAddr + sizeWords;
366                 RSA_HW_PKI_HW_CLEAR_PKA_MEM(virtualHwBaseAddr, currAddr, regSizeWords - sizeWords);
367         }
368 
369 #ifdef PKA_DEBUG
370     /*! PKA_DEBUG */
371 //!! RL RSA_PKA_Copy(LenID/*LenID*/, dstReg, dstReg, 0/*Tag*/ , virtualHwBaseAddr);
372 #endif
373     return;
374 } /* END OF function PkaCopyDataIntoPkaReg */
375 
376 
377 
378 /***********      RSA_HW_PKI_PKA_CopyDataFromPkaReg      **********************/
379 /**
380  * @brief This function copies data from PKA register into output buffer .
381  *
382  *        Assumings: - PKA is initialized.
383  *                   - Length of extended (by word) registers is placed into LenID entry of
384  *                     sizes table.
385  *                   - If the extra word of register must be cleared also the user must
386  *                     set LenID according to extended register size
387  *
388  * @param[in] srcReg       - Virtual address (number) of source PKA register.
389  * @param[in] dst_ptr      - Pointer to destination buffer.
390  * @param[in] sizeBytes - Source size in bytes.
391  *
392  * @return - no return parameters.
393  *
394  */
RSA_HW_PKI_PKA_CopyDataFromPkaReg(uint32_t * dst_ptr,uint32_t sizeWords,uint32_t srcReg,unsigned long virtualHwBaseAddr)395 void RSA_HW_PKI_PKA_CopyDataFromPkaReg(uint32_t *dst_ptr,       /*out*/
396                 uint32_t  sizeWords,        /*in*/
397                 uint32_t  srcReg,       /*in*/
398                 unsigned long  virtualHwBaseAddr)
399 {
400 
401     /* LOCAL DECLARATIONS */
402 
403     /* current register address and size */
404     uint32_t  currAddr = 0;
405 
406     /* FUNCTION LOGIC */
407 
408     RSA_PKA_WAIT_ON_PKA_DONE(virtualHwBaseAddr);
409     currAddr = RSA_PKA_GetRegAddress(srcReg, virtualHwBaseAddr);
410     RSA_HW_PKI_HW_READ_BLOCK_FROM_PKA_MEM(virtualHwBaseAddr, currAddr, dst_ptr, sizeWords );
411 
412     return;
413 
414 } /* END OF function PkaCopyDataFromPkaReg */
415 
416