Skip to content

Commit aeb5ea3

Browse files
committed
sign-efi-sig-list creates vardata
1 parent 9ce9e67 commit aeb5ea3

5 files changed

Lines changed: 42 additions & 168 deletions

File tree

Makefile

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,7 @@ esltest: cert-to-efi-sig-list
2525
md5sum fedora.esl | grep -q ^e868d249 && printf "\033[1;32m[OK]\033[0m\n"
2626

2727
sigtest: sign-efi-sig-list
28-
./sign-efi-sig-list -g $(TEST_OWNER) -t "2025-03-24 14:26:01" -k KEK.key -c KEK.crt db fedora.esl fedora.auth
29-
md5sum fedora.auth | grep -q ^960a4d050 && printf "\033[1;32m[OK]\033[0m\n"
30-
31-
efitest: mkefivardata
32-
./mkefivardata -q fedora.auth fedora.vardata
28+
./sign-efi-sig-list -g $(TEST_OWNER) -t "2025-03-24 14:26:01" -k KEK.key -c KEK.crt db fedora.esl fedora.vardata
3329
md5sum fedora.vardata | grep -q ^c0c07e6b0 && printf "\033[1;32m[OK]\033[0m\n"
3430

3531
expand:

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
[Upstream](https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git)
44

5-
[Services Runtime Services](https://uefi.org/specs/UEFI/2.11/08_Services_Runtime_Services.html)
5+
[Services - Runtime Services](https://uefi.org/specs/UEFI/2.11/08_Services_Runtime_Services.html)
66

77
[Secure Boot and Driver Signing](https://uefi.org/specs/UEFI/2.11/32_Secure_Boot_and_Driver_Signing.html)
88

9+
[kernel efivarfs](https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html)
10+
911
To enroll signed secureboot keys, aka `.auth` files, [efitools is needed](https://github.com/Foxboron/sbctl/issues/434). The purpose of `mkefivardata` is to convert `.auth` to a format which can be enrolled on a system where `efitools` is not available. This facilitates rollout of secureboot keys on "untrusted" machines.
1012

1113
Just like the `.auth` files, the `.vardata` files do not contain private signing keys. It is safe to copy them onto an untrusted machine. Note that `sbctl` can also do the enrolling, but it needs access to the private keys.

github-action.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22

33
sudo apt-get install -y gnu-efi || exit 1
44
make esltest || exit 1
5-
make sigtest || exit 1
6-
make efitest
5+
make sigtest

mkefivardata.c

Lines changed: 0 additions & 128 deletions
This file was deleted.

sign-efi-sig-list.c

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,23 @@
1616

1717
#define MAX_VAR_LEN 8
1818

19-
void usage(const char *progname)
19+
void usage()
2020
{
21-
printf("Usage: %s [-g <guid>] [-t <timestamp>] [-c <crt_file>] [-k <key_file>] <var> <efi_sig_list_file> <output_file>\n", progname);
21+
printf("Usage: sign-efi-sig-list [-g <guid>] [-t <timestamp>] [-c <crt_file>] [-k <key_file>] <var> <x.esl> <x.vardata>\n");
2222
}
2323

24-
void help(const char *progname)
24+
void help()
2525
{
26-
usage(progname);
26+
usage();
2727
printf("Produce an output file with an authentication header for direct\n"
2828
"update to a secure variable.\n\n"
29+
"Note:"
30+
"This version of sign-efi-sig-list does not create the usual \"auth\" format."
31+
"Instead, it creates \"vardata\" format for the \"efivarfs\" filesystem, which\n"
32+
"includes four leading bytes of \"attributes\" data.\n"
33+
"To update the efi variable <var>, simply copy the \"vardata\" file\n"
34+
"to the appropriate place in the efivarfs filesystem.\n"
35+
"So no \"efi-updatevar\" binary is needed.\n\n"
2936
"Options:\n"
3037
"\t-t <timestamp> Use <timestamp> as the timestamp of the timed variable update\n"
3138
"\t If not present, then the timestamp will be taken from system\n"
@@ -41,23 +48,21 @@ void help(const char *progname)
4148
int main(int argc, char *argv[])
4249
{
4350
char *certfile = NULL, *efifile, *keyfile = NULL, *outfile,
44-
*str, *timestampstr = NULL;
45-
const char *progname = argv[0];
51+
*var_str, *timestampstr = NULL;
4652
unsigned char *sigbuf;
4753
int varlen, sigsize;
4854
EFI_GUID vendor_guid;
4955
struct stat st;
50-
short unsigned int var[MAX_VAR_LEN];
5156
uint32_t attributes = EFI_VARIABLE_NON_VOLATILE
5257
| EFI_VARIABLE_RUNTIME_ACCESS
5358
| EFI_VARIABLE_BOOTSERVICE_ACCESS
5459
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
5560
EFI_TIME timestamp;
5661
memset(&timestamp, 0, sizeof(timestamp));
5762

58-
while (argc > 1) {
63+
while (argc) {
5964
if (strcmp("--help", argv[1]) == 0) {
60-
help(progname);
65+
help();
6166
exit(0);
6267
} else if (strcmp("-g", argv[1]) == 0) {
6368
str_to_guid(argv[2], &vendor_guid);
@@ -81,19 +86,19 @@ int main(int argc, char *argv[])
8186
}
8287

8388
if (argc != 4) {
84-
usage(progname);
89+
usage();
8590
exit(1);
8691
}
8792

88-
str = argv[1];
93+
var_str = argv[1];
8994
efifile = argv[2];
9095
outfile = argv[3];
9196

9297
/* Specific GUIDs for special variables */
93-
if (strcmp(str, "PK") == 0 || strcmp(str, "KEK") == 0) {
94-
vendor_guid = (EFI_GUID)EFI_GLOBAL_VARIABLE;
95-
} else if (strcmp(str, "db") == 0 || strcmp(str, "dbx") == 0) {
96-
vendor_guid = (EFI_GUID){ 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }};
98+
if (strcmp(var_str, "PK") == 0 || strcmp(var_str, "KEK") == 0) {
99+
vendor_guid = (EFI_GUID) EFI_GLOBAL_VARIABLE;
100+
} else if (strcmp(var_str, "db") == 0 || strcmp(var_str, "dbx") == 0) {
101+
vendor_guid = (EFI_GUID) { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }};
97102
}
98103

99104
time_t t;
@@ -107,10 +112,6 @@ int main(int argc, char *argv[])
107112
/* timestamp.Year is from 0 not 1900 as tm year is */
108113
tm->tm_year += 1900;
109114
tm->tm_mon += 1; /* tm_mon is 0-11 not 1-12 */
110-
} else if (attributes & EFI_VARIABLE_APPEND_WRITE) {
111-
/* for append update timestamp should be zero */
112-
memset(&tms, 0, sizeof(tms));
113-
tm = &tms;
114115
} else {
115116
time(&t);
116117
tm = localtime(&t);
@@ -131,12 +132,12 @@ int main(int argc, char *argv[])
131132
timestamp.Second);
132133

133134
int i = 0;
134-
while (i < MAX_VAR_LEN && str[i] != '\0') {
135-
var[i] = str[i];
135+
unsigned short int var[MAX_VAR_LEN];
136+
while (i < MAX_VAR_LEN && var_str[i] != '\0') {
137+
var[i] = var_str[i];
136138
i++;
137139
}
138-
139-
varlen = i * sizeof(short unsigned int);
140+
varlen = i * sizeof(unsigned short int);
140141

141142
int fdefifile = open(efifile, O_RDONLY);
142143
if (fdefifile == -1) {
@@ -167,7 +168,8 @@ int main(int argc, char *argv[])
167168
exit(1);
168169
printf("Signature of size %d\n", sigsize);
169170

170-
int outlen = sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize + st.st_size;
171+
172+
int outlen = sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize + st.st_size;
171173
unsigned char *var_auth = malloc(outlen);
172174

173175
// The length of the entire certificate, including the length of the header, in bytes.
@@ -184,29 +186,32 @@ int main(int argc, char *argv[])
184186
// This is the unique id which determines the format of the CertData.
185187
EFI_GUID certType = EFI_CERT_TYPE_PKCS7_GUID;
186188

189+
// efivarfs vardata format: 4_bytes_of_attributes + efivar_data
190+
memcpy(var_auth, &attributes, sizeof(uint32_t));
191+
187192
// EFI_TIME TimeStamp
188-
memcpy(var_auth, &timestamp, sizeof(EFI_TIME));
193+
memcpy(var_auth + sizeof(uint32_t), &timestamp, sizeof(EFI_TIME));
189194

190195
// UINT32 AuthInfo.Hdr.dwLength
191-
memcpy(var_auth + sizeof(EFI_TIME), &dwLength, sizeof(uint32_t));
196+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME), &dwLength, sizeof(uint32_t));
192197

193198
// UINT16 AuthInfo.Hdr.wRevision
194-
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(uint32_t), &wRevision, sizeof(uint16_t));
199+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(uint32_t), &wRevision, sizeof(uint16_t));
195200

196201
// UINT16 AuthInfo.Hdr.wCertificateType
197-
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(uint32_t) + sizeof(uint16_t),
202+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(uint32_t) + sizeof(uint16_t),
198203
&wCertificateType, sizeof(uint16_t));
199204

200205
// EFI_GUID AuthInfo.CertType
201-
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE),
206+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE),
202207
&certType, sizeof(EFI_GUID));
203208

204209
// AuthInfo.CertData
205-
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID),
210+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID),
206211
sigbuf, sigsize);
207212

208-
// Authentication header complete, now write the payload
209-
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize,
213+
// Authentication header complete, now write the payload (the original esl)
214+
memcpy(var_auth + sizeof(uint32_t) + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize,
210215
signbuf + signbuf_header_len, st.st_size);
211216

212217
int fdoutfile = open(outfile, O_CREAT|O_WRONLY|O_TRUNC, S_IWUSR|S_IRUSR);

0 commit comments

Comments
 (0)