forked from mjg59/tpmtotp
-
Notifications
You must be signed in to change notification settings - Fork 3
/
plymouth-unsealtotp.c
147 lines (123 loc) · 3.14 KB
/
plymouth-unsealtotp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* sealtotp - generate a TOTP secret and seal it to the local TPM
*
* Copyright 2015 Matthew Garrett <[email protected]>
*
* Portions derived from unsealfile.c by J. Kravitz and Copyright (C) 2004 IBM
* Corporation
*
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include "tpmfunc.h"
#include <ply-boot-client.h>
#include <liboath/oath.h>
#include <time.h>
#define keylen 20
char key[keylen];
static char efivarfs[] = "/sys/firmware/efi/efivars";
static ply_boot_client_t *ply_client;
static ply_event_loop_t *ply_loop;
static void on_failure(void* dummy)
{
ply_event_loop_exit(ply_loop, 0);
}
static void on_disconnect(void* dummy)
{
ply_event_loop_exit(ply_loop, 0);
}
static void display_totp() {
int ret;
char totp[7];
ret = oath_totp_generate(key, keylen, time(NULL), 30, 0, 6, totp);
if (ret != 0) {
fprintf(stderr, "Error generating totp value\n");
exit(-1);
}
ply_boot_client_tell_daemon_to_display_message (ply_client,
totp, NULL,
(ply_boot_client_response_handler_t) on_failure, NULL);
}
static void on_timeout(void* dummy)
{
time_t t = time(NULL);
time_t delay;
display_totp();
delay = 30 - (t % 30);
ply_event_loop_watch_for_timeout(ply_loop, delay, on_timeout, NULL);
}
int main(int argc, char *argv[])
{
int ret;
struct stat sbuf;
uint32_t parhandle; /* handle of parent key */
unsigned char blob[4096]; /* resulting sealed blob */
unsigned int bloblen = 322; /* blob length */
unsigned char passptr1[20] = {0};
int fd, outlen, i;
time_t t, delay;
parhandle = 0x40000000;
ret = TPM_NV_ReadValue(0x10004d47, 0, 322, blob, &bloblen, NULL);
if (ret != 0) {
for (i=1; i<argc; i++) {
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
argv++;
}
}
if (fd < 0) {
perror("Unable to open file");
return -1;
}
ret = fstat(fd, &sbuf);
if (ret) {
perror("Unable to stat file");
return -1;
}
bloblen = sbuf.st_size;
ret = read(fd, blob, bloblen);
if (ret != bloblen) {
fprintf(stderr, "Unable to read data\n");
return -1;
}
if (strncmp(argv[1], efivarfs, strlen(efivarfs)) == 0) {
bloblen -= sizeof(int);
memmove (blob, blob + sizeof(int), bloblen);
}
}
ret = TPM_Unseal(parhandle, /* KEY Entity Value */
passptr1, /* Key Password */
NULL,
blob, bloblen,
key, &outlen);
if (ret == 24) {
fprintf(stderr, "TPM refused to decrypt key - boot process attests that it is modified\n");
return -1;
}
if (ret != 0) {
printf("Error %s from TPM_Unseal\n", TPM_GetErrMsg(ret));
exit(6);
}
if (outlen != keylen) {
fprintf(stderr, "Returned buffer is incorrect length\n");
return -1;
}
ply_client = ply_boot_client_new();
ply_loop = ply_event_loop_new();
if (!ply_boot_client_connect (ply_client, (ply_boot_client_disconnect_handler_t) on_disconnect, NULL)) {
fprintf(stderr, "Plymouth not running\n");
return -1;
}
ply_boot_client_attach_to_event_loop(ply_client, ply_loop);
display_totp();
t = time(NULL);
delay = 30 - (t % 30);
ply_event_loop_watch_for_timeout(ply_loop, delay, on_timeout, NULL);
ply_event_loop_run(ply_loop);
return 0;
}