summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2013-04-04 19:58:12 +0400
committerkx <kx@radix.pro>2013-04-04 19:58:12 +0400
commit429fe7318944b1ec1d1d2518183e3570ab9ba276 (patch)
tree590f7c664181e4292f0889c96bbdcfb62348a64d
downloadmodSign-429fe7318944b1ec1d1d2518183e3570ab9ba276.tar.xz
Initial commit
-rw-r--r--.gitignore0
-rw-r--r--Makefile20
-rw-r--r--doxyref.cfg304
-rw-r--r--doxyref.h176
-rwxr-xr-xkeys/CEK4
-rw-r--r--keys/key.pem18
-rw-r--r--modSign.cpp1061
-rw-r--r--modSign.h239
-rwxr-xr-xscripts/module-sign173
-rw-r--r--scripts/signing.txt17
10 files changed, 2012 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.gitignore
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..35ecf0d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+
+CC = g++
+CFLAGS = -O3 -Wall -D__NO_PADDING_OF_NOR_PKH__
+LDLIBS = -lcrypto
+# uncomment EXEEXT for cygwin environment for correct cleaning.
+#EXEEXT = .exe
+
+all: modSign
+
+modSign: modSign.cpp modSign.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) modSign.cpp $(LDLIBS) -o modSign
+
+doc:
+ @doxygen doxyref.cfg
+
+doc-clean:
+ @rm -rf doc
+
+clean: doc-clean
+ @rm -f modSign$(EXEEXT)
diff --git a/doxyref.cfg b/doxyref.cfg
new file mode 100644
index 0000000..4cb8292
--- /dev/null
+++ b/doxyref.cfg
@@ -0,0 +1,304 @@
+# Doxyfile 1.5.6
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = modSign
+PROJECT_NUMBER = 00.90
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = .
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+SHOW_FILES = NO
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = doxyref.h
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.vhd \
+ *.vhdl \
+ *.C \
+ *.CC \
+ *.C++ \
+ *.II \
+ *.I++ \
+ *.H \
+ *.HH \
+ *.H++ \
+ *.CS \
+ *.PHP \
+ *.PHP3 \
+ *.M \
+ *.MM \
+ *.PY \
+ *.F90 \
+ *.F \
+ *.VHD \
+ *.VHDL
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NONE
+TREEVIEW_WIDTH = 250
+FORMULA_FONTSIZE = 10
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = YES
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+DOT_FONTNAME = FreeSans
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/doxyref.h b/doxyref.h
new file mode 100644
index 0000000..25fd46b
--- /dev/null
+++ b/doxyref.h
@@ -0,0 +1,176 @@
+/* ===================================================================
+ *
+ * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved
+ *
+ * Use of this software is controlled by the terms and conditions found
+ * in the license agreement under which this software has been supplied.
+ * =================================================================== */
+/*! @file doxyref.h
+ * This file generates Doxygen pages from files in the modSign
+ * source tree.
+ */
+
+/*! \mainpage modSign -- secure module signing utility
+\par Developer Documentation for modSign
+This is the developer documentation for the modSign utility. It is
+automatically generated through the doxygen utility.
+\par Usage documentation
+ \arg \ref modSign-boot
+ \arg \ref modSign-code
+ \arg \ref modSign-cert
+
+\section copyright Copyright
+(c) Copyright 2006 Texas Instruments, Incorporated. All Rights Reserved.
+Use of this software is controlled by the terms and conditions found
+in the license agreement under which this software has been supplied.
+ */
+
+/*! \page modSign-boot Creating Boot Headers
+To create a signed boot header, use the following form of the modSign utility
+\verbatim
+ Usage:
+ modSign <type> [-s <mode>] -e <entry> [-m <info>] -l <address>
+ -r <crc> [-p <password>] -c <certFile> <outFile>
+ <type> header type: nand | nor | uart
+ -s <mode> special mode: 0..9; default = 0
+ -e <entry> absolute entry pointer
+ -l <address> load address (Jacinto Only)
+ -r <crc> CRC value (Jacinto Only)
+ -m <info> UBL module start/size info
+ -p <password> (optional) password for key certificate file
+ -c <certFile> RSA key certificate file
+ <outFile> output file name
+\endverbatim
+This will create a signed root public key module consisting of a generic header,
+followed by a 136 byte Root Public Key structure, followed by a 128 byte
+(1024 bit) Key Signature value. The Root Public Key is taken from the same
+certificate that is being used to sign the module.
+<p>The available options are:
+<table border=0>
+<tr><td><b>-s</b></td><td>specify the special mode. The default
+value for the special mode is 0 (<i>Safe Boot Mode</i>)</td></tr>
+<tr><td><b>-e</b></td><td>absolute entry pointer. The value for this
+option must be in the range 0x0020 .. 0x381C. It indicates the
+absolute entry point after loading the UBL.</td></tr>
+<tr><td><b>-l</b></td><td>specify the load (destination) address.
+This option is only valid for Jacinto.</td></tr>
+<tr><td><b>-r</b></td><td>specify the CRC value. This option is
+only valid for Jacinto.</td></tr>
+<tr><td><b>-m</b></td><td>module start/size info. The exact form
+depends on the header type</td></tr>
+<tr><td><b>-p</b></td><td>optional password for the certificate
+file. If the certificate file requires a password and none is
+provided, the software will prompt you.</td></tr>
+<tr><td><b>-c</b></td><td>RSA private key certificate file. This
+is the key that will be used to sign the header module.</td></tr>
+</table>
+<p>
+The following special mode values can be used with the <b>-s</b> option:
+<table border=0>
+<tr><th></th><th align="center">Mode</th><th
+align="center">Value</th><th align="center">Description</th></tr>
+<tr><td><b>0</b></td><td>UBL_MAGIC_SAFE</td><td>0xA1ACED00</td>
+<td>Safe boot mode</td></tr>
+<tr><td><b>1</b></td><td>UBL_MAGIC_DMA</td><td>0xA1ACED11</td>
+<td>DMA boot mode</td></tr>
+<tr><td><b>2</b></td><td>UBL_MAGIC_IC</td><td>0xA1ACED22</td>
+<td>I Cache boot mode</td></tr>
+<tr><td><b>3</b></td><td>UBL_MAGIC_FAST</td><td>0xA1ACED33</td>
+<td>Fast EMIF boot mode</td></tr>
+<tr><td><b>4</b></td><td>UBL_MAGIC_DMA_IC</td><td>0xA1ACED44</td>
+<td>DMA + I Cache boot mode</td></tr>
+<tr><td><b>5</b></td><td>UBL_MAGIC_DMA_IC_FAST</td><td>0xA1ACED55</td>
+<td>DMA + I Cache + Fast EMIF boot mode</td></tr>
+</table>
+<p>The ARM boot loader distinguishes three different boot header types: <b>nand</b>,
+<b>nor</b>, and <b>uart</b>.
+<p>Each mode has a slightly different generic header, as explained
+in the following sections.
+ */
+
+/*! \page modSign-code Creating Code Modules
+To create a code module, use the following form of the modSign utility:
+\verbatim
+ Usage:
+ modSign load [-a <start> -s [1|2|3]] -b <block> -k <keyString>
+ [-p <password>] -c <certfile> <infile> <outfile>
+ -a <start> start address of module if self-executing
+ -s [1|2|3] self execution type
+ 1 = non-secure application
+ 2 = secure application - non-emulatable (default)
+ 3 = secure application - emulatable
+ -b <block> block size (optional)
+ -k <keyString> 32-character hex AES key
+ -p <password> (optional) password for key certificate file
+ -c <certFile> RSA key certificate file
+ <inFile> binary input file name
+ <outFile> output file name
+\endverbatim
+The following options are available:
+<table border=0 rules=groups>
+<tr><td width="20"><b>-a</b></td><td colspan=2>start address of the module if
+self-executing (should only be specified for self-executing DSP
+modules).</td></tr>
+<tr><td><b>-s</b></td><td colspan=2>self execution type (only for
+self-executing DSP modules). The following values can be
+used:</td></tr>
+<tr><td></td><td width="0" align="center"><b>1</b></td><td>non-secure application</td></tr>
+<tr><td></td><td width="0" align="center"><b>2</b></td><td>secure application -
+non-emulatable (<i>default</i>)</td></tr>
+<tr><td></td><td width="0" align="center"><b>3</b></td><td>secure application -
+emulatable</td></tr>
+<tr><td><b>-b</b></td><td colspan=2>block size (<i>optional</i>) -
+indicates the block size as a power of 2 (i.e. 8 equals a block
+size of 256 bytes, 10=1024 bytes, 12=4096, etc..). This option can
+be used to force the module size to be rounded up to fit in an
+integral number of blocks for NAND flash.</td></tr>
+<tr><td><b>-k</b></td><td colspan=2>optional 128-bit AES encryption
+key. If no encryption key is specified, the module will be signed
+only. The key value should be a 128-bit (or 32 character) hex
+value.</tr>
+<tr><td><b>-p</b></td><td colspan=2>optional password for the
+certificate file. If the certificate file requires a password and
+none is provided, the software will prompt you.</tr>
+<tr><td><b>-c</b></td><td colspan=2>RSA private key certificate
+file. This is the key that will be used to sign the header
+module.</tr>
+</table>
+ */
+
+/*! \page modSign-cert Creating Key Delegation Certificates
+To create a key delegation module, use the following form of the
+modSign utility:
+\verbatim
+ Usage:
+ modSign cert [-f] [-p <password>] -k <keyString> -c <certfile>
+ [-p <password>] -k <keyString> -d <dCertFile> <outfile>
+ -f <flag> SK add-on inhibit flag
+ -p <password> (optional) password for key certificate file
+ -k <keyString> 32-character hex AES key
+ -c <certFile> RSA key certificate file
+ -d <dCertFile> delegate RSA key certificate file
+ <outFile> output file name
+\endverbatim
+The following options are available:
+<table border=0 rules=groups>
+<tr><td width="20"><b>-f</b></td><td>Secure Kernel add-on inhibit
+flag. If set, no more Secure Kernel add-ons can be loaded with this
+certificate or any further delegate certificates.</td></tr>
+<tr><td><b>-p</b></td><td>The (optional password) for the following
+certificate or delegate certificate file.</td></tr>
+<tr><td><b>-k</b></td><td>The AES encryption key that is associated
+with the following certificate or delegate certificate file.</td></tr>
+<tr><td><b>-c</b></td><td>The signing certificate filename.</td></tr>
+<tr><td><b>-d</b></td><td>The delegate certificate filename. Should
+only contain a public key</td></tr>
+</table>
+The public key from the new certificate (<i>dCertFile</i>) is signed with the
+private key from the certificate <i>certfile</i>. The <i>password</i> and
+<i>keyString</i> arguments bind with the certificate file that follows them.
+ */
+
+#ifndef __DOXYREF_H
+#define __DOXYREF_H
+
+
+#endif /* __DOXYREF_H */
diff --git a/keys/CEK b/keys/CEK
new file mode 100755
index 0000000..c93b200
--- /dev/null
+++ b/keys/CEK
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+CEK=a93b936c506b68d853eae582f5052f84
+PASS=TestCertificate
diff --git a/keys/key.pem b/keys/key.pem
new file mode 100644
index 0000000..ad6e1f8
--- /dev/null
+++ b/keys/key.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7B128442C2819CA7
+
+dvTAHaKTsst50Dwzn3w6RywsQKpzfCephRKWA0/9KlYQX5adH5xn8TdPR6GMf6zH
+UfSOi5pUoC+FIozbPmUMAsRfGIltcDQsclSWJGwo2nLl1KP7IiPkMqtcG+wO3msf
+gVvsxC7sbheMaaUDXvUncCH4XiZSIvpUROd4MfHaNo8bQn40LWpDZd8mCvENwKsU
+Ep037hmw64dxj9IRk9vlxRgUR3QVwy8naukY/CikbIk8g3urhwj4aHgp704UAZPa
+PgEO3witxQCCmbZnTukGptoJExRlwsthQhrLppy5xogrvZd/nmfTfXWXcFr5p9XF
+c3XCYhm3pcGDyZaSt5Yg8VEVM975j5UPyz19juoxAStXXIZ5ibtiVdMvBx02WFij
+C7N4aH4nuoB+RBGJMfn7KGfR1jlEyEXZb59wOKrxA9LUFVchLNUnKAziXAVvY6Q5
+970SEFKjnCndhyqkxCxNLD2wyddigFhcjtvHHMsK1Ph8shb54tMLov/3/LXiOfK7
+KyzNz9WJJ1a9Yr3uPGpciCPprNpK/x+SmOHPtBdtXkE7VfZkXV4Org9vOvlM5GI+
+bQfWqePC+Al//0qFJ+pUiniYSnSkh5B2mdcZKq5i/1vj9b/uQWIqjMX0sx38kJ0p
+9uHozNTMw3JlecRifBPl44EsubMjrSv7w6nKkx4REIA5QAFkLaMLRP0RhcmVxtqL
+zczldpbo9Bo3kIGAguQrNLZFXry9wPuxZCr+CBNRABdvQ7XN7r3gGWm0S2TiIIIh
+Xgt9p72kqtkIDWy6gK19a72FEgh9jvmVjDizzl9IAP8adtgcXlCGNw==
+-----END RSA PRIVATE KEY-----
diff --git a/modSign.cpp b/modSign.cpp
new file mode 100644
index 0000000..7ab5256
--- /dev/null
+++ b/modSign.cpp
@@ -0,0 +1,1061 @@
+/* ==========================================================================
+ *
+ * (c) Copyright Texas Instruments, Incorporated. All Rights Reserved
+ *
+ * Use of this software is controlled by the terms and conditions found
+ * in the license agreement under which this software has been supplied.
+ *
+ * This software and software source code, as well as any related
+ * technology and any product developed with these items may be
+ * classified as an "encryption item" under Category 5, Part 2,
+ * Information Security, of the Commerce Control List ("CCL") of the
+ * Department of Commerce, Bureau of Industry and Security, Export
+ * Administration Regulations (EAR). Export, reexport, or release of
+ * any "encryption item" contrary to the EAR is prohibited.
+ * ========================================================================== */
+
+/*! \file modSign.cpp
+ * This file contains the code for the modSign utility.
+ * This file contains the code for the modSign utility.
+ *
+ * \version 00.90
+ */
+/* ==========================================================================
+ * Revision History
+ * ================
+ *
+ * ========================================================================== */
+
+#include "doxyref.h"
+#ifdef _WIN32
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "modSign.h"
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/aes.h>
+#include <openssl/ui.h>
+
+//! Legal return codes.
+//! This is the set of legal return codes. Any non-zero
+//! code indicates an error.
+typedef enum {
+ SUCCESS = 0, CMDERR, AES_KEY_SIZE_ERROR,
+ AES_KEY_FORMAT_ERROR, FILE_ERROR
+} returnType;
+
+//! Supported header types.
+//! This is the set of header types that is supported by
+//! the modSign utility.
+typedef enum {NAND, NOR, UART} headerType;
+
+//! Index into parent argv vector (see getopt()).
+//! Index into parent argv vector for getopt().
+int optind = 1,
+ //! Character checked for validity (see getopt()).
+ //! Current option character being checked for validity in getopt().
+ optopt,
+ //! Reset getopt (see getopt()).
+ //! If set, forces option reset in getopt().
+ optreset;
+//! Argument associated with option (see getopt()).
+//! Global variable used to pass the optional argument to the current
+//! option character from getopt().
+char *optarg;
+
+//! The usage explanation for header modules
+static const char *usageHeaderString = "Usage:\n\
+ modSign <type> [-s <mode>] -e <entry> [-m <info>] [-p <password>]\n\
+ -c <certFile> <outFile>\n\
+ <type> header type: NAND | NOR | UART\n\
+ -s <mode> special mode: 0..9; default = 0\n\
+ -e <entry> absolute entry pointer (0x0020 .. 0x381C)\n\
+ -m <info> UBL module start/size info\n\
+ -p <password> (optional) password for key certificate file\n\
+ -c <certFile> RSA key certificate file\n\
+ <outFile> output file name\n";
+
+//! The usage explanation for load/code modules
+static const char *usageLoadString = "Usage:\n\
+ modSign load [-a <start> -s [1|2|3]] -b <block> -k <keyString>\n\
+ [-p <password>] -c <certfile> <infile> <outfile>\n\
+ -a <start> start address of module if self-executing\n\
+ -s [1|2|3] self execution type\n\
+ 1 = non-secure application\n\
+ 2 = secure application - non-emulatable (default)\n\
+ 3 = secure application - emulatable\n\
+ -b <block> block size (optional)\n\
+ -k <keyString> 32-character hex AES key\n\
+ -p <password> (optional) password for key certificate file\n\
+ -c <certFile> RSA key certificate file\n\
+ <inFile> binary input file name\n\
+ <outFile> output file name\n";
+
+//! The usage explanation for certificate delegation modules
+static const char *usageCertString = "Usage:\n\
+ modSign cert [-f] [-p <password>] -k <keyString> -c <certfile>\n\
+ [-p <password>] -k <keyString> -d <dCertFile> <outfile>\n\
+ -f <flag> SK add-on inhibit flag\n\
+ -p <password> (optional) password for key certificate file\n\
+ -k <keyString> 32-character hex AES key\n\
+ -c <certFile> RSA key certificate file\n\
+ -d <dCertFile> delegate RSA key certificate file\n\
+ <outFile> output file name\n";
+
+//! User Interface method used during password callback
+static UI_METHOD *ui_method = NULL;
+//! Minimum password length
+#define PW_MIN_LENGTH 4
+//! Password callback user data structure
+typedef struct pw_cb_data
+{
+ const void *password;
+ const char *prompt_info;
+} PW_CB_DATA;
+
+// ===========================================================================
+//! Password callback routine.
+//! Password callback routine - called in case a password is required
+//! for the key file.
+//! @param buf pointer to password result buffer
+//! @param bufsiz length of password result buffer
+//! @param verify flags
+//! @param cb_tmp callback data structure
+// ===========================================================================
+int password_callback(
+ char *buf, int bufsiz, int verify,
+ PW_CB_DATA *cb_tmp)
+{
+ UI *ui = NULL;
+ int res = 0;
+ const char *prompt_info = NULL;
+ const char *password = NULL;
+ PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
+
+ if (cb_data) {
+ if (cb_data->password)
+ password = (const char *) cb_data->password;
+ if (cb_data->prompt_info)
+ prompt_info = cb_data->prompt_info;
+ }
+
+ if (password) {
+ res = strlen(password);
+ if (res > bufsiz) res = bufsiz;
+ memcpy(buf, password, res);
+ return res;
+ }
+
+ ui = UI_new_method(ui_method);
+ if (ui) {
+ int ok = 0;
+ char *buff = NULL;
+ int ui_flags = 0;
+ char *prompt = NULL;
+
+ prompt = UI_construct_prompt(ui, "pass phrase",
+ prompt_info);
+
+ ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
+ UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+
+ if (ok >= 0)
+ ok = UI_add_input_string(ui, prompt, ui_flags, buf,
+ PW_MIN_LENGTH, BUFSIZ-1);
+ if (ok >= 0 && verify) {
+ buff = (char *)OPENSSL_malloc(bufsiz);
+ ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
+ PW_MIN_LENGTH, BUFSIZ-1, buf);
+ }
+ if (ok >= 0)
+ do {
+ ok = UI_process(ui);
+ } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
+
+ if (buff) {
+ OPENSSL_cleanse(buff, (uint32_t)bufsiz);
+ OPENSSL_free(buff);
+ }
+
+ if (ok >= 0)
+ res = strlen(buf);
+ if (ok == -1) {
+ fprintf(stderr, "User interface error\n");
+ ERR_print_errors_fp(stderr);
+ OPENSSL_cleanse(buf, (uint32_t)bufsiz);
+ res = 0;
+ }
+ if (ok == -2) {
+ fprintf(stderr, "aborted!\n");
+ OPENSSL_cleanse(buf, (uint32_t)bufsiz);
+ res = 0;
+ }
+ UI_free(ui);
+ OPENSSL_free(prompt);
+ }
+ return res;
+}
+
+// ===========================================================================
+//! Read an RSA key certificate (private and public).
+//! Read a private key from the passed key file.
+//!
+//! @param keyfile name of the public key certificate file
+//! @param password password (NULL if not specified)
+//!
+//! @return pointer to key structure; NULL on error
+// ===========================================================================
+EVP_PKEY *ReadPrivateKey(const char *keyfile, const char *password)
+{
+ FILE *fp = fopen(keyfile, "r");
+ EVP_PKEY *pkey = NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = password;
+ cb_data.prompt_info = keyfile;
+ if (!fp) {
+ fprintf(stderr, "Can't open key file '%s'\n", keyfile);
+ return NULL;
+ }
+
+ if (!PEM_read_PrivateKey(fp, &pkey, (pem_password_cb *) password_callback, &cb_data)) {
+ fprintf(stderr, "Error reading key info from '%s'\n",
+ keyfile);
+ // ERR_print_errors_fp (stderr);
+ }
+
+ fclose (fp);
+ return pkey;
+}
+
+// ===========================================================================
+//! Read a public key certificate.
+//! Read a public key from the passed key file.
+//!
+//! @param keyfile name of the public key certificate file
+//!
+//! @return pointer to public key structure; NULL on error
+// ===========================================================================
+EVP_PKEY *ReadPublicKey(const char *keyfile)
+{
+ FILE *fp = fopen(keyfile, "r");
+ EVP_PKEY *pkey = NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = NULL;
+ cb_data.prompt_info = keyfile;
+ if (!fp) {
+ fprintf(stderr, "Can't open key file '%s'\n", keyfile);
+ return NULL;
+ }
+
+ if (!PEM_read_PUBKEY(fp, &pkey, (pem_password_cb *) password_callback, &cb_data)) {
+ fprintf(stderr, "Error reading public key info from '%s'\n",
+ keyfile);
+ // ERR_print_errors_fp (stderr);
+ }
+
+ fclose (fp);
+ return pkey;
+}
+
+// ===========================================================================
+//! Copy buffer in byte reversed order.
+//! Copy the string from src to dst in byte-reversed order.
+//!
+//! @param dst pointer to destination buffer
+//! @param src pointer to source buffer
+//! @param len length of buffer in bytes
+//!
+//! @return nothing
+// ===========================================================================
+void copyByteReversed(char *dst, const char *src, int len)
+{
+ char *pDst = dst;
+ const char *pSrc = src;
+ int i;
+
+ pSrc += len;
+
+ for (i = 0; i < len; i++) {
+ *pDst++ = *--pSrc;
+ }
+}
+
+// ===========================================================================
+//! Dump buffer contents in raw or hex format.
+//! Dump the buffer contents at location <i>p</i> with byte length <i>l</i>
+//! to the file. If <i>hexFormat</i> is true, dump the data in CCS data format;
+//! otherwise dump in raw format.
+//!
+//! @param outFile output file name
+//! @param hexFormat true if hex format requested
+//! @param hexAddress start address for hex format
+//! @param p pointer to buffer
+//! @param l length of buffer in bytes
+//!
+//! @return SUCCESS if successful; FILE_ERROR if not.
+// ===========================================================================
+returnType dumpBuffer(const char *outFile, bool hexFormat, uint32_t hexAddress, int *p, int l)
+{
+ int i;
+ FILE *hFile;
+
+ // create output data file
+ hFile = fopen(outFile, hexFormat ? "w" : "wb");
+ if (hFile == NULL) {
+ fprintf(stderr, "Can't create output file '%s'\n", outFile);
+ return FILE_ERROR;
+ }
+
+ if (hexFormat) {
+ int nWords = l / sizeof(int);
+
+ fprintf(hFile, "%x %d %08x 0 %x\n", CCS_DATA_MAGIC, CCS_HEX_FORMAT, hexAddress, nWords);
+ // dump all data in 32-bit hex format,
+ for (i = 0; i < nWords; i++) {
+ fprintf(hFile, "0x%08x\n", *p++);
+ }
+ } else {
+ fwrite((const void *) p, sizeof(char), l, hFile);
+ }
+ fclose (hFile);
+ return SUCCESS;
+}
+
+// ===========================================================================
+//! Generate a boot header.
+//! Routine to generate a general boot header. To keep the details of the
+//! boot header type hidden from this routine, the signature offset is passed
+//! in the argument <i>signOffset</i>, and the header size in <i>hdrSize</i>.
+//! The RSA signature is computed over everything in front of the signature field.
+//!
+//! @param fileName output file name
+//! @param hexFormat hex output format boolean
+//! @param hexAddress start address for hex output
+//! @param pkey pointer to RSA key structure
+//! @param pHeader pointer to header structure
+//! @param signOffset offset of signature field in header structure
+//! @param hdrSize total size of header
+//!
+//! @return SUCCESS if successful; FILE_ERROR otherwise
+// ===========================================================================
+returnType genBootHeader(
+ const char *fileName,
+ bool hexFormat,
+ uint32_t hexAddress,
+ EVP_PKEY *pkey,
+ char *pHeader,
+ int signOffset,
+ int hdrSize)
+{
+ int err;
+ uint32_t sig_len;
+ uint8_t sig_buf [4096];
+ EVP_MD_CTX md_ctx;
+
+ EVP_SignInit (&md_ctx, EVP_sha1());
+ EVP_SignUpdate (&md_ctx, pHeader, signOffset);
+ sig_len = sizeof(sig_buf);
+ err = EVP_SignFinal (&md_ctx, sig_buf, (unsigned int *)&sig_len, pkey);
+
+ if(sig_len == RSASIZE)
+ copyByteReversed(pHeader+signOffset, (const char *) sig_buf, sig_len);
+ else
+ fprintf(stderr, "Signature size incorrect - %d\n", sig_len);
+
+ return dumpBuffer(fileName, hexFormat, hexAddress, (int *) pHeader, hdrSize);
+}
+
+// ===========================================================================
+//! Generate a delegate key certificate.
+//! Sign the passed key certificate with the private key from the <i>pkey</i>
+//! structure, and encrypt with the given AES key.
+//!
+//! @param fileName output file name
+//! @param hexFormat hex output format boolean
+//! @param pkey pointer to RSA key structure
+//! @param privateKey pointer to AES encryption key
+//! @param header pointer to certificate header structure
+//!
+//! @return SUCCESS if successful; FILE_ERROR otherwise
+// ===========================================================================
+returnType genAltKey(
+ const char *fileName,
+ bool hexFormat,
+ EVP_PKEY *pkey,
+ uint8_t *privateKey,
+ struct alternateKey *header)
+{
+ int err;
+ uint32_t sig_len;
+ uint8_t sig_buf [4096];
+ EVP_MD_CTX md_ctx;
+ uint8_t initVec[16];
+ AES_KEY AESkey;
+
+ EVP_SignInit (&md_ctx, EVP_sha1());
+ EVP_SignUpdate (&md_ctx, (char *) header, offsetof(struct alternateKey, hdrSignature));
+ sig_len = sizeof(sig_buf);
+ err = EVP_SignFinal (&md_ctx, sig_buf, (unsigned int *)&sig_len, pkey);
+
+ if(sig_len == RSASIZE)
+ copyByteReversed((char *) header->hdrSignature, (const char *) sig_buf, sig_len);
+ else
+ fprintf(stderr, "Signature size incorrect - %d\n", sig_len);
+
+ memcpy(initVec, &header->hdr, sizeof(initVec));
+ AES_set_encrypt_key(privateKey, 128, &AESkey);
+ AES_ecb_encrypt((uint8_t *) &header->hdr, (uint8_t *) &header->hdr,
+ &AESkey, AES_ENCRYPT);
+ AES_cbc_encrypt((uint8_t *) header, (uint8_t *) header,
+ offsetof(struct alternateKey, hdr), &AESkey, initVec, AES_ENCRYPT);
+
+ return dumpBuffer(fileName, hexFormat, 0, (int *) header, sizeof(struct alternateKey));
+}
+
+// ===========================================================================
+//! Generate code/load header.
+//! Generate a code header module signed with the given private key, and
+//! optionally encrypted with the given AES key. If no encryption is
+//! desired, the AES key <i>privateKey</i> should be passed as a NULL pointer.
+//!
+//! @param fileName output file name
+//! @param hexFormat hex output format boolean
+//! @param hexAddress start address for hex output
+//! @param pkey pointer to public key structure
+//! @param privateKey pointer to AES encryption key
+//! @param codeBuf pointer to code buffer
+//! @param codeSize size of data in code buffer
+//! @param modEntryPt module entry point
+//!
+//! @return SUCCESS if successful; FILE_ERROR if not
+// ===========================================================================
+returnType genCodeHeader(
+ const char *fileName,
+ bool hexFormat,
+ uint32_t hexAddress,
+ EVP_PKEY *pkey,
+ uint8_t *privateKey,
+ uint8_t *codeBuf,
+ int codeSize,
+ int modEntryPt)
+{
+ int err;
+ uint32_t sig_len;
+ uint8_t sig_buf [4096];
+ EVP_MD_CTX md_ctx;
+ struct SL_modInfoHdr *loadModHdr;
+
+ // get pointer into first page following code
+ loadModHdr = (struct SL_modInfoHdr *) (codeBuf + codeSize);
+
+ // fill load module header
+ loadModHdr->loadModMagic = LOADMOD_MAGIC;
+ loadModHdr->loadModSize = codeSize + sizeof(struct SL_modInfoHdr) + RSASIZE;
+ loadModHdr->modEntryPt = modEntryPt;
+ loadModHdr->randomSeed1 = 0xBACCADDE;
+
+ // Do the signature
+ EVP_SignInit (&md_ctx, EVP_sha1());
+ EVP_SignUpdate (&md_ctx, (char *) codeBuf, codeSize + sizeof(struct SL_modInfoHdr));
+ sig_len = sizeof(sig_buf);
+ err = EVP_SignFinal (&md_ctx, sig_buf, (unsigned int *)&sig_len, pkey);
+
+ if(sig_len == RSASIZE)
+ copyByteReversed((char *) codeBuf + codeSize + sizeof(struct SL_modInfoHdr),
+ (const char *) sig_buf, sig_len);
+ else
+ fprintf(stderr, "Signature size incorrect - %d\n", sig_len);
+
+ // Only encrypt if an encryption key is specified
+ if (privateKey != NULL) {
+ uint8_t initVec[16];
+ AES_KEY AESkey;
+
+ memcpy(initVec, codeBuf + codeSize, sizeof(initVec));
+ AES_set_encrypt_key(privateKey, 128, &AESkey);
+ AES_ecb_encrypt(codeBuf + codeSize, codeBuf + codeSize, &AESkey, AES_ENCRYPT);
+ AES_cbc_encrypt(codeBuf, codeBuf,
+ codeSize, &AESkey, initVec, AES_ENCRYPT);
+ }
+
+ return dumpBuffer(fileName, hexFormat, hexAddress, (int *) codeBuf,
+ (codeSize + sizeof(struct SL_modInfoHdr) + RSASIZE));
+}
+
+// ===========================================================================
+//! Parse argc/argv argument vector.
+//! Option parsing routine to parse the given command line using the option
+//! string <i>ostr</i>. Returns next option character (and optional option
+//! string in the global variable #optarg).
+//!
+//! @param nargc number of arguments
+//! @param nargv pointer to array of string arguments
+//! @param ostr option string
+//!
+//! @return Option character or EOF if no more options remain
+// ===========================================================================
+int getopt(int nargc, char * const *nargv, const char *ostr)
+{
+ static char *place = (char *)""; // option letter processing
+ char *oli; // option letter list index
+
+ if (optreset || !*place) { // update scanning pointer
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = (char *)"";
+ return (EOF);
+ }
+ if (place[1] && *++place == '-') { // found "--"
+ ++optind;
+ place = (char *)"";
+ return (EOF);
+ }
+ } // option letter okay?
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ //
+ // if the user didn't specify '-' as an option,
+ // assume it means EOF.
+ //
+ if (optopt == (int)'-')
+ return (EOF);
+ if (!*place)
+ ++optind;
+ return ('?');
+ }
+ if (*++oli != ':') { // don't need argument
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { // need an argument
+ if (*place) // no white space
+ optarg = place;
+ else if (nargc <= ++optind) { // no arg
+ place = (char *)"";
+ if (*ostr == ':')
+ return (':');
+ return ('?');
+ }
+ else // white space
+ optarg = nargv[optind];
+ place = (char *)"";
+ ++optind;
+ }
+ return (optopt); // dump back option letter
+}
+
+// ===========================================================================
+//! Parse an AES key string.
+//! This routine parses an AES key value from the given <i>keyString</i>
+//! buffer. The length of the keyString is determined by the constant #CEK_SIZE.
+//!
+//! @param p pointer to the key output buffer
+//! @param keyString pointer to the key input string
+//!
+//! @return SUCCESS if Ok; AES_KEY_SIZE_ERROR if key is incorrect size;
+//! AES_KEY_FORMAT_ERROR if input is not a hexadecimal string.
+// ===========================================================================
+returnType parseKeyString(uint8_t *p, const char *keyString)
+{
+ int i;
+ uint32_t n;
+
+ if (strlen(keyString) != (CEK_SIZE << 1)) {
+ fprintf(stderr, "Key must be %d bytes (%d symbols) long\n",
+ CEK_SIZE, CEK_SIZE << 1);
+ return AES_KEY_SIZE_ERROR;
+ }
+ for (i = 0; i < CEK_SIZE; i++) {
+ if (!sscanf(&keyString[i<<1], "%2x", (unsigned int *)&n)) {
+ fprintf(stderr, "Key spec must be in hexadecimal format\n");
+ return AES_KEY_FORMAT_ERROR;
+ }
+ *p++ = (uint8_t) n;
+ }
+ return SUCCESS;
+}
+
+// ===========================================================================
+//! Parse an unsigned number and check range.
+//! This routine parses an unsigned number from the <i>str</i> argument, and
+//! checks the value against the range <i>min</i> to <i>max</i>. If the
+//! result is not within the given (inclusive) range, the value CMDERR will
+//! be returned; otherwise, <i>result</i> will contain the read number.
+//!
+//! @param str pointer to number string
+//! @param result pointer to result
+//! @param min low end of check range
+//! @param max high end of check range
+//!
+//! @return SUCCESS if Ok; CMDERR if failed.
+// ===========================================================================
+returnType parseUnsIntRange(const char *str, uint32_t *result, uint32_t min, uint32_t max)
+{
+ uint32_t temp;
+
+ temp = strtoul(str, NULL, 0);
+
+ if (temp >= min && temp <= max) {
+ *result = temp;
+ return SUCCESS;
+ }
+ return CMDERR;
+}
+
+// ===========================================================================
+//! Parse multiple unsigned integers separated by ':' markers.
+//! This routine parses multiple unsigned values from the passed <i>str</i>
+//! argument. The values should be separated by ':' markers. The number of
+//! values expected is given in <i>numInts</i>.
+//!
+//! @param str pointer to input string
+//! @param numInts number of unsigned integers to parse
+//! @param ... pointers to the results
+//!
+//! @return SUCCESS if Ok; CMDERR if failed.
+// ===========================================================================
+returnType parseMultUnsInts(const char *str, int numInts, ...)
+{
+ int i;
+ const char *p = str;
+ uint32_t temp, *pInt;
+ va_list varargMarker;
+
+ va_start(varargMarker, numInts);
+
+ for (i = 0; i < numInts;) {
+ temp = strtoul(p, (char **) &p, 0); // read the actual number
+ if (++i != numInts && *p != ':') {
+ fprintf(stderr, "Illegal number separators '%c'\n", *p);
+ return CMDERR;
+ }
+ p++; // skip separator
+ pInt = va_arg(varargMarker, uint32_t *);
+ *pInt = temp; // assign read value
+ }
+ va_end(varargMarker);
+ return SUCCESS;
+}
+
+// ===========================================================================
+//! Parse a header command line.
+//! This routine parses the command line for a header command (i.e. something
+//! that start with <b>nand</b>, <b>nor</b>, or <b>uart</b>).
+//!
+//! @param argc number of arguments
+//! @param argv list of argument strings
+//! @param type header type (NAND, NOR, or UART)
+//!
+//! @return SUCCESS if Ok; CMDERR if failed.
+// ===========================================================================
+returnType parseHeader(int argc, char* argv[], headerType type)
+{
+ const char *optString = "s:e:m:p:c:x:";
+ bool hexFormat = false;
+ uint32_t hexAddress = 0;
+ char *passWord = NULL, *certFile = NULL, *outFile;
+ uint32_t entryPoint = 0;
+ uint32_t specialMode = 0;
+ int magicId = HEADER_MAGIC;
+ int c;
+ struct bootHeaderNand bootNand;
+ struct bootHeaderNor bootNor;
+ struct bootHeaderUART bootUart;
+ EVP_PKEY *pkey;
+ struct publicKeyInfo *PKinfo;
+ returnType status = SUCCESS;
+
+ memset(&bootNand, 0, sizeof(struct bootHeaderNand));
+ memset(&bootNor, 0, sizeof(struct bootHeaderNor));
+ memset(&bootUart, 0, sizeof(struct bootHeaderUART));
+
+ while ((c = getopt(argc-1, &argv[1], optString)) != EOF) {
+ switch(c) {
+ case 's': // special mode
+ status = parseUnsIntRange(optarg, &specialMode, 0, 9);
+ if (status != SUCCESS) {
+ fprintf(stderr, "Special mode should be single digit (is %s)\n", optarg);
+ return status;
+ }
+ magicId = HEADER_MAGIC | ((specialMode << 4) | specialMode);
+ break;
+ case 'e': // entry pointer
+ if (type == UART) {
+ fprintf(stderr, "-e option not valid for UART module\n");
+ return CMDERR;
+ }
+ status = parseUnsIntRange(optarg, &entryPoint, 0x20, 0x381C);
+ if (status != SUCCESS) {
+ fprintf(stderr, "Entry point should be between 0x0020 and 0x381C (is %s)\n", optarg);
+ return status;
+ }
+ break;
+ case 'm': // module info
+ switch (type) {
+ case NAND: // NAND mode info: <page>:<block>:<size>
+ status = parseMultUnsInts(optarg, 3, &bootNand.ublStartPage,
+ &bootNand.ublStartBlock,
+ &bootNand.ublNumPages);
+ if (status != SUCCESS) {
+ return status;
+ }
+ break;
+ case NOR: // NOR mode info: <start>:<size>
+ status = parseMultUnsInts(optarg, 2, &bootNor.ublCodeStart,
+ &bootNor.ublSizeBytes);
+ if (status != SUCCESS) {
+ return status;
+ }
+ break;
+ case UART: // UART - device specific
+ // DaVinci doesn't allow -m option
+ fprintf(stderr, "-m option not valid for UART module\n");
+ return CMDERR;
+ }
+ break;
+ case 'p': // optional password
+ passWord = optarg;
+ break;
+ case 'c': // certificate file name
+ certFile = optarg;
+ break;
+ case 'x': // hex output format
+ hexFormat = true;
+ hexAddress = strtoul(optarg, NULL, 0);
+ break;
+ case '?':
+ fprintf(stderr, "Unknown command line option %s\n", argv[optind+1]);
+ return CMDERR;
+ }
+ }
+
+ if (certFile == NULL || ++optind == argc) {
+ fprintf(stderr, usageHeaderString);
+ return CMDERR;
+ }
+ outFile = argv[optind];
+
+ // Read the signing certificate
+ pkey = ReadPrivateKey(certFile, passWord);
+ if (pkey == NULL) {
+ fprintf(stderr, "Couldn't read signing key file %s\n", certFile);
+ ERR_print_errors_fp(stderr);
+
+ return CMDERR;
+ }
+
+ if (type == NAND) {
+ PKinfo = &bootNand.pkey;
+ } else if (type == NOR) {
+ PKinfo = &bootNor.pkey;
+ } else {
+ PKinfo = &bootUart.pkey;
+ }
+
+ // Initialize public key info structure
+ PKinfo->rpkExponent = (uint32_t) *pkey->pkey.rsa->e->d;
+ PKinfo->rpkUnused = 0;
+ PKinfo->rpkSize = 0x40; // size fixed at 64 16-bit words
+ memcpy(&PKinfo->rootPublicKey[0], pkey->pkey.rsa->n->d, 128);
+
+ switch (type) {
+ case NAND:
+ bootNand.magicNum = magicId;
+ bootNand.ublEntryPt = entryPoint;
+ status = genBootHeader(outFile, hexFormat, hexAddress, pkey,
+ (char *) &bootNand,
+ offsetof(struct bootHeaderNand, hdrSignature),
+ sizeof(struct bootHeaderNand));
+ break;
+ case NOR:
+ bootNor.magicNum = magicId;
+ bootNor.ublEntryPt = entryPoint;
+ status = genBootHeader(outFile, hexFormat, hexAddress, pkey,
+ (char *) &bootNor,
+ offsetof(struct bootHeaderNor, hdrSignature),
+ sizeof(struct bootHeaderNor));
+ break;
+ case UART:
+ bootUart.magicNum = magicId;
+ status = genBootHeader(outFile, hexFormat, hexAddress, pkey,
+ (char *) &bootUart,
+ offsetof(struct bootHeaderUART, hdrSignature),
+ sizeof(struct bootHeaderUART));
+ break;
+ }
+
+ return status;
+}
+
+// ===========================================================================
+//! Parse load/code command line.
+//! This routine parses the command line for the <b>load</b> command.
+//!
+//! @param argc number of arguments
+//! @param argv list of argument strings
+//!
+//! @return SUCCESS if Ok; CMDERR if failed.
+// ===========================================================================
+returnType parseLoadHeader(int argc, char* argv[])
+{
+ const char *optString = "a:b:s:p:k:c:x:";
+ char *passWord = NULL, *certFile = NULL, *inFile, *outFile;
+ uint32_t startAddress = 0;
+ uint32_t executionType = 0;
+ uint32_t blockSize = 0; // block size (indicates power of 2)
+ bool hexFormat = false;
+ uint32_t hexAddress = 0;
+ uint32_t fileSize;
+ uint8_t primaryKey[CEK_SIZE], *pKey = NULL;
+ uint8_t *pFileData;
+ int c, bufferSize;
+ returnType status;
+ FILE *hInFile;
+
+ while ((c = getopt(argc-1, &argv[1], optString)) != EOF) {
+ switch(c) {
+ case 'a': // optional start address
+ startAddress = strtoul(optarg, NULL, 16);
+ break;
+ case 'b': // (optional) block size
+ status = parseUnsIntRange(optarg, &blockSize, 4, 16);
+ if (status != SUCCESS) {
+ fprintf(stderr, "Block size should be between 4 (16 bytes) and 16 (64K bytes)\n");
+ return status;
+ }
+ break;
+ case 's': // self execution type
+ executionType = strtoul(optarg, NULL, 10);
+ if (executionType < 1 || executionType > 3) {
+ fprintf(stderr, "Incorrect execution type (%s)\n", optarg);
+ return CMDERR;
+ }
+ break;
+ case 'p': // password
+ passWord = optarg;
+ break;
+ case 'k': // key string
+ status = parseKeyString(&primaryKey[0], optarg);
+ if (status != SUCCESS)
+ return status;
+ pKey = primaryKey;
+ break;
+ case 'c': // certificate file name
+ certFile = optarg;
+ break;
+ case 'x': // hex format output
+ hexFormat = true;
+ hexAddress = strtoul(optarg, NULL, 0);
+ break;
+ case '?':
+ fprintf(stderr, "Unknown command line option %s\n", argv[optind+1]);
+ return CMDERR;
+ }
+ }
+
+ if (certFile == NULL || ++optind >= (argc-1)) {
+ fprintf(stderr, usageLoadString);
+ return CMDERR;
+ }
+ inFile = argv[optind++];
+ outFile = argv[optind];
+
+ hInFile = fopen(inFile, "rb"); // open input data file
+ if (hInFile == NULL) {
+ fprintf(stderr, "Can't open file %s for input\n", inFile);
+ return FILE_ERROR;
+ }
+
+ // Find the file size
+ fseek(hInFile, 0, SEEK_END); // move to end of file
+ fileSize = ftell(hInFile); // find out where that is
+ bufferSize = (fileSize + 15) & ~15; // round to full 16-byte buffers
+ bufferSize += sizeof(struct SL_modInfoHdr) + RSASIZE;
+
+ // next round to pagesize
+ blockSize = (1 << blockSize) - 1; // create appropriate rounder
+ bufferSize = (bufferSize + blockSize) & ~blockSize;
+
+ pFileData = (uint8_t *) calloc(bufferSize, sizeof(char)); // allocate a data buffer
+ fseek(hInFile, 0, SEEK_SET); // move back to start of file
+
+ // Next read the entire file into memory and check for read errors
+ if (fileSize != fread(pFileData, sizeof(char), fileSize, hInFile)) {
+ fprintf(stderr, "Read error in input file - expected %d bytes\n",
+ fileSize);
+ fclose(hInFile);
+ free(pFileData); // release code block
+
+ return FILE_ERROR;
+ } else {
+ // Collect the signing key
+ EVP_PKEY *sKey;
+
+ fclose(hInFile); // don't need input file anymore
+
+ // Read the signing certificate
+ sKey = ReadPrivateKey(certFile, passWord);
+ if (sKey == NULL) {
+ fprintf(stderr, "Couldn't read signing key file %s\n", certFile);
+ ERR_print_errors_fp(stderr);
+
+ return CMDERR;
+ }
+
+ startAddress |= executionType;
+ status = genCodeHeader(outFile, hexFormat, hexAddress, sKey, pKey, pFileData,
+ bufferSize - (sizeof(struct SL_modInfoHdr) + RSASIZE),
+ startAddress);
+ free(pFileData); // release code block
+
+ return status;
+ }
+}
+
+// ===========================================================================
+//! Parse delegation certificate command line.
+//! This routine parses the command line for the <b>cert</b> command.
+//!
+//! @param argc number of arguments
+//! @param argv list of argument strings
+//!
+//! @return SUCCESS if Ok; CMDERR if failed.
+// ===========================================================================
+returnType parseCertHeader(int argc, char* argv[])
+{
+ struct alternateKey altKey;
+ const char *optString = "fp:k:c:d:x";
+ int c;
+ bool primaryComplete = false;
+ char *passWord = NULL;
+ char *certFile = NULL, *delegateFile = NULL;
+ char *outFile;
+ bool hexFormat = false;
+ uint8_t primaryKey[CEK_SIZE];
+ returnType status;
+
+ memset(primaryKey, 0, CEK_SIZE);
+ memset((char *) &altKey, 0, sizeof(struct alternateKey));
+ while ((c = getopt(argc-1, &argv[1], optString)) != EOF) {
+ switch(c) {
+ case 'f': // flag (boolean)
+ altKey.keyFlags[0] = 0xff;
+ break;
+ case 'p': // password
+ if (primaryComplete) {
+ printf("Password option not available for delegate certificate\n");
+ return CMDERR;
+ } else {
+ passWord = optarg;
+ }
+ break;
+ case 'k': // key specification
+ status = parseKeyString(primaryComplete ? &altKey.aesKey[0] : &primaryKey[0], optarg);
+ if (status != SUCCESS)
+ return status;
+ break;
+ case 'c': // certificate file name
+ certFile = optarg;
+ primaryComplete = true;
+ break;
+ case 'd': // delegate certificate file name
+ delegateFile = optarg;
+ break;
+ case 'x': // hex data output format
+ hexFormat = true;
+ break;
+ case '?':
+ fprintf(stderr, "Unknown command line option %s\n", argv[optind+1]);
+ return CMDERR;
+ }
+ }
+
+ if (certFile == NULL || delegateFile == NULL || ++optind == argc) {
+ fprintf(stderr, usageCertString);
+ status = CMDERR;
+ } else {
+ EVP_PKEY *pkey;
+
+ outFile = argv[optind];
+ pkey = ReadPublicKey(delegateFile);
+ if (pkey == NULL) {
+ fprintf(stderr, "Couldn't read delegate public key file %s\n", delegateFile);
+ ERR_print_errors_fp(stderr);
+ return CMDERR;
+ }
+
+ // fill in the delegate public key value
+ altKey.pkey.rpkExponent = (uint32_t) *pkey->pkey.rsa->e->d;
+ altKey.pkey.rpkUnused = 0;
+ altKey.pkey.rpkSize = 0x40;
+ memcpy(&altKey.pkey.rootPublicKey[0], pkey->pkey.rsa->n->d, 128);
+
+ pkey = ReadPrivateKey(certFile, passWord);
+ if (pkey == NULL) {
+ fprintf(stderr, "Couldn't read signing key file %s\n", certFile);
+ ERR_print_errors_fp(stderr);
+ return CMDERR;
+ }
+
+ // fill in the header structure
+ altKey.hdr.loadModMagic = CERT_MAGIC; // special certificate magic
+ altKey.hdr.loadModSize = sizeof(struct alternateKey);
+ altKey.hdr.modEntryPt = 0; // no entry point possible
+ // TODO - this should become a real random seed...
+ altKey.hdr.randomSeed1 = 0xBACCADDE; // random seed
+
+ status = genAltKey(outFile, hexFormat, pkey, primaryKey, &altKey);
+ }
+ return status;
+}
+
+// ===========================================================================
+//! Main program.
+//! This is the main driver function for the modSign utility.
+//!
+//! @param argc number of arguments
+//! @param argv list of argument strings
+//!
+//! @return SUCCESS if Ok; error indicator if failed.
+// ===========================================================================
+int main(int argc, char* argv[])
+{
+ returnType status = CMDERR;
+
+ SSLeay_add_all_algorithms();
+ ERR_load_crypto_strings();
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: modSign <type>\n");
+ fprintf(stderr, " type nand | nor | uart | load | cert\n");
+ } else if (!strcmp(argv[1], "nand")) {
+ status = parseHeader(argc, argv, NAND);
+ } else if (!strcmp(argv[1], "nor")) {
+ status = parseHeader(argc, argv, NOR);
+ } else if (!strcmp(argv[1], "uart")) {
+ status = parseHeader(argc, argv, UART);
+ } else if (!strcmp(argv[1], "load")) {
+ status = parseLoadHeader(argc, argv);
+ } else if (!strcmp(argv[1], "cert")) {
+ status = parseCertHeader(argc, argv);
+ }
+
+ return (int) status;
+}
diff --git a/modSign.h b/modSign.h
new file mode 100644
index 0000000..634d4af
--- /dev/null
+++ b/modSign.h
@@ -0,0 +1,239 @@
+// ===================================================================
+//
+// (c) Copyright Texas Instruments, Incorporated. All Rights Reserved
+//
+// Use of this software is controlled by the terms and conditions found
+// in the license agreement under which this software has been supplied.
+//
+// This software and software source code, as well as any related
+// technology and any product developed with these items may be
+// classified as an "encryption item" under Category 5, Part 2,
+// Information Security, of the Commerce Control List ("CCL") of the
+// Department of Commerce, Bureau of Industry and Security, Export
+// Administration Regulations (EAR). Export, reexport, or release of
+// any "encryption item" contrary to the EAR is prohibited.
+// ===================================================================
+//! @file modSign.h
+//! This file describes the various structure used in the modSign
+//! utility.
+//!
+//! @version 00.90
+//!
+// ===================================================================
+// Revision History
+// ================
+//
+// ===================================================================
+
+#ifndef __MODSIGN_H
+#define __MODSIGN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//! Load module magic ID.
+//! Since load modules and certificate delegation modules share
+//! the same structure, this magic ID is used to distinguish
+//! between the two. Any legal load module must use this magic ID.
+#define LOADMOD_MAGIC 0x70ADC0DE
+
+//! Certificate delegation module magic ID.
+//! Since load modules and certificate delegation modules share
+//! the same structure, this magic ID is used to distinguish
+//! between the two. Any legal certificate delegation module must
+//! use this magic ID.
+#define CERT_MAGIC 0x70ADCE87
+
+//! Header module magic ID.
+//! The ARM boot ROM uses this magic ID to recognize legal header
+//! structures. Note that the lowest 2 nibbles are masked off for
+//! the comparison - they can contain additional configuration
+//! information.
+#define HEADER_MAGIC 0xA1ACED00
+
+//! Size of an RSA key in bytes (= 1024 bits).
+//! This is the size of a legal RSA key in bytes. We currently
+//! only support 1024-bit keys, but that will likely change in the
+//! future.
+#define RSASIZE 128
+
+//! Size of an AES key in bytes (= 128 bits).
+//! The is the size of an AES key expressed in bytes. The current
+//! implementation is optimized for 128-bit keys and 128-bit data
+//! blocks.
+#define CEK_SIZE 16
+
+//! CCS data file magic number.
+//! Any legal Code Composer Studio data file needs to start with
+//! this magic number.
+#define CCS_DATA_MAGIC 0x1651
+
+//! CCS data file types.
+//! Code Composer Studio uses these values to determine the format
+//! of data in a data file.
+enum {CCS_HEX_FORMAT = 1, CCS_INT_FORMAT, CCS_LONG_FORMAT, CCS_FLOAT_FORMAT};
+
+// Windows doesn't support the <stdint.h> header file, so we'll have to
+// extract the stuff we need here....
+#ifdef _WIN32
+//! Signed 32-bit integer
+typedef int int32_t;
+//! Signed 16-bit integer
+typedef short int16_t;
+//! Signed 8-bit integer
+typedef char int8_t;
+//! Unsigned 32-bit integer
+typedef unsigned int uint32_t;
+//! Unsigned 16-bit integer
+typedef unsigned short uint16_t;
+//! Unsigned 8-bit integer
+typedef unsigned char uint8_t;
+#else
+#include <stdint.h>
+#endif
+
+//! Public key information structure for boot blocks.
+//! This structure decribes the layout for the public key
+//! information within a boot header. It is typically preceded
+//! by the boot header proper, and followed by the signature field.
+struct publicKeyInfo {
+ //! Root public key exponent value.
+ //! Root Public Key exponent value, typically set to 3, 17, or
+ //! 0x10001.
+ uint32_t rpkExponent;
+ //! Unused field.
+ //! This field is for alignment only. It should be set to 0.
+ uint16_t rpkUnused;
+ //! Root public key size.
+ //! Root Public Key size - should be set to 0x40 (which equals
+ //! 64 16-bit words).
+ uint16_t rpkSize;
+ //! Root public key modulus value.
+ //! Root Public Key modulus value in openssl format, i.e.
+ //! most significant byte first. Note that this is backwards
+ //! from the way we use it inside the ROM code, so this is
+ //! corrected during RPK installation in secure memory.
+ uint8_t rootPublicKey[RSASIZE];
+};
+
+//! Boot header for a NAND boot block
+//!
+//! This structure describes the layout for a NAND type boot
+//! header. The main difference from other boot headers is
+//! the fact that the starting location is indicated with a
+//! block #/page # combination.
+struct bootHeaderNand {
+ //! Unique magic number for NAND boot block.
+ //! Is set to the value #HEADER_MAGIC so the ARM boot ROM
+ //! can find the boot header.
+ uint32_t magicNum;
+ //! User Boot Loader entry point.
+ uint32_t ublEntryPt;
+ //! UBL number of pages.
+ uint32_t ublNumPages;
+ //! UBL starting block number.
+ uint32_t ublStartBlock;
+ //! UBL starting page number.
+ uint32_t ublStartPage;
+ //! Public key info.
+ struct publicKeyInfo pkey;
+ //! NAND header signature.
+ uint8_t hdrSignature[RSASIZE];
+ //! padding to next 16-byte boundary.
+ uint32_t zeroField;
+};
+
+//! This structure describes the layout for a NOR type boot
+//! header.
+struct bootHeaderNor {
+ //! Unique magic number for NOR boot block.
+ //! Is set to the value #HEADER_MAGIC so the ARM boot ROM
+ //! can find the boot header.
+ uint32_t magicNum;
+ //! User Boot Loader entry point.
+ uint32_t ublEntryPt;
+ //! UBL size in bytes.
+ uint32_t ublSizeBytes;
+ //! UBL code start in NOR space.
+ uint32_t ublCodeStart;
+ //! Public key info.
+ struct publicKeyInfo pkey;
+ //! NOR header signature.
+ uint8_t hdrSignature[RSASIZE];
+ //! padding to next 16-byte boundary.
+#if !defined( __NO_PADDING_OF_NOR_PKH__ )
+ uint32_t zeroField[2];
+#endif
+};
+
+//! This structure describes the layout for a UART type boot
+//! header.
+struct bootHeaderUART {
+ //! Unique magic number for UART boot block.
+ //! Is set to the value #HEADER_MAGIC so the ARM boot ROM
+ //! can find the boot header.
+ uint32_t magicNum;
+ //! unused entry.
+ uint32_t unused;
+ //! Public key info.
+ struct publicKeyInfo pkey;
+ //! UART header signature.
+ uint8_t hdrSignature[RSASIZE];
+};
+
+//! Module info structure
+//! This structure describes the module info layout.
+struct SL_modInfoHdr {
+ //! Load module header magic.
+ //! Contains the value #LOADMOD_MAGIC if this is a
+ //! DSP or ARM code module, or the value #CERT_MAGIC if
+ //! this is a delegation certificate.
+ int loadModMagic;
+ //! Size of the module in bytes.
+ //! Size of the module expressed in bytes. This size includes
+ //! the payload size, the module info structure, and the
+ //! signature field.
+ int loadModSize;
+ //! Module entry point.
+ //! For self-executing DSP modules, this field contains the
+ //! start address of the module, and the execution type in the
+ //! least significant 2 bits. If these 2 bits are 0, this is not
+ //! a self-executing module. It is recommended that the entire
+ //! field is set to 0 for non-executing modules.
+ int modEntryPt;
+ //! Random value.
+ //! This field is not used, so it can be set to any value to
+ //! enhance the module encryption.
+ int randomSeed1;
+};
+
+//! Key delegation packet structure.
+//!
+//! This structure describes the layout of a key delegation
+//! packet.
+struct alternateKey {
+ //! Delegate AES encryption key.
+ //! This will be the new CEK' decryption key after the delegation
+ //! certificate has been successfully installed.
+ uint8_t aesKey[16];
+ //! Public key info.
+ //! This will be the new public key used for signature verification
+ //! after the delegation certificate has been successfully installed.
+ struct publicKeyInfo pkey;
+ //! Key certificate flag info.
+ //! This field currently only contains the <i>inhibit SK add-on</i> flag.
+ uint8_t keyFlags[8];
+ //! Info header.
+ //! The module info header for the delegation certificate module.
+ struct SL_modInfoHdr hdr;
+ //! Delegation certificate signature.
+ //! The signature field for the delegation certificate.
+ uint8_t hdrSignature[RSASIZE];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __MODSIGN_H
diff --git a/scripts/module-sign b/scripts/module-sign
new file mode 100755
index 0000000..fd14375
--- /dev/null
+++ b/scripts/module-sign
@@ -0,0 +1,173 @@
+#!/usr/bin/perl
+
+use IO::File;
+use File::Basename;
+use File::Copy;
+use POSIX qw(tmpnam);
+
+use strict;
+use warnings FATAL => 'all';
+
+my $TMP = "/tmp";
+
+my $program = basename( $0 );
+my $program_dir = dirname( $0 );
+
+my ($type, $infile, $outfile, $exitstatus );
+my @cmdargs;
+
+# temporary filename and handle:
+my ( $fname, $fh );
+
+
+sub usage_type
+{
+ print <<END;
+
+Usage: $program <type>
+ type nand | nor | uart | load | cert
+
+END
+ exit 0;
+}
+
+sub usage_boot
+{
+ print <<END;
+
+ Usage:
+ $program <type> [-s <mode>] -e <entry> [-m <info>] -l <address>
+ -r <crc> <outFile>
+ <type> header type: nand | nor | uart
+ -s <mode> special mode: 0..9; default = 0
+ -e <entry> absolute entry pointer
+ -l <address> load address (Jacinto Only)
+ -r <crc> CRC value (Jacinto Only)
+ -m <info> UBL module start/size info
+ <outFile> output file name
+
+END
+ exit 0;
+}
+
+sub usage_code
+{
+ print <<END;
+
+ Usage:
+ modSign load [-a <start> -s [1|2|3]] -b <block> -k <keyString>
+ <infile> <outfile>
+ -a <start> start address of module if self-executing
+ -s [1|2|3] self execution type
+ 1 = non-secure application
+ 2 = secure application - non-emulatable (default)
+ 3 = secure application - emulatable
+ -b <block> block size (optional)
+ -k <keyString> 32-character hex AES key
+ <inFile> binary input file name
+ <outFile> output file name
+
+END
+ exit 0;
+}
+
+sub usage_cert
+{
+ print <<END;
+
+ Usage:
+ modSign cert [-f] -k <keyString> -d <dCertFile> <outfile>
+ -f <flag> SK add-on inhibit flag
+ -k <keyString> 32-character hex AES key
+ -d <dCertFile> delegate RSA key certificate file
+ <outFile> output file name
+
+END
+ exit 0;
+}
+
+do { $fname = tmpnam() }
+ until $fh = IO::File->new( "$fname", O_RDWR | O_CREAT | O_EXCL );
+$fh->autoflush( 1 ); # important!
+# delete tmp file at exit (at END).
+END { unlink( $fname ) or die "Cannot unlink $fname: $!\n"; }
+
+foreach ( @ARGV )
+{
+ push @cmdargs, $_;
+}
+if( @cmdargs == 0 ) { usage_type(); }
+$type = shift @cmdargs;
+
+if( $type ne "nand" &&
+ $type ne "nor" &&
+ $type ne "uart" &&
+ $type ne "load" &&
+ $type ne "cert" ) { usage_type(); }
+if( @cmdargs == 0 )
+{
+ if( $type eq "nand" || $type eq "nor" || $type eq "uart" ) { usage_boot(); }
+ elsif( $type eq "load" ) { usage_code(); }
+ elsif( $type eq "cert" ) { usage_cert(); }
+ else { usage_type(); }
+}
+
+if( $type eq "nand" || $type eq "nor" || $type eq "uart" )
+{
+ if( @cmdargs == 0 ) { usage_code(); }
+ $outfile = pop @cmdargs;
+}
+elsif( $type eq "load" )
+{
+ if( @cmdargs == 0 ) { usage_code(); }
+ $outfile = pop @cmdargs;
+ if( @cmdargs == 0 ) { usage_code(); }
+ $infile = pop @cmdargs;
+}
+elsif( $type eq "cert" )
+{
+ if( @cmdargs == 0 ) { usage_code(); }
+ $outfile = pop @cmdargs;
+}
+
+my $CEK = "a93b936c506b68d853eae582f5052f84";
+my $PASS = "TestCertificate";
+
+print $fh <<END;
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7B128442C2819CA7
+
+dvTAHaKTsst50Dwzn3w6RywsQKpzfCephRKWA0/9KlYQX5adH5xn8TdPR6GMf6zH
+UfSOi5pUoC+FIozbPmUMAsRfGIltcDQsclSWJGwo2nLl1KP7IiPkMqtcG+wO3msf
+gVvsxC7sbheMaaUDXvUncCH4XiZSIvpUROd4MfHaNo8bQn40LWpDZd8mCvENwKsU
+Ep037hmw64dxj9IRk9vlxRgUR3QVwy8naukY/CikbIk8g3urhwj4aHgp704UAZPa
+PgEO3witxQCCmbZnTukGptoJExRlwsthQhrLppy5xogrvZd/nmfTfXWXcFr5p9XF
+c3XCYhm3pcGDyZaSt5Yg8VEVM975j5UPyz19juoxAStXXIZ5ibtiVdMvBx02WFij
+C7N4aH4nuoB+RBGJMfn7KGfR1jlEyEXZb59wOKrxA9LUFVchLNUnKAziXAVvY6Q5
+970SEFKjnCndhyqkxCxNLD2wyddigFhcjtvHHMsK1Ph8shb54tMLov/3/LXiOfK7
+KyzNz9WJJ1a9Yr3uPGpciCPprNpK/x+SmOHPtBdtXkE7VfZkXV4Org9vOvlM5GI+
+bQfWqePC+Al//0qFJ+pUiniYSnSkh5B2mdcZKq5i/1vj9b/uQWIqjMX0sx38kJ0p
+9uHozNTMw3JlecRifBPl44EsubMjrSv7w6nKkx4REIA5QAFkLaMLRP0RhcmVxtqL
+zczldpbo9Bo3kIGAguQrNLZFXry9wPuxZCr+CBNRABdvQ7XN7r3gGWm0S2TiIIIh
+Xgt9p72kqtkIDWy6gK19a72FEgh9jvmVjDizzl9IAP8adtgcXlCGNw==
+-----END RSA PRIVATE KEY-----
+END
+
+if( $type eq "cert" )
+{
+ system( "$program_dir/modSign $type -k$CEK -p$PASS -c $fname @cmdargs $outfile" );
+ $exitstatus = $? >> 8;
+}
+elsif( $type eq "load" )
+{
+ system( "$program_dir/modSign $type @cmdargs -k$CEK -p$PASS -c $fname $infile $outfile" );
+ $exitstatus = $? >> 8;
+}
+else
+{
+ system( "$program_dir/modSign $type @cmdargs -p$PASS -c $fname $outfile" );
+ $exitstatus = $? >> 8;
+}
+
+exit $exitstatus;
diff --git a/scripts/signing.txt b/scripts/signing.txt
new file mode 100644
index 0000000..6c90d2e
--- /dev/null
+++ b/scripts/signing.txt
@@ -0,0 +1,17 @@
+
+create uart_PKH:
+
+./module-sign uart uart_PKH.dat
+
+create nor_PKH:
+
+./module-sign nor -s 3 -e0x0020 -m0x02000118:0x3800 ubl_NOR_PKH.dat
+
+sign module:
+
+./module-sign load ubl.bin ubl_MODULE.dat
+
+sign DSP leave secure mode:
+
+./module-sign load -a 0x11801800 -s 1 dsp_module.bin dsp_module.bin.protected
+./module-sign load -a 0x8f40 -s 1 dsp_module.bin dsp_module.bin.protected