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