Line data Source code
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_err.h"
13 : #include "ubifs.h"
14 : #include "sign.h"
15 : #include "defs.h"
16 :
17 5669 : int ubifs_shash_init(const struct ubifs_info *c,
18 : __unused struct shash_desc *desc)
19 : {
20 19781 : if (ubifs_authenticated(c))
21 0 : return hash_digest_init();
22 : else
23 : return 0;
24 : }
25 :
26 101568 : int ubifs_shash_update(const struct ubifs_info *c,
27 : __unused struct shash_desc *desc,
28 : const void *buf, unsigned int len)
29 : {
30 101568 : int err = 0;
31 :
32 101568 : if (ubifs_authenticated(c)) {
33 0 : err = hash_digest_update(buf, len);
34 0 : if (err < 0)
35 : return err;
36 : }
37 :
38 : return 0;
39 : }
40 :
41 810 : int ubifs_shash_final(const struct ubifs_info *c,
42 : __unused struct shash_desc *desc, u8 *out)
43 : {
44 810 : return ubifs_authenticated(c) ? hash_digest_final(out) : 0;
45 : }
46 :
47 14112 : struct shash_desc *ubifs_hash_get_desc(const struct ubifs_info *c)
48 : {
49 : int err;
50 :
51 0 : err = ubifs_shash_init(c, NULL);
52 0 : if (err)
53 0 : return ERR_PTR(err);
54 :
55 : return NULL;
56 : }
57 :
58 : /**
59 : * ubifs_node_calc_hash - calculate the hash of a UBIFS node
60 : * @c: UBIFS file-system description object
61 : * @node: the node to calculate a hash for
62 : * @hash: the returned hash
63 : *
64 : * Returns 0 for success or a negative error code otherwise.
65 : */
66 0 : int __ubifs_node_calc_hash(__unused const struct ubifs_info *c,
67 : const void *node, u8 *hash)
68 : {
69 0 : const struct ubifs_ch *ch = node;
70 :
71 0 : return hash_digest(node, le32_to_cpu(ch->len), hash);
72 : }
73 :
74 : /**
75 : * ubifs_master_node_calc_hash - calculate the hash of a UBIFS master node
76 : * @node: the node to calculate a hash for
77 : * @hash: the returned hash
78 : */
79 640 : int ubifs_master_node_calc_hash(const struct ubifs_info *c, const void *node,
80 : uint8_t *hash)
81 : {
82 640 : if (!ubifs_authenticated(c))
83 : return 0;
84 :
85 0 : return hash_digest(node + sizeof(struct ubifs_ch),
86 : UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch), hash);
87 : }
88 :
89 640 : int ubifs_sign_superblock_node(struct ubifs_info *c, void *node)
90 : {
91 : int err, len;
92 640 : struct ubifs_sig_node *sig = node + UBIFS_SB_NODE_SZ;
93 :
94 640 : if (!ubifs_authenticated(c))
95 : return 0;
96 :
97 0 : err = hash_sign_node(c->auth_key_filename, c->auth_cert_filename, node,
98 0 : &len, sig + 1);
99 0 : if (err)
100 : return err;
101 :
102 0 : sig->type = UBIFS_SIGNATURE_TYPE_PKCS7;
103 0 : sig->len = cpu_to_le32(len);
104 0 : sig->ch.node_type = UBIFS_SIG_NODE;
105 :
106 0 : return 0;
107 : }
108 :
109 : /**
110 : * ubifs_bad_hash - Report hash mismatches
111 : * @c: UBIFS file-system description object
112 : * @node: the node
113 : * @hash: the expected hash
114 : * @lnum: the LEB @node was read from
115 : * @offs: offset in LEB @node was read from
116 : *
117 : * This function reports a hash mismatch when a node has a different hash than
118 : * expected.
119 : */
120 0 : void ubifs_bad_hash(const struct ubifs_info *c, const void *node, const u8 *hash,
121 : int lnum, int offs)
122 : {
123 0 : int len = min(c->hash_len, 20);
124 0 : int cropped = len != c->hash_len;
125 0 : const char *cont = cropped ? "..." : "";
126 :
127 : u8 calc[UBIFS_HASH_ARR_SZ];
128 :
129 0 : __ubifs_node_calc_hash(c, node, calc);
130 :
131 0 : ubifs_err(c, "hash mismatch on node at LEB %d:%d", lnum, offs);
132 0 : ubifs_err(c, "hash expected: %*ph%s", len, hash, cont);
133 0 : ubifs_err(c, "hash calculated: %*ph%s", len, calc, cont);
134 0 : }
135 :
136 : /**
137 : * ubifs_init_authentication - initialize UBIFS authentication support
138 : * @c: UBIFS file-system description object
139 : *
140 : * This function returns 0 for success or a negative error code otherwise.
141 : */
142 640 : int ubifs_init_authentication(struct ubifs_info *c)
143 : {
144 : int err, hash_len, hash_algo;
145 :
146 640 : if (!c->auth_key_filename && !c->auth_cert_filename && !c->hash_algo_name)
147 : return 0;
148 :
149 0 : if (!c->auth_key_filename) {
150 0 : ubifs_err(c, "authentication key not given (--auth-key)");
151 : return -EINVAL;
152 : }
153 :
154 0 : if (!c->hash_algo_name) {
155 0 : ubifs_err(c, "Hash algorithm not given (--hash-algo)");
156 : return -EINVAL;
157 : }
158 :
159 0 : err = init_authentication(c->hash_algo_name, &hash_len, &hash_algo);
160 0 : if (err) {
161 0 : ubifs_err(c, "Init authentication failed");
162 : return err;
163 : }
164 :
165 0 : c->hash_len = hash_len;
166 0 : c->hash_algo = hash_algo;
167 0 : c->authenticated = 1;
168 :
169 0 : return 0;
170 : }
171 :
172 0 : void __ubifs_exit_authentication(__unused struct ubifs_info *c)
173 : {
174 0 : exit_authentication();
175 0 : }
|