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 */
ipe_digest_parse(const char * valstr)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_obj(*info);
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 */
ipe_digest_eval(const struct digest_info * expected,const struct digest_info * digest)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 */
ipe_digest_free(struct digest_info * info)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 */
ipe_digest_audit(struct audit_buffer * ab,const struct digest_info * info)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