1*05799ae0SJuan Castillo /* 2*05799ae0SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*05799ae0SJuan Castillo * 4*05799ae0SJuan Castillo * Redistribution and use in source and binary forms, with or without 5*05799ae0SJuan Castillo * modification, are permitted provided that the following conditions are met: 6*05799ae0SJuan Castillo * 7*05799ae0SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 8*05799ae0SJuan Castillo * list of conditions and the following disclaimer. 9*05799ae0SJuan Castillo * 10*05799ae0SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 11*05799ae0SJuan Castillo * this list of conditions and the following disclaimer in the documentation 12*05799ae0SJuan Castillo * and/or other materials provided with the distribution. 13*05799ae0SJuan Castillo * 14*05799ae0SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 15*05799ae0SJuan Castillo * to endorse or promote products derived from this software without specific 16*05799ae0SJuan Castillo * prior written permission. 17*05799ae0SJuan Castillo * 18*05799ae0SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*05799ae0SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*05799ae0SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*05799ae0SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*05799ae0SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*05799ae0SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*05799ae0SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*05799ae0SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*05799ae0SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*05799ae0SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*05799ae0SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 29*05799ae0SJuan Castillo */ 30*05799ae0SJuan Castillo 31*05799ae0SJuan Castillo #include <assert.h> 32*05799ae0SJuan Castillo #include <auth_common.h> 33*05799ae0SJuan Castillo #include <auth_mod.h> 34*05799ae0SJuan Castillo #include <cot_def.h> 35*05799ae0SJuan Castillo #include <crypto_mod.h> 36*05799ae0SJuan Castillo #include <debug.h> 37*05799ae0SJuan Castillo #include <img_parser_mod.h> 38*05799ae0SJuan Castillo #include <platform.h> 39*05799ae0SJuan Castillo #include <platform_def.h> 40*05799ae0SJuan Castillo #include <stdint.h> 41*05799ae0SJuan Castillo #include <string.h> 42*05799ae0SJuan Castillo 43*05799ae0SJuan Castillo #define return_if_error(rc) \ 44*05799ae0SJuan Castillo do { \ 45*05799ae0SJuan Castillo if (rc != 0) { \ 46*05799ae0SJuan Castillo return rc; \ 47*05799ae0SJuan Castillo } \ 48*05799ae0SJuan Castillo } while (0) 49*05799ae0SJuan Castillo 50*05799ae0SJuan Castillo /* Pointer to CoT */ 51*05799ae0SJuan Castillo extern const auth_img_desc_t *const cot_desc_ptr; 52*05799ae0SJuan Castillo extern unsigned int auth_img_flags[]; 53*05799ae0SJuan Castillo 54*05799ae0SJuan Castillo static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, 55*05799ae0SJuan Castillo const auth_param_type_desc_t *b) 56*05799ae0SJuan Castillo { 57*05799ae0SJuan Castillo if ((a->type == b->type) && (a->cookie == b->cookie)) { 58*05799ae0SJuan Castillo return 0; 59*05799ae0SJuan Castillo } 60*05799ae0SJuan Castillo return 1; 61*05799ae0SJuan Castillo } 62*05799ae0SJuan Castillo 63*05799ae0SJuan Castillo /* 64*05799ae0SJuan Castillo * This function obtains the requested authentication parameter data from the 65*05799ae0SJuan Castillo * information extracted from the parent image after its authentication. 66*05799ae0SJuan Castillo */ 67*05799ae0SJuan Castillo static int auth_get_param(const auth_param_type_desc_t *param_type_desc, 68*05799ae0SJuan Castillo const auth_img_desc_t *img_desc, 69*05799ae0SJuan Castillo void **param, unsigned int *len) 70*05799ae0SJuan Castillo { 71*05799ae0SJuan Castillo int i; 72*05799ae0SJuan Castillo 73*05799ae0SJuan Castillo for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { 74*05799ae0SJuan Castillo if (0 == cmp_auth_param_type_desc(param_type_desc, 75*05799ae0SJuan Castillo img_desc->authenticated_data[i].type_desc)) { 76*05799ae0SJuan Castillo *param = img_desc->authenticated_data[i].data.ptr; 77*05799ae0SJuan Castillo *len = img_desc->authenticated_data[i].data.len; 78*05799ae0SJuan Castillo return 0; 79*05799ae0SJuan Castillo } 80*05799ae0SJuan Castillo } 81*05799ae0SJuan Castillo 82*05799ae0SJuan Castillo return 1; 83*05799ae0SJuan Castillo } 84*05799ae0SJuan Castillo 85*05799ae0SJuan Castillo /* 86*05799ae0SJuan Castillo * Authenticate an image by matching the data hash 87*05799ae0SJuan Castillo * 88*05799ae0SJuan Castillo * This function implements 'AUTH_METHOD_HASH'. To authenticate an image using 89*05799ae0SJuan Castillo * this method, the image must contain: 90*05799ae0SJuan Castillo * 91*05799ae0SJuan Castillo * - The data to calculate the hash from 92*05799ae0SJuan Castillo * 93*05799ae0SJuan Castillo * The parent image must contain: 94*05799ae0SJuan Castillo * 95*05799ae0SJuan Castillo * - The hash to be matched with (including hash algorithm) 96*05799ae0SJuan Castillo * 97*05799ae0SJuan Castillo * For a successful authentication, both hashes must match. The function calls 98*05799ae0SJuan Castillo * the crypto-module to check this matching. 99*05799ae0SJuan Castillo * 100*05799ae0SJuan Castillo * Parameters: 101*05799ae0SJuan Castillo * param: parameters to perform the hash authentication 102*05799ae0SJuan Castillo * img_desc: pointer to image descriptor so we can know the image type 103*05799ae0SJuan Castillo * and parent image 104*05799ae0SJuan Castillo * img: pointer to image in memory 105*05799ae0SJuan Castillo * img_len: length of image (in bytes) 106*05799ae0SJuan Castillo * 107*05799ae0SJuan Castillo * Return: 108*05799ae0SJuan Castillo * 0 = success, Otherwise = error 109*05799ae0SJuan Castillo */ 110*05799ae0SJuan Castillo static int auth_hash(const auth_method_param_hash_t *param, 111*05799ae0SJuan Castillo const auth_img_desc_t *img_desc, 112*05799ae0SJuan Castillo void *img, unsigned int img_len) 113*05799ae0SJuan Castillo { 114*05799ae0SJuan Castillo void *data_ptr, *hash_der_ptr; 115*05799ae0SJuan Castillo unsigned int data_len, hash_der_len; 116*05799ae0SJuan Castillo int rc = 0; 117*05799ae0SJuan Castillo 118*05799ae0SJuan Castillo /* Get the hash from the parent image. This hash will be DER encoded 119*05799ae0SJuan Castillo * and contain the hash algorithm */ 120*05799ae0SJuan Castillo rc = auth_get_param(param->hash, img_desc->parent, 121*05799ae0SJuan Castillo &hash_der_ptr, &hash_der_len); 122*05799ae0SJuan Castillo return_if_error(rc); 123*05799ae0SJuan Castillo 124*05799ae0SJuan Castillo /* Get the data to be hashed from the current image */ 125*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, param->data, 126*05799ae0SJuan Castillo img, img_len, &data_ptr, &data_len); 127*05799ae0SJuan Castillo return_if_error(rc); 128*05799ae0SJuan Castillo 129*05799ae0SJuan Castillo /* Ask the crypto module to verify this hash */ 130*05799ae0SJuan Castillo rc = crypto_mod_verify_hash(data_ptr, data_len, 131*05799ae0SJuan Castillo hash_der_ptr, hash_der_len); 132*05799ae0SJuan Castillo 133*05799ae0SJuan Castillo return rc; 134*05799ae0SJuan Castillo } 135*05799ae0SJuan Castillo 136*05799ae0SJuan Castillo /* 137*05799ae0SJuan Castillo * Authenticate by digital signature 138*05799ae0SJuan Castillo * 139*05799ae0SJuan Castillo * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using 140*05799ae0SJuan Castillo * this method, the image must contain: 141*05799ae0SJuan Castillo * 142*05799ae0SJuan Castillo * - Data to be signed 143*05799ae0SJuan Castillo * - Signature 144*05799ae0SJuan Castillo * - Signature algorithm 145*05799ae0SJuan Castillo * 146*05799ae0SJuan Castillo * We rely on the image parser module to extract this data from the image. 147*05799ae0SJuan Castillo * The parent image must contain: 148*05799ae0SJuan Castillo * 149*05799ae0SJuan Castillo * - Public key (or a hash of it) 150*05799ae0SJuan Castillo * 151*05799ae0SJuan Castillo * If the parent image contains only a hash of the key, we will try to obtain 152*05799ae0SJuan Castillo * the public key from the image itself (i.e. self-signed certificates). In that 153*05799ae0SJuan Castillo * case, the signature verification is considered just an integrity check and 154*05799ae0SJuan Castillo * the authentication is established by calculating the hash of the key and 155*05799ae0SJuan Castillo * comparing it with the hash obtained from the parent. 156*05799ae0SJuan Castillo * 157*05799ae0SJuan Castillo * If the image has no parent (NULL), it means it has to be authenticated using 158*05799ae0SJuan Castillo * the ROTPK stored in the platform. Again, this ROTPK could be the key itself 159*05799ae0SJuan Castillo * or a hash of it. 160*05799ae0SJuan Castillo * 161*05799ae0SJuan Castillo * Return: 0 = success, Otherwise = error 162*05799ae0SJuan Castillo */ 163*05799ae0SJuan Castillo static int auth_signature(const auth_method_param_sig_t *param, 164*05799ae0SJuan Castillo const auth_img_desc_t *img_desc, 165*05799ae0SJuan Castillo void *img, unsigned int img_len) 166*05799ae0SJuan Castillo { 167*05799ae0SJuan Castillo void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr; 168*05799ae0SJuan Castillo unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len; 169*05799ae0SJuan Castillo unsigned int flags = 0; 170*05799ae0SJuan Castillo int rc = 0; 171*05799ae0SJuan Castillo 172*05799ae0SJuan Castillo /* Get the data to be signed from current image */ 173*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, param->data, 174*05799ae0SJuan Castillo img, img_len, &data_ptr, &data_len); 175*05799ae0SJuan Castillo return_if_error(rc); 176*05799ae0SJuan Castillo 177*05799ae0SJuan Castillo /* Get the signature from current image */ 178*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, param->sig, 179*05799ae0SJuan Castillo img, img_len, &sig_ptr, &sig_len); 180*05799ae0SJuan Castillo return_if_error(rc); 181*05799ae0SJuan Castillo 182*05799ae0SJuan Castillo /* Get the signature algorithm from current image */ 183*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, param->alg, 184*05799ae0SJuan Castillo img, img_len, &sig_alg_ptr, &sig_alg_len); 185*05799ae0SJuan Castillo return_if_error(rc); 186*05799ae0SJuan Castillo 187*05799ae0SJuan Castillo /* Get the public key from the parent. If there is no parent (NULL), 188*05799ae0SJuan Castillo * the certificate has been signed with the ROTPK, so we have to get 189*05799ae0SJuan Castillo * the PK from the platform */ 190*05799ae0SJuan Castillo if (img_desc->parent) { 191*05799ae0SJuan Castillo rc = auth_get_param(param->pk, img_desc->parent, 192*05799ae0SJuan Castillo &pk_ptr, &pk_len); 193*05799ae0SJuan Castillo } else { 194*05799ae0SJuan Castillo rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len, 195*05799ae0SJuan Castillo &flags); 196*05799ae0SJuan Castillo } 197*05799ae0SJuan Castillo return_if_error(rc); 198*05799ae0SJuan Castillo 199*05799ae0SJuan Castillo /* If the PK is a hash of the key, retrieve the key from the image */ 200*05799ae0SJuan Castillo if (flags & ROTPK_IS_HASH) { 201*05799ae0SJuan Castillo pk_hash_ptr = pk_ptr; 202*05799ae0SJuan Castillo pk_hash_len = pk_len; 203*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, 204*05799ae0SJuan Castillo param->pk, img, img_len, 205*05799ae0SJuan Castillo &pk_ptr, &pk_len); 206*05799ae0SJuan Castillo return_if_error(rc); 207*05799ae0SJuan Castillo 208*05799ae0SJuan Castillo /* Ask the crypto module to verify the signature */ 209*05799ae0SJuan Castillo rc = crypto_mod_verify_signature(data_ptr, data_len, 210*05799ae0SJuan Castillo sig_ptr, sig_len, 211*05799ae0SJuan Castillo sig_alg_ptr, sig_alg_len, 212*05799ae0SJuan Castillo pk_ptr, pk_len); 213*05799ae0SJuan Castillo return_if_error(rc); 214*05799ae0SJuan Castillo 215*05799ae0SJuan Castillo /* Ask the crypto-module to verify the key hash */ 216*05799ae0SJuan Castillo rc = crypto_mod_verify_hash(pk_ptr, pk_len, 217*05799ae0SJuan Castillo pk_hash_ptr, pk_hash_len); 218*05799ae0SJuan Castillo } else { 219*05799ae0SJuan Castillo /* Ask the crypto module to verify the signature */ 220*05799ae0SJuan Castillo rc = crypto_mod_verify_signature(data_ptr, data_len, 221*05799ae0SJuan Castillo sig_ptr, sig_len, 222*05799ae0SJuan Castillo sig_alg_ptr, sig_alg_len, 223*05799ae0SJuan Castillo pk_ptr, pk_len); 224*05799ae0SJuan Castillo } 225*05799ae0SJuan Castillo 226*05799ae0SJuan Castillo return rc; 227*05799ae0SJuan Castillo } 228*05799ae0SJuan Castillo 229*05799ae0SJuan Castillo /* 230*05799ae0SJuan Castillo * Return the parent id in the output parameter '*parent_id' 231*05799ae0SJuan Castillo * 232*05799ae0SJuan Castillo * Return value: 233*05799ae0SJuan Castillo * 0 = Image has parent, 1 = Image has no parent or parent is authenticated 234*05799ae0SJuan Castillo */ 235*05799ae0SJuan Castillo int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) 236*05799ae0SJuan Castillo { 237*05799ae0SJuan Castillo const auth_img_desc_t *img_desc = NULL; 238*05799ae0SJuan Castillo 239*05799ae0SJuan Castillo assert(parent_id != NULL); 240*05799ae0SJuan Castillo 241*05799ae0SJuan Castillo /* Get the image descriptor */ 242*05799ae0SJuan Castillo img_desc = &cot_desc_ptr[img_id]; 243*05799ae0SJuan Castillo 244*05799ae0SJuan Castillo /* Check if the image has no parent (ROT) */ 245*05799ae0SJuan Castillo if (img_desc->parent == NULL) { 246*05799ae0SJuan Castillo *parent_id = 0; 247*05799ae0SJuan Castillo return 1; 248*05799ae0SJuan Castillo } 249*05799ae0SJuan Castillo 250*05799ae0SJuan Castillo /* Check if the parent has already been authenticated */ 251*05799ae0SJuan Castillo if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) { 252*05799ae0SJuan Castillo *parent_id = 0; 253*05799ae0SJuan Castillo return 1; 254*05799ae0SJuan Castillo } 255*05799ae0SJuan Castillo 256*05799ae0SJuan Castillo *parent_id = img_desc->parent->img_id; 257*05799ae0SJuan Castillo return 0; 258*05799ae0SJuan Castillo } 259*05799ae0SJuan Castillo 260*05799ae0SJuan Castillo /* 261*05799ae0SJuan Castillo * Initialize the different modules in the authentication framework 262*05799ae0SJuan Castillo */ 263*05799ae0SJuan Castillo void auth_mod_init(void) 264*05799ae0SJuan Castillo { 265*05799ae0SJuan Castillo /* Check we have a valid CoT registered */ 266*05799ae0SJuan Castillo assert(cot_desc_ptr != NULL); 267*05799ae0SJuan Castillo 268*05799ae0SJuan Castillo /* Crypto module */ 269*05799ae0SJuan Castillo crypto_mod_init(); 270*05799ae0SJuan Castillo 271*05799ae0SJuan Castillo /* Image parser module */ 272*05799ae0SJuan Castillo img_parser_init(); 273*05799ae0SJuan Castillo } 274*05799ae0SJuan Castillo 275*05799ae0SJuan Castillo /* 276*05799ae0SJuan Castillo * Authenticate a certificate/image 277*05799ae0SJuan Castillo * 278*05799ae0SJuan Castillo * Return: 0 = success, Otherwise = error 279*05799ae0SJuan Castillo */ 280*05799ae0SJuan Castillo int auth_mod_verify_img(unsigned int img_id, 281*05799ae0SJuan Castillo void *img_ptr, 282*05799ae0SJuan Castillo unsigned int img_len) 283*05799ae0SJuan Castillo { 284*05799ae0SJuan Castillo const auth_img_desc_t *img_desc = NULL; 285*05799ae0SJuan Castillo const auth_method_desc_t *auth_method = NULL; 286*05799ae0SJuan Castillo void *param_ptr; 287*05799ae0SJuan Castillo unsigned int param_len; 288*05799ae0SJuan Castillo int rc, i; 289*05799ae0SJuan Castillo 290*05799ae0SJuan Castillo /* Get the image descriptor from the chain of trust */ 291*05799ae0SJuan Castillo img_desc = &cot_desc_ptr[img_id]; 292*05799ae0SJuan Castillo 293*05799ae0SJuan Castillo /* Ask the parser to check the image integrity */ 294*05799ae0SJuan Castillo rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len); 295*05799ae0SJuan Castillo return_if_error(rc); 296*05799ae0SJuan Castillo 297*05799ae0SJuan Castillo /* Authenticate the image using the methods indicated in the image 298*05799ae0SJuan Castillo * descriptor. */ 299*05799ae0SJuan Castillo for (i = 0 ; i < AUTH_METHOD_NUM ; i++) { 300*05799ae0SJuan Castillo auth_method = &img_desc->img_auth_methods[i]; 301*05799ae0SJuan Castillo switch (auth_method->type) { 302*05799ae0SJuan Castillo case AUTH_METHOD_NONE: 303*05799ae0SJuan Castillo rc = 0; 304*05799ae0SJuan Castillo break; 305*05799ae0SJuan Castillo case AUTH_METHOD_HASH: 306*05799ae0SJuan Castillo rc = auth_hash(&auth_method->param.hash, 307*05799ae0SJuan Castillo img_desc, img_ptr, img_len); 308*05799ae0SJuan Castillo break; 309*05799ae0SJuan Castillo case AUTH_METHOD_SIG: 310*05799ae0SJuan Castillo rc = auth_signature(&auth_method->param.sig, 311*05799ae0SJuan Castillo img_desc, img_ptr, img_len); 312*05799ae0SJuan Castillo break; 313*05799ae0SJuan Castillo default: 314*05799ae0SJuan Castillo /* Unknown authentication method */ 315*05799ae0SJuan Castillo rc = 1; 316*05799ae0SJuan Castillo break; 317*05799ae0SJuan Castillo } 318*05799ae0SJuan Castillo return_if_error(rc); 319*05799ae0SJuan Castillo } 320*05799ae0SJuan Castillo 321*05799ae0SJuan Castillo /* Extract the parameters indicated in the image descriptor to 322*05799ae0SJuan Castillo * authenticate the children images. */ 323*05799ae0SJuan Castillo for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { 324*05799ae0SJuan Castillo if (img_desc->authenticated_data[i].type_desc == NULL) { 325*05799ae0SJuan Castillo continue; 326*05799ae0SJuan Castillo } 327*05799ae0SJuan Castillo 328*05799ae0SJuan Castillo /* Get the parameter from the image parser module */ 329*05799ae0SJuan Castillo rc = img_parser_get_auth_param(img_desc->img_type, 330*05799ae0SJuan Castillo img_desc->authenticated_data[i].type_desc, 331*05799ae0SJuan Castillo img_ptr, img_len, ¶m_ptr, ¶m_len); 332*05799ae0SJuan Castillo return_if_error(rc); 333*05799ae0SJuan Castillo 334*05799ae0SJuan Castillo /* Check parameter size */ 335*05799ae0SJuan Castillo if (param_len > img_desc->authenticated_data[i].data.len) { 336*05799ae0SJuan Castillo return 1; 337*05799ae0SJuan Castillo } 338*05799ae0SJuan Castillo 339*05799ae0SJuan Castillo /* Copy the parameter for later use */ 340*05799ae0SJuan Castillo memcpy((void *)img_desc->authenticated_data[i].data.ptr, 341*05799ae0SJuan Castillo (void *)param_ptr, param_len); 342*05799ae0SJuan Castillo } 343*05799ae0SJuan Castillo 344*05799ae0SJuan Castillo /* Mark image as authenticated */ 345*05799ae0SJuan Castillo auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED; 346*05799ae0SJuan Castillo 347*05799ae0SJuan Castillo return 0; 348*05799ae0SJuan Castillo } 349