1/*
2* Copyright (c) International Business Machines  Corp., 2009
3*
4* Authors:
5* Mimi Zohar <zohar@us.ibm.com>
6*
7* This program is free software; you can redistribute it and/or
8* modify it under the terms of the GNU General Public License as
9* published by the Free Software Foundation, version 2 of the
10* License.
11*
12* File: ima_boot_aggregate.c
13*
14* Calculate a SHA1 boot aggregate value based on the TPM
15* binary_bios_measurements.
16*/
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <string.h>
23#include <unistd.h>
24
25#include "config.h"
26#include "test.h"
27
28char *TCID = "ima_boot_aggregate";
29
30#if HAVE_LIBCRYPTO
31#include <openssl/sha.h>
32
33#define MAX_EVENT_SIZE 500
34#define EVENT_HEADER_SIZE 32
35#define MAX_EVENT_DATA_SIZE (MAX_EVENT_SIZE - EVENT_HEADER_SIZE)
36#define NUM_PCRS 8		/*  PCR registers 0-7 in boot aggregate */
37
38int TST_TOTAL = 1;
39
40static void display_sha1_digest(unsigned char *pcr)
41{
42	int i;
43
44	for (i = 0; i < 20; i++)
45		printf("%02x", *(pcr + i) & 0xff);
46	printf("\n");
47}
48
49int main(int argc, char *argv[])
50{
51	unsigned char boot_aggregate[SHA_DIGEST_LENGTH];
52	struct {
53		struct {
54			u_int32_t pcr;
55			int type;
56			unsigned char digest[SHA_DIGEST_LENGTH];
57			u_int16_t len;
58		} header;
59		unsigned char data[MAX_EVENT_DATA_SIZE];
60	} event;
61	struct {
62		unsigned char digest[SHA_DIGEST_LENGTH];
63	} pcr[NUM_PCRS];
64	FILE *fp;
65	int i;
66	int debug = 0;
67	SHA_CTX c;
68
69	if (argc != 2) {
70		printf("format: %s binary_bios_measurement file\n", argv[0]);
71		return 1;
72	}
73	fp = fopen(argv[1], "r");
74	if (!fp) {
75		perror("unable to open pcr file\n");
76		return 1;
77	}
78
79	/* Initialize psuedo PCR registers 0 - 7 */
80	for (i = 0; i < NUM_PCRS; i++)
81		memset(&pcr[i].digest, 0, SHA_DIGEST_LENGTH);
82
83	/* Extend the pseudo PCRs with the event digest */
84	while (fread(&event, sizeof(event.header), 1, fp)) {
85		if (debug) {
86			printf("%03u ", event.header.pcr);
87			display_sha1_digest(event.header.digest);
88		}
89		SHA1_Init(&c);
90		SHA1_Update(&c, pcr[event.header.pcr].digest, 20);
91		SHA1_Update(&c, event.header.digest, 20);
92		SHA1_Final(pcr[event.header.pcr].digest, &c);
93		if (event.header.len > MAX_EVENT_DATA_SIZE) {
94			printf("Error event too long");
95			break;
96		}
97		fread(event.data, event.header.len, 1, fp);
98	}
99	fclose(fp);
100
101	/* Extend the boot aggregate with the pseudo PCR digest values */
102	memset(&boot_aggregate, 0, SHA_DIGEST_LENGTH);
103	SHA1_Init(&c);
104	for (i = 0; i < NUM_PCRS; i++) {
105		if (debug) {
106			printf("PCR-%2.2x: ", i);
107			display_sha1_digest(pcr[i].digest);
108		}
109		SHA1_Update(&c, pcr[i].digest, 20);
110	}
111	SHA1_Final(boot_aggregate, &c);
112
113	printf("boot_aggregate:");
114	display_sha1_digest(boot_aggregate);
115	tst_exit();
116}
117
118#else
119int main(void)
120{
121	tst_brkm(TCONF, NULL, "test requires libcrypto and openssl development packages");
122}
123#endif
124