Skip to content

Commit 459a4f5

Browse files
committed
refactoring: write signature to array
1 parent ba3f3ce commit 459a4f5

5 files changed

Lines changed: 56 additions & 17 deletions

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ sigtest: sign-efi-sig-list
2828
./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
2929
md5sum fedora.auth | grep -q ^960a4d050 && printf "\033[1;32m[OK]\033[0m\n" || printf "\033[1;31m[FAIL]\033[0m\n"
3030

31+
expand:
32+
$(CC) -E $(CFLAGS) sign-efi-sig-list.c
33+
3134
clean:
3235
rm -f mkefivardata cert-to-efi-sig-list sign-efi-sig-list
3336

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# mkefivardata
22

3-
Source: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git
3+
[Upstream](https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git)
44

5-
openssl engines: https://github.com/openssl/openssl/blob/master/README-ENGINES.md
5+
[Services Runtime Services](https://uefi.org/specs/UEFI/2.11/08_Services_Runtime_Services.html)
6+
7+
[Secure Boot and Driver Signing](https://uefi.org/specs/UEFI/2.11/32_Secure_Boot_and_Driver_Signing.html)
68

79
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.
810

cert-to-efi-sig-list.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ int main(int argc, char *argv[])
6464
X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL);
6565
unsigned char *PkCert = NULL;
6666
UINT32 PkCertLen = i2d_X509(cert, &PkCert);
67-
UINT32 zero = 0;
6867

6968
UINT32 signature_size = PkCertLen + sizeof(EFI_GUID);
7069
UINT32 result_size = PkCertLen + 2 * sizeof(EFI_GUID) + 3 * sizeof(UINT32);
@@ -73,7 +72,7 @@ int main(int argc, char *argv[])
7372
// https://uefi.org/specs/UEFI/2.11/32_Secure_Boot_and_Driver_Signing.html
7473
memcpy(result + 0 * sizeof(EFI_GUID) + 0 * sizeof(UINT32), &EFI_CERT_X509_GUID, sizeof(EFI_GUID)); // SignatureType
7574
memcpy(result + 1 * sizeof(EFI_GUID) + 0 * sizeof(UINT32), &result_size, sizeof(UINT32)); // SignatureListSize
76-
memcpy(result + 1 * sizeof(EFI_GUID) + 1 * sizeof(UINT32), &zero, sizeof(UINT32)); // SignatureHeaderSize
75+
memset(result + 1 * sizeof(EFI_GUID) + 1 * sizeof(UINT32), 0, sizeof(UINT32)); // SignatureHeaderSize
7776
memcpy(result + 1 * sizeof(EFI_GUID) + 2 * sizeof(UINT32), &signature_size, sizeof(UINT32)); // SignatureSize
7877
memcpy(result + 1 * sizeof(EFI_GUID) + 3 * sizeof(UINT32), &owner, sizeof(EFI_GUID)); // Signatures[0]->SignatureOwner
7978
memcpy(result + 2 * sizeof(EFI_GUID) + 3 * sizeof(UINT32), PkCert, PkCertLen); // Signatures[0]->SignatureData

include/efiauthenticated.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ typedef struct {
147147
UINT8 Signature[256];
148148
} EFI_CERT_BLOCK_RSA_2048_SHA256;
149149

150+
/// https://uefi.org/specs/UEFI/2.10/32_Secure_Boot_and_Driver_Signing.html
151+
///
152+
/// typedef struct {
153+
/// UINT32 dwLength;
154+
/// UINT16 wRevision;
155+
/// UINT16 wCertificateType;
156+
/// } WIN_CERTIFICATE;
150157

151158
///
152159
/// Certificate which encapsulates a GUID-specific digital signature

sign-efi-sig-list.c

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,29 +168,57 @@ int main(int argc, char *argv[])
168168
exit(1);
169169
printf("Signature of size %d\n", sigsize);
170170

171-
int outlen = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData) + sigsize;
172-
EFI_VARIABLE_AUTHENTICATION_2 *var_auth = malloc(outlen);
171+
int outlen = sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize + st.st_size;
172+
unsigned char *var_auth = malloc(outlen);
173173

174-
var_auth->TimeStamp = timestamp;
175-
var_auth->AuthInfo.CertType = EFI_CERT_TYPE_PKCS7_GUID;
176-
var_auth->AuthInfo.Hdr.dwLength = sigsize + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
177-
var_auth->AuthInfo.Hdr.wRevision = 0x0200;
178-
var_auth->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
174+
// The length of the entire certificate, including the length of the header, in bytes.
175+
// -- Is this correct? What about sizeof(EFI_TIME) and st.st_size?
176+
UINT32 dwLength = sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize;
179177

180-
memcpy(var_auth->AuthInfo.CertData, sigbuf, sigsize);
181-
sigbuf = var_auth->AuthInfo.CertData;
182-
printf("Signature at: %ld\n", sigbuf - (unsigned char *)var_auth);
178+
// The revision level of the WIN_CERTIFICATE structure. The current revision level is 0x0200.
179+
UINT16 wRevision = 0x0200;
180+
181+
// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI certificate types.
182+
// The UEFI specification reserves the range of certificate type values from 0x0EF0 to 0x0EFF.
183+
UINT16 wCertificateType = WIN_CERT_TYPE_EFI_GUID;
184+
185+
// This is the unique id which determines the format of the CertData.
186+
EFI_GUID certType = EFI_CERT_TYPE_PKCS7_GUID;
187+
188+
// EFI_TIME TimeStamp
189+
memcpy(var_auth, &timestamp, sizeof(EFI_TIME));
190+
191+
// UINT32 AuthInfo.Hdr.dwLength
192+
memcpy(var_auth + sizeof(EFI_TIME), &dwLength, sizeof(UINT32));
193+
194+
// UINT16 AuthInfo.Hdr.wRevision
195+
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(UINT32), &wRevision, sizeof(UINT16));
196+
197+
// UINT16 AuthInfo.Hdr.wCertificateType
198+
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(UINT32) + sizeof(UINT16),
199+
&wCertificateType, sizeof(UINT16));
200+
201+
// EFI_GUID AuthInfo.CertType
202+
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE),
203+
&certType, sizeof(EFI_GUID));
204+
205+
// AuthInfo.CertData
206+
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID),
207+
sigbuf, sigsize);
208+
209+
// Authentication header complete, now write the payload
210+
memcpy(var_auth + sizeof(EFI_TIME) + sizeof(WIN_CERTIFICATE) + sizeof(EFI_GUID) + sigsize,
211+
signbuf + signbuf_header_len, st.st_size);
183212

184213
int fdoutfile = open(outfile, O_CREAT|O_WRONLY|O_TRUNC, S_IWUSR|S_IRUSR);
185214
if (fdoutfile == -1) {
186215
fprintf(stderr, "failed to open %s: ", outfile);
187216
perror("");
188217
exit(1);
189218
}
190-
/* first we write the authentication header */
219+
191220
write(fdoutfile, var_auth, outlen);
192-
/* Then we write the payload */
193-
write(fdoutfile, signbuf + signbuf_header_len, st.st_size);
221+
194222
/* so now the file is complete and can be fed straight into
195223
* SetVariable() as an authenticated variable update */
196224
close(fdoutfile);

0 commit comments

Comments
 (0)