summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYossi Mansharoff <yossim@codeaurora.org>2016-09-04 12:15:22 +0300
committerNicolas Dechesne <nicolas.dechesne@linaro.org>2016-11-16 14:17:47 +0100
commit0ae7c9542b61df60ff5ed537489fd4d3f4e73c09 (patch)
tree8a966d246866ed53858bb21c34eb8f92017a2195
LK simple sign tool to work in non secure boot
Imported in git from https://source.codeaurora.org/patches/quic/imm/PATCH_1694964_410c_signlk.tar.gz Signed-off-by: Yossi Mansharoff <yossim@codeaurora.org> Change-Id: Ia8823b78c4d9bbe901e6807d4ff03a29c1e496db Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
-rwxr-xr-xLICENSE26
-rwxr-xr-xsigner/Makefile26
-rwxr-xr-xsigner/signlk.cpp271
-rwxr-xr-xsignlk.sh134
4 files changed, 457 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..820d40c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/signer/Makefile b/signer/Makefile
new file mode 100755
index 0000000..ebf5f4e
--- /dev/null
+++ b/signer/Makefile
@@ -0,0 +1,26 @@
+CXX=g++
+cur-dir := $(mfile_path)
+ELFIODIR=${cur-dir}/ELFIO/elfio/
+SOURCES=${cur-dir}/signlk.cpp
+CPPFLAGS=-c -Wall -std=c++0x -I$(cur-dir)/ELFIO/
+INCLUDES=$(ELFIODIR)elfio.hpp $(ELFIODIR)elfio_header.hpp \
+ $(ELFIODIR)elfio_note.hpp $(ELFIODIR)elfio_section.hpp \
+ $(ELFIODIR)elfio_segment.hpp $(ELFIODIR)elfio_strings.hpp \
+ $(ELFIODIR)elfio_symbols.hpp $(ELFIODIR)elfio_utils.hpp \
+ $(ELFIODIR)elf_types.hpp
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE=${cur-dir}/signlk
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) $(LDFLAGS) $(OBJECTS) -o $@
+
+.cpp.o:
+ $(CXX) $(CPPFLAGS) $< -o $@
+
+test: $(EXECUTABLE)
+ ./$(EXECUTABLE)
+
+clean:
+ rm $(OBJECTS) $(EXECUTABLE)
diff --git a/signer/signlk.cpp b/signer/signlk.cpp
new file mode 100755
index 0000000..77fa639
--- /dev/null
+++ b/signer/signlk.cpp
@@ -0,0 +1,271 @@
+/******************************************************************************/
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions are */
+/* met: */
+/* * Redistributions of source code must retain the above copyright */
+/* notice, this list of conditions and the following disclaimer. */
+/* * Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials provided */
+/* with the distribution. */
+/* * Neither the name of The Linux Foundation nor the names of its */
+/* contributors may be used to endorse or promote products derived */
+/* from this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED */
+/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT */
+/* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
+/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
+/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */
+/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
+/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
+/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE */
+/* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN */
+/* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/******************************************************************************/
+
+
+#include <iostream>
+#include <elfio/elfio.hpp>
+
+using namespace ELFIO;
+
+/* struct to store hash segment header */
+typedef struct
+{
+ unsigned int header_vsn_num; /* Header version number. */
+ unsigned int image_id; /* Identifies the type of image this header */
+ unsigned int image_src; /* Location of image in flash */
+ unsigned int image_dest_ptr; /* Pointer to location to store image in RAM. */
+ unsigned int image_size; /* Size of complete image in bytes */
+ unsigned int code_size; /* Size of code region of image in bytes */
+ unsigned int signature_ptr; /* Pointer to images attestation signature */
+ unsigned int signature_size; /* Size of the attestation signature in bytes */
+ unsigned int cert_chain_ptr; /* Pointer to the chain of attestation
+ certificates associated with the image. */
+ unsigned int cert_chain_size; /* Size of the attestation chain in bytes */
+
+} mi_boot_image_header_type;
+
+#define HASH_CODE_SIZE 0x80
+#define SIGNATURE_SIZE 0x100
+#define CERT_CHAIN_SIZE 0x1800
+#define MAX_CERT_CHAIN_SIZE 0x2000
+#define SHT_QC 0x70000003
+#define SHT_EXIDX 0x70000001
+#define HASH_SE_ALIGN 0x1000
+#define HASH_SE_FLAG 0x2200000
+
+int readSecurityDataFromFile(char *buff, std::string root_cert_file_name, std::string atte_cert_file_name)
+{
+ std::ifstream stream;
+ // Read ELF file signature
+ stream.open( atte_cert_file_name, std::ios::in | std::ios::binary );
+ if ( !stream ) {
+ std::cout << "cant open attestation certificate file"<< atte_cert_file_name << std::endl;
+ return 1;
+ }
+ // Read ELF file signature
+ stream.seekg( 0 );
+ int atte_cert_size=0;
+ for (atte_cert_size = HASH_CODE_SIZE+SIGNATURE_SIZE+sizeof(mi_boot_image_header_type); atte_cert_size < MAX_CERT_CHAIN_SIZE ; atte_cert_size++)
+ {
+ if(stream.eof()) break;
+ stream.read(&buff[atte_cert_size],1);
+ if(stream.eof()) break;
+ }
+ stream.close();
+
+ stream.open( root_cert_file_name, std::ios::in | std::ios::binary );
+ if ( !stream ) {
+ std::cout << "cant open root certificate file"<< root_cert_file_name << std::endl;
+ return 1;
+ }
+
+ stream.seekg( 0 );
+ for (; atte_cert_size < MAX_CERT_CHAIN_SIZE ; atte_cert_size++)
+ {
+ if(stream.eof()) break;
+ stream.read(&buff[atte_cert_size],1);
+ if(stream.eof()) break;
+ }
+
+ stream.close();
+ for (int i=atte_cert_size; i < MAX_CERT_CHAIN_SIZE ; i++)
+ {
+ buff[i] = 0xff;
+ }
+ return 0;
+}
+
+
+int main( int argc, char** argv )
+{
+
+ if ( argc != 5 ) {
+ std::cout << "Usage: signlk <unsigned_elf_file> <signed_elf_file> <root_certificate_file> <attestation_CA_certificate_file>" << std::endl;
+ return 1;
+ }
+ // Create an elfio reader and writer
+ elfio reader;
+ elfio writer;
+ char cert_chain[MAX_CERT_CHAIN_SIZE]={0};
+ unsigned int hash_segment_address = 0;
+ std::string root_cert_file_name=(std::string )argv[3];
+ std::string atte_cert_file_name=(std::string )argv[4];
+ section* data_sec;
+ Elf_Word maxAddress = 0;
+ section* maxSec = NULL;
+ section* mi_sec = NULL;
+ segment* header_seg = NULL;
+ segment* hash_seg = NULL;
+ Elf_Half sec_num;
+ Elf_Half seg_num;
+ Elf_Half headerSize;
+ mi_boot_image_header_type mi={0};
+
+ /* create a write configuration */
+ writer.create( ELFCLASS32, ELFDATA2LSB );
+ writer.set_os_abi( ELFOSABI_NONE );
+ writer.set_type( ET_EXEC );
+ writer.set_machine( EM_ARM );
+ writer.set_flags(0x5000002);
+
+ // Load ELF data
+ if ( !reader.load( argv[1] ) ) {
+ std::cout << "Can't find or process ELF file " << argv[1] << std::endl;
+ return 2;
+ }
+
+ sec_num = reader.sections.size();
+ seg_num = reader.segments.size();
+
+ std::cout << "using attestation certificate file: "<< atte_cert_file_name << std::endl
+ <<"root certificate file: "<< root_cert_file_name << std::endl
+ <<"input file: "<<argv[1]<<std::endl
+ <<"output file: "<<argv[2]<<std::endl;
+
+ /* create new segments for header and hash */
+ header_seg = writer.segments.add();
+ hash_seg = writer.segments.add();
+
+ /* copy the original elf segments to the signed elf */
+ for ( int i = 0; i < seg_num; ++i ) {
+ const segment* pseg = reader.segments[i];
+ segment* data_seg = writer.segments.add();
+ data_seg->set_type( pseg->get_type() );
+ data_seg->set_virtual_address( pseg->get_virtual_address() );
+ data_seg->set_physical_address( pseg->get_physical_address() );
+ data_seg->set_flags( pseg->get_flags() );
+ data_seg->set_align( pseg->get_align() );
+ data_seg->set_file_size(pseg->get_file_size());
+ data_seg->set_memory_size(pseg->get_memory_size());
+ }
+
+ /* copy loadable sections to target file*/
+ for ( int i = 0; i < sec_num; ++i ) {
+ section* psec = reader.sections[i];
+
+ /* copy only loadable sections */
+ if ((psec->get_type()==SHT_PROGBITS)
+ ||(psec->get_type()==SHT_HASH)
+ ||(psec->get_type()==SHT_EXIDX))
+ {
+ data_sec = writer.sections.add(psec->get_name());
+ data_sec->set_type( psec->get_type() );
+ data_sec->set_flags( psec->get_flags() );
+ data_sec->set_addr_align( psec->get_addr_align() );
+ data_sec->set_data( psec->get_data(), psec->get_size() );
+ writer.segments[writer.segments.size() - 1]->add_section_index( data_sec->get_index(), data_sec->get_addr_align() );
+ }
+ }
+
+ /* Create data section*/
+ headerSize = writer.get_header_size() +(writer.segments.size())*32;
+ data_sec = writer.sections.add( "" );
+ data_sec->set_type( SHT_NULL );
+ data_sec->set_flags( SHF_ALLOC );
+ data_sec->set_addr_align( 0 );
+ char data[0x100]={0};
+ data_sec->set_data( data, headerSize );
+
+ /* Create a read/write segment */
+ header_seg->set_type( PT_NULL );
+ header_seg->set_virtual_address( 0 );
+ header_seg->set_physical_address( 0 );
+ header_seg->set_flags( 0 );
+ header_seg->set_align( 4 );
+ header_seg->set_memory_size(headerSize);
+
+ // Add code section into program segment
+ header_seg->add_section_index( data_sec->get_index(), data_sec->get_addr_align() );
+
+ /* scan for the elf file section max address to insert the hash section */
+ for ( int i = 0; i < sec_num; ++i ) {
+ section* psec = reader.sections[i];
+ /* copy only loadable sections */
+ if ((psec->get_type()==SHT_PROGBITS)
+ ||(psec->get_type()==SHT_HASH)
+ ||(psec->get_type()==SHT_EXIDX))
+ {
+ /* store max section address for hash section */
+ if (psec->get_address() > maxAddress)
+ {
+ maxAddress = psec->get_address();
+ maxSec = psec;
+ }
+ }
+ }
+
+ /* calculate section address */
+ hash_segment_address = (maxSec->get_address() + (maxSec->get_addr_align() - (maxSec->get_address() % maxSec->get_addr_align())));
+ hash_segment_address = (hash_segment_address + (HASH_SE_ALIGN - (hash_segment_address % HASH_SE_ALIGN)));
+
+ /* read the certificates from input files */
+ if (readSecurityDataFromFile(cert_chain, root_cert_file_name, atte_cert_file_name))
+ {
+ std::cout << "exiting" << std::endl;
+ return 1;
+ }
+
+ /* set the hash segment header data */
+ mi.image_id = 0x3;
+ mi.image_dest_ptr = hash_segment_address + sizeof(mi_boot_image_header_type);
+ mi.code_size = HASH_CODE_SIZE;
+ mi.header_vsn_num = 0;
+ mi.signature_ptr = mi.image_dest_ptr + mi.code_size;
+ mi.signature_size =SIGNATURE_SIZE;
+ mi.cert_chain_ptr = mi.signature_ptr + mi.signature_size;
+ mi.cert_chain_size = CERT_CHAIN_SIZE;
+ mi.image_size = mi.cert_chain_size + mi.signature_size + mi.code_size;
+ memcpy(cert_chain,&mi,sizeof(mi));
+
+ /* create section */
+ mi_sec = writer.sections.add( ".mi" );
+ mi_sec->set_type( PT_LOPROC );
+ mi_sec->set_flags( SHF_ALLOC );
+ mi_sec->set_addr_align( HASH_SE_ALIGN );
+ mi_sec->set_data( cert_chain, sizeof( cert_chain ) );
+
+ // Create a read/write segment
+ hash_seg->set_type( PT_LOPROC);
+ hash_seg->set_virtual_address( hash_segment_address );
+ hash_seg->set_physical_address( hash_segment_address);
+ hash_seg->set_flags( HASH_SE_FLAG );
+ hash_seg->set_align( HASH_SE_ALIGN );
+ hash_seg->set_file_size(mi.image_size);
+ hash_seg->set_memory_size(MAX_CERT_CHAIN_SIZE);
+
+ /* Add code section into program segment */
+ hash_seg->add_section_index( mi_sec->get_index(), mi_sec->get_addr_align() );
+
+ /* set the entry point */
+ writer.set_entry(reader.get_entry());
+
+ /* Create ELF file */
+ writer.save(argv[2]);
+ return 0;
+}
diff --git a/signlk.sh b/signlk.sh
new file mode 100755
index 0000000..954b737
--- /dev/null
+++ b/signlk.sh
@@ -0,0 +1,134 @@
+################################################################################
+# Copyright (c) 2016, The Linux Foundation. All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are #
+# met: #
+# * Redistributions of source code must retain the above copyright #
+# notice, this list of conditions and the following disclaimer. #
+# * Redistributions in binary form must reproduce the above #
+# copyright notice, this list of conditions and the following #
+# disclaimer in the documentation and/or other materials provided #
+# with the distribution. #
+# * Neither the name of The Linux Foundation nor the names of its #
+# contributors may be used to endorse or promote products derived #
+# from this software without specific prior written permission. #
+# #
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED #
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT #
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS #
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR #
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, #
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE #
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN #
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
+# #
+# THIS IS A WORKAROUND TO GET LK INTO THE PROPER FORMAT, #
+# NO SECURITY IS BEING PROVIDED BY THE OPENSSL CALLS HAPPENING UNDER THE HOOD #
+################################################################################
+
+INFILE=""
+OUTFILE=""
+DIR=$(dirname $0)
+EXECUTABLE="$DIR/signer/signlk"
+CN=""
+OU=""
+for i in "$@"
+do
+case $i in
+ -i=*|--in=*)
+ INFILE="${i#*=}"
+
+ ;;
+ -o=*|--out=*)
+ OUTFILE="${i#*=}"
+ ;;
+ -OU=*|-ou=*)
+ OU="${i#*=}"
+
+ ;;
+ -CN=*|-cn=*)
+ CN="${i#*=}"
+
+ ;;
+ -h*|--help*)
+ echo "signlk -i=input_file_name [-o=output_file_name]"
+ echo "-i input ELF/MBN file name"
+ echo "-o output file name, input_file_name with suffix of 'signed' as default "
+ exit 0
+ ;;
+ *)
+ echo "unsupported option" # unknown option
+ echo "type signlk --help for help"
+ exit 1
+ ;;
+esac
+done
+
+if [ "$INFILE" == "" ]; then
+ echo "signlk -i=input_file_name [-o=output_file_name]"
+ exit 2
+fi
+
+INFILE_filename=$(echo $INFILE | rev | cut -f 2- -d '.' | rev)
+INFILE_extension=$(echo $INFILE | rev | cut -f 1 -d '.' | rev)
+
+if [ "$INFILE_extension" == "" ]; then
+ echo "input file must be an elf or mbn file"
+ exit 3
+fi
+
+if [ "$INFILE_extension" != "elf" ] && [ "$INFILE_extension" != "mbn" ] && [ "$INFILE_extension" != "ELF" ] && [ "$INFILE_extension" != "MBN" ]; then
+ echo "input file must be an elf or mbn file"
+ exit 4
+fi
+
+if [ "$OUTFILE" == "" ]; then
+ OUTFILE=$INFILE_filename"_signed.mbn"
+
+fi
+echo "generating output file $OUTFILE"
+
+if [ ! -f "$EXECUTABLE" ]; then
+ echo "building executable..."
+ export mfile_path=$DIR/signer
+ make -f $mfile_path/Makefile
+
+ if [ "$?" != 0 ]; then
+ echo " failed to build executable"
+ exit 5
+ fi
+fi
+tmp=$(mktemp -d)
+tmp_att_file=$tmp/e.ext
+
+echo "authorityKeyIdentifier=keyid,issuer" >> $tmp_att_file
+echo "basicConstraints=CA:FALSE,pathlen:0" >> $tmp_att_file
+echo "keyUsage=digitalSignature" >> $tmp_att_file
+if [ ! "$(openssl version)" ]; then
+ echo "please install openssl"
+ exit 6
+fi
+if [ ! "$(make -v)" ]; then
+ echo "please install gcc"
+ exit 7
+fi
+if [ ! "$(g++ --version)" ]; then
+ echo "please install g++"
+ exit 8
+fi
+openssl req -new -x509 -keyout $tmp/root_key.PEM -nodes -newkey rsa:2048 -days 7300 -set_serial 1 -sha256 -subj "/CN=$CN/O=$OU/C=/CN=DRAGONBOARD TEST PKI – NOT SECURE/L=/O=S/ST=/OU=01 0000000000000009 SW_ID/OU=02 0000000000000000 HW_ID" > $tmp/root_certificate.PEM 2>/dev/null
+openssl x509 -in $tmp/root_certificate.PEM -inform PEM -outform DER > $tmp/root_cert.DER 2>/dev/null
+openssl genpkey -algorithm RSA -outform PEM -pkeyopt rsa_keygen_bits:2048 >$tmp/atte_key.PEM 2>/dev/null
+openssl req -new -key $tmp/atte_key.PEM -subj "/CN=$CN/O=$OU/C=/CN=DRAGONBOARD TEST PKI – NOT SECURE/L=/O=/ST=/OU=01 0000000000000009 SW_ID/OU=02 0000000000000000 HW_ID" -days 7300 > $tmp/atte_csr.PEM 2>/dev/null
+openssl x509 -req -in $tmp/atte_csr.PEM -CAkey $tmp/root_key.PEM -CA $tmp/root_certificate.PEM -days 7300 -set_serial 1 -extfile $tmp_att_file -sha256 -out $tmp/atte_cert.PEM 2>/dev/null
+openssl x509 -in $tmp/atte_cert.PEM -inform PEM -outform DER > $tmp/atte_cert.DER 2>/dev/null
+
+$EXECUTABLE $INFILE $OUTFILE $tmp/root_cert.DER $tmp/atte_cert.DER
+
+rm -rf $tmp
+
+echo done