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