xref: /linux/security/integrity/ima/ima_template_lib.c (revision 6cc7c266e5b47d3cd2b5bb7fd3aac4e6bb2dd1d2)
1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23ce1217dSRoberto Sassu /*
33ce1217dSRoberto Sassu  * Copyright (C) 2013 Politecnico di Torino, Italy
43ce1217dSRoberto Sassu  *                    TORSEC group -- http://security.polito.it
53ce1217dSRoberto Sassu  *
63ce1217dSRoberto Sassu  * Author: Roberto Sassu <roberto.sassu@polito.it>
73ce1217dSRoberto Sassu  *
83ce1217dSRoberto Sassu  * File: ima_template_lib.c
93ce1217dSRoberto Sassu  *      Library of supported template fields.
103ce1217dSRoberto Sassu  */
114d7aeee7SRoberto Sassu 
123ce1217dSRoberto Sassu #include "ima_template_lib.h"
133ce1217dSRoberto Sassu 
144d7aeee7SRoberto Sassu static bool ima_template_hash_algo_allowed(u8 algo)
154d7aeee7SRoberto Sassu {
164d7aeee7SRoberto Sassu 	if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5)
174d7aeee7SRoberto Sassu 		return true;
184d7aeee7SRoberto Sassu 
194d7aeee7SRoberto Sassu 	return false;
204d7aeee7SRoberto Sassu }
214d7aeee7SRoberto Sassu 
224d7aeee7SRoberto Sassu enum data_formats {
234d7aeee7SRoberto Sassu 	DATA_FMT_DIGEST = 0,
244d7aeee7SRoberto Sassu 	DATA_FMT_DIGEST_WITH_ALGO,
25bcbc9b0cSMimi Zohar 	DATA_FMT_STRING,
26bcbc9b0cSMimi Zohar 	DATA_FMT_HEX
274d7aeee7SRoberto Sassu };
284d7aeee7SRoberto Sassu 
293ce1217dSRoberto Sassu static int ima_write_template_field_data(const void *data, const u32 datalen,
303ce1217dSRoberto Sassu 					 enum data_formats datafmt,
313ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
323ce1217dSRoberto Sassu {
333ce1217dSRoberto Sassu 	u8 *buf, *buf_ptr;
34e3b64c26SRoberto Sassu 	u32 buflen = datalen;
353ce1217dSRoberto Sassu 
36e3b64c26SRoberto Sassu 	if (datafmt == DATA_FMT_STRING)
373ce1217dSRoberto Sassu 		buflen = datalen + 1;
383ce1217dSRoberto Sassu 
393ce1217dSRoberto Sassu 	buf = kzalloc(buflen, GFP_KERNEL);
403ce1217dSRoberto Sassu 	if (!buf)
413ce1217dSRoberto Sassu 		return -ENOMEM;
423ce1217dSRoberto Sassu 
433ce1217dSRoberto Sassu 	memcpy(buf, data, datalen);
443ce1217dSRoberto Sassu 
453ce1217dSRoberto Sassu 	/*
463ce1217dSRoberto Sassu 	 * Replace all space characters with underscore for event names and
473ce1217dSRoberto Sassu 	 * strings. This avoid that, during the parsing of a measurements list,
483ce1217dSRoberto Sassu 	 * filenames with spaces or that end with the suffix ' (deleted)' are
493ce1217dSRoberto Sassu 	 * split into multiple template fields (the space is the delimitator
503ce1217dSRoberto Sassu 	 * character for measurements lists in ASCII format).
513ce1217dSRoberto Sassu 	 */
52e3b64c26SRoberto Sassu 	if (datafmt == DATA_FMT_STRING) {
533ce1217dSRoberto Sassu 		for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
543ce1217dSRoberto Sassu 			if (*buf_ptr == ' ')
553ce1217dSRoberto Sassu 				*buf_ptr = '_';
563ce1217dSRoberto Sassu 	}
573ce1217dSRoberto Sassu 
583ce1217dSRoberto Sassu 	field_data->data = buf;
593ce1217dSRoberto Sassu 	field_data->len = buflen;
603ce1217dSRoberto Sassu 	return 0;
613ce1217dSRoberto Sassu }
623ce1217dSRoberto Sassu 
633ce1217dSRoberto Sassu static void ima_show_template_data_ascii(struct seq_file *m,
643ce1217dSRoberto Sassu 					 enum ima_show_type show,
653ce1217dSRoberto Sassu 					 enum data_formats datafmt,
663ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
673ce1217dSRoberto Sassu {
6845b26133SMimi Zohar 	u8 *buf_ptr = field_data->data;
6945b26133SMimi Zohar 	u32 buflen = field_data->len;
704d7aeee7SRoberto Sassu 
713ce1217dSRoberto Sassu 	switch (datafmt) {
724d7aeee7SRoberto Sassu 	case DATA_FMT_DIGEST_WITH_ALGO:
734d7aeee7SRoberto Sassu 		buf_ptr = strnchr(field_data->data, buflen, ':');
744d7aeee7SRoberto Sassu 		if (buf_ptr != field_data->data)
754d7aeee7SRoberto Sassu 			seq_printf(m, "%s", field_data->data);
764d7aeee7SRoberto Sassu 
774d7aeee7SRoberto Sassu 		/* skip ':' and '\0' */
784d7aeee7SRoberto Sassu 		buf_ptr += 2;
794d7aeee7SRoberto Sassu 		buflen -= buf_ptr - field_data->data;
8009186e50SGustavo A. R. Silva 		/* fall through */
813ce1217dSRoberto Sassu 	case DATA_FMT_DIGEST:
82bcbc9b0cSMimi Zohar 	case DATA_FMT_HEX:
83bcbc9b0cSMimi Zohar 		if (!buflen)
84bcbc9b0cSMimi Zohar 			break;
854d7aeee7SRoberto Sassu 		ima_print_digest(m, buf_ptr, buflen);
863ce1217dSRoberto Sassu 		break;
873ce1217dSRoberto Sassu 	case DATA_FMT_STRING:
884d7aeee7SRoberto Sassu 		seq_printf(m, "%s", buf_ptr);
893ce1217dSRoberto Sassu 		break;
903ce1217dSRoberto Sassu 	default:
913ce1217dSRoberto Sassu 		break;
923ce1217dSRoberto Sassu 	}
933ce1217dSRoberto Sassu }
943ce1217dSRoberto Sassu 
953ce1217dSRoberto Sassu static void ima_show_template_data_binary(struct seq_file *m,
963ce1217dSRoberto Sassu 					  enum ima_show_type show,
973ce1217dSRoberto Sassu 					  enum data_formats datafmt,
983ce1217dSRoberto Sassu 					  struct ima_field_data *field_data)
993ce1217dSRoberto Sassu {
100c019e307SRoberto Sassu 	u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
101c019e307SRoberto Sassu 	    strlen(field_data->data) : field_data->len;
1023e8e5503SRoberto Sassu 
103d68a6fe9SMimi Zohar 	if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) {
104d68a6fe9SMimi Zohar 		u32 field_len = !ima_canonical_fmt ? len : cpu_to_le32(len);
105d68a6fe9SMimi Zohar 
106d68a6fe9SMimi Zohar 		ima_putc(m, &field_len, sizeof(field_len));
107d68a6fe9SMimi Zohar 	}
108c019e307SRoberto Sassu 
109c019e307SRoberto Sassu 	if (!len)
1103ce1217dSRoberto Sassu 		return;
1113e8e5503SRoberto Sassu 
112c019e307SRoberto Sassu 	ima_putc(m, field_data->data, len);
1133ce1217dSRoberto Sassu }
1143ce1217dSRoberto Sassu 
1153ce1217dSRoberto Sassu static void ima_show_template_field_data(struct seq_file *m,
1163ce1217dSRoberto Sassu 					 enum ima_show_type show,
1173ce1217dSRoberto Sassu 					 enum data_formats datafmt,
1183ce1217dSRoberto Sassu 					 struct ima_field_data *field_data)
1193ce1217dSRoberto Sassu {
1203ce1217dSRoberto Sassu 	switch (show) {
1213ce1217dSRoberto Sassu 	case IMA_SHOW_ASCII:
1223ce1217dSRoberto Sassu 		ima_show_template_data_ascii(m, show, datafmt, field_data);
1233ce1217dSRoberto Sassu 		break;
1243ce1217dSRoberto Sassu 	case IMA_SHOW_BINARY:
1253e8e5503SRoberto Sassu 	case IMA_SHOW_BINARY_NO_FIELD_LEN:
126c019e307SRoberto Sassu 	case IMA_SHOW_BINARY_OLD_STRING_FMT:
1273ce1217dSRoberto Sassu 		ima_show_template_data_binary(m, show, datafmt, field_data);
1283ce1217dSRoberto Sassu 		break;
1293ce1217dSRoberto Sassu 	default:
1303ce1217dSRoberto Sassu 		break;
1313ce1217dSRoberto Sassu 	}
1323ce1217dSRoberto Sassu }
1333ce1217dSRoberto Sassu 
1343ce1217dSRoberto Sassu void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
1353ce1217dSRoberto Sassu 			      struct ima_field_data *field_data)
1363ce1217dSRoberto Sassu {
1373ce1217dSRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
1383ce1217dSRoberto Sassu }
1393ce1217dSRoberto Sassu 
1404d7aeee7SRoberto Sassu void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
1414d7aeee7SRoberto Sassu 				 struct ima_field_data *field_data)
1424d7aeee7SRoberto Sassu {
1434d7aeee7SRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO,
1444d7aeee7SRoberto Sassu 				     field_data);
1454d7aeee7SRoberto Sassu }
1464d7aeee7SRoberto Sassu 
1473ce1217dSRoberto Sassu void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
1483ce1217dSRoberto Sassu 			      struct ima_field_data *field_data)
1493ce1217dSRoberto Sassu {
1503ce1217dSRoberto Sassu 	ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
1513ce1217dSRoberto Sassu }
1523ce1217dSRoberto Sassu 
153bcbc9b0cSMimi Zohar void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
154bcbc9b0cSMimi Zohar 			   struct ima_field_data *field_data)
155bcbc9b0cSMimi Zohar {
156bcbc9b0cSMimi Zohar 	ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
157bcbc9b0cSMimi Zohar }
158bcbc9b0cSMimi Zohar 
15986b4da8cSPrakhar Srivastava void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
16086b4da8cSPrakhar Srivastava 			   struct ima_field_data *field_data)
16186b4da8cSPrakhar Srivastava {
16286b4da8cSPrakhar Srivastava 	ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
16386b4da8cSPrakhar Srivastava }
16486b4da8cSPrakhar Srivastava 
165b17fd9ecSRoberto Sassu /**
166b17fd9ecSRoberto Sassu  * ima_parse_buf() - Parses lengths and data from an input buffer
167b17fd9ecSRoberto Sassu  * @bufstartp:       Buffer start address.
168b17fd9ecSRoberto Sassu  * @bufendp:         Buffer end address.
169b17fd9ecSRoberto Sassu  * @bufcurp:         Pointer to remaining (non-parsed) data.
170b17fd9ecSRoberto Sassu  * @maxfields:       Length of fields array.
171b17fd9ecSRoberto Sassu  * @fields:          Array containing lengths and pointers of parsed data.
172b17fd9ecSRoberto Sassu  * @curfields:       Number of array items containing parsed data.
173b17fd9ecSRoberto Sassu  * @len_mask:        Bitmap (if bit is set, data length should not be parsed).
174b17fd9ecSRoberto Sassu  * @enforce_mask:    Check if curfields == maxfields and/or bufcurp == bufendp.
175b17fd9ecSRoberto Sassu  * @bufname:         String identifier of the input buffer.
176b17fd9ecSRoberto Sassu  *
177b17fd9ecSRoberto Sassu  * Return: 0 on success, -EINVAL on error.
178b17fd9ecSRoberto Sassu  */
179b17fd9ecSRoberto Sassu int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
180b17fd9ecSRoberto Sassu 		  int maxfields, struct ima_field_data *fields, int *curfields,
181b17fd9ecSRoberto Sassu 		  unsigned long *len_mask, int enforce_mask, char *bufname)
182b17fd9ecSRoberto Sassu {
183b17fd9ecSRoberto Sassu 	void *bufp = bufstartp;
184b17fd9ecSRoberto Sassu 	int i;
185b17fd9ecSRoberto Sassu 
186b17fd9ecSRoberto Sassu 	for (i = 0; i < maxfields; i++) {
187b17fd9ecSRoberto Sassu 		if (len_mask == NULL || !test_bit(i, len_mask)) {
188b17fd9ecSRoberto Sassu 			if (bufp > (bufendp - sizeof(u32)))
189b17fd9ecSRoberto Sassu 				break;
190b17fd9ecSRoberto Sassu 
191b17fd9ecSRoberto Sassu 			fields[i].len = *(u32 *)bufp;
192b17fd9ecSRoberto Sassu 			if (ima_canonical_fmt)
193b17fd9ecSRoberto Sassu 				fields[i].len = le32_to_cpu(fields[i].len);
194b17fd9ecSRoberto Sassu 
195b17fd9ecSRoberto Sassu 			bufp += sizeof(u32);
196b17fd9ecSRoberto Sassu 		}
197b17fd9ecSRoberto Sassu 
198b17fd9ecSRoberto Sassu 		if (bufp > (bufendp - fields[i].len))
199b17fd9ecSRoberto Sassu 			break;
200b17fd9ecSRoberto Sassu 
201b17fd9ecSRoberto Sassu 		fields[i].data = bufp;
202b17fd9ecSRoberto Sassu 		bufp += fields[i].len;
203b17fd9ecSRoberto Sassu 	}
204b17fd9ecSRoberto Sassu 
205b17fd9ecSRoberto Sassu 	if ((enforce_mask & ENFORCE_FIELDS) && i != maxfields) {
206b17fd9ecSRoberto Sassu 		pr_err("%s: nr of fields mismatch: expected: %d, current: %d\n",
207b17fd9ecSRoberto Sassu 		       bufname, maxfields, i);
208b17fd9ecSRoberto Sassu 		return -EINVAL;
209b17fd9ecSRoberto Sassu 	}
210b17fd9ecSRoberto Sassu 
211b17fd9ecSRoberto Sassu 	if ((enforce_mask & ENFORCE_BUFEND) && bufp != bufendp) {
212b17fd9ecSRoberto Sassu 		pr_err("%s: buf end mismatch: expected: %p, current: %p\n",
213b17fd9ecSRoberto Sassu 		       bufname, bufendp, bufp);
214b17fd9ecSRoberto Sassu 		return -EINVAL;
215b17fd9ecSRoberto Sassu 	}
216b17fd9ecSRoberto Sassu 
217b17fd9ecSRoberto Sassu 	if (curfields)
218b17fd9ecSRoberto Sassu 		*curfields = i;
219b17fd9ecSRoberto Sassu 
220b17fd9ecSRoberto Sassu 	if (bufcurp)
221b17fd9ecSRoberto Sassu 		*bufcurp = bufp;
222b17fd9ecSRoberto Sassu 
223b17fd9ecSRoberto Sassu 	return 0;
224b17fd9ecSRoberto Sassu }
225b17fd9ecSRoberto Sassu 
2263878d505SThiago Jung Bauermann static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
2273878d505SThiago Jung Bauermann 				       u8 hash_algo,
228dcf4e392SRoberto Sassu 				       struct ima_field_data *field_data)
2294d7aeee7SRoberto Sassu {
2303ce1217dSRoberto Sassu 	/*
2314d7aeee7SRoberto Sassu 	 * digest formats:
2324d7aeee7SRoberto Sassu 	 *  - DATA_FMT_DIGEST: digest
2334d7aeee7SRoberto Sassu 	 *  - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest,
2344d7aeee7SRoberto Sassu 	 *    where <hash algo> is provided if the hash algoritm is not
2354d7aeee7SRoberto Sassu 	 *    SHA1 or MD5
2364d7aeee7SRoberto Sassu 	 */
2374d7aeee7SRoberto Sassu 	u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
2384d7aeee7SRoberto Sassu 	enum data_formats fmt = DATA_FMT_DIGEST;
2394d7aeee7SRoberto Sassu 	u32 offset = 0;
2404d7aeee7SRoberto Sassu 
241dcf4e392SRoberto Sassu 	if (hash_algo < HASH_ALGO__LAST) {
2424d7aeee7SRoberto Sassu 		fmt = DATA_FMT_DIGEST_WITH_ALGO;
243dcf4e392SRoberto Sassu 		offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s",
244dcf4e392SRoberto Sassu 				   hash_algo_name[hash_algo]);
2454d7aeee7SRoberto Sassu 		buffer[offset] = ':';
2464d7aeee7SRoberto Sassu 		offset += 2;
2474d7aeee7SRoberto Sassu 	}
2484d7aeee7SRoberto Sassu 
2494d7aeee7SRoberto Sassu 	if (digest)
2504d7aeee7SRoberto Sassu 		memcpy(buffer + offset, digest, digestsize);
2514d7aeee7SRoberto Sassu 	else
2524d7aeee7SRoberto Sassu 		/*
2534d7aeee7SRoberto Sassu 		 * If digest is NULL, the event being recorded is a violation.
2544d7aeee7SRoberto Sassu 		 * Make room for the digest by increasing the offset of
2554d7aeee7SRoberto Sassu 		 * IMA_DIGEST_SIZE.
2564d7aeee7SRoberto Sassu 		 */
2574d7aeee7SRoberto Sassu 		offset += IMA_DIGEST_SIZE;
2584d7aeee7SRoberto Sassu 
2594d7aeee7SRoberto Sassu 	return ima_write_template_field_data(buffer, offset + digestsize,
2604d7aeee7SRoberto Sassu 					     fmt, field_data);
2614d7aeee7SRoberto Sassu }
2624d7aeee7SRoberto Sassu 
2634d7aeee7SRoberto Sassu /*
2644d7aeee7SRoberto Sassu  * This function writes the digest of an event (with size limit).
2653ce1217dSRoberto Sassu  */
26623b57419SRoberto Sassu int ima_eventdigest_init(struct ima_event_data *event_data,
2673ce1217dSRoberto Sassu 			 struct ima_field_data *field_data)
2683ce1217dSRoberto Sassu {
2693ce1217dSRoberto Sassu 	struct {
2703ce1217dSRoberto Sassu 		struct ima_digest_data hdr;
2713ce1217dSRoberto Sassu 		char digest[IMA_MAX_DIGEST_SIZE];
2723ce1217dSRoberto Sassu 	} hash;
2734d7aeee7SRoberto Sassu 	u8 *cur_digest = NULL;
2744d7aeee7SRoberto Sassu 	u32 cur_digestsize = 0;
2753ce1217dSRoberto Sassu 	struct inode *inode;
2763ce1217dSRoberto Sassu 	int result;
2773ce1217dSRoberto Sassu 
2783ce1217dSRoberto Sassu 	memset(&hash, 0, sizeof(hash));
2793ce1217dSRoberto Sassu 
2808d94eb9bSRoberto Sassu 	if (event_data->violation)	/* recording a violation. */
2813ce1217dSRoberto Sassu 		goto out;
2823ce1217dSRoberto Sassu 
28323b57419SRoberto Sassu 	if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
28423b57419SRoberto Sassu 		cur_digest = event_data->iint->ima_hash->digest;
28523b57419SRoberto Sassu 		cur_digestsize = event_data->iint->ima_hash->length;
2863ce1217dSRoberto Sassu 		goto out;
2873ce1217dSRoberto Sassu 	}
2883ce1217dSRoberto Sassu 
289*6cc7c266SRoberto Sassu 	if ((const char *)event_data->filename == boot_aggregate_name) {
290*6cc7c266SRoberto Sassu 		if (ima_tpm_chip) {
291*6cc7c266SRoberto Sassu 			hash.hdr.algo = HASH_ALGO_SHA1;
292*6cc7c266SRoberto Sassu 			result = ima_calc_boot_aggregate(&hash.hdr);
293*6cc7c266SRoberto Sassu 
294*6cc7c266SRoberto Sassu 			/* algo can change depending on available PCR banks */
295*6cc7c266SRoberto Sassu 			if (!result && hash.hdr.algo != HASH_ALGO_SHA1)
296*6cc7c266SRoberto Sassu 				result = -EINVAL;
297*6cc7c266SRoberto Sassu 
298*6cc7c266SRoberto Sassu 			if (result < 0)
299*6cc7c266SRoberto Sassu 				memset(&hash, 0, sizeof(hash));
300*6cc7c266SRoberto Sassu 		}
301*6cc7c266SRoberto Sassu 
302*6cc7c266SRoberto Sassu 		cur_digest = hash.hdr.digest;
303*6cc7c266SRoberto Sassu 		cur_digestsize = hash_digest_size[HASH_ALGO_SHA1];
304*6cc7c266SRoberto Sassu 		goto out;
305*6cc7c266SRoberto Sassu 	}
306*6cc7c266SRoberto Sassu 
30723b57419SRoberto Sassu 	if (!event_data->file)	/* missing info to re-calculate the digest */
3083ce1217dSRoberto Sassu 		return -EINVAL;
3093ce1217dSRoberto Sassu 
31023b57419SRoberto Sassu 	inode = file_inode(event_data->file);
3114d7aeee7SRoberto Sassu 	hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
3124d7aeee7SRoberto Sassu 	    ima_hash_algo : HASH_ALGO_SHA1;
31323b57419SRoberto Sassu 	result = ima_calc_file_hash(event_data->file, &hash.hdr);
3143ce1217dSRoberto Sassu 	if (result) {
3153ce1217dSRoberto Sassu 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
31623b57419SRoberto Sassu 				    event_data->filename, "collect_data",
3173ce1217dSRoberto Sassu 				    "failed", result, 0);
3183ce1217dSRoberto Sassu 		return result;
3193ce1217dSRoberto Sassu 	}
3204d7aeee7SRoberto Sassu 	cur_digest = hash.hdr.digest;
3214d7aeee7SRoberto Sassu 	cur_digestsize = hash.hdr.length;
3223ce1217dSRoberto Sassu out:
323712a49bdSRoberto Sassu 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
324dcf4e392SRoberto Sassu 					   HASH_ALGO__LAST, field_data);
3253ce1217dSRoberto Sassu }
3263ce1217dSRoberto Sassu 
3273ce1217dSRoberto Sassu /*
3284d7aeee7SRoberto Sassu  * This function writes the digest of an event (without size limit).
3293ce1217dSRoberto Sassu  */
33023b57419SRoberto Sassu int ima_eventdigest_ng_init(struct ima_event_data *event_data,
33123b57419SRoberto Sassu 			    struct ima_field_data *field_data)
3323ce1217dSRoberto Sassu {
333c502c78bSRoberto Sassu 	u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1;
3344d7aeee7SRoberto Sassu 	u32 cur_digestsize = 0;
3354d7aeee7SRoberto Sassu 
3368d94eb9bSRoberto Sassu 	if (event_data->violation)	/* recording a violation. */
3374d7aeee7SRoberto Sassu 		goto out;
3384d7aeee7SRoberto Sassu 
33923b57419SRoberto Sassu 	cur_digest = event_data->iint->ima_hash->digest;
34023b57419SRoberto Sassu 	cur_digestsize = event_data->iint->ima_hash->length;
3414d7aeee7SRoberto Sassu 
34223b57419SRoberto Sassu 	hash_algo = event_data->iint->ima_hash->algo;
3434d7aeee7SRoberto Sassu out:
3444d7aeee7SRoberto Sassu 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
345dcf4e392SRoberto Sassu 					   hash_algo, field_data);
3464d7aeee7SRoberto Sassu }
3474d7aeee7SRoberto Sassu 
3483878d505SThiago Jung Bauermann /*
3493878d505SThiago Jung Bauermann  * This function writes the digest of the file which is expected to match the
3503878d505SThiago Jung Bauermann  * digest contained in the file's appended signature.
3513878d505SThiago Jung Bauermann  */
3523878d505SThiago Jung Bauermann int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
3533878d505SThiago Jung Bauermann 				struct ima_field_data *field_data)
3543878d505SThiago Jung Bauermann {
3553878d505SThiago Jung Bauermann 	enum hash_algo hash_algo;
3563878d505SThiago Jung Bauermann 	const u8 *cur_digest;
3573878d505SThiago Jung Bauermann 	u32 cur_digestsize;
3583878d505SThiago Jung Bauermann 
3593878d505SThiago Jung Bauermann 	if (!event_data->modsig)
3603878d505SThiago Jung Bauermann 		return 0;
3613878d505SThiago Jung Bauermann 
3623878d505SThiago Jung Bauermann 	if (event_data->violation) {
3633878d505SThiago Jung Bauermann 		/* Recording a violation. */
3643878d505SThiago Jung Bauermann 		hash_algo = HASH_ALGO_SHA1;
3653878d505SThiago Jung Bauermann 		cur_digest = NULL;
3663878d505SThiago Jung Bauermann 		cur_digestsize = 0;
3673878d505SThiago Jung Bauermann 	} else {
3683878d505SThiago Jung Bauermann 		int rc;
3693878d505SThiago Jung Bauermann 
3703878d505SThiago Jung Bauermann 		rc = ima_get_modsig_digest(event_data->modsig, &hash_algo,
3713878d505SThiago Jung Bauermann 					   &cur_digest, &cur_digestsize);
3723878d505SThiago Jung Bauermann 		if (rc)
3733878d505SThiago Jung Bauermann 			return rc;
3743878d505SThiago Jung Bauermann 		else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
3753878d505SThiago Jung Bauermann 			/* There was some error collecting the digest. */
3763878d505SThiago Jung Bauermann 			return -EINVAL;
3773878d505SThiago Jung Bauermann 	}
3783878d505SThiago Jung Bauermann 
3793878d505SThiago Jung Bauermann 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
3803878d505SThiago Jung Bauermann 					   hash_algo, field_data);
3813878d505SThiago Jung Bauermann }
3823878d505SThiago Jung Bauermann 
38323b57419SRoberto Sassu static int ima_eventname_init_common(struct ima_event_data *event_data,
3844d7aeee7SRoberto Sassu 				     struct ima_field_data *field_data,
3854d7aeee7SRoberto Sassu 				     bool size_limit)
3864d7aeee7SRoberto Sassu {
3873ce1217dSRoberto Sassu 	const char *cur_filename = NULL;
3883ce1217dSRoberto Sassu 	u32 cur_filename_len = 0;
3893ce1217dSRoberto Sassu 
39023b57419SRoberto Sassu 	BUG_ON(event_data->filename == NULL && event_data->file == NULL);
3913ce1217dSRoberto Sassu 
39223b57419SRoberto Sassu 	if (event_data->filename) {
39323b57419SRoberto Sassu 		cur_filename = event_data->filename;
39423b57419SRoberto Sassu 		cur_filename_len = strlen(event_data->filename);
3953ce1217dSRoberto Sassu 
3964d7aeee7SRoberto Sassu 		if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
3973ce1217dSRoberto Sassu 			goto out;
3983ce1217dSRoberto Sassu 	}
3993ce1217dSRoberto Sassu 
40023b57419SRoberto Sassu 	if (event_data->file) {
40123b57419SRoberto Sassu 		cur_filename = event_data->file->f_path.dentry->d_name.name;
4023ce1217dSRoberto Sassu 		cur_filename_len = strlen(cur_filename);
4033ce1217dSRoberto Sassu 	} else
4043ce1217dSRoberto Sassu 		/*
4053ce1217dSRoberto Sassu 		 * Truncate filename if the latter is too long and
4063ce1217dSRoberto Sassu 		 * the file descriptor is not available.
4073ce1217dSRoberto Sassu 		 */
4083ce1217dSRoberto Sassu 		cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
4093ce1217dSRoberto Sassu out:
4103ce1217dSRoberto Sassu 	return ima_write_template_field_data(cur_filename, cur_filename_len,
411e3b64c26SRoberto Sassu 					     DATA_FMT_STRING, field_data);
4124d7aeee7SRoberto Sassu }
4134d7aeee7SRoberto Sassu 
4144d7aeee7SRoberto Sassu /*
4154d7aeee7SRoberto Sassu  * This function writes the name of an event (with size limit).
4164d7aeee7SRoberto Sassu  */
41723b57419SRoberto Sassu int ima_eventname_init(struct ima_event_data *event_data,
4184d7aeee7SRoberto Sassu 		       struct ima_field_data *field_data)
4194d7aeee7SRoberto Sassu {
42023b57419SRoberto Sassu 	return ima_eventname_init_common(event_data, field_data, true);
4214d7aeee7SRoberto Sassu }
4224d7aeee7SRoberto Sassu 
4234d7aeee7SRoberto Sassu /*
4244d7aeee7SRoberto Sassu  * This function writes the name of an event (without size limit).
4254d7aeee7SRoberto Sassu  */
42623b57419SRoberto Sassu int ima_eventname_ng_init(struct ima_event_data *event_data,
4274d7aeee7SRoberto Sassu 			  struct ima_field_data *field_data)
4284d7aeee7SRoberto Sassu {
42923b57419SRoberto Sassu 	return ima_eventname_init_common(event_data, field_data, false);
4303ce1217dSRoberto Sassu }
431bcbc9b0cSMimi Zohar 
432bcbc9b0cSMimi Zohar /*
433bcbc9b0cSMimi Zohar  *  ima_eventsig_init - include the file signature as part of the template data
434bcbc9b0cSMimi Zohar  */
43523b57419SRoberto Sassu int ima_eventsig_init(struct ima_event_data *event_data,
436bcbc9b0cSMimi Zohar 		      struct ima_field_data *field_data)
437bcbc9b0cSMimi Zohar {
43823b57419SRoberto Sassu 	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
439bcbc9b0cSMimi Zohar 
440bcbc9b0cSMimi Zohar 	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
4411775cb87SThiago Jung Bauermann 		return 0;
442bcbc9b0cSMimi Zohar 
4431775cb87SThiago Jung Bauermann 	return ima_write_template_field_data(xattr_value, event_data->xattr_len,
4441775cb87SThiago Jung Bauermann 					     DATA_FMT_HEX, field_data);
445bcbc9b0cSMimi Zohar }
44686b4da8cSPrakhar Srivastava 
44786b4da8cSPrakhar Srivastava /*
44886b4da8cSPrakhar Srivastava  *  ima_eventbuf_init - include the buffer(kexec-cmldine) as part of the
44986b4da8cSPrakhar Srivastava  *  template data.
45086b4da8cSPrakhar Srivastava  */
45186b4da8cSPrakhar Srivastava int ima_eventbuf_init(struct ima_event_data *event_data,
45286b4da8cSPrakhar Srivastava 		      struct ima_field_data *field_data)
45386b4da8cSPrakhar Srivastava {
45486b4da8cSPrakhar Srivastava 	if ((!event_data->buf) || (event_data->buf_len == 0))
45586b4da8cSPrakhar Srivastava 		return 0;
45686b4da8cSPrakhar Srivastava 
45786b4da8cSPrakhar Srivastava 	return ima_write_template_field_data(event_data->buf,
45886b4da8cSPrakhar Srivastava 					     event_data->buf_len, DATA_FMT_HEX,
45986b4da8cSPrakhar Srivastava 					     field_data);
46086b4da8cSPrakhar Srivastava }
4613878d505SThiago Jung Bauermann 
4623878d505SThiago Jung Bauermann /*
4633878d505SThiago Jung Bauermann  *  ima_eventmodsig_init - include the appended file signature as part of the
4643878d505SThiago Jung Bauermann  *  template data
4653878d505SThiago Jung Bauermann  */
4663878d505SThiago Jung Bauermann int ima_eventmodsig_init(struct ima_event_data *event_data,
4673878d505SThiago Jung Bauermann 			 struct ima_field_data *field_data)
4683878d505SThiago Jung Bauermann {
4693878d505SThiago Jung Bauermann 	const void *data;
4703878d505SThiago Jung Bauermann 	u32 data_len;
4713878d505SThiago Jung Bauermann 	int rc;
4723878d505SThiago Jung Bauermann 
4733878d505SThiago Jung Bauermann 	if (!event_data->modsig)
4743878d505SThiago Jung Bauermann 		return 0;
4753878d505SThiago Jung Bauermann 
4763878d505SThiago Jung Bauermann 	/*
4773878d505SThiago Jung Bauermann 	 * modsig is a runtime structure containing pointers. Get its raw data
4783878d505SThiago Jung Bauermann 	 * instead.
4793878d505SThiago Jung Bauermann 	 */
4803878d505SThiago Jung Bauermann 	rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len);
4813878d505SThiago Jung Bauermann 	if (rc)
4823878d505SThiago Jung Bauermann 		return rc;
4833878d505SThiago Jung Bauermann 
4843878d505SThiago Jung Bauermann 	return ima_write_template_field_data(data, data_len, DATA_FMT_HEX,
4853878d505SThiago Jung Bauermann 					     field_data);
4863878d505SThiago Jung Bauermann }
487