12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20bfb2374SThiebaud Weksteen /*
30bfb2374SThiebaud Weksteen * Copyright (C) 2016 IBM Corporation
40bfb2374SThiebaud Weksteen *
50bfb2374SThiebaud Weksteen * Authors:
60bfb2374SThiebaud Weksteen * Nayna Jain <nayna@linux.vnet.ibm.com>
70bfb2374SThiebaud Weksteen *
80bfb2374SThiebaud Weksteen * Access to TPM 2.0 event log as written by Firmware.
90bfb2374SThiebaud Weksteen * It assumes that writer of event log has followed TCG Specification
100bfb2374SThiebaud Weksteen * for Family "2.0" and written the event data in little endian.
110bfb2374SThiebaud Weksteen * With that, it doesn't need any endian conversion for structure
120bfb2374SThiebaud Weksteen * content.
130bfb2374SThiebaud Weksteen */
140bfb2374SThiebaud Weksteen
150bfb2374SThiebaud Weksteen #include <linux/seq_file.h>
160bfb2374SThiebaud Weksteen #include <linux/fs.h>
170bfb2374SThiebaud Weksteen #include <linux/security.h>
180bfb2374SThiebaud Weksteen #include <linux/module.h>
190bfb2374SThiebaud Weksteen #include <linux/slab.h>
200bfb2374SThiebaud Weksteen #include <linux/tpm_eventlog.h>
210bfb2374SThiebaud Weksteen
220bfb2374SThiebaud Weksteen #include "../tpm.h"
2375d647f5SThiebaud Weksteen #include "common.h"
240bfb2374SThiebaud Weksteen
250bfb2374SThiebaud Weksteen /*
260bfb2374SThiebaud Weksteen * calc_tpm2_event_size() - calculate the event size, where event
270bfb2374SThiebaud Weksteen * is an entry in the TPM 2.0 event log. The event is of type Crypto
280bfb2374SThiebaud Weksteen * Agile Log Entry Format as defined in TCG EFI Protocol Specification
290bfb2374SThiebaud Weksteen * Family "2.0".
300bfb2374SThiebaud Weksteen
310bfb2374SThiebaud Weksteen * @event: event whose size is to be calculated.
320bfb2374SThiebaud Weksteen * @event_header: the first event in the event log.
330bfb2374SThiebaud Weksteen *
340bfb2374SThiebaud Weksteen * Returns size of the event. If it is an invalid event, returns 0.
350bfb2374SThiebaud Weksteen */
calc_tpm2_event_size(struct tcg_pcr_event2_head * event,struct tcg_pcr_event * event_header)36b9d0a85dSYue Haibing static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
370bfb2374SThiebaud Weksteen struct tcg_pcr_event *event_header)
380bfb2374SThiebaud Weksteen {
39c46f3405SMatthew Garrett return __calc_tpm2_event_size(event, event_header, false);
400bfb2374SThiebaud Weksteen }
410bfb2374SThiebaud Weksteen
tpm2_bios_measurements_start(struct seq_file * m,loff_t * pos)420bfb2374SThiebaud Weksteen static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
430bfb2374SThiebaud Weksteen {
440bfb2374SThiebaud Weksteen struct tpm_chip *chip = m->private;
450bfb2374SThiebaud Weksteen struct tpm_bios_log *log = &chip->log;
460bfb2374SThiebaud Weksteen void *addr = log->bios_event_log;
470bfb2374SThiebaud Weksteen void *limit = log->bios_event_log_end;
480bfb2374SThiebaud Weksteen struct tcg_pcr_event *event_header;
49c8faabfcSRoberto Sassu struct tcg_pcr_event2_head *event;
500bfb2374SThiebaud Weksteen size_t size;
510bfb2374SThiebaud Weksteen int i;
520bfb2374SThiebaud Weksteen
530bfb2374SThiebaud Weksteen event_header = addr;
54*ab91c2a8SGustavo A. R. Silva size = struct_size(event_header, event, event_header->event_size);
550bfb2374SThiebaud Weksteen
560bfb2374SThiebaud Weksteen if (*pos == 0) {
570bfb2374SThiebaud Weksteen if (addr + size < limit) {
580bfb2374SThiebaud Weksteen if ((event_header->event_type == 0) &&
590bfb2374SThiebaud Weksteen (event_header->event_size == 0))
600bfb2374SThiebaud Weksteen return NULL;
610bfb2374SThiebaud Weksteen return SEQ_START_TOKEN;
620bfb2374SThiebaud Weksteen }
630bfb2374SThiebaud Weksteen }
640bfb2374SThiebaud Weksteen
650bfb2374SThiebaud Weksteen if (*pos > 0) {
660bfb2374SThiebaud Weksteen addr += size;
670bfb2374SThiebaud Weksteen event = addr;
680bfb2374SThiebaud Weksteen size = calc_tpm2_event_size(event, event_header);
690bfb2374SThiebaud Weksteen if ((addr + size >= limit) || (size == 0))
700bfb2374SThiebaud Weksteen return NULL;
710bfb2374SThiebaud Weksteen }
720bfb2374SThiebaud Weksteen
730bfb2374SThiebaud Weksteen for (i = 0; i < (*pos - 1); i++) {
740bfb2374SThiebaud Weksteen event = addr;
750bfb2374SThiebaud Weksteen size = calc_tpm2_event_size(event, event_header);
760bfb2374SThiebaud Weksteen
770bfb2374SThiebaud Weksteen if ((addr + size >= limit) || (size == 0))
780bfb2374SThiebaud Weksteen return NULL;
790bfb2374SThiebaud Weksteen addr += size;
800bfb2374SThiebaud Weksteen }
810bfb2374SThiebaud Weksteen
820bfb2374SThiebaud Weksteen return addr;
830bfb2374SThiebaud Weksteen }
840bfb2374SThiebaud Weksteen
tpm2_bios_measurements_next(struct seq_file * m,void * v,loff_t * pos)850bfb2374SThiebaud Weksteen static void *tpm2_bios_measurements_next(struct seq_file *m, void *v,
860bfb2374SThiebaud Weksteen loff_t *pos)
870bfb2374SThiebaud Weksteen {
880bfb2374SThiebaud Weksteen struct tcg_pcr_event *event_header;
89c8faabfcSRoberto Sassu struct tcg_pcr_event2_head *event;
900bfb2374SThiebaud Weksteen struct tpm_chip *chip = m->private;
910bfb2374SThiebaud Weksteen struct tpm_bios_log *log = &chip->log;
920bfb2374SThiebaud Weksteen void *limit = log->bios_event_log_end;
930bfb2374SThiebaud Weksteen size_t event_size;
940bfb2374SThiebaud Weksteen void *marker;
950bfb2374SThiebaud Weksteen
96f9bf8adbSVasily Averin (*pos)++;
970bfb2374SThiebaud Weksteen event_header = log->bios_event_log;
980bfb2374SThiebaud Weksteen
990bfb2374SThiebaud Weksteen if (v == SEQ_START_TOKEN) {
100*ab91c2a8SGustavo A. R. Silva event_size = struct_size(event_header, event,
101*ab91c2a8SGustavo A. R. Silva event_header->event_size);
1020bfb2374SThiebaud Weksteen marker = event_header;
1030bfb2374SThiebaud Weksteen } else {
1040bfb2374SThiebaud Weksteen event = v;
1050bfb2374SThiebaud Weksteen event_size = calc_tpm2_event_size(event, event_header);
1060bfb2374SThiebaud Weksteen if (event_size == 0)
1070bfb2374SThiebaud Weksteen return NULL;
1080bfb2374SThiebaud Weksteen marker = event;
1090bfb2374SThiebaud Weksteen }
1100bfb2374SThiebaud Weksteen
1110bfb2374SThiebaud Weksteen marker = marker + event_size;
1120bfb2374SThiebaud Weksteen if (marker >= limit)
1130bfb2374SThiebaud Weksteen return NULL;
1140bfb2374SThiebaud Weksteen v = marker;
1150bfb2374SThiebaud Weksteen event = v;
1160bfb2374SThiebaud Weksteen
1170bfb2374SThiebaud Weksteen event_size = calc_tpm2_event_size(event, event_header);
1180bfb2374SThiebaud Weksteen if (((v + event_size) >= limit) || (event_size == 0))
1190bfb2374SThiebaud Weksteen return NULL;
1200bfb2374SThiebaud Weksteen
1210bfb2374SThiebaud Weksteen return v;
1220bfb2374SThiebaud Weksteen }
1230bfb2374SThiebaud Weksteen
tpm2_bios_measurements_stop(struct seq_file * m,void * v)1240bfb2374SThiebaud Weksteen static void tpm2_bios_measurements_stop(struct seq_file *m, void *v)
1250bfb2374SThiebaud Weksteen {
1260bfb2374SThiebaud Weksteen }
1270bfb2374SThiebaud Weksteen
tpm2_binary_bios_measurements_show(struct seq_file * m,void * v)1280bfb2374SThiebaud Weksteen static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v)
1290bfb2374SThiebaud Weksteen {
1300bfb2374SThiebaud Weksteen struct tpm_chip *chip = m->private;
1310bfb2374SThiebaud Weksteen struct tpm_bios_log *log = &chip->log;
1320bfb2374SThiebaud Weksteen struct tcg_pcr_event *event_header = log->bios_event_log;
133c8faabfcSRoberto Sassu struct tcg_pcr_event2_head *event = v;
1340bfb2374SThiebaud Weksteen void *temp_ptr;
1350bfb2374SThiebaud Weksteen size_t size;
1360bfb2374SThiebaud Weksteen
1370bfb2374SThiebaud Weksteen if (v == SEQ_START_TOKEN) {
138*ab91c2a8SGustavo A. R. Silva size = struct_size(event_header, event,
139*ab91c2a8SGustavo A. R. Silva event_header->event_size);
1400bfb2374SThiebaud Weksteen temp_ptr = event_header;
1410bfb2374SThiebaud Weksteen
1420bfb2374SThiebaud Weksteen if (size > 0)
1430bfb2374SThiebaud Weksteen seq_write(m, temp_ptr, size);
1440bfb2374SThiebaud Weksteen } else {
1450bfb2374SThiebaud Weksteen size = calc_tpm2_event_size(event, event_header);
1460bfb2374SThiebaud Weksteen temp_ptr = event;
1470bfb2374SThiebaud Weksteen if (size > 0)
1480bfb2374SThiebaud Weksteen seq_write(m, temp_ptr, size);
1490bfb2374SThiebaud Weksteen }
1500bfb2374SThiebaud Weksteen
1510bfb2374SThiebaud Weksteen return 0;
1520bfb2374SThiebaud Weksteen }
1530bfb2374SThiebaud Weksteen
1540bfb2374SThiebaud Weksteen const struct seq_operations tpm2_binary_b_measurements_seqops = {
1550bfb2374SThiebaud Weksteen .start = tpm2_bios_measurements_start,
1560bfb2374SThiebaud Weksteen .next = tpm2_bios_measurements_next,
1570bfb2374SThiebaud Weksteen .stop = tpm2_bios_measurements_stop,
1580bfb2374SThiebaud Weksteen .show = tpm2_binary_bios_measurements_show,
1590bfb2374SThiebaud Weksteen };
160