xref: /linux/security/ipe/digest.c (revision a430d95c5efa2b545d26a094eb5f624e36732af0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4  */
5 
6 #include "digest.h"
7 
8 /**
9  * ipe_digest_parse() - parse a digest in IPE's policy.
10  * @valstr: Supplies the string parsed from the policy.
11  *
12  * Digests in IPE are defined in a standard way:
13  *	<alg_name>:<hex>
14  *
15  * Use this function to create a property to parse the digest
16  * consistently. The parsed digest will be saved in @value in IPE's
17  * policy.
18  *
19  * Return: The parsed digest_info structure on success. If an error occurs,
20  * the function will return the error value (via ERR_PTR).
21  */
ipe_digest_parse(const char * valstr)22 struct digest_info *ipe_digest_parse(const char *valstr)
23 {
24 	struct digest_info *info = NULL;
25 	char *sep, *raw_digest;
26 	size_t raw_digest_len;
27 	u8 *digest = NULL;
28 	char *alg = NULL;
29 	int rc = 0;
30 
31 	info = kzalloc(sizeof(*info), GFP_KERNEL);
32 	if (!info)
33 		return ERR_PTR(-ENOMEM);
34 
35 	sep = strchr(valstr, ':');
36 	if (!sep) {
37 		rc = -EBADMSG;
38 		goto err;
39 	}
40 
41 	alg = kstrndup(valstr, sep - valstr, GFP_KERNEL);
42 	if (!alg) {
43 		rc = -ENOMEM;
44 		goto err;
45 	}
46 
47 	raw_digest = sep + 1;
48 	raw_digest_len = strlen(raw_digest);
49 
50 	info->digest_len = (raw_digest_len + 1) / 2;
51 	digest = kzalloc(info->digest_len, GFP_KERNEL);
52 	if (!digest) {
53 		rc = -ENOMEM;
54 		goto err;
55 	}
56 
57 	rc = hex2bin(digest, raw_digest, info->digest_len);
58 	if (rc < 0) {
59 		rc = -EINVAL;
60 		goto err;
61 	}
62 
63 	info->alg = alg;
64 	info->digest = digest;
65 	return info;
66 
67 err:
68 	kfree(alg);
69 	kfree(digest);
70 	kfree(info);
71 	return ERR_PTR(rc);
72 }
73 
74 /**
75  * ipe_digest_eval() - evaluate an IPE digest against another digest.
76  * @expected: Supplies the policy-provided digest value.
77  * @digest: Supplies the digest to compare against the policy digest value.
78  *
79  * Return:
80  * * %true	- digests match
81  * * %false	- digests do not match
82  */
ipe_digest_eval(const struct digest_info * expected,const struct digest_info * digest)83 bool ipe_digest_eval(const struct digest_info *expected,
84 		     const struct digest_info *digest)
85 {
86 	return (expected->digest_len == digest->digest_len) &&
87 	       (!strcmp(expected->alg, digest->alg)) &&
88 	       (!memcmp(expected->digest, digest->digest, expected->digest_len));
89 }
90 
91 /**
92  * ipe_digest_free() - free an IPE digest.
93  * @info: Supplies a pointer the policy-provided digest to free.
94  */
ipe_digest_free(struct digest_info * info)95 void ipe_digest_free(struct digest_info *info)
96 {
97 	if (IS_ERR_OR_NULL(info))
98 		return;
99 
100 	kfree(info->alg);
101 	kfree(info->digest);
102 	kfree(info);
103 }
104 
105 /**
106  * ipe_digest_audit() - audit a digest that was sourced from IPE's policy.
107  * @ab: Supplies the audit_buffer to append the formatted result.
108  * @info: Supplies a pointer to source the audit record from.
109  *
110  * Digests in IPE are audited in this format:
111  *	<alg_name>:<hex>
112  */
ipe_digest_audit(struct audit_buffer * ab,const struct digest_info * info)113 void ipe_digest_audit(struct audit_buffer *ab, const struct digest_info *info)
114 {
115 	audit_log_untrustedstring(ab, info->alg);
116 	audit_log_format(ab, ":");
117 	audit_log_n_hex(ab, info->digest, info->digest_len);
118 }
119