1 // SPDX-License-Identifier: GPL-2.0
3 * This file is part of UBIFS.
5 * Copyright (C) 2018 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
9 * This file implements various helper functions for UBIFS authentication support
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>
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
26 * Returns 0 for success or a negative error code otherwise.
28 int __ubifs_node_calc_hash(const struct ubifs_info
*c
, const void *node
,
31 const struct ubifs_ch
*ch
= node
;
32 SHASH_DESC_ON_STACK(shash
, c
->hash_tfm
);
35 shash
->tfm
= c
->hash_tfm
;
36 shash
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
38 err
= crypto_shash_digest(shash
, node
, le32_to_cpu(ch
->len
), hash
);
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
50 * Returns 0 for success or a negative error code otherwise.
52 static int ubifs_hash_calc_hmac(const struct ubifs_info
*c
, const u8
*hash
,
55 SHASH_DESC_ON_STACK(shash
, c
->hmac_tfm
);
58 shash
->tfm
= c
->hmac_tfm
;
59 shash
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
61 err
= crypto_shash_digest(shash
, hash
, c
->hash_len
, hmac
);
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
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.
76 * Returns 0 for success or a negative error code otherwise.
78 int ubifs_prepare_auth_node(struct ubifs_info
*c
, void *node
,
79 struct shash_desc
*inhash
)
81 SHASH_DESC_ON_STACK(hash_desc
, c
->hash_tfm
);
82 struct ubifs_auth_node
*auth
= node
;
86 hash
= kmalloc(crypto_shash_descsize(c
->hash_tfm
), GFP_NOFS
);
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
);
94 err
= crypto_shash_final(hash_desc
, hash
);
98 err
= ubifs_hash_calc_hmac(c
, hash
, auth
->hmac
);
102 auth
->ch
.node_type
= UBIFS_AUTH_NODE
;
103 ubifs_prepare_node(c
, auth
, ubifs_auth_node_sz(c
), 0);
112 static struct shash_desc
*ubifs_get_desc(const struct ubifs_info
*c
,
113 struct crypto_shash
*tfm
)
115 struct shash_desc
*desc
;
118 if (!ubifs_authenticated(c
))
121 desc
= kmalloc(sizeof(*desc
) + crypto_shash_descsize(tfm
), GFP_KERNEL
);
123 return ERR_PTR(-ENOMEM
);
126 desc
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
128 err
= crypto_shash_init(desc
);
138 * __ubifs_hash_get_desc - get a descriptor suitable for hashing a node
139 * @c: UBIFS file-system description object
141 * This function returns a descriptor suitable for hashing a node. Free after use
144 struct shash_desc
*__ubifs_hash_get_desc(const struct ubifs_info
*c
)
146 return ubifs_get_desc(c
, c
->hash_tfm
);
150 * __ubifs_shash_final - finalize shash
151 * @c: UBIFS file-system description object
152 * @desc: the descriptor
153 * @out: the output hash
155 * Simple wrapper around crypto_shash_final(), safe to be called with
156 * disabled authentication.
158 int __ubifs_shash_final(const struct ubifs_info
*c
, struct shash_desc
*desc
,
161 if (ubifs_authenticated(c
))
162 return crypto_shash_final(desc
, out
);
168 * ubifs_bad_hash - Report hash mismatches
169 * @c: UBIFS file-system description object
171 * @hash: the expected hash
172 * @lnum: the LEB @node was read from
173 * @offs: offset in LEB @node was read from
175 * This function reports a hash mismatch when a node has a different hash than
178 void ubifs_bad_hash(const struct ubifs_info
*c
, const void *node
, const u8
*hash
,
181 int len
= min(c
->hash_len
, 20);
182 int cropped
= len
!= c
->hash_len
;
183 const char *cont
= cropped
? "..." : "";
185 u8 calc
[UBIFS_HASH_ARR_SZ
];
187 __ubifs_node_calc_hash(c
, node
, calc
);
189 ubifs_err(c
, "hash mismatch on node at LEB %d:%d", lnum
, offs
);
190 ubifs_err(c
, "hash expected: %*ph%s", len
, hash
, cont
);
191 ubifs_err(c
, "hash calculated: %*ph%s", len
, calc
, cont
);
195 * __ubifs_node_check_hash - check the hash of a node against given hash
196 * @c: UBIFS file-system description object
198 * @expected: the expected hash
200 * This function calculates a hash over a node and compares it to the given hash.
201 * Returns 0 if both hashes are equal or authentication is disabled, otherwise a
202 * negative error code is returned.
204 int __ubifs_node_check_hash(const struct ubifs_info
*c
, const void *node
,
207 u8 calc
[UBIFS_HASH_ARR_SZ
];
210 err
= __ubifs_node_calc_hash(c
, node
, calc
);
214 if (ubifs_check_hash(c
, expected
, calc
))
221 * ubifs_init_authentication - initialize UBIFS authentication support
222 * @c: UBIFS file-system description object
224 * This function returns 0 for success or a negative error code otherwise.
226 int ubifs_init_authentication(struct ubifs_info
*c
)
228 struct key
*keyring_key
;
229 const struct user_key_payload
*ukp
;
231 char hmac_name
[CRYPTO_MAX_ALG_NAME
];
233 if (!c
->auth_hash_name
) {
234 ubifs_err(c
, "authentication hash name needed with authentication");
238 c
->auth_hash_algo
= match_string(hash_algo_name
, HASH_ALGO__LAST
,
240 if ((int)c
->auth_hash_algo
< 0) {
241 ubifs_err(c
, "Unknown hash algo %s specified",
246 snprintf(hmac_name
, CRYPTO_MAX_ALG_NAME
, "hmac(%s)",
249 keyring_key
= request_key(&key_type_logon
, c
->auth_key_name
, NULL
);
251 if (IS_ERR(keyring_key
)) {
252 ubifs_err(c
, "Failed to request key: %ld",
253 PTR_ERR(keyring_key
));
254 return PTR_ERR(keyring_key
);
257 down_read(&keyring_key
->sem
);
259 if (keyring_key
->type
!= &key_type_logon
) {
260 ubifs_err(c
, "key type must be logon");
265 ukp
= user_key_payload_locked(keyring_key
);
267 /* key was revoked before we acquired its semaphore */
272 c
->hash_tfm
= crypto_alloc_shash(c
->auth_hash_name
, 0,
274 if (IS_ERR(c
->hash_tfm
)) {
275 err
= PTR_ERR(c
->hash_tfm
);
276 ubifs_err(c
, "Can not allocate %s: %d",
277 c
->auth_hash_name
, err
);
281 c
->hash_len
= crypto_shash_digestsize(c
->hash_tfm
);
282 if (c
->hash_len
> UBIFS_HASH_ARR_SZ
) {
283 ubifs_err(c
, "hash %s is bigger than maximum allowed hash size (%d > %d)",
284 c
->auth_hash_name
, c
->hash_len
, UBIFS_HASH_ARR_SZ
);
289 c
->hmac_tfm
= crypto_alloc_shash(hmac_name
, 0, CRYPTO_ALG_ASYNC
);
290 if (IS_ERR(c
->hmac_tfm
)) {
291 err
= PTR_ERR(c
->hmac_tfm
);
292 ubifs_err(c
, "Can not allocate %s: %d", hmac_name
, err
);
296 c
->hmac_desc_len
= crypto_shash_digestsize(c
->hmac_tfm
);
297 if (c
->hmac_desc_len
> UBIFS_HMAC_ARR_SZ
) {
298 ubifs_err(c
, "hmac %s is bigger than maximum allowed hmac size (%d > %d)",
299 hmac_name
, c
->hmac_desc_len
, UBIFS_HMAC_ARR_SZ
);
304 err
= crypto_shash_setkey(c
->hmac_tfm
, ukp
->data
, ukp
->datalen
);
308 c
->authenticated
= true;
310 c
->log_hash
= ubifs_hash_get_desc(c
);
311 if (IS_ERR(c
->log_hash
))
318 crypto_free_shash(c
->hmac_tfm
);
321 crypto_free_shash(c
->hash_tfm
);
323 up_read(&keyring_key
->sem
);
324 key_put(keyring_key
);
330 * __ubifs_exit_authentication - release resource
331 * @c: UBIFS file-system description object
333 * This function releases the authentication related resources.
335 void __ubifs_exit_authentication(struct ubifs_info
*c
)
337 if (!ubifs_authenticated(c
))
340 crypto_free_shash(c
->hmac_tfm
);
341 crypto_free_shash(c
->hash_tfm
);
346 * ubifs_node_calc_hmac - calculate the HMAC of a UBIFS node
347 * @c: UBIFS file-system description object
348 * @node: the node to insert a HMAC into.
349 * @len: the length of the node
350 * @ofs_hmac: the offset in the node where the HMAC is inserted
351 * @hmac: returned HMAC
353 * This function calculates a HMAC of a UBIFS node. The HMAC is expected to be
354 * embedded into the node, so this area is not covered by the HMAC. Also not
355 * covered is the UBIFS_NODE_MAGIC and the CRC of the node.
357 static int ubifs_node_calc_hmac(const struct ubifs_info
*c
, const void *node
,
358 int len
, int ofs_hmac
, void *hmac
)
360 SHASH_DESC_ON_STACK(shash
, c
->hmac_tfm
);
361 int hmac_len
= c
->hmac_desc_len
;
364 ubifs_assert(c
, ofs_hmac
> 8);
365 ubifs_assert(c
, ofs_hmac
+ hmac_len
< len
);
367 shash
->tfm
= c
->hmac_tfm
;
368 shash
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
370 err
= crypto_shash_init(shash
);
374 /* behind common node header CRC up to HMAC begin */
375 err
= crypto_shash_update(shash
, node
+ 8, ofs_hmac
- 8);
379 /* behind HMAC, if any */
380 if (len
- ofs_hmac
- hmac_len
> 0) {
381 err
= crypto_shash_update(shash
, node
+ ofs_hmac
+ hmac_len
,
382 len
- ofs_hmac
- hmac_len
);
387 return crypto_shash_final(shash
, hmac
);
391 * __ubifs_node_insert_hmac - insert a HMAC into a UBIFS node
392 * @c: UBIFS file-system description object
393 * @node: the node to insert a HMAC into.
394 * @len: the length of the node
395 * @ofs_hmac: the offset in the node where the HMAC is inserted
397 * This function inserts a HMAC at offset @ofs_hmac into the node given in
400 * This function returns 0 for success or a negative error code otherwise.
402 int __ubifs_node_insert_hmac(const struct ubifs_info
*c
, void *node
, int len
,
405 return ubifs_node_calc_hmac(c
, node
, len
, ofs_hmac
, node
+ ofs_hmac
);
409 * __ubifs_node_verify_hmac - verify the HMAC of UBIFS node
410 * @c: UBIFS file-system description object
411 * @node: the node to insert a HMAC into.
412 * @len: the length of the node
413 * @ofs_hmac: the offset in the node where the HMAC is inserted
415 * This function verifies the HMAC at offset @ofs_hmac of the node given in
416 * @node. Returns 0 if successful or a negative error code otherwise.
418 int __ubifs_node_verify_hmac(const struct ubifs_info
*c
, const void *node
,
419 int len
, int ofs_hmac
)
421 int hmac_len
= c
->hmac_desc_len
;
425 hmac
= kmalloc(hmac_len
, GFP_NOFS
);
429 err
= ubifs_node_calc_hmac(c
, node
, len
, ofs_hmac
, hmac
);
433 err
= crypto_memneq(hmac
, node
+ ofs_hmac
, hmac_len
);
443 int __ubifs_shash_copy_state(const struct ubifs_info
*c
, struct shash_desc
*src
,
444 struct shash_desc
*target
)
449 state
= kmalloc(crypto_shash_descsize(src
->tfm
), GFP_NOFS
);
453 err
= crypto_shash_export(src
, state
);
457 err
= crypto_shash_import(target
, state
);
466 * ubifs_hmac_wkm - Create a HMAC of the well known message
467 * @c: UBIFS file-system description object
468 * @hmac: The HMAC of the well known message
470 * This function creates a HMAC of a well known message. This is used
471 * to check if the provided key is suitable to authenticate a UBIFS
472 * image. This is only a convenience to the user to provide a better
473 * error message when the wrong key is provided.
475 * This function returns 0 for success or a negative error code otherwise.
477 int ubifs_hmac_wkm(struct ubifs_info
*c
, u8
*hmac
)
479 SHASH_DESC_ON_STACK(shash
, c
->hmac_tfm
);
481 const char well_known_message
[] = "UBIFS";
483 if (!ubifs_authenticated(c
))
486 shash
->tfm
= c
->hmac_tfm
;
487 shash
->flags
= CRYPTO_TFM_REQ_MAY_SLEEP
;
489 err
= crypto_shash_init(shash
);
493 err
= crypto_shash_update(shash
, well_known_message
,
494 sizeof(well_known_message
) - 1);
498 err
= crypto_shash_final(shash
, hmac
);