1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This file is part of UBIFS. 4 * 5 * Copyright (C) 2018 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> 6 */ 7 8 /* 9 * This file implements various helper functions for UBIFS authentication support 10 */ 11 12 #include <linux/crypto.h> 13 #include <crypto/hash.h> 14 #include <crypto/sha.h> 15 #include <crypto/algapi.h> 16 #include <keys/user-type.h> 17 18 #include "ubifs.h" 19 20 /** 21 * ubifs_node_calc_hash - calculate the hash of a UBIFS node 22 * @c: UBIFS file-system description object 23 * @node: the node to calculate a hash for 24 * @hash: the returned hash 25 * 26 * Returns 0 for success or a negative error code otherwise. 27 */ 28 int __ubifs_node_calc_hash(const struct ubifs_info *c, const void *node, 29 u8 *hash) 30 { 31 const struct ubifs_ch *ch = node; 32 SHASH_DESC_ON_STACK(shash, c->hash_tfm); 33 int err; 34 35 shash->tfm = c->hash_tfm; 36 shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 37 38 err = crypto_shash_digest(shash, node, le32_to_cpu(ch->len), hash); 39 if (err < 0) 40 return err; 41 return 0; 42 } 43 44 /** 45 * ubifs_hash_calc_hmac - calculate a HMAC from a hash 46 * @c: UBIFS file-system description object 47 * @hash: the node to calculate a HMAC for 48 * @hmac: the returned HMAC 49 * 50 * Returns 0 for success or a negative error code otherwise. 51 */ 52 static int ubifs_hash_calc_hmac(const struct ubifs_info *c, const u8 *hash, 53 u8 *hmac) 54 { 55 SHASH_DESC_ON_STACK(shash, c->hmac_tfm); 56 int err; 57 58 shash->tfm = c->hmac_tfm; 59 shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 60 61 err = crypto_shash_digest(shash, hash, c->hash_len, hmac); 62 if (err < 0) 63 return err; 64 return 0; 65 } 66 67 /** 68 * ubifs_prepare_auth_node - Prepare an authentication node 69 * @c: UBIFS file-system description object 70 * @node: the node to calculate a hash for 71 * @hash: input hash of previous nodes 72 * 73 * This function prepares an authentication node for writing onto flash. 74 * It creates a HMAC from the given input hash and writes it to the node. 75 * 76 * Returns 0 for success or a negative error code otherwise. 77 */ 78 int ubifs_prepare_auth_node(struct ubifs_info *c, void *node, 79 struct shash_desc *inhash) 80 { 81 SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm); 82 struct ubifs_auth_node *auth = node; 83 u8 *hash; 84 int err; 85 86 hash = kmalloc(crypto_shash_descsize(c->hash_tfm), GFP_NOFS); 87 if (!hash) 88 return -ENOMEM; 89 90 hash_desc->tfm = c->hash_tfm; 91 hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 92 ubifs_shash_copy_state(c, inhash, hash_desc); 93 94 err = crypto_shash_final(hash_desc, hash); 95 if (err) 96 goto out; 97 98 err = ubifs_hash_calc_hmac(c, hash, auth->hmac); 99 if (err) 100 goto out; 101 102 auth->ch.node_type = UBIFS_AUTH_NODE; 103 ubifs_prepare_node(c, auth, ubifs_auth_node_sz(c), 0); 104 105 err = 0; 106 out: 107 kfree(hash); 108 109 return err; 110 } 111 112 static struct shash_desc *ubifs_get_desc(const struct ubifs_info *c, 113 struct crypto_shash *tfm) 114 { 115 struct shash_desc *desc; 116 int err; 117 118 if (!ubifs_authenticated(c)) 119 return NULL; 120 121 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); 122 if (!desc) 123 return ERR_PTR(-ENOMEM); 124 125 desc->tfm = tfm; 126 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 127 128 err = crypto_shash_init(desc); 129 if (err) { 130 kfree(desc); 131 return ERR_PTR(err); 132 } 133 134 return desc; 135 } 136 137 /** 138 * __ubifs_hash_get_desc - get a descriptor suitable for hashing a node 139 * @c: UBIFS file-system description object 140 * 141 * This function returns a descriptor suitable for hashing a node. Free after use 142 * with kfree. 143 */ 144 struct shash_desc *__ubifs_hash_get_desc(const struct ubifs_info *c) 145 { 146 return ubifs_get_desc(c, c->hash_tfm); 147 } 148 149 /** 150 * ubifs_bad_hash - Report hash mismatches 151 * @c: UBIFS file-system description object 152 * @node: the node 153 * @hash: the expected hash 154 * @lnum: the LEB @node was read from 155 * @offs: offset in LEB @node was read from 156 * 157 * This function reports a hash mismatch when a node has a different hash than 158 * expected. 159 */ 160 void ubifs_bad_hash(const struct ubifs_info *c, const void *node, const u8 *hash, 161 int lnum, int offs) 162 { 163 int len = min(c->hash_len, 20); 164 int cropped = len != c->hash_len; 165 const char *cont = cropped ? "..." : ""; 166 167 u8 calc[UBIFS_HASH_ARR_SZ]; 168 169 __ubifs_node_calc_hash(c, node, calc); 170 171 ubifs_err(c, "hash mismatch on node at LEB %d:%d", lnum, offs); 172 ubifs_err(c, "hash expected: %*ph%s", len, hash, cont); 173 ubifs_err(c, "hash calculated: %*ph%s", len, calc, cont); 174 } 175 176 /** 177 * __ubifs_node_check_hash - check the hash of a node against given hash 178 * @c: UBIFS file-system description object 179 * @node: the node 180 * @expected: the expected hash 181 * 182 * This function calculates a hash over a node and compares it to the given hash. 183 * Returns 0 if both hashes are equal or authentication is disabled, otherwise a 184 * negative error code is returned. 185 */ 186 int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node, 187 const u8 *expected) 188 { 189 u8 calc[UBIFS_HASH_ARR_SZ]; 190 int err; 191 192 err = __ubifs_node_calc_hash(c, node, calc); 193 if (err) 194 return err; 195 196 if (ubifs_check_hash(c, expected, calc)) 197 return -EPERM; 198 199 return 0; 200 } 201 202 /** 203 * ubifs_init_authentication - initialize UBIFS authentication support 204 * @c: UBIFS file-system description object 205 * 206 * This function returns 0 for success or a negative error code otherwise. 207 */ 208 int ubifs_init_authentication(struct ubifs_info *c) 209 { 210 struct key *keyring_key; 211 const struct user_key_payload *ukp; 212 int err; 213 char hmac_name[CRYPTO_MAX_ALG_NAME]; 214 215 if (!c->auth_hash_name) { 216 ubifs_err(c, "authentication hash name needed with authentication"); 217 return -EINVAL; 218 } 219 220 c->auth_hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST, 221 c->auth_hash_name); 222 if ((int)c->auth_hash_algo < 0) { 223 ubifs_err(c, "Unknown hash algo %s specified", 224 c->auth_hash_name); 225 return -EINVAL; 226 } 227 228 snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", 229 c->auth_hash_name); 230 231 keyring_key = request_key(&key_type_logon, c->auth_key_name, NULL); 232 233 if (IS_ERR(keyring_key)) { 234 ubifs_err(c, "Failed to request key: %ld", 235 PTR_ERR(keyring_key)); 236 return PTR_ERR(keyring_key); 237 } 238 239 down_read(&keyring_key->sem); 240 241 if (keyring_key->type != &key_type_logon) { 242 ubifs_err(c, "key type must be logon"); 243 err = -ENOKEY; 244 goto out; 245 } 246 247 ukp = user_key_payload_locked(keyring_key); 248 if (!ukp) { 249 /* key was revoked before we acquired its semaphore */ 250 err = -EKEYREVOKED; 251 goto out; 252 } 253 254 c->hash_tfm = crypto_alloc_shash(c->auth_hash_name, 0, 0); 255 if (IS_ERR(c->hash_tfm)) { 256 err = PTR_ERR(c->hash_tfm); 257 ubifs_err(c, "Can not allocate %s: %d", 258 c->auth_hash_name, err); 259 goto out; 260 } 261 262 c->hash_len = crypto_shash_digestsize(c->hash_tfm); 263 if (c->hash_len > UBIFS_HASH_ARR_SZ) { 264 ubifs_err(c, "hash %s is bigger than maximum allowed hash size (%d > %d)", 265 c->auth_hash_name, c->hash_len, UBIFS_HASH_ARR_SZ); 266 err = -EINVAL; 267 goto out_free_hash; 268 } 269 270 c->hmac_tfm = crypto_alloc_shash(hmac_name, 0, 0); 271 if (IS_ERR(c->hmac_tfm)) { 272 err = PTR_ERR(c->hmac_tfm); 273 ubifs_err(c, "Can not allocate %s: %d", hmac_name, err); 274 goto out_free_hash; 275 } 276 277 c->hmac_desc_len = crypto_shash_digestsize(c->hmac_tfm); 278 if (c->hmac_desc_len > UBIFS_HMAC_ARR_SZ) { 279 ubifs_err(c, "hmac %s is bigger than maximum allowed hmac size (%d > %d)", 280 hmac_name, c->hmac_desc_len, UBIFS_HMAC_ARR_SZ); 281 err = -EINVAL; 282 goto out_free_hash; 283 } 284 285 err = crypto_shash_setkey(c->hmac_tfm, ukp->data, ukp->datalen); 286 if (err) 287 goto out_free_hmac; 288 289 c->authenticated = true; 290 291 c->log_hash = ubifs_hash_get_desc(c); 292 if (IS_ERR(c->log_hash)) 293 goto out_free_hmac; 294 295 err = 0; 296 297 out_free_hmac: 298 if (err) 299 crypto_free_shash(c->hmac_tfm); 300 out_free_hash: 301 if (err) 302 crypto_free_shash(c->hash_tfm); 303 out: 304 up_read(&keyring_key->sem); 305 key_put(keyring_key); 306 307 return err; 308 } 309 310 /** 311 * __ubifs_exit_authentication - release resource 312 * @c: UBIFS file-system description object 313 * 314 * This function releases the authentication related resources. 315 */ 316 void __ubifs_exit_authentication(struct ubifs_info *c) 317 { 318 if (!ubifs_authenticated(c)) 319 return; 320 321 crypto_free_shash(c->hmac_tfm); 322 crypto_free_shash(c->hash_tfm); 323 kfree(c->log_hash); 324 } 325 326 /** 327 * ubifs_node_calc_hmac - calculate the HMAC of a UBIFS node 328 * @c: UBIFS file-system description object 329 * @node: the node to insert a HMAC into. 330 * @len: the length of the node 331 * @ofs_hmac: the offset in the node where the HMAC is inserted 332 * @hmac: returned HMAC 333 * 334 * This function calculates a HMAC of a UBIFS node. The HMAC is expected to be 335 * embedded into the node, so this area is not covered by the HMAC. Also not 336 * covered is the UBIFS_NODE_MAGIC and the CRC of the node. 337 */ 338 static int ubifs_node_calc_hmac(const struct ubifs_info *c, const void *node, 339 int len, int ofs_hmac, void *hmac) 340 { 341 SHASH_DESC_ON_STACK(shash, c->hmac_tfm); 342 int hmac_len = c->hmac_desc_len; 343 int err; 344 345 ubifs_assert(c, ofs_hmac > 8); 346 ubifs_assert(c, ofs_hmac + hmac_len < len); 347 348 shash->tfm = c->hmac_tfm; 349 shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 350 351 err = crypto_shash_init(shash); 352 if (err) 353 return err; 354 355 /* behind common node header CRC up to HMAC begin */ 356 err = crypto_shash_update(shash, node + 8, ofs_hmac - 8); 357 if (err < 0) 358 return err; 359 360 /* behind HMAC, if any */ 361 if (len - ofs_hmac - hmac_len > 0) { 362 err = crypto_shash_update(shash, node + ofs_hmac + hmac_len, 363 len - ofs_hmac - hmac_len); 364 if (err < 0) 365 return err; 366 } 367 368 return crypto_shash_final(shash, hmac); 369 } 370 371 /** 372 * __ubifs_node_insert_hmac - insert a HMAC into a UBIFS node 373 * @c: UBIFS file-system description object 374 * @node: the node to insert a HMAC into. 375 * @len: the length of the node 376 * @ofs_hmac: the offset in the node where the HMAC is inserted 377 * 378 * This function inserts a HMAC at offset @ofs_hmac into the node given in 379 * @node. 380 * 381 * This function returns 0 for success or a negative error code otherwise. 382 */ 383 int __ubifs_node_insert_hmac(const struct ubifs_info *c, void *node, int len, 384 int ofs_hmac) 385 { 386 return ubifs_node_calc_hmac(c, node, len, ofs_hmac, node + ofs_hmac); 387 } 388 389 /** 390 * __ubifs_node_verify_hmac - verify the HMAC of UBIFS node 391 * @c: UBIFS file-system description object 392 * @node: the node to insert a HMAC into. 393 * @len: the length of the node 394 * @ofs_hmac: the offset in the node where the HMAC is inserted 395 * 396 * This function verifies the HMAC at offset @ofs_hmac of the node given in 397 * @node. Returns 0 if successful or a negative error code otherwise. 398 */ 399 int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *node, 400 int len, int ofs_hmac) 401 { 402 int hmac_len = c->hmac_desc_len; 403 u8 *hmac; 404 int err; 405 406 hmac = kmalloc(hmac_len, GFP_NOFS); 407 if (!hmac) 408 return -ENOMEM; 409 410 err = ubifs_node_calc_hmac(c, node, len, ofs_hmac, hmac); 411 if (err) 412 return err; 413 414 err = crypto_memneq(hmac, node + ofs_hmac, hmac_len); 415 416 kfree(hmac); 417 418 if (!err) 419 return 0; 420 421 return -EPERM; 422 } 423 424 int __ubifs_shash_copy_state(const struct ubifs_info *c, struct shash_desc *src, 425 struct shash_desc *target) 426 { 427 u8 *state; 428 int err; 429 430 state = kmalloc(crypto_shash_descsize(src->tfm), GFP_NOFS); 431 if (!state) 432 return -ENOMEM; 433 434 err = crypto_shash_export(src, state); 435 if (err) 436 goto out; 437 438 err = crypto_shash_import(target, state); 439 440 out: 441 kfree(state); 442 443 return err; 444 } 445 446 /** 447 * ubifs_hmac_wkm - Create a HMAC of the well known message 448 * @c: UBIFS file-system description object 449 * @hmac: The HMAC of the well known message 450 * 451 * This function creates a HMAC of a well known message. This is used 452 * to check if the provided key is suitable to authenticate a UBIFS 453 * image. This is only a convenience to the user to provide a better 454 * error message when the wrong key is provided. 455 * 456 * This function returns 0 for success or a negative error code otherwise. 457 */ 458 int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac) 459 { 460 SHASH_DESC_ON_STACK(shash, c->hmac_tfm); 461 int err; 462 const char well_known_message[] = "UBIFS"; 463 464 if (!ubifs_authenticated(c)) 465 return 0; 466 467 shash->tfm = c->hmac_tfm; 468 shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 469 470 err = crypto_shash_init(shash); 471 if (err) 472 return err; 473 474 err = crypto_shash_update(shash, well_known_message, 475 sizeof(well_known_message) - 1); 476 if (err < 0) 477 return err; 478 479 err = crypto_shash_final(shash, hmac); 480 if (err) 481 return err; 482 return 0; 483 } 484