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