1*5acaca2fSWilliam A. Kennington III /*
2*5acaca2fSWilliam A. Kennington III  * Copyright 2021 Google LLC
3*5acaca2fSWilliam A. Kennington III  *
4*5acaca2fSWilliam A. Kennington III  * Licensed under the Apache License, Version 2.0 (the "License");
5*5acaca2fSWilliam A. Kennington III  * you may not use this file except in compliance with the License.
6*5acaca2fSWilliam A. Kennington III  * You may obtain a copy of the License at
7*5acaca2fSWilliam A. Kennington III  *
8*5acaca2fSWilliam A. Kennington III  *      http://www.apache.org/licenses/LICENSE-2.0
9*5acaca2fSWilliam A. Kennington III  *
10*5acaca2fSWilliam A. Kennington III  * Unless required by applicable law or agreed to in writing, software
11*5acaca2fSWilliam A. Kennington III  * distributed under the License is distributed on an "AS IS" BASIS,
12*5acaca2fSWilliam A. Kennington III  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5acaca2fSWilliam A. Kennington III  * See the License for the specific language governing permissions and
14*5acaca2fSWilliam A. Kennington III  * limitations under the License.
15*5acaca2fSWilliam A. Kennington III  */
16*5acaca2fSWilliam A. Kennington III #include <assert.h>
17*5acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign.h>
18*5acaca2fSWilliam A. Kennington III #include <stdio.h>
19*5acaca2fSWilliam A. Kennington III #include <stdlib.h>
20*5acaca2fSWilliam A. Kennington III #include <string.h>
21*5acaca2fSWilliam A. Kennington III 
22*5acaca2fSWilliam A. Kennington III #ifdef __cplusplus
23*5acaca2fSWilliam A. Kennington III extern "C"
24*5acaca2fSWilliam A. Kennington III {
25*5acaca2fSWilliam A. Kennington III #endif
26*5acaca2fSWilliam A. Kennington III 
27*5acaca2fSWilliam A. Kennington III #ifndef USER_PRINT
28*5acaca2fSWilliam A. Kennington III #define CPRINTS(ctx, format, args...) printf(format, ##args)
29*5acaca2fSWilliam A. Kennington III #endif
30*5acaca2fSWilliam A. Kennington III 
31*5acaca2fSWilliam A. Kennington III #define MEMBER_SIZE(type, field) sizeof(((type*)0)->field)
32*5acaca2fSWilliam A. Kennington III 
33*5acaca2fSWilliam A. Kennington III // True of x is a power of two
34*5acaca2fSWilliam A. Kennington III #define POWER_OF_TWO(x) ((x) && !((x) & ((x)-1)))
35*5acaca2fSWilliam A. Kennington III 
36*5acaca2fSWilliam A. Kennington III // Maximum version supported. Major revisions are not backwards compatible.
37*5acaca2fSWilliam A. Kennington III #define MAX_MAJOR_VERSION 1
38*5acaca2fSWilliam A. Kennington III 
39*5acaca2fSWilliam A. Kennington III // Descriptor alignment on the external EEPROM.
40*5acaca2fSWilliam A. Kennington III #define DESCRIPTOR_ALIGNMENT (64 * 1024)
41*5acaca2fSWilliam A. Kennington III 
42*5acaca2fSWilliam A. Kennington III // SPS EEPROM sector size is 4KiB, since this is the smallest erasable size.
43*5acaca2fSWilliam A. Kennington III #define IMAGE_REGION_ALIGNMENT 4096
44*5acaca2fSWilliam A. Kennington III 
45*5acaca2fSWilliam A. Kennington III #define MAX_READ_SIZE 1024
46*5acaca2fSWilliam A. Kennington III 
47*5acaca2fSWilliam A. Kennington III #ifndef ARRAY_SIZE
48*5acaca2fSWilliam A. Kennington III #define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0]))
49*5acaca2fSWilliam A. Kennington III #endif
50*5acaca2fSWilliam A. Kennington III 
51*5acaca2fSWilliam A. Kennington III // Values of SIGNATURE_OFFSET shuold be same for all sig types (2048,3072,4096)
52*5acaca2fSWilliam A. Kennington III #define SIGNATURE_OFFSET offsetof(struct signature_rsa3072_pkcs15, modulus)
53*5acaca2fSWilliam A. Kennington III 
54*5acaca2fSWilliam A. Kennington III #ifndef BUILD_ASSERT
55*5acaca2fSWilliam A. Kennington III #define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
56*5acaca2fSWilliam A. Kennington III #endif
57*5acaca2fSWilliam A. Kennington III 
58*5acaca2fSWilliam A. Kennington III     typedef enum libcr51sign_validation_failure_reason failure_reason;
59*5acaca2fSWilliam A. Kennington III 
60*5acaca2fSWilliam A. Kennington III     // Returns the bytes size of keys used in the given signature_scheme.
61*5acaca2fSWilliam A. Kennington III     // Return error if signature_scheme is invalid.
62*5acaca2fSWilliam A. Kennington III     //
63*5acaca2fSWilliam A. Kennington III     static failure_reason get_key_size(enum signature_scheme signature_scheme,
64*5acaca2fSWilliam A. Kennington III                                        uint16_t* key_size)
65*5acaca2fSWilliam A. Kennington III     {
66*5acaca2fSWilliam A. Kennington III         switch (signature_scheme)
67*5acaca2fSWilliam A. Kennington III         {
68*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
69*5acaca2fSWilliam A. Kennington III                 *key_size = 256;
70*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
71*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
72*5acaca2fSWilliam A. Kennington III                 *key_size = 384;
73*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
74*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
75*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
76*5acaca2fSWilliam A. Kennington III                 *key_size = 512;
77*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
78*5acaca2fSWilliam A. Kennington III             default:
79*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
80*5acaca2fSWilliam A. Kennington III         }
81*5acaca2fSWilliam A. Kennington III     }
82*5acaca2fSWilliam A. Kennington III 
83*5acaca2fSWilliam A. Kennington III     // Returns the hash_type for a given signature scheme
84*5acaca2fSWilliam A. Kennington III     // Returns error if scheme is invalid.
85*5acaca2fSWilliam A. Kennington III     failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
86*5acaca2fSWilliam A. Kennington III                                                 enum hash_type* type)
87*5acaca2fSWilliam A. Kennington III     {
88*5acaca2fSWilliam A. Kennington III         switch (scheme)
89*5acaca2fSWilliam A. Kennington III         {
90*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
91*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
92*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
93*5acaca2fSWilliam A. Kennington III                 *type = HASH_SHA2_256;
94*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
95*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
96*5acaca2fSWilliam A. Kennington III                 *type = HASH_SHA2_512;
97*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
98*5acaca2fSWilliam A. Kennington III             default:
99*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
100*5acaca2fSWilliam A. Kennington III         }
101*5acaca2fSWilliam A. Kennington III     }
102*5acaca2fSWilliam A. Kennington III 
103*5acaca2fSWilliam A. Kennington III     // Check if the given hash_type is supported.
104*5acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
105*5acaca2fSWilliam A. Kennington III     static failure_reason is_hash_type_supported(enum hash_type type)
106*5acaca2fSWilliam A. Kennington III     {
107*5acaca2fSWilliam A. Kennington III         switch (type)
108*5acaca2fSWilliam A. Kennington III         {
109*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
110*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
111*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
112*5acaca2fSWilliam A. Kennington III             default:
113*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
114*5acaca2fSWilliam A. Kennington III         }
115*5acaca2fSWilliam A. Kennington III     }
116*5acaca2fSWilliam A. Kennington III 
117*5acaca2fSWilliam A. Kennington III     // Determines digest size for a given hash_type.
118*5acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
119*5acaca2fSWilliam A. Kennington III     static failure_reason get_hash_digest_size(enum hash_type type,
120*5acaca2fSWilliam A. Kennington III                                                uint32_t* size)
121*5acaca2fSWilliam A. Kennington III     {
122*5acaca2fSWilliam A. Kennington III         switch (type)
123*5acaca2fSWilliam A. Kennington III         {
124*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
125*5acaca2fSWilliam A. Kennington III                 *size = LIBCR51SIGN_SHA256_DIGEST_SIZE;
126*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
127*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
128*5acaca2fSWilliam A. Kennington III                 *size = LIBCR51SIGN_SHA512_DIGEST_SIZE;
129*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
130*5acaca2fSWilliam A. Kennington III             default:
131*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
132*5acaca2fSWilliam A. Kennington III         }
133*5acaca2fSWilliam A. Kennington III     }
134*5acaca2fSWilliam A. Kennington III 
135*5acaca2fSWilliam A. Kennington III     // Determines hash struct size for a given hash_type.
136*5acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
137*5acaca2fSWilliam A. Kennington III     static failure_reason get_hash_struct_size(enum hash_type type,
138*5acaca2fSWilliam A. Kennington III                                                uint32_t* size)
139*5acaca2fSWilliam A. Kennington III     {
140*5acaca2fSWilliam A. Kennington III         switch (type)
141*5acaca2fSWilliam A. Kennington III         {
142*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
143*5acaca2fSWilliam A. Kennington III                 *size = sizeof(struct hash_sha256);
144*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
145*5acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
146*5acaca2fSWilliam A. Kennington III                 *size = sizeof(struct hash_sha256);
147*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
148*5acaca2fSWilliam A. Kennington III             default:
149*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
150*5acaca2fSWilliam A. Kennington III         }
151*5acaca2fSWilliam A. Kennington III     }
152*5acaca2fSWilliam A. Kennington III 
153*5acaca2fSWilliam A. Kennington III     // Checks that:
154*5acaca2fSWilliam A. Kennington III     //  - The signing key is trusted
155*5acaca2fSWilliam A. Kennington III     //  - The target version is not denylisted
156*5acaca2fSWilliam A. Kennington III     // If validating a staged update, also checks that:
157*5acaca2fSWilliam A. Kennington III     //  - The target image family matches the current image family
158*5acaca2fSWilliam A. Kennington III     //  - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
159*5acaca2fSWilliam A. Kennington III     //    alternatively that the hardware ID is allowlisted
160*5acaca2fSWilliam A. Kennington III     // Assuming the caller has performed following:
161*5acaca2fSWilliam A. Kennington III     // board_get_base_key_index();
162*5acaca2fSWilliam A. Kennington III     // board_get_key_array
163*5acaca2fSWilliam A. Kennington III     // Possible return codes:
164*5acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_SUCCESS = 0,
165*5acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
166*5acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
167*5acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
168*5acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
169*5acaca2fSWilliam A. Kennington III 
170*5acaca2fSWilliam A. Kennington III     static failure_reason
171*5acaca2fSWilliam A. Kennington III         validate_transition(const struct libcr51sign_ctx* ctx,
172*5acaca2fSWilliam A. Kennington III                             const struct libcr51sign_intf* intf,
173*5acaca2fSWilliam A. Kennington III                             uint32_t signature_struct_offset)
174*5acaca2fSWilliam A. Kennington III     {
175*5acaca2fSWilliam A. Kennington III         BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
176*5acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET &&
177*5acaca2fSWilliam A. Kennington III                       offsetof(struct signature_rsa3072_pkcs15, modulus) ==
178*5acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET &&
179*5acaca2fSWilliam A. Kennington III                       offsetof(struct signature_rsa4096_pkcs15, modulus) ==
180*5acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET));
181*5acaca2fSWilliam A. Kennington III 
182*5acaca2fSWilliam A. Kennington III         // Read up to the modulus.
183*5acaca2fSWilliam A. Kennington III         enum
184*5acaca2fSWilliam A. Kennington III         {
185*5acaca2fSWilliam A. Kennington III             read_len = SIGNATURE_OFFSET
186*5acaca2fSWilliam A. Kennington III         };
187*5acaca2fSWilliam A. Kennington III         uint8_t buffer[read_len];
188*5acaca2fSWilliam A. Kennington III         // "modulus" & "signature" will not be indexed.
189*5acaca2fSWilliam A. Kennington III         struct signature_rsa4096_pkcs15* sig_data = (void*)&buffer;
190*5acaca2fSWilliam A. Kennington III         int rv;
191*5acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
192*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
193*5acaca2fSWilliam A. Kennington III         {
194*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
195*5acaca2fSWilliam A. Kennington III                     "validate_transition: failed to read signature struct");
196*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
197*5acaca2fSWilliam A. Kennington III         }
198*5acaca2fSWilliam A. Kennington III         if (sig_data->signature_magic != SIGNATURE_MAGIC)
199*5acaca2fSWilliam A. Kennington III         {
200*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: bad signature magic");
201*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
202*5acaca2fSWilliam A. Kennington III         }
203*5acaca2fSWilliam A. Kennington III 
204*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.image_family != ctx->current_image_family &&
205*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
206*5acaca2fSWilliam A. Kennington III             ctx->current_image_family != IMAGE_FAMILY_ALL)
207*5acaca2fSWilliam A. Kennington III         {
208*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: invalid image family");
209*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
210*5acaca2fSWilliam A. Kennington III         }
211*5acaca2fSWilliam A. Kennington III 
212*5acaca2fSWilliam A. Kennington III         if (!intf->is_production_mode)
213*5acaca2fSWilliam A. Kennington III         {
214*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: missing is_production_mode");
215*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
216*5acaca2fSWilliam A. Kennington III         }
217*5acaca2fSWilliam A. Kennington III         if (intf->is_production_mode() &&
218*5acaca2fSWilliam A. Kennington III             (ctx->descriptor.image_type == IMAGE_DEV))
219*5acaca2fSWilliam A. Kennington III         {
220*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: checking exemption allowlist");
221*5acaca2fSWilliam A. Kennington III 
222*5acaca2fSWilliam A. Kennington III             if (!intf->prod_to_dev_downgrade_allowed)
223*5acaca2fSWilliam A. Kennington III             {
224*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
225*5acaca2fSWilliam A. Kennington III             }
226*5acaca2fSWilliam A. Kennington III             else if (!intf->prod_to_dev_downgrade_allowed())
227*5acaca2fSWilliam A. Kennington III             {
228*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx, "validate_transition: illegal image type");
229*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
230*5acaca2fSWilliam A. Kennington III             }
231*5acaca2fSWilliam A. Kennington III         }
232*5acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
233*5acaca2fSWilliam A. Kennington III     }
234*5acaca2fSWilliam A. Kennington III 
235*5acaca2fSWilliam A. Kennington III     // If caller had provided read_and_hash_update call that, otherwise call
236*5acaca2fSWilliam A. Kennington III     // read and then update.
237*5acaca2fSWilliam A. Kennington III 
238*5acaca2fSWilliam A. Kennington III     static failure_reason
239*5acaca2fSWilliam A. Kennington III         read_and_hash_update(const struct libcr51sign_ctx* ctx,
240*5acaca2fSWilliam A. Kennington III                              const struct libcr51sign_intf* intf,
241*5acaca2fSWilliam A. Kennington III                              uint32_t offset, uint32_t size)
242*5acaca2fSWilliam A. Kennington III     {
243*5acaca2fSWilliam A. Kennington III         uint8_t read_buffer[MAX_READ_SIZE];
244*5acaca2fSWilliam A. Kennington III         int rv;
245*5acaca2fSWilliam A. Kennington III         int read_size;
246*5acaca2fSWilliam A. Kennington III 
247*5acaca2fSWilliam A. Kennington III         if (intf->read_and_hash_update)
248*5acaca2fSWilliam A. Kennington III         {
249*5acaca2fSWilliam A. Kennington III             rv = intf->read_and_hash_update((void*)ctx, offset, size);
250*5acaca2fSWilliam A. Kennington III         }
251*5acaca2fSWilliam A. Kennington III         else
252*5acaca2fSWilliam A. Kennington III         {
253*5acaca2fSWilliam A. Kennington III             if (!intf->hash_update)
254*5acaca2fSWilliam A. Kennington III             {
255*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx, "read_and_hash_update: missing hash_update");
256*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
257*5acaca2fSWilliam A. Kennington III             }
258*5acaca2fSWilliam A. Kennington III             do
259*5acaca2fSWilliam A. Kennington III             {
260*5acaca2fSWilliam A. Kennington III                 read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
261*5acaca2fSWilliam A. Kennington III                 rv = intf->read((void*)ctx, offset, read_size, read_buffer);
262*5acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
263*5acaca2fSWilliam A. Kennington III                 {
264*5acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
265*5acaca2fSWilliam A. Kennington III                 }
266*5acaca2fSWilliam A. Kennington III                 rv = intf->hash_update((void*)ctx, read_buffer, read_size);
267*5acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
268*5acaca2fSWilliam A. Kennington III                 {
269*5acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
270*5acaca2fSWilliam A. Kennington III                 }
271*5acaca2fSWilliam A. Kennington III                 offset += read_size;
272*5acaca2fSWilliam A. Kennington III                 size -= read_size;
273*5acaca2fSWilliam A. Kennington III             } while (size > 0);
274*5acaca2fSWilliam A. Kennington III         }
275*5acaca2fSWilliam A. Kennington III         return rv;
276*5acaca2fSWilliam A. Kennington III     }
277*5acaca2fSWilliam A. Kennington III 
278*5acaca2fSWilliam A. Kennington III     // Validates the image_region array, namely that:
279*5acaca2fSWilliam A. Kennington III     //  - The regions are aligned, contiguous & exhaustive
280*5acaca2fSWilliam A. Kennington III     //  - That the image descriptor resides in a static region
281*5acaca2fSWilliam A. Kennington III     //
282*5acaca2fSWilliam A. Kennington III     // If the array is consistent, proceeds to hash the static regions and
283*5acaca2fSWilliam A. Kennington III     // validates the hash. d_offset is the absolute image descriptor offset
284*5acaca2fSWilliam A. Kennington III 
285*5acaca2fSWilliam A. Kennington III     static failure_reason validate_payload_regions(
286*5acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
287*5acaca2fSWilliam A. Kennington III         uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
288*5acaca2fSWilliam A. Kennington III     {
289*5acaca2fSWilliam A. Kennington III         // Allocate buffer to accomodate largest supported hash-type(SHA512)
290*5acaca2fSWilliam A. Kennington III         uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
291*5acaca2fSWilliam A. Kennington III                                  LIBCR51SIGN_SHA512_DIGEST_SIZE];
292*5acaca2fSWilliam A. Kennington III         uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
293*5acaca2fSWilliam A. Kennington III         uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
294*5acaca2fSWilliam A. Kennington III         uint8_t d_region_num = 0;
295*5acaca2fSWilliam A. Kennington III         int i, rv;
296*5acaca2fSWilliam A. Kennington III         struct image_region const* region;
297*5acaca2fSWilliam A. Kennington III 
298*5acaca2fSWilliam A. Kennington III         if (image_regions == NULL)
299*5acaca2fSWilliam A. Kennington III         {
300*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "Missing image region input");
301*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
302*5acaca2fSWilliam A. Kennington III         }
303*5acaca2fSWilliam A. Kennington III 
304*5acaca2fSWilliam A. Kennington III         BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
305*5acaca2fSWilliam A. Kennington III                       MEMBER_SIZE(struct hash_sha512, hash_magic)));
306*5acaca2fSWilliam A. Kennington III         image_size = ctx->descriptor.image_size;
307*5acaca2fSWilliam A. Kennington III         region_count = ctx->descriptor.region_count;
308*5acaca2fSWilliam A. Kennington III         hash_offset = d_offset + sizeof(struct image_descriptor) +
309*5acaca2fSWilliam A. Kennington III                       region_count * sizeof(struct image_region);
310*5acaca2fSWilliam A. Kennington III         // Read the image_region array.
311*5acaca2fSWilliam A. Kennington III 
312*5acaca2fSWilliam A. Kennington III         if (region_count > ARRAY_SIZE(image_regions->image_regions))
313*5acaca2fSWilliam A. Kennington III         {
314*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: "
315*5acaca2fSWilliam A. Kennington III                          "ctx->descriptor.region_count is greater "
316*5acaca2fSWilliam A. Kennington III                          "than LIBCR51SIGN_MAX_REGION_COUNT");
317*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
318*5acaca2fSWilliam A. Kennington III         }
319*5acaca2fSWilliam A. Kennington III 
320*5acaca2fSWilliam A. Kennington III         rv = intf->read(
321*5acaca2fSWilliam A. Kennington III             ctx, d_offset + offsetof(struct image_descriptor, image_regions),
322*5acaca2fSWilliam A. Kennington III             region_count * sizeof(struct image_region),
323*5acaca2fSWilliam A. Kennington III             (uint8_t*)&image_regions->image_regions);
324*5acaca2fSWilliam A. Kennington III 
325*5acaca2fSWilliam A. Kennington III         image_regions->region_count = region_count;
326*5acaca2fSWilliam A. Kennington III 
327*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
328*5acaca2fSWilliam A. Kennington III         {
329*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
330*5acaca2fSWilliam A. Kennington III                     "validate_payload_regions: failed to read region array");
331*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
332*5acaca2fSWilliam A. Kennington III         }
333*5acaca2fSWilliam A. Kennington III 
334*5acaca2fSWilliam A. Kennington III         // Validate that the regions are contiguous & exhaustive.
335*5acaca2fSWilliam A. Kennington III         for (i = 0, byte_count = 0; i < region_count; i++)
336*5acaca2fSWilliam A. Kennington III         {
337*5acaca2fSWilliam A. Kennington III             region = image_regions->image_regions + i;
338*5acaca2fSWilliam A. Kennington III 
339*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
340*5acaca2fSWilliam A. Kennington III                     "validate_payload_regions: region #%d \"%s\" (%x - %x)", i,
341*5acaca2fSWilliam A. Kennington III                     region->region_name, region->region_offset,
342*5acaca2fSWilliam A. Kennington III                     region->region_offset + region->region_size);
343*5acaca2fSWilliam A. Kennington III             if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
344*5acaca2fSWilliam A. Kennington III                 (region->region_size % IMAGE_REGION_ALIGNMENT) != 0)
345*5acaca2fSWilliam A. Kennington III             {
346*5acaca2fSWilliam A. Kennington III                 CPRINTS(
347*5acaca2fSWilliam A. Kennington III                     ctx,
348*5acaca2fSWilliam A. Kennington III                     "validate_payload_regions: regions must be sector aligned");
349*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
350*5acaca2fSWilliam A. Kennington III             }
351*5acaca2fSWilliam A. Kennington III             if (region->region_offset != byte_count ||
352*5acaca2fSWilliam A. Kennington III                 region->region_size > image_size - byte_count)
353*5acaca2fSWilliam A. Kennington III             {
354*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx, "validate_payload_regions: invalid region array");
355*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
356*5acaca2fSWilliam A. Kennington III             }
357*5acaca2fSWilliam A. Kennington III             byte_count += region->region_size;
358*5acaca2fSWilliam A. Kennington III             // The image descriptor must be part of a static region.
359*5acaca2fSWilliam A. Kennington III             if (d_offset >= region->region_offset && d_offset < byte_count)
360*5acaca2fSWilliam A. Kennington III             {
361*5acaca2fSWilliam A. Kennington III                 d_region_num = i;
362*5acaca2fSWilliam A. Kennington III                 CPRINTS(
363*5acaca2fSWilliam A. Kennington III                     ctx,
364*5acaca2fSWilliam A. Kennington III                     "validate_payload_regions: image descriptor in region %d",
365*5acaca2fSWilliam A. Kennington III                     i);
366*5acaca2fSWilliam A. Kennington III                 // The descriptor can't span regions.
367*5acaca2fSWilliam A. Kennington III                 if (ctx->descriptor.descriptor_area_size > byte_count ||
368*5acaca2fSWilliam A. Kennington III                     !(region->region_attributes & IMAGE_REGION_STATIC))
369*5acaca2fSWilliam A. Kennington III                 {
370*5acaca2fSWilliam A. Kennington III                     CPRINTS(
371*5acaca2fSWilliam A. Kennington III                         ctx,
372*5acaca2fSWilliam A. Kennington III                         "validate_payload_regions: descriptor must reside in "
373*5acaca2fSWilliam A. Kennington III                         "static region");
374*5acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
375*5acaca2fSWilliam A. Kennington III                 }
376*5acaca2fSWilliam A. Kennington III             }
377*5acaca2fSWilliam A. Kennington III         }
378*5acaca2fSWilliam A. Kennington III         if (byte_count != image_size)
379*5acaca2fSWilliam A. Kennington III         {
380*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid image size");
381*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
382*5acaca2fSWilliam A. Kennington III         }
383*5acaca2fSWilliam A. Kennington III 
384*5acaca2fSWilliam A. Kennington III         rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
385*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
386*5acaca2fSWilliam A. Kennington III         {
387*5acaca2fSWilliam A. Kennington III             return rv;
388*5acaca2fSWilliam A. Kennington III         }
389*5acaca2fSWilliam A. Kennington III 
390*5acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, hash_offset,
391*5acaca2fSWilliam A. Kennington III                         MEMBER_SIZE(struct hash_sha256, hash_magic) +
392*5acaca2fSWilliam A. Kennington III                             digest_size,
393*5acaca2fSWilliam A. Kennington III                         magic_and_digest);
394*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
395*5acaca2fSWilliam A. Kennington III         {
396*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
397*5acaca2fSWilliam A. Kennington III                     "validate_payload_regions: failed to read hash from flash");
398*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
399*5acaca2fSWilliam A. Kennington III         }
400*5acaca2fSWilliam A. Kennington III         if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
401*5acaca2fSWilliam A. Kennington III         {
402*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: bad hash magic");
403*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
404*5acaca2fSWilliam A. Kennington III         }
405*5acaca2fSWilliam A. Kennington III         rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
406*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
407*5acaca2fSWilliam A. Kennington III         {
408*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: hash_init failed");
409*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
410*5acaca2fSWilliam A. Kennington III         }
411*5acaca2fSWilliam A. Kennington III         for (i = 0; i < region_count; i++)
412*5acaca2fSWilliam A. Kennington III         {
413*5acaca2fSWilliam A. Kennington III             uint32_t hash_start, hash_size;
414*5acaca2fSWilliam A. Kennington III             region = image_regions->image_regions + i;
415*5acaca2fSWilliam A. Kennington III 
416*5acaca2fSWilliam A. Kennington III             if (!(region->region_attributes & IMAGE_REGION_STATIC))
417*5acaca2fSWilliam A. Kennington III             {
418*5acaca2fSWilliam A. Kennington III                 continue;
419*5acaca2fSWilliam A. Kennington III             }
420*5acaca2fSWilliam A. Kennington III             hash_start = region->region_offset;
421*5acaca2fSWilliam A. Kennington III             hash_size = region->region_size;
422*5acaca2fSWilliam A. Kennington III 
423*5acaca2fSWilliam A. Kennington III             // Skip the descriptor.
424*5acaca2fSWilliam A. Kennington III             do
425*5acaca2fSWilliam A. Kennington III             {
426*5acaca2fSWilliam A. Kennington III                 if (i == d_region_num)
427*5acaca2fSWilliam A. Kennington III                 {
428*5acaca2fSWilliam A. Kennington III                     hash_size = d_offset - hash_start;
429*5acaca2fSWilliam A. Kennington III                 }
430*5acaca2fSWilliam A. Kennington III 
431*5acaca2fSWilliam A. Kennington III                 if (!hash_size)
432*5acaca2fSWilliam A. Kennington III                 {
433*5acaca2fSWilliam A. Kennington III                     hash_start += ctx->descriptor.descriptor_area_size;
434*5acaca2fSWilliam A. Kennington III                     hash_size = (region->region_offset + region->region_size -
435*5acaca2fSWilliam A. Kennington III                                  hash_start);
436*5acaca2fSWilliam A. Kennington III                 }
437*5acaca2fSWilliam A. Kennington III                 CPRINTS("validate_payload_regions: hashing %s (%x - %x)",
438*5acaca2fSWilliam A. Kennington III                         region->region_name, hash_start,
439*5acaca2fSWilliam A. Kennington III                         hash_start + hash_size);
440*5acaca2fSWilliam A. Kennington III                 // Read the image_region array.
441*5acaca2fSWilliam A. Kennington III                 rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
442*5acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
443*5acaca2fSWilliam A. Kennington III                 {
444*5acaca2fSWilliam A. Kennington III                     return rv;
445*5acaca2fSWilliam A. Kennington III                 }
446*5acaca2fSWilliam A. Kennington III                 hash_start += hash_size;
447*5acaca2fSWilliam A. Kennington III             } while (hash_start != region->region_offset + region->region_size);
448*5acaca2fSWilliam A. Kennington III         }
449*5acaca2fSWilliam A. Kennington III         rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
450*5acaca2fSWilliam A. Kennington III 
451*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
452*5acaca2fSWilliam A. Kennington III         {
453*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
454*5acaca2fSWilliam A. Kennington III         }
455*5acaca2fSWilliam A. Kennington III 
456*5acaca2fSWilliam A. Kennington III         if (memcmp(magic_and_digest +
457*5acaca2fSWilliam A. Kennington III                        MEMBER_SIZE(struct hash_sha256, hash_magic),
458*5acaca2fSWilliam A. Kennington III                    dcrypto_digest, digest_size))
459*5acaca2fSWilliam A. Kennington III         {
460*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid hash");
461*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_HASH;
462*5acaca2fSWilliam A. Kennington III         }
463*5acaca2fSWilliam A. Kennington III         // Image is valid.
464*5acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
465*5acaca2fSWilliam A. Kennington III     }
466*5acaca2fSWilliam A. Kennington III 
467*5acaca2fSWilliam A. Kennington III     // Create empty image_regions to pass to validate_payload_regions
468*5acaca2fSWilliam A. Kennington III     // Support validate_payload_regions_helper to remove image_regions as a
469*5acaca2fSWilliam A. Kennington III     // required input.
470*5acaca2fSWilliam A. Kennington III 
471*5acaca2fSWilliam A. Kennington III     static failure_reason
472*5acaca2fSWilliam A. Kennington III         allocate_and_validate_payload_regions(const struct libcr51sign_ctx* ctx,
473*5acaca2fSWilliam A. Kennington III                                               struct libcr51sign_intf* intf,
474*5acaca2fSWilliam A. Kennington III                                               uint32_t d_offset)
475*5acaca2fSWilliam A. Kennington III     {
476*5acaca2fSWilliam A. Kennington III         struct libcr51sign_validated_regions image_regions;
477*5acaca2fSWilliam A. Kennington III         return validate_payload_regions(ctx, intf, d_offset, &image_regions);
478*5acaca2fSWilliam A. Kennington III     }
479*5acaca2fSWilliam A. Kennington III 
480*5acaca2fSWilliam A. Kennington III     // Wrapper around validate_payload_regions to allow nullptr for
481*5acaca2fSWilliam A. Kennington III     // image_regions. Calls allocate_and_validate_payload_regions when
482*5acaca2fSWilliam A. Kennington III     // image_regions is nullptr to create placer holder image_regions.
483*5acaca2fSWilliam A. Kennington III 
484*5acaca2fSWilliam A. Kennington III     static failure_reason validate_payload_regions_helper(
485*5acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
486*5acaca2fSWilliam A. Kennington III         uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
487*5acaca2fSWilliam A. Kennington III     {
488*5acaca2fSWilliam A. Kennington III         if (image_regions)
489*5acaca2fSWilliam A. Kennington III         {
490*5acaca2fSWilliam A. Kennington III             return validate_payload_regions(ctx, intf, d_offset, image_regions);
491*5acaca2fSWilliam A. Kennington III         }
492*5acaca2fSWilliam A. Kennington III 
493*5acaca2fSWilliam A. Kennington III         return allocate_and_validate_payload_regions(ctx, intf, d_offset);
494*5acaca2fSWilliam A. Kennington III     }
495*5acaca2fSWilliam A. Kennington III 
496*5acaca2fSWilliam A. Kennington III     // Check if the given signature_scheme is supported.
497*5acaca2fSWilliam A. Kennington III     // Returns nonzero on error, zero on success
498*5acaca2fSWilliam A. Kennington III 
499*5acaca2fSWilliam A. Kennington III     static failure_reason
500*5acaca2fSWilliam A. Kennington III         is_signature_scheme_supported(enum signature_scheme scheme)
501*5acaca2fSWilliam A. Kennington III     {
502*5acaca2fSWilliam A. Kennington III         switch (scheme)
503*5acaca2fSWilliam A. Kennington III         {
504*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
505*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
506*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
507*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
508*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
509*5acaca2fSWilliam A. Kennington III             default:
510*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
511*5acaca2fSWilliam A. Kennington III         }
512*5acaca2fSWilliam A. Kennington III     }
513*5acaca2fSWilliam A. Kennington III 
514*5acaca2fSWilliam A. Kennington III     // Returns size of signature struct size in |size|
515*5acaca2fSWilliam A. Kennington III     // Returns nonzero on error, zero on success
516*5acaca2fSWilliam A. Kennington III 
517*5acaca2fSWilliam A. Kennington III     static failure_reason
518*5acaca2fSWilliam A. Kennington III         get_signature_struct_size(enum signature_scheme scheme, uint32_t* size)
519*5acaca2fSWilliam A. Kennington III     {
520*5acaca2fSWilliam A. Kennington III         switch (scheme)
521*5acaca2fSWilliam A. Kennington III         {
522*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
523*5acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa2048_pkcs15);
524*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
525*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
526*5acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa3072_pkcs15);
527*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
528*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
529*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
530*5acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa4096_pkcs15);
531*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
532*5acaca2fSWilliam A. Kennington III             default:
533*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
534*5acaca2fSWilliam A. Kennington III         }
535*5acaca2fSWilliam A. Kennington III     }
536*5acaca2fSWilliam A. Kennington III 
537*5acaca2fSWilliam A. Kennington III     static failure_reason
538*5acaca2fSWilliam A. Kennington III         get_signature_field_offset(enum signature_scheme scheme,
539*5acaca2fSWilliam A. Kennington III                                    uint32_t* offset)
540*5acaca2fSWilliam A. Kennington III     {
541*5acaca2fSWilliam A. Kennington III         switch (scheme)
542*5acaca2fSWilliam A. Kennington III         {
543*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
544*5acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
545*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
546*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
547*5acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
548*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
549*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
550*5acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
551*5acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
552*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
553*5acaca2fSWilliam A. Kennington III             default:
554*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
555*5acaca2fSWilliam A. Kennington III         }
556*5acaca2fSWilliam A. Kennington III     }
557*5acaca2fSWilliam A. Kennington III 
558*5acaca2fSWilliam A. Kennington III     // Validates the signature (of type scheme) read from "device" at
559*5acaca2fSWilliam A. Kennington III     //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
560*5acaca2fSWilliam A. Kennington III     // EEPROM area "data_offset:data_size".
561*5acaca2fSWilliam A. Kennington III 
562*5acaca2fSWilliam A. Kennington III     static failure_reason validate_signature(
563*5acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
564*5acaca2fSWilliam A. Kennington III         uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme,
565*5acaca2fSWilliam A. Kennington III         uint32_t raw_signature_offset)
566*5acaca2fSWilliam A. Kennington III     {
567*5acaca2fSWilliam A. Kennington III         uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE];
568*5acaca2fSWilliam A. Kennington III         uint16_t key_size;
569*5acaca2fSWilliam A. Kennington III         uint32_t digest_size;
570*5acaca2fSWilliam A. Kennington III         uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
571*5acaca2fSWilliam A. Kennington III         int rv;
572*5acaca2fSWilliam A. Kennington III         enum hash_type hash_type;
573*5acaca2fSWilliam A. Kennington III 
574*5acaca2fSWilliam A. Kennington III         if (!intf->hash_init)
575*5acaca2fSWilliam A. Kennington III         {
576*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing hash_init");
577*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
578*5acaca2fSWilliam A. Kennington III         }
579*5acaca2fSWilliam A. Kennington III         rv = get_hash_type_from_signature(scheme, &hash_type);
580*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
581*5acaca2fSWilliam A. Kennington III         {
582*5acaca2fSWilliam A. Kennington III             CPRINTS(
583*5acaca2fSWilliam A. Kennington III                 ctx,
584*5acaca2fSWilliam A. Kennington III                 "validate_payload_regions: hash_type from signature failed");
585*5acaca2fSWilliam A. Kennington III             return rv;
586*5acaca2fSWilliam A. Kennington III         }
587*5acaca2fSWilliam A. Kennington III         rv = intf->hash_init(ctx, hash_type);
588*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
589*5acaca2fSWilliam A. Kennington III         {
590*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: hash_init failed");
591*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
592*5acaca2fSWilliam A. Kennington III         }
593*5acaca2fSWilliam A. Kennington III         rv = read_and_hash_update(ctx, intf, data_offset, data_size);
594*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
595*5acaca2fSWilliam A. Kennington III         {
596*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: hash_update failed");
597*5acaca2fSWilliam A. Kennington III             return rv;
598*5acaca2fSWilliam A. Kennington III         }
599*5acaca2fSWilliam A. Kennington III         if (!intf->hash_final)
600*5acaca2fSWilliam A. Kennington III         {
601*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing hash_final");
602*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
603*5acaca2fSWilliam A. Kennington III         }
604*5acaca2fSWilliam A. Kennington III         rv = intf->hash_final((void*)ctx, dcrypto_digest);
605*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
606*5acaca2fSWilliam A. Kennington III         {
607*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: hash_final failed (status = %d)",
608*5acaca2fSWilliam A. Kennington III                     rv);
609*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
610*5acaca2fSWilliam A. Kennington III         }
611*5acaca2fSWilliam A. Kennington III         rv = get_key_size(scheme, &key_size);
612*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
613*5acaca2fSWilliam A. Kennington III         {
614*5acaca2fSWilliam A. Kennington III             return rv;
615*5acaca2fSWilliam A. Kennington III         }
616*5acaca2fSWilliam A. Kennington III 
617*5acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, raw_signature_offset, key_size, signature);
618*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
619*5acaca2fSWilliam A. Kennington III         {
620*5acaca2fSWilliam A. Kennington III             CPRINTS(
621*5acaca2fSWilliam A. Kennington III                 ctx,
622*5acaca2fSWilliam A. Kennington III                 "validate_signature: failed to read signature (status = %d)",
623*5acaca2fSWilliam A. Kennington III                 rv);
624*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
625*5acaca2fSWilliam A. Kennington III         }
626*5acaca2fSWilliam A. Kennington III         if (!intf->verify_signature)
627*5acaca2fSWilliam A. Kennington III         {
628*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing verify_signature");
629*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
630*5acaca2fSWilliam A. Kennington III         }
631*5acaca2fSWilliam A. Kennington III         rv = get_hash_digest_size(hash_type, &digest_size);
632*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
633*5acaca2fSWilliam A. Kennington III         {
634*5acaca2fSWilliam A. Kennington III             return rv;
635*5acaca2fSWilliam A. Kennington III         }
636*5acaca2fSWilliam A. Kennington III         rv = intf->verify_signature(ctx, scheme, signature, key_size,
637*5acaca2fSWilliam A. Kennington III                                     dcrypto_digest, digest_size);
638*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
639*5acaca2fSWilliam A. Kennington III         {
640*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
641*5acaca2fSWilliam A. Kennington III                     "validate_signature: verification failed (status = %d)",
642*5acaca2fSWilliam A. Kennington III                     rv);
643*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
644*5acaca2fSWilliam A. Kennington III         }
645*5acaca2fSWilliam A. Kennington III         CPRINTS(ctx, "validate_signature: verification succeeded");
646*5acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
647*5acaca2fSWilliam A. Kennington III     }
648*5acaca2fSWilliam A. Kennington III 
649*5acaca2fSWilliam A. Kennington III     // Sanity checks the image descriptor & validates its signature.
650*5acaca2fSWilliam A. Kennington III     // This function does not validate the image_region array or image hash.
651*5acaca2fSWilliam A. Kennington III     //
652*5acaca2fSWilliam A. Kennington III     //@param[in] ctx  context which describes the image and holds opaque private
653*5acaca2fSWilliam A. Kennington III     //                 data for the user of the library
654*5acaca2fSWilliam A. Kennington III     //@param[in] intf  function pointers which interface to the current system
655*5acaca2fSWilliam A. Kennington III     // and environment
656*5acaca2fSWilliam A. Kennington III     //@param offset  Absolute image descriptor flash offset.
657*5acaca2fSWilliam A. Kennington III     //@param relative_offset  Image descriptor offset relative to image start.
658*5acaca2fSWilliam A. Kennington III     //@param image_size  Image size in bytes.
659*5acaca2fSWilliam A. Kennington III     //@param descriptor  Output pointer to an image_descriptor struct
660*5acaca2fSWilliam A. Kennington III 
661*5acaca2fSWilliam A. Kennington III     static failure_reason validate_descriptor(
662*5acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
663*5acaca2fSWilliam A. Kennington III         uint32_t offset, uint32_t relative_offset, uint32_t image_size)
664*5acaca2fSWilliam A. Kennington III     {
665*5acaca2fSWilliam A. Kennington III         uint32_t max_descriptor_size, signed_size, signature_scheme,
666*5acaca2fSWilliam A. Kennington III             signature_offset;
667*5acaca2fSWilliam A. Kennington III         uint32_t signature_struct_offset, signature_struct_size,
668*5acaca2fSWilliam A. Kennington III             hash_struct_size;
669*5acaca2fSWilliam A. Kennington III         int rv;
670*5acaca2fSWilliam A. Kennington III 
671*5acaca2fSWilliam A. Kennington III         max_descriptor_size = image_size - relative_offset;
672*5acaca2fSWilliam A. Kennington III         if (image_size < relative_offset ||
673*5acaca2fSWilliam A. Kennington III             max_descriptor_size < sizeof(struct image_descriptor))
674*5acaca2fSWilliam A. Kennington III         {
675*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: invalid arguments");
676*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
677*5acaca2fSWilliam A. Kennington III         }
678*5acaca2fSWilliam A. Kennington III 
679*5acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
680*5acaca2fSWilliam A. Kennington III                         (uint8_t*)&ctx->descriptor);
681*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
682*5acaca2fSWilliam A. Kennington III         {
683*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: failed to read descriptor");
684*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
685*5acaca2fSWilliam A. Kennington III         }
686*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
687*5acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_offset != relative_offset ||
688*5acaca2fSWilliam A. Kennington III             ctx->descriptor.region_count == 0 ||
689*5acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_area_size > max_descriptor_size ||
690*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_size != image_size)
691*5acaca2fSWilliam A. Kennington III         {
692*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: invalid descriptor");
693*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
694*5acaca2fSWilliam A. Kennington III         }
695*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.image_type != IMAGE_DEV &&
696*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_PROD &&
697*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_BREAKOUT &&
698*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_TEST &&
699*5acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
700*5acaca2fSWilliam A. Kennington III         {
701*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: bad image type");
702*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
703*5acaca2fSWilliam A. Kennington III         }
704*5acaca2fSWilliam A. Kennington III         // Although the image_descriptor struct supports unauthenticated
705*5acaca2fSWilliam A. Kennington III         // images, Haven will not allow it.
706*5acaca2fSWilliam A. Kennington III         // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
707*5acaca2fSWilliam A. Kennington III 
708*5acaca2fSWilliam A. Kennington III         signature_scheme = ctx->descriptor.signature_scheme;
709*5acaca2fSWilliam A. Kennington III 
710*5acaca2fSWilliam A. Kennington III         rv = is_signature_scheme_supported(signature_scheme);
711*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
712*5acaca2fSWilliam A. Kennington III         {
713*5acaca2fSWilliam A. Kennington III             return rv;
714*5acaca2fSWilliam A. Kennington III         }
715*5acaca2fSWilliam A. Kennington III         rv = is_hash_type_supported(ctx->descriptor.hash_type);
716*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
717*5acaca2fSWilliam A. Kennington III         {
718*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid hash type");
719*5acaca2fSWilliam A. Kennington III             return rv;
720*5acaca2fSWilliam A. Kennington III         }
721*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
722*5acaca2fSWilliam A. Kennington III             ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT)
723*5acaca2fSWilliam A. Kennington III         {
724*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: unsupported descriptor");
725*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
726*5acaca2fSWilliam A. Kennington III         }
727*5acaca2fSWilliam A. Kennington III         rv =
728*5acaca2fSWilliam A. Kennington III             get_signature_struct_size(signature_scheme, &signature_struct_size);
729*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
730*5acaca2fSWilliam A. Kennington III         {
731*5acaca2fSWilliam A. Kennington III             return rv;
732*5acaca2fSWilliam A. Kennington III         }
733*5acaca2fSWilliam A. Kennington III 
734*5acaca2fSWilliam A. Kennington III         // Compute the size of the signed portion of the image descriptor.
735*5acaca2fSWilliam A. Kennington III         signed_size =
736*5acaca2fSWilliam A. Kennington III             sizeof(struct image_descriptor) +
737*5acaca2fSWilliam A. Kennington III             ctx->descriptor.region_count * sizeof(struct image_region);
738*5acaca2fSWilliam A. Kennington III         rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
739*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
740*5acaca2fSWilliam A. Kennington III         {
741*5acaca2fSWilliam A. Kennington III             return rv;
742*5acaca2fSWilliam A. Kennington III         }
743*5acaca2fSWilliam A. Kennington III         signed_size += hash_struct_size;
744*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.denylist_size)
745*5acaca2fSWilliam A. Kennington III         {
746*5acaca2fSWilliam A. Kennington III             signed_size += sizeof(struct denylist);
747*5acaca2fSWilliam A. Kennington III             signed_size +=
748*5acaca2fSWilliam A. Kennington III                 ctx->descriptor.denylist_size * sizeof(struct denylist_record);
749*5acaca2fSWilliam A. Kennington III         }
750*5acaca2fSWilliam A. Kennington III         if (ctx->descriptor.blob_size)
751*5acaca2fSWilliam A. Kennington III         {
752*5acaca2fSWilliam A. Kennington III             signed_size += sizeof(struct blob);
753*5acaca2fSWilliam A. Kennington III             // Previous additions are guaranteed not to overflow.
754*5acaca2fSWilliam A. Kennington III             if (ctx->descriptor.blob_size >
755*5acaca2fSWilliam A. Kennington III                 ctx->descriptor.descriptor_area_size - signed_size)
756*5acaca2fSWilliam A. Kennington III             {
757*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)",
758*5acaca2fSWilliam A. Kennington III                         ctx->descriptor.blob_size);
759*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
760*5acaca2fSWilliam A. Kennington III             }
761*5acaca2fSWilliam A. Kennington III             signed_size += ctx->descriptor.blob_size;
762*5acaca2fSWilliam A. Kennington III         }
763*5acaca2fSWilliam A. Kennington III         if (signature_struct_size >
764*5acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_area_size - signed_size)
765*5acaca2fSWilliam A. Kennington III         {
766*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
767*5acaca2fSWilliam A. Kennington III                     "validate_descriptor: invalid descriptor area size "
768*5acaca2fSWilliam A. Kennington III                     "(expected = 0x%x, actual = 0x%x)",
769*5acaca2fSWilliam A. Kennington III                     ctx->descriptor.descriptor_area_size,
770*5acaca2fSWilliam A. Kennington III                     signed_size + signature_struct_size);
771*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
772*5acaca2fSWilliam A. Kennington III         }
773*5acaca2fSWilliam A. Kennington III         signature_struct_offset = signed_size;
774*5acaca2fSWilliam A. Kennington III         // Omit the actual signature.
775*5acaca2fSWilliam A. Kennington III         rv = get_signature_field_offset(signature_scheme, &signature_offset);
776*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
777*5acaca2fSWilliam A. Kennington III         {
778*5acaca2fSWilliam A. Kennington III             return rv;
779*5acaca2fSWilliam A. Kennington III         }
780*5acaca2fSWilliam A. Kennington III         signed_size += signature_offset;
781*5acaca2fSWilliam A. Kennington III 
782*5acaca2fSWilliam A. Kennington III         // Lookup key & validate transition.
783*5acaca2fSWilliam A. Kennington III         rv = validate_transition(ctx, intf, offset + signature_struct_offset);
784*5acaca2fSWilliam A. Kennington III 
785*5acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
786*5acaca2fSWilliam A. Kennington III         {
787*5acaca2fSWilliam A. Kennington III             return rv;
788*5acaca2fSWilliam A. Kennington III         }
789*5acaca2fSWilliam A. Kennington III         return validate_signature(ctx, intf, offset, signed_size,
790*5acaca2fSWilliam A. Kennington III                                   signature_scheme, offset + signed_size);
791*5acaca2fSWilliam A. Kennington III     }
792*5acaca2fSWilliam A. Kennington III 
793*5acaca2fSWilliam A. Kennington III     // Scans the external EEPROM for a magic value at "alignment" boundaries.
794*5acaca2fSWilliam A. Kennington III     //
795*5acaca2fSWilliam A. Kennington III     //@param device  Handle to the external EEPROM.
796*5acaca2fSWilliam A. Kennington III     //@param magic   8-byte pattern to search for.
797*5acaca2fSWilliam A. Kennington III     //@param start_offset  Offset to begin searching at.
798*5acaca2fSWilliam A. Kennington III     //@param limit   Exclusive address (e.g. EEPROM size).
799*5acaca2fSWilliam A. Kennington III     //@param alignment   Alignment boundaries (POW2) to search on.
800*5acaca2fSWilliam A. Kennington III     //@param header_offset   Location to place the new header offset.
801*5acaca2fSWilliam A. Kennington III     //@return LIBCR51SIGN_SUCCESS (or non-zero on error).
802*5acaca2fSWilliam A. Kennington III 
803*5acaca2fSWilliam A. Kennington III     int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
804*5acaca2fSWilliam A. Kennington III                          const struct libcr51sign_intf* intf, uint64_t magic,
805*5acaca2fSWilliam A. Kennington III                          uint32_t start_offset, uint32_t limit,
806*5acaca2fSWilliam A. Kennington III                          uint32_t alignment, uint32_t* header_offset)
807*5acaca2fSWilliam A. Kennington III     {
808*5acaca2fSWilliam A. Kennington III         uint64_t read_data;
809*5acaca2fSWilliam A. Kennington III         uint32_t offset;
810*5acaca2fSWilliam A. Kennington III         int rv;
811*5acaca2fSWilliam A. Kennington III 
812*5acaca2fSWilliam A. Kennington III         if (limit <= start_offset || limit > ctx->end_offset ||
813*5acaca2fSWilliam A. Kennington III             limit < sizeof(magic) || !POWER_OF_TWO(alignment))
814*5acaca2fSWilliam A. Kennington III         {
815*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
816*5acaca2fSWilliam A. Kennington III         }
817*5acaca2fSWilliam A. Kennington III 
818*5acaca2fSWilliam A. Kennington III         if (!intf->read)
819*5acaca2fSWilliam A. Kennington III         {
820*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "scan_for_magic_8: missing intf->read");
821*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
822*5acaca2fSWilliam A. Kennington III         }
823*5acaca2fSWilliam A. Kennington III         // Align start_offset to the next valid boundary.
824*5acaca2fSWilliam A. Kennington III         start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
825*5acaca2fSWilliam A. Kennington III         for (offset = start_offset; offset < limit - sizeof(magic);
826*5acaca2fSWilliam A. Kennington III              offset += alignment)
827*5acaca2fSWilliam A. Kennington III         {
828*5acaca2fSWilliam A. Kennington III             rv = intf->read((void*)ctx, offset, sizeof(read_data),
829*5acaca2fSWilliam A. Kennington III                             (uint8_t*)&read_data);
830*5acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS)
831*5acaca2fSWilliam A. Kennington III             {
832*5acaca2fSWilliam A. Kennington III                 return rv;
833*5acaca2fSWilliam A. Kennington III             }
834*5acaca2fSWilliam A. Kennington III             if (read_data == magic)
835*5acaca2fSWilliam A. Kennington III             {
836*5acaca2fSWilliam A. Kennington III                 if (header_offset)
837*5acaca2fSWilliam A. Kennington III                 {
838*5acaca2fSWilliam A. Kennington III                     *header_offset = offset;
839*5acaca2fSWilliam A. Kennington III                 }
840*5acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
841*5acaca2fSWilliam A. Kennington III             }
842*5acaca2fSWilliam A. Kennington III         }
843*5acaca2fSWilliam A. Kennington III         // Failed to locate magic.
844*5acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
845*5acaca2fSWilliam A. Kennington III     }
846*5acaca2fSWilliam A. Kennington III 
847*5acaca2fSWilliam A. Kennington III     // Check whether the signature on the image is valid.
848*5acaca2fSWilliam A. Kennington III     // Validates the authenticity of an EEPROM image. Scans for & validates the
849*5acaca2fSWilliam A. Kennington III     // signature on the image descriptor. If the descriptor validates, hashes
850*5acaca2fSWilliam A. Kennington III     // the rest of the image to verify its integrity.
851*5acaca2fSWilliam A. Kennington III     //
852*5acaca2fSWilliam A. Kennington III     // @param[in] ctx - context which describes the image and holds opaque
853*5acaca2fSWilliam A. Kennington III     // private
854*5acaca2fSWilliam A. Kennington III     //                 data for the user of the library
855*5acaca2fSWilliam A. Kennington III     // @param[in] intf - function pointers which interface to the current system
856*5acaca2fSWilliam A. Kennington III     //                  and environment
857*5acaca2fSWilliam A. Kennington III     // @param[out] image_regions - image_region pointer to an array for the
858*5acaca2fSWilliam A. Kennington III     // output
859*5acaca2fSWilliam A. Kennington III     //
860*5acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
861*5acaca2fSWilliam A. Kennington III 
862*5acaca2fSWilliam A. Kennington III     failure_reason libcr51sign_validate(
863*5acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
864*5acaca2fSWilliam A. Kennington III         struct libcr51sign_validated_regions* image_regions)
865*5acaca2fSWilliam A. Kennington III     {
866*5acaca2fSWilliam A. Kennington III         uint32_t image_limit = 0;
867*5acaca2fSWilliam A. Kennington III         int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
868*5acaca2fSWilliam A. Kennington III         uint32_t descriptor_offset;
869*5acaca2fSWilliam A. Kennington III 
870*5acaca2fSWilliam A. Kennington III         if (!ctx)
871*5acaca2fSWilliam A. Kennington III         {
872*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "MIssing context");
873*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
874*5acaca2fSWilliam A. Kennington III         }
875*5acaca2fSWilliam A. Kennington III         else if (!intf)
876*5acaca2fSWilliam A. Kennington III         {
877*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "Missing interface");
878*5acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
879*5acaca2fSWilliam A. Kennington III         }
880*5acaca2fSWilliam A. Kennington III 
881*5acaca2fSWilliam A. Kennington III         rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
882*5acaca2fSWilliam A. Kennington III                               ctx->end_offset, DESCRIPTOR_ALIGNMENT,
883*5acaca2fSWilliam A. Kennington III                               &descriptor_offset);
884*5acaca2fSWilliam A. Kennington III         while (rv == LIBCR51SIGN_SUCCESS)
885*5acaca2fSWilliam A. Kennington III         {
886*5acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate: potential image descriptor found @%x ",
887*5acaca2fSWilliam A. Kennington III                     descriptor_offset);
888*5acaca2fSWilliam A. Kennington III             // Validation is split into 2 functions to minimize
889*5acaca2fSWilliam A. Kennington III             // stack usage.
890*5acaca2fSWilliam A. Kennington III 
891*5acaca2fSWilliam A. Kennington III             rv = validate_descriptor(ctx, intf, descriptor_offset,
892*5acaca2fSWilliam A. Kennington III                                      descriptor_offset - ctx->start_offset,
893*5acaca2fSWilliam A. Kennington III                                      ctx->end_offset - ctx->start_offset);
894*5acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS)
895*5acaca2fSWilliam A. Kennington III             {
896*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx, "validate: validate_descriptor() failed ec%d ",
897*5acaca2fSWilliam A. Kennington III                         rv);
898*5acaca2fSWilliam A. Kennington III             }
899*5acaca2fSWilliam A. Kennington III 
900*5acaca2fSWilliam A. Kennington III             if (rv == LIBCR51SIGN_SUCCESS)
901*5acaca2fSWilliam A. Kennington III             {
902*5acaca2fSWilliam A. Kennington III                 rv = validate_payload_regions_helper(
903*5acaca2fSWilliam A. Kennington III                     ctx, intf, descriptor_offset, image_regions);
904*5acaca2fSWilliam A. Kennington III                 if (rv == LIBCR51SIGN_SUCCESS)
905*5acaca2fSWilliam A. Kennington III                 {
906*5acaca2fSWilliam A. Kennington III                     CPRINTS(ctx, "validate: success!");
907*5acaca2fSWilliam A. Kennington III                     return rv;
908*5acaca2fSWilliam A. Kennington III                 }
909*5acaca2fSWilliam A. Kennington III                 CPRINTS(ctx,
910*5acaca2fSWilliam A. Kennington III                         "validate: validate_payload_regions() failed ec%d ",
911*5acaca2fSWilliam A. Kennington III                         rv);
912*5acaca2fSWilliam A. Kennington III             }
913*5acaca2fSWilliam A. Kennington III             // Store the first desc fail reason if any
914*5acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS &&
915*5acaca2fSWilliam A. Kennington III                 rv_first_desc == LIBCR51SIGN_SUCCESS)
916*5acaca2fSWilliam A. Kennington III                 rv_first_desc = rv;
917*5acaca2fSWilliam A. Kennington III 
918*5acaca2fSWilliam A. Kennington III             // scan_for_magic_8() will round up to the next aligned boundary.
919*5acaca2fSWilliam A. Kennington III             descriptor_offset++;
920*5acaca2fSWilliam A. Kennington III             image_limit = ctx->end_offset - ctx->start_offset;
921*5acaca2fSWilliam A. Kennington III             rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC,
922*5acaca2fSWilliam A. Kennington III                                   descriptor_offset, image_limit,
923*5acaca2fSWilliam A. Kennington III                                   DESCRIPTOR_ALIGNMENT, &descriptor_offset);
924*5acaca2fSWilliam A. Kennington III         }
925*5acaca2fSWilliam A. Kennington III         CPRINTS(ctx, "validate: failed to validate image ec%d ", rv);
926*5acaca2fSWilliam A. Kennington III         // If desc validation failed for some reason then return that reason
927*5acaca2fSWilliam A. Kennington III         if (rv_first_desc != LIBCR51SIGN_SUCCESS)
928*5acaca2fSWilliam A. Kennington III             return rv_first_desc;
929*5acaca2fSWilliam A. Kennington III         else
930*5acaca2fSWilliam A. Kennington III             return rv;
931*5acaca2fSWilliam A. Kennington III     }
932*5acaca2fSWilliam A. Kennington III 
933*5acaca2fSWilliam A. Kennington III     // @func to returns the libcr51sign error code as a string
934*5acaca2fSWilliam A. Kennington III     // @param[in] ec - Error code
935*5acaca2fSWilliam A. Kennington III     // @return error code in string format
936*5acaca2fSWilliam A. Kennington III 
937*5acaca2fSWilliam A. Kennington III     const char* libcr51sign_errorcode_to_string(failure_reason ec)
938*5acaca2fSWilliam A. Kennington III     {
939*5acaca2fSWilliam A. Kennington III         switch (ec)
940*5acaca2fSWilliam A. Kennington III         {
941*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_SUCCESS:
942*5acaca2fSWilliam A. Kennington III                 return "Success";
943*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
944*5acaca2fSWilliam A. Kennington III                 return "Runtime Error Failure";
945*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
946*5acaca2fSWilliam A. Kennington III                 return "Unsupported descriptor";
947*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
948*5acaca2fSWilliam A. Kennington III                 return "Invalid descriptor";
949*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
950*5acaca2fSWilliam A. Kennington III                 return "Invalid image family";
951*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
952*5acaca2fSWilliam A. Kennington III                 return "Image type disallowed";
953*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
954*5acaca2fSWilliam A. Kennington III                 return "Dev downgrade disallowed";
955*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
956*5acaca2fSWilliam A. Kennington III                 return "Untrusted key";
957*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
958*5acaca2fSWilliam A. Kennington III                 return "Invalid signature";
959*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_HASH:
960*5acaca2fSWilliam A. Kennington III                 return "Invalid hash";
961*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
962*5acaca2fSWilliam A. Kennington III                 return "Invalid hash type";
963*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
964*5acaca2fSWilliam A. Kennington III                 return "Invalid Argument";
965*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
966*5acaca2fSWilliam A. Kennington III                 return "Failed to locate descriptor";
967*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
968*5acaca2fSWilliam A. Kennington III                 return "Invalid context";
969*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
970*5acaca2fSWilliam A. Kennington III                 return "Invalid interface";
971*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
972*5acaca2fSWilliam A. Kennington III                 return "Invalid signature scheme";
973*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT:
974*5acaca2fSWilliam A. Kennington III                 return "Invalid image region input";
975*5acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE:
976*5acaca2fSWilliam A. Kennington III                 return "Invalid image region size";
977*5acaca2fSWilliam A. Kennington III             default:
978*5acaca2fSWilliam A. Kennington III                 return "Unknown error";
979*5acaca2fSWilliam A. Kennington III         }
980*5acaca2fSWilliam A. Kennington III     }
981*5acaca2fSWilliam A. Kennington III 
982*5acaca2fSWilliam A. Kennington III #ifdef __cplusplus
983*5acaca2fSWilliam A. Kennington III } //  extern "C"
984*5acaca2fSWilliam A. Kennington III #endif
985