root/fs/ubifs/auth.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __ubifs_node_calc_hash
  2. ubifs_hash_calc_hmac
  3. ubifs_prepare_auth_node
  4. ubifs_get_desc
  5. __ubifs_hash_get_desc
  6. ubifs_bad_hash
  7. __ubifs_node_check_hash
  8. ubifs_sb_verify_signature
  9. ubifs_init_authentication
  10. __ubifs_exit_authentication
  11. ubifs_node_calc_hmac
  12. __ubifs_node_insert_hmac
  13. __ubifs_node_verify_hmac
  14. __ubifs_shash_copy_state
  15. ubifs_hmac_wkm
  16. ubifs_hmac_zero

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

/* [<][>][^][v][top][bottom][index][help] */