|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* Copyright (c) 2018, Red Hat Inc.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
3749ba |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
3749ba |
* are met:
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* * Redistributions of source code must retain the above
|
|
Packit Service |
3749ba |
* copyright notice, this list of conditions and the
|
|
Packit Service |
3749ba |
* following disclaimer.
|
|
Packit Service |
3749ba |
* * Redistributions in binary form must reproduce the
|
|
Packit Service |
3749ba |
* above copyright notice, this list of conditions and
|
|
Packit Service |
3749ba |
* the following disclaimer in the documentation and/or
|
|
Packit Service |
3749ba |
* other materials provided with the distribution.
|
|
Packit Service |
3749ba |
* * The names of contributors to this software may not be
|
|
Packit Service |
3749ba |
* used to endorse or promote products derived from this
|
|
Packit Service |
3749ba |
* software without specific prior written permission.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit Service |
3749ba |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit Service |
3749ba |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
Packit Service |
3749ba |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
Packit Service |
3749ba |
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
Packit Service |
3749ba |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
Packit Service |
3749ba |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
Packit Service |
3749ba |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
Packit Service |
3749ba |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit Service |
3749ba |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
Packit Service |
3749ba |
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
Packit Service |
3749ba |
* DAMAGE.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Author: Laszlo Ersek <lersek@redhat.com>
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "config.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "buffer.h" /* p11_buffer */
|
|
Packit Service |
3749ba |
#include "debug.h" /* return_val_if_fail() */
|
|
Packit Service |
3749ba |
#include "message.h" /* p11_message() */
|
|
Packit Service |
3749ba |
#include "extract.h" /* p11_extract_edk2_cacerts() */
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include <stdint.h> /* UINT32_MAX */
|
|
Packit Service |
3749ba |
#include <limits.h> /* SSIZE_MAX */
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* types from the UEFI 2.7 spec, section "31.4.1 Signature Database" */
|
|
Packit Service |
3749ba |
typedef struct {
|
|
Packit Service |
3749ba |
uint32_t data1;
|
|
Packit Service |
3749ba |
uint16_t data2;
|
|
Packit Service |
3749ba |
uint16_t data3;
|
|
Packit Service |
3749ba |
uint8_t data4[8];
|
|
Packit Service |
3749ba |
} efi_guid;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
typedef struct {
|
|
Packit Service |
3749ba |
efi_guid signature_type;
|
|
Packit Service |
3749ba |
uint32_t signature_list_size;
|
|
Packit Service |
3749ba |
uint32_t signature_header_size;
|
|
Packit Service |
3749ba |
uint32_t signature_size;
|
|
Packit Service |
3749ba |
} efi_signature_list;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
typedef struct {
|
|
Packit Service |
3749ba |
efi_guid signature_owner;
|
|
Packit Service |
3749ba |
} efi_signature_data;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* EFI_CERT_X509_GUID (A5C059A1-94E4-4AA7-87B5-AB155C2BF072) from the UEFI 2.7
|
|
Packit Service |
3749ba |
* spec, in host byte order
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
static const efi_guid efi_cert_x509_guid_host = {
|
|
Packit Service |
3749ba |
0xa5c059a1,
|
|
Packit Service |
3749ba |
0x94e4,
|
|
Packit Service |
3749ba |
0x4aa7,
|
|
Packit Service |
3749ba |
{ 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 }
|
|
Packit Service |
3749ba |
};
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* the GUID identifying this extractor as "agent"
|
|
Packit Service |
3749ba |
* (DCDD3B50-F405-43FD-96BE-BD33B1734776, generated with "uuidgen"), in host
|
|
Packit Service |
3749ba |
* byte order
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
static const efi_guid agent_guid_host = {
|
|
Packit Service |
3749ba |
0xdcdd3b50,
|
|
Packit Service |
3749ba |
0xf405,
|
|
Packit Service |
3749ba |
0x43fd,
|
|
Packit Service |
3749ba |
{ 0x96, 0xbe, 0xbd, 0x33, 0xb1, 0x73, 0x47, 0x76 }
|
|
Packit Service |
3749ba |
};
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* serialization helpers */
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
buffer_add_uint16 (p11_buffer *buffer,
|
|
Packit Service |
3749ba |
uint16_t uint16)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
uint8_t uint16_buf[2];
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
uint16_buf[0] = uint16;
|
|
Packit Service |
3749ba |
uint16_buf[1] = uint16 >> 8;
|
|
Packit Service |
3749ba |
p11_buffer_add (buffer, &uint16_buf, sizeof uint16_buf);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
buffer_add_uint32 (p11_buffer *buffer,
|
|
Packit Service |
3749ba |
uint32_t uint32)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
uint8_t uint32_buf[4];
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
uint32_buf[0] = uint32;
|
|
Packit Service |
3749ba |
uint32_buf[1] = uint32 >> 8;
|
|
Packit Service |
3749ba |
uint32_buf[2] = uint32 >> 16;
|
|
Packit Service |
3749ba |
uint32_buf[3] = uint32 >> 24;
|
|
Packit Service |
3749ba |
p11_buffer_add (buffer, &uint32_buf, sizeof uint32_buf);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
buffer_add_efi_guid (p11_buffer *buffer,
|
|
Packit Service |
3749ba |
const efi_guid *guid)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
buffer_add_uint32 (buffer, guid->data1);
|
|
Packit Service |
3749ba |
buffer_add_uint16 (buffer, guid->data2);
|
|
Packit Service |
3749ba |
buffer_add_uint16 (buffer, guid->data3);
|
|
Packit Service |
3749ba |
p11_buffer_add (buffer, guid->data4, sizeof guid->data4);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
buffer_add_efi_signature_list (p11_buffer *buffer,
|
|
Packit Service |
3749ba |
const efi_signature_list *siglist)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
buffer_add_efi_guid (buffer, &siglist->signature_type);
|
|
Packit Service |
3749ba |
buffer_add_uint32 (buffer, siglist->signature_list_size);
|
|
Packit Service |
3749ba |
buffer_add_uint32 (buffer, siglist->signature_header_size);
|
|
Packit Service |
3749ba |
buffer_add_uint32 (buffer, siglist->signature_size);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
buffer_add_efi_signature_data (p11_buffer *buffer,
|
|
Packit Service |
3749ba |
const efi_signature_data *sigdata)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
buffer_add_efi_guid (buffer, &sigdata->signature_owner);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* main routine */
|
|
Packit Service |
3749ba |
static bool
|
|
Packit Service |
3749ba |
prepare_edk2_buffer (p11_enumerate *ex,
|
|
Packit Service |
3749ba |
p11_buffer *buffer)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
efi_signature_list siglist;
|
|
Packit Service |
3749ba |
efi_signature_data sigdata;
|
|
Packit Service |
3749ba |
CK_RV rv;
|
|
Packit Service |
3749ba |
size_t size;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* set "siglist.signature_type" and "sigdata.signature_owner" for reuse
|
|
Packit Service |
3749ba |
* across all certificates
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
siglist.signature_type = efi_cert_x509_guid_host;
|
|
Packit Service |
3749ba |
sigdata.signature_owner = agent_guid_host;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* also reuse a zero "siglist.signature_header_size" */
|
|
Packit Service |
3749ba |
siglist.signature_header_size = 0;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* for every certificate */
|
|
Packit Service |
3749ba |
while ((rv = p11_kit_iter_next (ex->iter)) == CKR_OK) {
|
|
Packit Service |
3749ba |
size = sizeof sigdata;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* set the variable size fields in "siglist" while catching any
|
|
Packit Service |
3749ba |
* (unlikely) integer overflows
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
return_val_if_fail (ex->cert_len <= UINT32_MAX - size, false);
|
|
Packit Service |
3749ba |
size += ex->cert_len;
|
|
Packit Service |
3749ba |
siglist.signature_size = size;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return_val_if_fail (sizeof siglist <= UINT32_MAX - size, false);
|
|
Packit Service |
3749ba |
size += sizeof siglist;
|
|
Packit Service |
3749ba |
siglist.signature_list_size = size;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* serialize the headers */
|
|
Packit Service |
3749ba |
buffer_add_efi_signature_list (buffer, &siglist);
|
|
Packit Service |
3749ba |
buffer_add_efi_signature_data (buffer, &sigdata);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* serialize the DER encoding of the certificate */
|
|
Packit Service |
3749ba |
return_val_if_fail (ex->cert_len <= SSIZE_MAX, false);
|
|
Packit Service |
3749ba |
p11_buffer_add (buffer, ex->cert_der, ex->cert_len);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (rv != CKR_CANCEL) {
|
|
Packit Service |
3749ba |
p11_message ("failed to find certificate: %s",
|
|
Packit Service |
3749ba |
p11_kit_strerror (rv));
|
|
Packit Service |
3749ba |
return false;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return_val_if_fail (p11_buffer_ok (buffer), false);
|
|
Packit Service |
3749ba |
return true;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
bool
|
|
Packit Service |
3749ba |
p11_extract_edk2_cacerts (p11_enumerate *ex,
|
|
Packit Service |
3749ba |
const char *destination)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_buffer buffer;
|
|
Packit Service |
3749ba |
p11_save_file *file;
|
|
Packit Service |
3749ba |
bool ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_buffer_init (&buffer, 1024 * 10);
|
|
Packit Service |
3749ba |
ret = prepare_edk2_buffer (ex, &buffer);
|
|
Packit Service |
3749ba |
if (ret) {
|
|
Packit Service |
3749ba |
file = p11_save_open_file (destination, NULL, ex->flags);
|
|
Packit Service |
3749ba |
ret = p11_save_write_and_finish (file, buffer.data, buffer.len);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_buffer_uninit (&buffer);
|
|
Packit Service |
3749ba |
return ret;
|
|
Packit Service |
3749ba |
}
|