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 
10 /************* Include Files ****************/
11 
12 #include "secureboot_basetypes.h"
13 #include "secureboot_error.h"
14 #include "rsa_bsv.h"
15 #include "cc_pka_hw_plat_defs.h"
16 #include "secureboot_stage_defs.h"
17 
18 
19 /************************ Defines ******************************/
20 
21 /************************ Global Data **************************/
22 
23 /*********************** Private Functions *********************/
24 
25 /*
26 \brief The function implements the RSA_PSS_Decode algorithm (PKCS#1 v2.1).
27 \note The input data is placed as BE bytes arrays into 32-bit word buffers
28       for alignment goal. Order of bytes in arrays is BE (MS byte is left most one).
29 @return CC_OK on success,
30 @return A non-zero value from secureboot_error.h on failure.
31 */
32 
RSA_PSS_Decode(unsigned long hwBaseAddress,CCHashResult_t mHash,uint8_t * pEncodedMsg,int32_t * pVerifyStat)33 CCError_t RSA_PSS_Decode(unsigned long hwBaseAddress,  /* [in] HW base address of registers. */
34                          CCHashResult_t mHash,         /* [in] SHA256 hash of the message (32 bytes). */
35                          uint8_t *pEncodedMsg,         /* [in] Pointer to PSS encoded message (EM). Size = modulus size. */
36                          int32_t *pVerifyStat          /* [out] Pointer to validation status value, equalled to:
37                                                                 1 - if valid, 0 - if not valid. */ )
38 {
39         /* FUNCTION DECLERATIONS */
40 
41 #define MASKED_DB_SIZE (SB_CERT_RSA_KEY_SIZE_IN_BYTES - HASH_RESULT_SIZE_IN_BYTES - 1)
42 
43     /* error variable */
44     CCError_t error = CC_OK;
45         uint32_t stat = 0;
46 
47     /* temp buffers and byte pointers */
48     uint32_t tmpBuff[HASH_RESULT_SIZE_IN_WORDS + 1/*for counter*/];
49     uint32_t dbMask[SB_CERT_RSA_KEY_SIZE_IN_WORDS];
50     uint8_t *pDbMask;
51 
52         /* loop variables */
53     uint32_t i, counter;
54 
55     /* FUNCTION LOGIC */
56 
57         /* check input pointers */
58         if(mHash == NULL || pEncodedMsg == NULL || pVerifyStat == NULL) {
59                 return CC_BOOT_RSA_VERIFIER_ALG_FAILURE;
60         }
61 
62         *pVerifyStat = 0; /*set status to "not valid"*/
63 
64         /* setting the EM and masked DB byte-pointers */
65     pDbMask = (uint8_t*)dbMask;
66 
67         /*   operating the RSA PSS decoding scheme      */
68         /*----------------------------------------------*/
69 
70         /* 9.1.2 <1,2,3> meet  */
71         /* 9.1.2 <4> Check that the rightmost octet of EM = 0xbc */
72     if (pEncodedMsg[SB_CERT_RSA_KEY_SIZE_IN_BYTES - 1] != 0xbc) {
73         error = CC_BOOT_RSA_VERIFIER_CMP_FAILURE;
74         goto End;
75     }
76 
77         /*  9.1.2 <6> Check that the leftmost (8*emLen - emLenbit) of  *
78         *   masked DB are equalled to 0, i.e. in our case MSbit = 0    */
79     if (pEncodedMsg[0] & 0x80) {
80         error = CC_BOOT_RSA_VERIFIER_CMP_FAILURE;
81         goto End;
82     }
83 
84         /*  9.1.2 <7> Let dbMask = MGF1(H,emLen-hLen-1)                *
85          *  B.2.1 MGF1:                                                *
86          *  For counter from 0 to  | L / hLen | , do the following:    *
87      *  a.  Convert counter to an octet string C of length 4       *
88          *  b.  Concatenate the hash of the seed H and C to the octet  *
89          *      string T:  T = T || Hash(H || C)                       *
90          *      C = C + 1                                              */
91 
92         /* copy the HASH from the EM (EncodedMsg) to the temp buffer */
93         UTIL_MemCopy((uint8_t*)tmpBuff, &pEncodedMsg[MASKED_DB_SIZE], HASH_RESULT_SIZE_IN_BYTES);
94 
95     for (counter = 0; counter <= (MASKED_DB_SIZE/HASH_RESULT_SIZE_IN_BYTES); counter++ ) {
96 
97                 /* a. tmp = H||C */
98         tmpBuff[HASH_RESULT_SIZE_IN_WORDS] = UTIL_INVERSE_UINT32_BYTES(counter);
99 
100                 /* b. Calculate and concatenate the hash on dbMask buffer: *
101                 *           T = T || HASH(H || C)                          */
102                 error = SBROM_CryptoHash(hwBaseAddress, CONVERT_TO_ADDR(tmpBuff),
103                                      (HASH_RESULT_SIZE_IN_WORDS+1)*sizeof(uint32_t),
104                                      &dbMask[counter*HASH_RESULT_SIZE_IN_WORDS]);
105 
106         if (error != CC_OK) {
107                         goto End;
108         }
109     }
110 
111         /*  9.1.2 <8> Xor operation */
112     for (i=0; i < MASKED_DB_SIZE; i++) {
113         pDbMask[i] ^= pEncodedMsg[i];
114     }
115 
116         /*  9.1.2 <9> Set the leftmost (8emLen - emBits) bits of the leftmost
117                       octet in DB to zero (in this case it is MS bit only) */
118     pDbMask[0] &= 0x7F;
119 
120         /*  9.1.2 <10> Check, that padding PS is zero and next byte = 0x01*/
121     for (i = 0; i < SB_CERT_RSA_KEY_SIZE_IN_BYTES - HASH_RESULT_SIZE_IN_BYTES - RSA_PSS_SALT_LENGTH - 2; i++) {
122                 stat |= pDbMask[i];
123     }
124         if ((stat != 0) || (pDbMask[i] != 0x01)) {
125                 error = CC_BOOT_RSA_VERIFIER_CMP_FAILURE;
126                 goto End;
127         }
128 
129         /*  9.1.2 <11> Let salt be the last sLen octets in DB */
130         /*  9.1.2 <12> Let M' => (0x) 00 00 00 00 00 00 00 00 || mHash || salt*/
131 
132     UTIL_MemSet(pEncodedMsg, 0x00, RSA_PSS_PAD1_LEN); /* PS zero padding */
133         /* Hash and Salt */
134     UTIL_MemCopy(&pEncodedMsg[RSA_PSS_PAD1_LEN], (uint8_t*)mHash, HASH_RESULT_SIZE_IN_BYTES);
135     UTIL_MemCopy(&pEncodedMsg[RSA_PSS_PAD1_LEN + HASH_RESULT_SIZE_IN_BYTES],
136                      &pDbMask[MASKED_DB_SIZE - RSA_PSS_SALT_LENGTH], RSA_PSS_SALT_LENGTH);
137 
138         /*  9.1.2 <13> H' = Hash(M') ==> dbMask*/
139     error = SBROM_CryptoHash(hwBaseAddress,
140                         CONVERT_TO_ADDR(pEncodedMsg),
141                         (RSA_PSS_PAD1_LEN + HASH_RESULT_SIZE_IN_BYTES + RSA_PSS_SALT_LENGTH),
142                         dbMask/*H'*/);
143 
144         if (error != CC_OK) {
145         goto End;
146     }
147 
148         /*  9.1.2 <14> Compare H' == H; Note: If buffers are equalled,        *
149         *   then CC_TRUE = 1 is returned                                      */
150     *pVerifyStat = UTIL_MemCmp((uint8_t*)dbMask/*H'*/, (uint8_t*)tmpBuff/*hash on EM*/, sizeof(CCHashResult_t));
151 
152     if(*pVerifyStat != CC_TRUE) {
153         error = CC_BOOT_RSA_VERIFIER_CMP_FAILURE;
154                 *pVerifyStat = CC_FALSE;
155                 goto End;
156         }
157 
158         /* end of function, clean temp buffers */
159 End:
160         UTIL_MemSet((uint8_t*)tmpBuff, 0, (HASH_RESULT_SIZE_IN_BYTES +4));
161         UTIL_MemSet((uint8_t*)dbMask, 0, (SB_CERT_RSA_KEY_SIZE_IN_BYTES));
162 
163     return error;
164 
165 #undef MASKED_DB_SIZE
166 
167 }/* End of RSA_PSS_Decode */
168 
169 
170 /*
171 \brief The function implements the RSA_PSS_Verify algorithm (PKCS#1 v2.1).
172 @return CC_OK on success,
173 @return A non-zero value from secureboot_error.h on failure.
174 */
RSA_PSS_Verify(unsigned long hwBaseAddress,CCHashResult_t mHash,uint32_t * pN,uint32_t * pNp,uint32_t * pSign)175 CCError_t RSA_PSS_Verify(unsigned long hwBaseAddress,  /* [in] HW base address of registers. */
176                          CCHashResult_t mHash,    /* [in] Pointer to the SHA256 hash of the message. */
177                          uint32_t      *pN,            /* [in] Pointer to the RSA modulus (LE words array). */
178                          uint32_t      *pNp,           /* [in] Pointer to the Barrett tag of the RSA modulus (LE words array). */
179                          uint32_t      *pSign          /* [out] Pointer to the signature output (it is placed as BE bytes
180                                                                 array into words buffer for alignments goal). */)
181 {
182         /* DECLARATIONS */
183 
184     CCError_t error = CC_OK;
185         int32_t verifyStat = 0; /* 1 - valid, 0 - not valid */
186 
187         /* a buffer for the decrypted signiture */
188     uint32_t ED[SB_CERT_RSA_KEY_SIZE_IN_WORDS + 1];
189 
190     /* FUNCTION LOGIC */
191 
192         /* execute the decryption */
193     RSA_CalcExponent(hwBaseAddress, pSign/*in*/, pN, pNp, ED/*res*/);
194         /* reverse to big.end format */
195     UTIL_ReverseBuff((uint8_t*)ED, SB_CERT_RSA_KEY_SIZE_IN_BYTES);
196 
197         /*  operating the RSA PSS decoding primitive  */
198     /* ------------------------------------------ */
199 
200         error = RSA_PSS_Decode(hwBaseAddress,
201                          mHash, /*32 bytes*/
202                          (uint8_t*)ED/*RSA mod. size*/,
203                          &verifyStat);
204         if (error) {
205                 goto End;
206     }
207 
208         if(verifyStat != 1) {
209                 error = CC_BOOT_RSA_VERIFIER_CMP_FAILURE;
210     }
211 
212 End:
213         /* zeroing temp buffer */
214         UTIL_MemSet((uint8_t*)ED, 0, (SB_CERT_RSA_KEY_SIZE_IN_BYTES + 4));
215 
216         return error;
217 
218 }/* END OF RSA_PSS_Verify */
219 
220 
221 
222