blob: fe65e1542f51e608fef92420400732886dfb4649 [file] [log] [blame]
/*
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
*
* see COPYING file
*/
#include <stdint.h>
#define __STDC_VERSION__ 199901L
#include <efi.h>
#ifdef CONFIG_arm
/* FIXME:
* arm efi leaves a visibilit pragma pushed that won't work for
* non efi programs, so eliminate it */
#pragma GCC visibility pop
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <guid.h>
#include <variables.h>
#include <version.h>
static void
usage(const char *progname)
{
printf("Usage: %s [-g <guid>] <crt file> <efi sig list file>\n", progname);
}
static void
help(const char * progname)
{
usage(progname);
printf("Take an input X509 certificate (in PEM format) and convert it to an EFI\n"
"signature list file containing only that single certificate\n\n"
"Options:\n"
"\t-g <guid> Use <guid> as the owner of the signature. If this is not\n"
"\t supplied, an all zero guid will be used\n"
);
}
int
main(int argc, char *argv[])
{
char *certfile, *efifile;
const char *progname = argv[0];
EFI_GUID owner = { 0 };
while (argc > 1) {
if (strcmp("--version", argv[1]) == 0) {
version(progname);
exit(0);
} else if (strcmp("--help", argv[1]) == 0) {
help(progname);
exit(0);
} else if (strcmp("-g", argv[1]) == 0) {
str_to_guid(argv[2], &owner);
argv += 2;
argc -= 2;
} else {
break;
}
}
if (argc != 3) {
exit(1);
}
certfile = argv[1];
efifile = argv[2];
ERR_load_crypto_strings();
OpenSSL_add_all_digests();
OpenSSL_add_all_ciphers();
/* here we may get highly unlikely failures or we'll get a
* complaint about FIPS signatures (usually becuase the FIPS
* module isn't present). In either case ignore the errors
* (malloc will cause other failures out lower down */
ERR_clear_error();
BIO *cert_bio = BIO_new_file(certfile, "r");
X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL);
int PkCertLen = i2d_X509(cert, NULL);
PkCertLen += sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData);
EFI_SIGNATURE_LIST *PkCert = malloc (PkCertLen);
if (!PkCert) {
fprintf(stderr, "failed to malloc cert\n");
exit(1);
}
unsigned char *tmp = (unsigned char *)PkCert + sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData);
i2d_X509(cert, &tmp);
PkCert->SignatureListSize = PkCertLen;
PkCert->SignatureSize = (UINT32) (PkCertLen - sizeof(EFI_SIGNATURE_LIST));
PkCert->SignatureHeaderSize = 0;
PkCert->SignatureType = EFI_CERT_X509_GUID;
EFI_SIGNATURE_DATA *PkCertData = (void *)PkCert + sizeof(EFI_SIGNATURE_LIST);
PkCertData->SignatureOwner = owner;
FILE *f = fopen(efifile, "w");
if (!f) {
fprintf(stderr, "failed to open efi file %s: ", efifile);
perror("");
exit(1);
}
if (fwrite(PkCert, 1, PkCertLen, f) != PkCertLen) {
perror("Did not write enough bytes to efi file");
exit(1);
}
return 0;
}