Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Shawn Webb
Fwupd
Commits
fcb5667d
Commit
fcb5667d
authored
Jan 05, 2021
by
Richard Hughes
Browse files
libfwupdplugin: Subclass FuFirmware in FuEfiSignatureList
This allows us to get fuzzing support 'for free' and also simplifies the code.
parent
ac927583
Changes
18
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
fcb5667d
...
...
@@ -137,5 +137,4 @@ There are several automated fuzzing tests in fwupd. These take some time to run:
ninja install
ninja fuzz-firmware
ninja fuzz-smbios
ninja fuzz-efidbx
ninja fuzz-tpm-eventlog
plugins/uefi-dbx/create-fuzzing-targets.py
deleted
100755 → 0
View file @
ac927583
#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1+
import
sys
import
struct
if
__name__
==
'__main__'
:
# SignatureType
buf
=
b
'0'
*
16
# SignatureListSize
buf
+=
struct
.
pack
(
'<I'
,
16
+
4
+
4
+
4
+
16
+
32
)
# SignatureHeaderSize
buf
+=
struct
.
pack
(
'<I'
,
0
)
# SignatureSize
buf
+=
struct
.
pack
(
'<I'
,
16
+
32
)
# SignatureOwner
buf
+=
b
'1'
*
16
# SignatureData
buf
+=
b
'2'
*
32
with
open
(
sys
.
argv
[
1
],
'wb'
)
as
f
:
f
.
write
(
buf
)
plugins/uefi-dbx/fu-dbxtool.c
View file @
fcb5667d
...
...
@@ -18,7 +18,7 @@
#include
"fu-efivar.h"
#include
"fu-uefi-dbx-common.h"
#include
"fu-efi-signature-common.h"
#include
"fu-efi-signature
-parser
.h"
#include
"fu-efi-signature.h"
/* custom return code */
#define EXIT_NOTHING_TO_DO 2
...
...
@@ -29,29 +29,30 @@ fu_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level,
{
}
static
GPtrArray
*
static
FuFirmware
*
fu_dbxtool_get_siglist_system
(
GError
**
error
)
{
g
size
bufsz
=
0
;
g_auto
free
guint8
*
buf
=
NULL
;
if
(
!
fu_efivar_get_data
(
FU_EFIVAR_GUID_SECURITY_DATABASE
,
"dbx"
,
&
buf
,
&
bufsz
,
NULL
,
error
)
)
g
_autoptr
(
GBytes
)
blob
=
NULL
;
g_auto
ptr
(
FuFirmware
)
dbx
=
fu_efi_signature_list_new
()
;
blob
=
fu_efivar_get_data
_bytes
(
FU_EFIVAR_GUID_SECURITY_DATABASE
,
"dbx"
,
NULL
,
error
);
if
(
blob
==
NULL
)
return
NULL
;
return
fu_
e
fi
_signature_parser_new
(
buf
,
bufsz
,
FU_EFI_SIGNATURE_PARSER_FLAGS_NONE
,
error
);
if
(
!
fu_fi
rmware_parse
(
dbx
,
blob
,
FWUPD_INSTALL_FLAG_NO_SEARCH
,
error
))
return
NULL
;
return
g_steal_pointer
(
&
dbx
);
}
static
GPtrArray
*
static
FuFirmware
*
fu_dbxtool_get_siglist_local
(
const
gchar
*
filename
,
GError
**
error
)
{
gsize
bufsz
=
0
;
g_autofree
guint8
*
buf
=
NULL
;
if
(
!
g_file_get_contents
(
filename
,
(
gchar
**
)
&
buf
,
&
bufsz
,
error
))
g_autoptr
(
GBytes
)
blob
=
NULL
;
g_autoptr
(
FuFirmware
)
siglist
=
fu_efi_signature_list_new
();
blob
=
fu_common_get_contents_bytes
(
filename
,
error
);
if
(
blob
==
NULL
)
return
NULL
;
if
(
!
fu_firmware_parse
(
siglist
,
blob
,
FWUPD_INSTALL_FLAG_NONE
,
error
))
return
NULL
;
return
fu_efi_signature_parser_new
(
buf
,
bufsz
,
FU_EFI_SIGNATURE_PARSER_FLAGS_IGNORE_HEADER
,
error
);
return
g_steal_pointer
(
&
siglist
);
}
int
...
...
@@ -123,7 +124,8 @@ main (int argc, char *argv[])
/* list contents, either of the existing system, or an update */
if
(
action_list
||
action_version
)
{
guint
cnt
=
1
;
g_autoptr
(
GPtrArray
)
dbx
=
NULL
;
g_autoptr
(
FuFirmware
)
dbx
=
NULL
;
g_autoptr
(
GPtrArray
)
sigs
=
NULL
;
if
(
dbxfile
!=
NULL
)
{
dbx
=
fu_dbxtool_get_siglist_local
(
dbxfile
,
&
error
);
if
(
dbx
==
NULL
)
{
...
...
@@ -141,20 +143,21 @@ main (int argc, char *argv[])
}
if
(
action_version
)
{
/* TRANSLATORS: the detected version number of the dbx */
g_print
(
"%s: %
u
\n
"
,
_
(
"Version"
),
fu_
e
fi
_signature_list_array
_version
(
dbx
));
g_print
(
"%s: %
s
\n
"
,
_
(
"Version"
),
fu_fi
rmware_get
_version
(
dbx
));
return
EXIT_SUCCESS
;
}
for
(
guint
j
=
0
;
j
<
dbx
->
len
;
j
++
)
{
FuEfiSignatureList
*
siglist
=
g_ptr_array_index
(
dbx
,
j
);
GPtrArray
*
sigs
=
fu_efi_signature_list_get_all
(
siglist
);
for
(
guint
i
=
0
;
i
<
sigs
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
sigs
,
i
);
g_print
(
"%4u: {%s} {%s} %s
\n
"
,
cnt
++
,
fu_efi_signature_guid_to_string
(
fu_efi_signature_get_owner
(
sig
)),
fu_efi_signature_kind_to_string
(
fu_efi_signature_get_kind
(
sig
)),
fu_efi_signature_get_checksum
(
sig
));
}
sigs
=
fu_firmware_get_images
(
FU_FIRMWARE
(
dbx
));
for
(
guint
i
=
0
;
i
<
sigs
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
sigs
,
i
);
g_autofree
gchar
*
checksum
=
NULL
;
checksum
=
fu_firmware_image_get_checksum
(
FU_FIRMWARE_IMAGE
(
sig
),
G_CHECKSUM_SHA256
,
NULL
);
g_print
(
"%4u: {%s} {%s} %s
\n
"
,
cnt
++
,
fu_efi_signature_guid_to_string
(
fu_efi_signature_get_owner
(
sig
)),
fu_efi_signature_kind_to_string
(
fu_efi_signature_get_kind
(
sig
)),
checksum
);
}
return
EXIT_SUCCESS
;
}
...
...
@@ -169,10 +172,9 @@ main (int argc, char *argv[])
/* apply update */
if
(
action_apply
)
{
gsize
bufsz
=
0
;
g_autofree
guint8
*
buf
=
NULL
;
g_autoptr
(
GPtrArray
)
dbx_system
=
NULL
;
g_autoptr
(
GPtrArray
)
dbx_update
=
NULL
;
g_autoptr
(
FuFirmware
)
dbx_system
=
NULL
;
g_autoptr
(
FuFirmware
)
dbx_update
=
fu_efi_signature_list_new
();
g_autoptr
(
GBytes
)
blob
=
NULL
;
if
(
dbxfile
==
NULL
)
{
/* TRANSLATORS: user did not include a filename parameter */
...
...
@@ -191,27 +193,20 @@ main (int argc, char *argv[])
/* TRANSLATORS: reading new dbx from the update */
g_print
(
"%s
\n
"
,
_
(
"Parsing dbx update…"
));
if
(
!
g_file_get_contents
(
dbxfile
,
(
gchar
**
)
&
buf
,
&
bufsz
,
&
error
))
{
blob
=
fu_common_get_contents_bytes
(
dbxfile
,
&
error
);
if
(
blob
==
NULL
)
{
/* TRANSLATORS: could not read file */
g_printerr
(
"%s: %s
\n
"
,
_
(
"Failed to load local dbx"
),
error
->
message
);
return
EXIT_FAILURE
;
}
dbx_update
=
fu_efi_signature_parser_new
(
buf
,
bufsz
,
FU_EFI_SIGNATURE_PARSER_FLAGS_IGNORE_HEADER
,
&
error
);
if
(
dbx_update
==
NULL
)
{
if
(
!
fu_firmware_parse
(
dbx_update
,
blob
,
FWUPD_INSTALL_FLAG_NONE
,
&
error
))
{
/* TRANSLATORS: could not parse file */
g_printerr
(
"%s: %s
\n
"
,
_
(
"Failed to parse local dbx"
),
error
->
message
);
return
EXIT_FAILURE
;
}
if
(
dbx_update
->
len
!=
1
)
{
/* TRANSLATORS: could not parse file */
g_printerr
(
"%s: %s
\n
"
,
_
(
"Failed to extract local dbx "
),
error
->
message
);
return
EXIT_FAILURE
;
}
/* check this is a newer dbx update */
if
(
!
force
&&
fu_efi_signature_list_
array_
inclusive
(
dbx_system
,
dbx_update
))
{
if
(
!
force
&&
fu_efi_signature_list_inclusive
(
FU_EFI_SIGNATURE_LIST
(
dbx_system
)
,
FU_EFI_SIGNATURE_LIST
(
dbx_update
))
)
{
/* TRANSLATORS: same or newer update already applied */
g_printerr
(
"%s
\n
"
,
_
(
"Cannot apply as dbx update has already been applied."
));
return
EXIT_FAILURE
;
...
...
@@ -228,7 +223,7 @@ main (int argc, char *argv[])
if
(
!
force
)
{
/* TRANSLATORS: ESP refers to the EFI System Partition */
g_print
(
"%s
\n
"
,
_
(
"Validating ESP contents…"
));
if
(
!
fu_uefi_dbx_signature_list_validate
(
dbx_update
,
&
error
))
{
if
(
!
fu_uefi_dbx_signature_list_validate
(
FU_EFI_SIGNATURE_LIST
(
dbx_update
)
,
&
error
))
{
/* TRANSLATORS: something with a blocked hash exists
* in the users ESP -- which would be bad! */
g_printerr
(
"%s: %s
\n
"
,
_
(
"Failed to validate ESP contents"
),
error
->
message
);
...
...
@@ -238,14 +233,14 @@ main (int argc, char *argv[])
/* TRANSLATORS: actually sending the update to the hardware */
g_print
(
"%s
\n
"
,
_
(
"Applying update…"
));
if
(
!
fu_efivar_set_data
(
FU_EFIVAR_GUID_SECURITY_DATABASE
,
"dbx"
,
b
uf
,
bufsz
,
FU_EFIVAR_ATTR_APPEND_WRITE
|
FU_EFIVAR_ATTR_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
|
FU_EFIVAR_ATTR_RUNTIME_ACCESS
|
FU_EFIVAR_ATTR_BOOTSERVICE_ACCESS
|
FU_EFIVAR_ATTR_NON_VOLATILE
,
&
error
))
{
if
(
!
fu_efivar_set_data
_bytes
(
FU_EFIVAR_GUID_SECURITY_DATABASE
,
"dbx"
,
b
lob
,
FU_EFIVAR_ATTR_APPEND_WRITE
|
FU_EFIVAR_ATTR_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
|
FU_EFIVAR_ATTR_RUNTIME_ACCESS
|
FU_EFIVAR_ATTR_BOOTSERVICE_ACCESS
|
FU_EFIVAR_ATTR_NON_VOLATILE
,
&
error
))
{
/* TRANSLATORS: dbx file failed to be applied as an update */
g_printerr
(
"%s: %s
\n
"
,
_
(
"Failed to apply update"
),
error
->
message
);
return
EXIT_FAILURE
;
...
...
plugins/uefi-dbx/fu-efi-signature-common.c
View file @
fcb5667d
...
...
@@ -8,52 +8,29 @@
#include
"fu-efi-signature-common.h"
#include
"fu-efi-signature-list.h"
#include
"fu-efi-signature.h"
gboolean
fu_efi_signature_list_
array_
has_checksum
(
GPtrArray
*
siglist
s
,
const
gchar
*
checksum
)
fu_efi_signature_list_has_checksum
(
FuEfiSignatureList
*
siglist
,
const
gchar
*
checksum
)
{
for
(
guint
i
=
0
;
i
<
siglists
->
len
;
i
++
)
{
FuEfiSignatureList
*
siglist
=
g_ptr_array_index
(
siglists
,
i
);
if
(
fu_efi_signature_list_has_checksum
(
siglist
,
checksum
))
return
TRUE
;
}
return
FALSE
;
g_autoptr
(
FuFirmwareImage
)
img
=
NULL
;
img
=
fu_firmware_get_image_by_checksum
(
FU_FIRMWARE
(
siglist
),
checksum
,
NULL
);
return
img
!=
NULL
;
}
gboolean
fu_efi_signature_list_
array_
inclusive
(
GPtrArray
*
outer
,
GPtrArray
*
inner
)
fu_efi_signature_list_inclusive
(
FuEfiSignatureList
*
outer
,
FuEfiSignatureList
*
inner
)
{
for
(
guint
j
=
0
;
j
<
inner
->
len
;
j
++
)
{
FuEfiSignatureList
*
siglist
=
g_ptr_array_index
(
inner
,
j
);
GPtrArray
*
items
=
fu_efi_signature_list_get_all
(
siglist
);
for
(
guint
i
=
0
;
i
<
items
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
items
,
i
);
const
gchar
*
checksum
=
fu_efi_signature_get_checksum
(
sig
);
if
(
!
fu_efi_signature_list_array_has_checksum
(
outer
,
checksum
))
return
FALSE
;
}
g_autoptr
(
GPtrArray
)
sigs
=
fu_firmware_get_images
(
FU_FIRMWARE
(
inner
));
for
(
guint
i
=
0
;
i
<
sigs
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
sigs
,
i
);
g_autofree
gchar
*
checksum
=
NULL
;
checksum
=
fu_firmware_image_get_checksum
(
FU_FIRMWARE_IMAGE
(
sig
),
G_CHECKSUM_SHA256
,
NULL
);
if
(
checksum
==
NULL
)
continue
;
if
(
!
fu_efi_signature_list_has_checksum
(
outer
,
checksum
))
return
FALSE
;
}
return
TRUE
;
}
guint
fu_efi_signature_list_array_version
(
GPtrArray
*
siglists
)
{
guint
csum_cnt
=
0
;
const
gchar
*
ignored_guids
[]
=
{
FU_EFI_SIGNATURE_GUID_OVMF
,
NULL
};
for
(
guint
j
=
0
;
j
<
siglists
->
len
;
j
++
)
{
FuEfiSignatureList
*
siglist
=
g_ptr_array_index
(
siglists
,
j
);
GPtrArray
*
items
=
fu_efi_signature_list_get_all
(
siglist
);
for
(
guint
i
=
0
;
i
<
items
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
items
,
i
);
if
(
fu_efi_signature_get_kind
(
sig
)
!=
FU_EFI_SIGNATURE_KIND_SHA256
)
continue
;
if
(
g_strv_contains
(
ignored_guids
,
fu_efi_signature_get_owner
(
sig
)))
continue
;
csum_cnt
++
;
}
}
return
csum_cnt
;
}
plugins/uefi-dbx/fu-efi-signature-common.h
View file @
fcb5667d
...
...
@@ -6,10 +6,9 @@
#pragma once
#include
"fu-efi-signature.h"
#include
"fu-efi-signature
-list
.h"
gboolean
fu_efi_signature_list_array_inclusive
(
GPtrArray
*
outer
,
GPtrArray
*
inner
);
guint
fu_efi_signature_list_array_version
(
GPtrArray
*
siglists
);
gboolean
fu_efi_signature_list_array_has_checksum
(
GPtrArray
*
siglists
,
const
gchar
*
checksum
);
gboolean
fu_efi_signature_list_inclusive
(
FuEfiSignatureList
*
outer
,
FuEfiSignatureList
*
inner
);
gboolean
fu_efi_signature_list_has_checksum
(
FuEfiSignatureList
*
siglist
,
const
gchar
*
checksum
);
plugins/uefi-dbx/fu-efi-signature-list.c
View file @
fcb5667d
...
...
@@ -6,74 +6,242 @@
#include
"config.h"
#include
<fwupd.h>
#include
"fu-common.h"
#include
"fu-efi-signature.h"
#include
"fu-efi-signature-list.h"
struct
_FuEfiSignatureList
{
GObject
parent_instance
;
FuEfiSignatureKind
kind
;
GPtrArray
*
items
;
/* element-type: FuEfiSignature */
FuFirmware
parent_instance
;
};
G_DEFINE_TYPE
(
FuEfiSignatureList
,
fu_efi_signature_list
,
G
_TYPE_
OBJECT
)
G_DEFINE_TYPE
(
FuEfiSignatureList
,
fu_efi_signature_list
,
FU
_TYPE_
FIRMWARE
)
FuEfiSignatureList
*
fu_efi_signature_list_new
(
FuEfiSignatureKind
kind
)
static
gboolean
fu_efi_signature_list_parse_item
(
FuEfiSignatureList
*
self
,
FuEfiSignatureKind
sig_kind
,
const
guint8
*
buf
,
gsize
bufsz
,
gsize
offset
,
guint32
sig_size
,
GError
**
error
)
{
g_autoptr
(
FuEfiSignatureList
)
self
=
g_object_new
(
FU_TYPE_EFI_SIGNATURE_LIST
,
NULL
);
self
->
kind
=
kind
;
return
g_steal_pointer
(
&
self
);
fwupd_guid_t
guid
;
gsize
sig_datasz
=
sig_size
-
sizeof
(
fwupd_guid_t
);
g_autofree
gchar
*
sig_owner
=
NULL
;
g_autofree
guint8
*
sig_data
=
g_malloc0
(
sig_datasz
);
g_autoptr
(
FuEfiSignature
)
sig
=
NULL
;
g_autoptr
(
GBytes
)
data
=
NULL
;
/* read both blocks of data */
if
(
!
fu_memcpy_safe
((
guint8
*
)
&
guid
,
sizeof
(
guid
),
0x0
,
/* dst */
buf
,
bufsz
,
offset
,
/* src */
sizeof
(
guid
),
error
))
{
g_prefix_error
(
error
,
"failed to read signature GUID: "
);
return
FALSE
;
}
if
(
!
fu_memcpy_safe
(
sig_data
,
sig_datasz
,
0x0
,
/* dst */
buf
,
bufsz
,
offset
+
sizeof
(
fwupd_guid_t
),
/* src */
sig_datasz
,
error
))
{
g_prefix_error
(
error
,
"failed to read signature data: "
);
return
FALSE
;
}
/* create item */
sig_owner
=
fwupd_guid_to_string
(
&
guid
,
FWUPD_GUID_FLAG_MIXED_ENDIAN
);
data
=
g_bytes_new
(
sig_data
,
sig_datasz
);
sig
=
fu_efi_signature_new
(
sig_kind
,
sig_owner
);
fu_firmware_image_set_bytes
(
FU_FIRMWARE_IMAGE
(
sig
),
data
);
fu_firmware_add_image
(
FU_FIRMWARE
(
self
),
FU_FIRMWARE_IMAGE
(
sig
));
return
TRUE
;
}
FuEfiSignatureKind
fu_efi_signature_list_get_kind
(
FuEfiSignatureList
*
self
)
static
gboolean
fu_efi_signature_list_parse_list
(
FuEfiSignatureList
*
self
,
const
guint8
*
buf
,
gsize
bufsz
,
gsize
*
offset
,
GError
**
error
)
{
g_return_val_if_fail
(
FU_IS_EFI_SIGNATURE_LIST
(
self
),
0
);
return
self
->
kind
;
FuEfiSignatureKind
sig_kind
=
FU_EFI_SIGNATURE_KIND_UNKNOWN
;
fwupd_guid_t
guid
;
gsize
offset_tmp
;
guint32
sig_header_size
=
0
;
guint32
sig_list_size
=
0
;
guint32
sig_size
=
0
;
g_autofree
gchar
*
sig_type
=
NULL
;
/* read EFI_SIGNATURE_LIST */
if
(
!
fu_memcpy_safe
((
guint8
*
)
&
guid
,
sizeof
(
guid
),
0x0
,
/* dst */
buf
,
bufsz
,
*
offset
,
/* src */
sizeof
(
guid
),
error
))
{
g_prefix_error
(
error
,
"failed to read GUID header: "
);
return
FALSE
;
}
sig_type
=
fwupd_guid_to_string
(
&
guid
,
FWUPD_GUID_FLAG_MIXED_ENDIAN
);
if
(
g_strcmp0
(
sig_type
,
"c1c41626-504c-4092-aca9-41f936934328"
)
==
0
)
{
sig_kind
=
FU_EFI_SIGNATURE_KIND_SHA256
;
}
else
if
(
g_strcmp0
(
sig_type
,
"a5c059a1-94e4-4aa7-87b5-ab155c2bf072"
)
==
0
)
{
sig_kind
=
FU_EFI_SIGNATURE_KIND_X509
;
}
if
(
!
fu_common_read_uint32_safe
(
buf
,
bufsz
,
*
offset
+
0x10
,
&
sig_list_size
,
G_LITTLE_ENDIAN
,
error
))
return
FALSE
;
if
(
sig_list_size
<
0x1c
||
sig_list_size
>
1024
*
1024
)
{
g_set_error
(
error
,
G_IO_ERROR
,
G_IO_ERROR_FAILED
,
"SignatureListSize invalid: 0x%x"
,
sig_list_size
);
return
FALSE
;
}
if
(
!
fu_common_read_uint32_safe
(
buf
,
bufsz
,
*
offset
+
0x14
,
&
sig_header_size
,
G_LITTLE_ENDIAN
,
error
))
return
FALSE
;
if
(
sig_header_size
>
1024
*
1024
)
{
g_set_error
(
error
,
G_IO_ERROR
,
G_IO_ERROR_FAILED
,
"SignatureHeaderSize invalid: 0x%x"
,
sig_size
);
return
FALSE
;
}
if
(
!
fu_common_read_uint32_safe
(
buf
,
bufsz
,
*
offset
+
0x18
,
&
sig_size
,
G_LITTLE_ENDIAN
,
error
))
return
FALSE
;
if
(
sig_size
<
sizeof
(
fwupd_guid_t
)
||
sig_size
>
1024
*
1024
)
{
g_set_error
(
error
,
G_IO_ERROR
,
G_IO_ERROR_FAILED
,
"SignatureSize invalid: 0x%x"
,
sig_size
);
return
FALSE
;
}
/* header is typically unused */
offset_tmp
=
*
offset
+
0x1c
+
sig_header_size
;
for
(
guint
i
=
0
;
i
<
(
sig_list_size
-
0x1c
)
/
sig_size
;
i
++
)
{
if
(
!
fu_efi_signature_list_parse_item
(
self
,
sig_kind
,
buf
,
bufsz
,
offset_tmp
,
sig_size
,
error
))
return
FALSE
;
offset_tmp
+=
sig_size
;
}
*
offset
+=
sig_list_size
;
return
TRUE
;
}
GPtrArray
*
fu_efi_signature_list_get_
all
(
FuEfiSignatureList
*
self
)
static
gchar
*
fu_efi_signature_list_get_
version
(
FuEfiSignatureList
*
self
)
{
g_return_val_if_fail
(
FU_IS_EFI_SIGNATURE_LIST
(
self
),
NULL
);
return
self
->
items
;
guint
csum_cnt
=
0
;
const
gchar
*
ignored_guids
[]
=
{
FU_EFI_SIGNATURE_GUID_OVMF
,
NULL
};
g_autoptr
(
GPtrArray
)
sigs
=
NULL
;
sigs
=
fu_firmware_get_images
(
FU_FIRMWARE
(
self
));
for
(
guint
i
=
0
;
i
<
sigs
->
len
;
i
++
)
{
FuEfiSignature
*
sig
=
g_ptr_array_index
(
sigs
,
i
);
if
(
fu_efi_signature_get_kind
(
sig
)
!=
FU_EFI_SIGNATURE_KIND_SHA256
)
continue
;
if
(
g_strv_contains
(
ignored_guids
,
fu_efi_signature_get_owner
(
sig
)))
continue
;
csum_cnt
++
;
}
return
g_strdup_printf
(
"%u"
,
csum_cnt
);
}
void
fu_efi_signature_list_add
(
FuEfiSignatureList
*
self
,
FuEfiSignature
*
signature
)
static
gboolean
fu_efi_signature_list_parse
(
FuFirmware
*
firmware
,
GBytes
*
fw
,
guint64
addr_start
,
guint64
addr_end
,
FwupdInstallFlags
flags
,
GError
**
error
)
{
g_return_if_fail
(
FU_IS_EFI_SIGNATURE_LIST
(
self
));
g_ptr_array_add
(
self
->
items
,
g_object_ref
(
signature
));
FuEfiSignatureList
*
self
=
FU_EFI_SIGNATURE_LIST
(
firmware
);
gsize
bufsz
=
0
;
gsize
offset_fs
=
0
;
const
guint8
*
buf
=
g_bytes_get_data
(
fw
,
&
bufsz
);
g_autofree
gchar
*
version_str
=
NULL
;
/* this allows us to skip the efi permissions uint32_t or even the
* Microsoft PKCS-7 signature */
if
((
flags
&
FWUPD_INSTALL_FLAG_NO_SEARCH
)
==
0
)
{
if
(
bufsz
<
5
)
{
g_set_error
(
error
,
G_IO_ERROR
,
G_IO_ERROR_FAILED
,
"signature invalid: 0x%x"
,
(
guint
)
bufsz
);
return
FALSE
;
}
for
(
gsize
i
=
0
;
i
<
bufsz
-
5
;
i
++
)
{
if
(
memcmp
(
buf
+
i
,
"
\x26\x16\xc4\xc1\x4c
"
,
5
)
==
0
)
{
g_debug
(
"found EFI_SIGNATURE_LIST @0x%x"
,
(
guint
)
i
);
offset_fs
=
i
;
break
;
}
}
}
/* parse each EFI_SIGNATURE_LIST */
for
(
gsize
offset
=
offset_fs
;
offset
<
bufsz
;)
{
if
(
!
fu_efi_signature_list_parse_list
(
self
,
buf
,
bufsz
,
&
offset
,
error
))
return
FALSE
;
}
/* set version */
version_str
=
fu_efi_signature_list_get_version
(
self
);
if
(
version_str
!=
NULL
)
fu_firmware_set_version
(
firmware
,
version_str
);
/* success */
return
TRUE
;
}
gboolean
fu_efi_signature_list_
has_checksum
(
FuEfiSignatureList
*
self
,
const
gchar
*
checksum
)
static
GBytes
*
fu_efi_signature_list_
write
(
FuFirmware
*
firmware
,
GError
**
error
)
{
g_return_val_if_fail
(
FU_IS_EFI_SIGNATURE_LIST
(
self
),
FALSE
);
for
(
guint
i
=
0
;
i
<
self
->
items
->
len
;
i
++
)
{
FuEfiSignature
*
item
=
g_ptr_array_index
(
self
->
items
,
i
);
if
(
g_strcmp0
(
fu_efi_signature_get_checksum
(
item
),
checksum
)
==
0
)
return
TRUE
;
}
return
FALSE
;
GByteArray
*
buf
=
g_byte_array_new
();
/* SignatureType */
for
(
guint
i
=
0
;
i
<
16
;
i
++
)
fu_byte_array_append_uint8
(
buf
,
0x0
);
/* SignatureListSize */
fu_byte_array_append_uint32
(
buf
,
16
+
4
+
4
+
4
+
16
+
32
,
G_LITTLE_ENDIAN
);
/* SignatureHeaderSize */
fu_byte_array_append_uint32
(
buf
,
0
,
G_LITTLE_ENDIAN
);
/* SignatureSize */
fu_byte_array_append_uint32
(
buf
,
16
+
32
,
G_LITTLE_ENDIAN
);
/* SignatureOwner */
for
(
guint
i
=
0
;
i
<
16
;
i
++
)
fu_byte_array_append_uint8
(
buf
,
'1'
);
/* SignatureData */
for
(
guint
i
=
0
;
i
<
16
;
i
++
)
fu_byte_array_append_uint8
(
buf
,
'2'
);
return
g_byte_array_free_to_bytes
(
buf
);
}
static
void
fu_efi_signature_list_
finalize
(
GObject
*
obj
)
FuFirmware
*
fu_efi_signature_list_
new
(
void
)
{
FuEfiSignatureList
*
self
=
FU_EFI_SIGNATURE_LIST
(
obj
);
g_ptr_array_unref
(
self
->
items
);
G_OBJECT_CLASS
(
fu_efi_signature_list_parent_class
)
->
finalize
(
obj
);
return
g_object_new
(
FU_TYPE_EFI_SIGNATURE_LIST
,
NULL
);
}
static
void
fu_efi_signature_list_class_init
(
FuEfiSignatureListClass
*
klass
)
{
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
klass
);
object_class
->
finalize
=
fu_efi_signature_list_finalize
;
FuFirmwareClass
*
klass_firmware
=
FU_FIRMWARE_CLASS
(
klass
);
klass_firmware
->
parse
=
fu_efi_signature_list_parse
;
klass_firmware
->
write
=
fu_efi_signature_list_write
;
}
static
void
fu_efi_signature_list_init
(
FuEfiSignatureList
*
self
)
{
self
->
items
=
g_ptr_array_new_with_free_func
((
GDestroyNotify
)
g_object_unref
);
}
plugins/uefi-dbx/fu-efi-signature-list.h
View file @
fcb5667d
...
...
@@ -6,16 +6,9 @@
#pragma once
#include
"fu-
e
fi
-signatu
re.h"
#include
"fu-fi
rmwa
re.h"
#define FU_TYPE_EFI_SIGNATURE_LIST (fu_efi_signature_list_get_type ())
G_DECLARE_FINAL_TYPE
(
FuEfiSignatureList
,
fu_efi_signature_list
,
FU
,
EFI_SIGNATURE_LIST
,
GObject
)
G_DECLARE_FINAL_TYPE
(
FuEfiSignatureList
,
fu_efi_signature_list
,
FU
,
EFI_SIGNATURE_LIST
,
FuFirmware
)
FuEfiSignatureList
*
fu_efi_signature_list_new
(
FuEfiSignatureKind
kind
);
FuEfiSignatureKind
fu_efi_signature_list_get_kind
(
FuEfiSignatureList
*
self
);
void
fu_efi_signature_list_add
(
FuEfiSignatureList
*
self
,
FuEfiSignature
*
signature
);