Skip to content

Commit dccfbaf

Browse files
committed
ima: Define asymmetric_verify_v3() to verify IMA sigv3 signatures
Define asymmetric_verify_v3() to calculate the hash of the struct ima_file_id, before calling asymmetric_verify() to verify the signature. Move and update the existing calc_file_id_hash() function with a simpler, self contained version. In addition to the existing hash data and hash data length arguments, also pass the hash algorithm. Suggested-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Stefan Berger <stefanb@linux.ibm.com> Acked-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent 7a60fe4 commit dccfbaf

5 files changed

Lines changed: 90 additions & 56 deletions

File tree

security/integrity/digsig.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static struct key *integrity_keyring_from_id(const unsigned int id)
5959
}
6060

6161
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
62-
const char *digest, int digestlen)
62+
const char *digest, int digestlen, u8 algo)
6363
{
6464
struct key *keyring;
6565

@@ -76,9 +76,11 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
7676
return digsig_verify(keyring, sig + 1, siglen - 1, digest,
7777
digestlen);
7878
case 2: /* regular file data hash based signature */
79-
case 3: /* struct ima_file_id data based signature */
8079
return asymmetric_verify(keyring, sig, siglen, digest,
81-
digestlen);
80+
digestlen);
81+
case 3: /* struct ima_file_id data based signature */
82+
return asymmetric_verify_v3(keyring, sig, siglen, digest,
83+
digestlen, algo);
8284
}
8385

8486
return -EOPNOTSUPP;

security/integrity/digsig_asymmetric.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,61 @@ int asymmetric_verify(struct key *keyring, const char *sig,
131131
pr_debug("%s() = %d\n", __func__, ret);
132132
return ret;
133133
}
134+
135+
/*
136+
* calc_file_id_hash - calculate the hash of the ima_file_id struct data
137+
* @type: xattr type [enum evm_ima_xattr_type]
138+
* @algo: hash algorithm [enum hash_algo]
139+
* @digest: pointer to the digest to be hashed
140+
* @hash: (out) pointer to the hash
141+
*
142+
* IMA signature version 3 disambiguates the data that is signed by
143+
* indirectly signing the hash of the ima_file_id structure data.
144+
*
145+
* Return 0 on success, error code otherwise.
146+
*/
147+
static int calc_file_id_hash(enum evm_ima_xattr_type type,
148+
enum hash_algo algo, const u8 *digest,
149+
struct ima_max_digest_data *hash)
150+
{
151+
struct ima_file_id file_id = {.hash_type = type, .hash_algorithm = algo};
152+
size_t digest_size = hash_digest_size[algo];
153+
struct crypto_shash *tfm;
154+
size_t file_id_size;
155+
int rc;
156+
157+
if (type != IMA_VERITY_DIGSIG)
158+
return -EINVAL;
159+
160+
tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
161+
if (IS_ERR(tfm))
162+
return PTR_ERR(tfm);
163+
164+
memcpy(file_id.hash, digest, digest_size);
165+
166+
/* Calculate the ima_file_id struct hash on the portion used. */
167+
file_id_size = sizeof(file_id) - (HASH_MAX_DIGESTSIZE - digest_size);
168+
169+
hash->hdr.algo = algo;
170+
hash->hdr.length = digest_size;
171+
rc = crypto_shash_tfm_digest(tfm, (const u8 *)&file_id, file_id_size,
172+
hash->digest);
173+
174+
crypto_free_shash(tfm);
175+
return rc;
176+
}
177+
178+
int asymmetric_verify_v3(struct key *keyring, const char *sig, int siglen,
179+
const char *data, int datalen, u8 algo)
180+
{
181+
struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
182+
struct ima_max_digest_data hash;
183+
int rc;
184+
185+
rc = calc_file_id_hash(hdr->type, algo, data, &hash);
186+
if (rc)
187+
return -EINVAL;
188+
189+
return asymmetric_verify(keyring, sig, siglen, hash.digest,
190+
hash.hdr.length);
191+
}

security/integrity/evm/evm_main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
266266
break;
267267
rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
268268
(const char *)xattr_data, xattr_len,
269-
digest.digest, digest.hdr.length);
269+
digest.digest, digest.hdr.length,
270+
digest.hdr.algo);
270271
if (!rc) {
271272
if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
272273
if (iint)

security/integrity/ima/ima_appraise.c

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -234,40 +234,6 @@ int ima_read_xattr(struct dentry *dentry,
234234
return ret;
235235
}
236236

237-
/*
238-
* calc_file_id_hash - calculate the hash of the ima_file_id struct data
239-
* @type: xattr type [enum evm_ima_xattr_type]
240-
* @algo: hash algorithm [enum hash_algo]
241-
* @digest: pointer to the digest to be hashed
242-
* @hash: (out) pointer to the hash
243-
*
244-
* IMA signature version 3 disambiguates the data that is signed by
245-
* indirectly signing the hash of the ima_file_id structure data.
246-
*
247-
* Signing the ima_file_id struct is currently only supported for
248-
* IMA_VERITY_DIGSIG type xattrs.
249-
*
250-
* Return 0 on success, error code otherwise.
251-
*/
252-
static int calc_file_id_hash(enum evm_ima_xattr_type type,
253-
enum hash_algo algo, const u8 *digest,
254-
struct ima_digest_data *hash)
255-
{
256-
struct ima_file_id file_id = {
257-
.hash_type = IMA_VERITY_DIGSIG, .hash_algorithm = algo};
258-
unsigned int unused = HASH_MAX_DIGESTSIZE - hash_digest_size[algo];
259-
260-
if (type != IMA_VERITY_DIGSIG)
261-
return -EINVAL;
262-
263-
memcpy(file_id.hash, digest, hash_digest_size[algo]);
264-
265-
hash->algo = algo;
266-
hash->length = hash_digest_size[algo];
267-
268-
return ima_calc_buffer_hash(&file_id, sizeof(file_id) - unused, hash);
269-
}
270-
271237
/*
272238
* xattr_verify - verify xattr digest or signature
273239
*
@@ -279,7 +245,6 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
279245
struct evm_ima_xattr_data *xattr_value, int xattr_len,
280246
enum integrity_status *status, const char **cause)
281247
{
282-
struct ima_max_digest_data hash;
283248
struct signature_v2_hdr *sig;
284249
int rc = -EINVAL, hash_start = 0;
285250
int mask;
@@ -341,7 +306,8 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
341306
(const char *)xattr_value,
342307
xattr_len,
343308
iint->ima_hash->digest,
344-
iint->ima_hash->length);
309+
iint->ima_hash->length,
310+
iint->ima_hash->algo);
345311
if (rc == -EOPNOTSUPP) {
346312
*status = INTEGRITY_UNKNOWN;
347313
break;
@@ -352,7 +318,9 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
352318
(const char *)xattr_value,
353319
xattr_len,
354320
iint->ima_hash->digest,
355-
iint->ima_hash->length);
321+
iint->ima_hash->length,
322+
iint->ima_hash->algo);
323+
356324
if (rc) {
357325
*cause = "invalid-signature";
358326
*status = INTEGRITY_FAIL;
@@ -378,21 +346,16 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
378346
break;
379347
}
380348

381-
rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo,
382-
iint->ima_hash->digest,
383-
container_of(&hash.hdr,
384-
struct ima_digest_data, hdr));
385-
if (rc) {
386-
*cause = "sigv3-hashing-error";
387-
*status = INTEGRITY_FAIL;
388-
break;
389-
}
390-
391349
rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
392350
(const char *)xattr_value,
393-
xattr_len, hash.digest,
394-
hash.hdr.length);
395-
if (rc) {
351+
xattr_len,
352+
iint->ima_hash->digest,
353+
iint->ima_hash->length,
354+
iint->ima_hash->algo);
355+
if (rc == -EOPNOTSUPP) {
356+
*status = INTEGRITY_UNKNOWN;
357+
break;
358+
} else if (rc) {
396359
*cause = "invalid-verity-signature";
397360
*status = INTEGRITY_FAIL;
398361
} else {

security/integrity/integrity.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ struct modsig;
131131
#ifdef CONFIG_INTEGRITY_SIGNATURE
132132

133133
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
134-
const char *digest, int digestlen);
134+
const char *digest, int digestlen, u8 algo);
135135
int integrity_modsig_verify(unsigned int id, const struct modsig *modsig);
136136

137137
int __init integrity_init_keyring(const unsigned int id);
@@ -142,7 +142,8 @@ int __init integrity_load_cert(const unsigned int id, const char *source,
142142

143143
static inline int integrity_digsig_verify(const unsigned int id,
144144
const char *sig, int siglen,
145-
const char *digest, int digestlen)
145+
const char *digest, int digestlen,
146+
u8 algo)
146147
{
147148
return -EOPNOTSUPP;
148149
}
@@ -170,12 +171,21 @@ static inline int __init integrity_load_cert(const unsigned int id,
170171
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
171172
int asymmetric_verify(struct key *keyring, const char *sig,
172173
int siglen, const char *data, int datalen);
174+
int asymmetric_verify_v3(struct key *keyring, const char *sig,
175+
int siglen, const char *data, int datalen, u8 algo);
173176
#else
174177
static inline int asymmetric_verify(struct key *keyring, const char *sig,
175178
int siglen, const char *data, int datalen)
176179
{
177180
return -EOPNOTSUPP;
178181
}
182+
183+
static inline int asymmetric_verify_v3(struct key *keyring,
184+
const char *sig, int siglen,
185+
const char *data, int datalen, u8 algo)
186+
{
187+
return -EOPNOTSUPP;
188+
}
179189
#endif
180190

181191
#ifdef CONFIG_IMA_APPRAISE_MODSIG

0 commit comments

Comments
 (0)