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