iPXE
efi_cacert.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * EFI CA certificates
30 *
31 */
32
33#include <stdlib.h>
34#include <string.h>
35#include <assert.h>
36#include <errno.h>
37#include <ipxe/init.h>
38#include <ipxe/x509.h>
39#include <ipxe/rootcert.h>
40#include <ipxe/efi/efi.h>
43
44/** List of EFI CA certificates */
45static struct x509_chain efi_cacerts = {
46 .refcnt = REF_INIT ( ref_no_free ),
47 .links = LIST_HEAD_INIT ( efi_cacerts.links ),
48};
49
50/**
51 * Retrieve EFI CA certificate
52 *
53 * @v data TlsCaCertificate variable data
54 * @v len Length of TlsCaCertificate
55 * @v offset Offset within data
56 * @v next Next offset, or negative error
57 */
58static int efi_cacert ( const void *data, size_t len, size_t offset ) {
59 struct asn1_cursor *cursor;
60 struct x509_certificate *cert;
61 int next;
62 int rc;
63
64 /* Extract ASN.1 object */
65 next = efisig_asn1 ( data, len, offset, &cursor );
66 if ( next < 0 ) {
67 rc = next;
68 DBGC ( &efi_cacerts, "EFICA could not parse at +%#zx: %s\n",
69 offset, strerror ( rc ) );
70 goto err_asn1;
71 }
72
73 /* Append to list of EFI CA certificates */
74 if ( ( rc = x509_append_raw ( &efi_cacerts, cursor->data,
75 cursor->len ) ) != 0 ) {
76 DBGC ( &efi_cacerts, "EFICA could not append at +%#zx: %s\n",
77 offset, strerror ( rc ) );
78 goto err_append;
79 }
80 cert = x509_last ( &efi_cacerts );
81 DBGC ( &efi_cacerts, "EFICA found certificate %s\n",
82 x509_name ( cert ) );
83
84 /* Mark certificate as valid (i.e. trusted) if permitted */
86 DBGC ( &efi_cacerts, "EFICA trusting certificate %s\n",
87 x509_name ( cert ) );
89 }
90
91 /* Free ASN.1 object */
92 free ( cursor );
93
94 return next;
95
96 err_append:
97 free ( cursor );
98 err_asn1:
99 return rc;
100}
101
102/**
103 * Retrieve all EFI CA certificates
104 *
105 * @ret rc Return status code
106 */
107static int efi_cacert_all ( void ) {
108 EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
111 int offset = 0;
112 UINT32 attrs;
113 UINTN size;
114 void *data;
115 EFI_STATUS efirc;
116 int rc;
117
118 /* Get variable length */
119 size = 0;
120 if ( ( efirc = rs->GetVariable ( wname, guid, &attrs, &size,
121 NULL ) ) != EFI_BUFFER_TOO_SMALL ) {
122 rc = -EEFI ( efirc );
123 DBGC ( &efi_cacerts, "EFICA could not get %ls size: %s\n",
124 wname, strerror ( rc ) );
125 goto err_len;
126 }
127
128 /* Allocate temporary buffer */
129 data = malloc ( size );
130 if ( ! data ) {
131 rc = -ENOMEM;
132 goto err_alloc;
133 }
134
135 /* Read variable */
136 if ( ( efirc = rs->GetVariable ( wname, guid, &attrs, &size,
137 data ) ) != 0 ) {
138 rc = -EEFI ( efirc );
139 DBGC ( &efi_cacerts, "EFICA could not read %ls: %s\n",
140 wname, strerror ( rc ) );
141 goto err_get;
142 }
143
144 /* Parse certificates */
145 while ( ( ( size_t ) offset ) < size ) {
147 if ( offset < 0 ) {
148 rc = offset;
149 goto err_cacert;
150 }
151 }
152
153 /* Success */
154 rc = 0;
155
156 err_cacert:
157 err_get:
158 free ( data );
159 err_alloc:
160 err_len:
161 return rc;
162}
163
164/**
165 * Initialise EFI CA certificates
166 *
167 */
168static void efi_cacert_init ( void ) {
169 int rc;
170
171 /* Initialise all certificates */
172 if ( ( rc = efi_cacert_all() ) != 0 ) {
173 DBGC ( &efi_cacert, "EFICA could not initialise: %s\n",
174 strerror ( rc ) );
175 /* Nothing we can do at this point */
176 return;
177 }
178}
179
180/** EFI CA certificates initialisation function */
181struct init_fn efi_cacert_init_fn __init_fn ( INIT_LATE ) = {
182 .name = "eficacert",
183 .initialise = efi_cacert_init,
184};
185
186/**
187 * Discard any EFI CA certificates
188 *
189 */
190static void efi_cacert_shutdown ( int booting __unused ) {
191
192 /* Drop our references to the certificates */
193 DBGC ( &efi_cacert, "EFICA discarding certificates\n" );
195 assert ( list_empty ( &efi_cacerts.links ) );
196}
197
198/** EFI CA certificates shutdown function */
199struct startup_fn efi_cacert_shutdown_fn __startup_fn ( STARTUP_NORMAL ) = {
200 .name = "efi_cacert",
201 .shutdown = efi_cacert_shutdown,
202};
UINT64 UINTN
Unsigned value of native width.
unsigned short CHAR16
2-byte Character.
unsigned int UINT32
4-byte unsigned value.
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
This file defines TlsCaCertificate variable.
#define EFI_TLS_CA_CERTIFICATE_VARIABLE
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
GUID EFI_GUID
128-bit buffer containing a unique identifier value.
#define EFI_BUFFER_TOO_SMALL
Enumeration of EFI_STATUS.
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint32_t next
Next descriptor address.
Definition dwmac.h:11
ring len
Length.
Definition dwmac.h:226
uint64_t guid
GUID.
Definition edd.h:1
static struct x509_chain efi_cacerts
List of EFI CA certificates.
Definition efi_cacert.c:45
static void efi_cacert_init(void)
Initialise EFI CA certificates.
Definition efi_cacert.c:168
static int efi_cacert_all(void)
Retrieve all EFI CA certificates.
Definition efi_cacert.c:107
static void efi_cacert_shutdown(int booting __unused)
Discard any EFI CA certificates.
Definition efi_cacert.c:190
static int efi_cacert(const void *data, size_t len, size_t offset)
Retrieve EFI CA certificate.
Definition efi_cacert.c:58
EFI_GUID efi_tls_ca_certificate_guid
TLS CA certificate variable GUID.
Definition efi_guid.c:478
int efisig_asn1(const void *data, size_t len, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from EFI signature list.
PEM-encoded ASN.1 data.
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define INIT_LATE
Late initialisation.
Definition init.h:33
uint16_t size
Buffer size.
Definition dwmac.h:3
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define STARTUP_NORMAL
Normal startup.
Definition init.h:65
EFI API.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:175
EFI_SYSTEM_TABLE * efi_systab
String functions.
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
#define __startup_fn(startup_order)
Declare a startup/shutdown function.
Definition init.h:53
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
void ref_no_free(struct refcnt *refcnt __unused)
Do not free reference-counted object.
Definition refcnt.c:102
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define REF_INIT(free_fn)
Initialise a static reference counter.
Definition refcnt.h:78
const int allow_trust_override
Flag indicating if root of trust may be overridden at runtime.
Definition rootcert.c:65
struct x509_root root_certificates
Root certificates.
Definition rootcert.c:79
Root certificate store.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
EFI Runtime Services Table.
Definition UefiSpec.h:1880
EFI_GET_VARIABLE GetVariable
Definition UefiSpec.h:1903
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
An initialisation function.
Definition init.h:15
A startup/shutdown function.
Definition init.h:43
An X.509 certificate.
Definition x509.h:216
An X.509 certificate chain.
Definition x509.h:201
void x509_truncate(struct x509_chain *chain, struct x509_link *link)
Truncate X.509 certificate chain.
Definition x509.c:1704
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147
int x509_append_raw(struct x509_chain *chain, const void *data, size_t len)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1674
void x509_set_valid(struct x509_certificate *cert, struct x509_certificate *issuer, struct x509_root *root)
Set X.509 certificate as validated.
Definition x509.c:1329
X.509 certificates.
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition x509.h:325