=======================================
Security X509 Certificate Documentation
=======================================

.. _sysfw_x509_ext_doc:

Introduction
============

This document describes the X509 extensions supported by the X509 parser in System Firmware.

.. note::

   This document is only applicable to HS devices. |sysfw| does not include a
   X509 parser on GP devices.

References
==========

1. ISO 8824-1 | ITU-T X.680 (08/2015): Information technology - Abstract Syntax
   Notation One (ASN.1): Specification of basic notation,
   http://handle.itu.int/11.1002/1000/12479
2. ISO 8825-1 | ITU-T X.690 (09/2015): Information technology - ASN.1 encoding
   rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules
   (CER) and Distinguished Encoding Rules (DER)
   http://handle.itu.int/11.1002/1000/12483
3. ISO/IEC 9594-8 | ITU-T X.509 (10/2016): Information technology - Open Systems
   Interconnection - The Directory: Public-key and attribute certificate
   frameworks
   http://handle.itu.int/11.1002/1000/13031
4. :doc:`PROC_BOOT`


.. _sysfw_x509_ext_summary:

Extensions
==========

The following X509 extensions are supported by |sysfw|.

+--------------------------------------+----------------------------------------+
|         Extension Name               |     Purpose                            |
+======================================+========================================+
| :ref:`sysfw_boot_ext`                | Provide boot information               |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_image_integrity_ext`     | Image hash and length                  |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_swrev_ext`               | revision of binary for anti-rollback   |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_load_ext`                | Provide load information               |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_debug_ext`               | To unlock debug port                   |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_encryption_ext`          | Encryption extension                   |
+--------------------------------------+----------------------------------------+
| :ref:`sysfw_hs_bcfg_ext`             | HS Boardcfg extension                  |
+--------------------------------------+----------------------------------------+

.. _sysfw_boot_ext:

|sysfw| Boot Extension
----------------------

This extension adds support for booting various cores on a K3 SOC. It is
identified by the OID **1.3.6.1.4.1.294.1.33**. The structure of the field is
shown below in ASN.1 notation.

::

    SYSFW-Boot := SEQUENCE
    {
        bootCore INTEGER, -- indicates the core in the device that needs to be booted
                          -- with the image accompanying this certificate.
        configFlags_set INTEGER, -- Configuration options for the core being booted.
                                 -- flags to set
        configFlags_clr INTEGER, -- Configuration options for the core being booted
                                 -- flags to clear
        resetVec OCTET STRING, -- Location of reset vector for the core.

        fieldValid INTEGER -- indicates which of the reserved fields in the extension are
                           -- valid
        rsvd1     INTEGER, -- reserved field for future use 
        rsvd2     INTEGER, -- reserved field for future use 
        rsvd3     INTEGER, -- reserved field for future use 
    }

The boot extension is decoded into the below structure.

::

    struct sec_boot_ctrl {
        u32 bootCore;
        u32 configFlags_set;
        u32 configFlags_clr;
        u64 resetVec;
    }

The reserved fields are for future use and are not decoded currently.


Populating the certificate fields
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For an example, please refer to the section ``[ sysfw_boot_seq ]`` in :ref:`sysfw_x509_template_example`.

1. ``bootCore`` should be initialized to the Core ID of the targeted core.
   Core ID should be obtained from the SOC data. e.g. For booting a
   core with ID ``0x20``, the relevant line in the X509 template is

   ::

        [ boot_seq ]
        bootCore = INTEGER:0x20

2. ``configFlags_set``

  - This is a 32 bit field that indicates core specific flags that need
    to be set before booting the core. The representation is big endian.

3. ``configFlags_clr``

  - This is a 32 bit field that indicates core specific flags that need
    to be cleared before booting core. The representation is big endian.

   Please refer to the SOC and core specific documentation on the supported
   flags. The flags are passed to
   :ref:`set_processor_config <proc-boot-set-processor-configuration>` API as
   is. Please ensure that the flags set or cleared are valid according to the
   API.

4. ``resetVec``

  - This is a 64 bit field indicating the address of the reset vector
    that needs to be programmed. The representation is big endian.

.. _sysfw_image_integrity_ext:

|sysfw| Image Integrity Extension
---------------------------------

This extension adds support for specifying a hash and size of the accompanying
payload. It is identified by the OID **1.3.6.1.4.1.294.1.34**. The structure of
the field is shown below in ASN.1 notation.

::

   SYSFW-INTEGRITY := SEQUENCE
   {
      shaType OID, -- indicates OID of the hash used. Must always be set to SHA2-512
                   -- OID:2.16.840.1.101.3.4.2.3
      shaValue OCTET STRING, -- SHA2-512 value of the payload
      imageSize INTEGER, -- Size of the image in bytes. This will be amount of data
                         -- used when checking the image integrity, copying the image
                         -- to its destination or when decrypting the image.
   }


.. _sysfw_swrev_ext:

|sysfw| Software Revision Extension
-----------------------------------

|sysfw| reuses the Software Revision extension/OID as defined by ROM as no
additional information is required. This is identified by OID
**1.3.6.1.4.1.294.1.3**.

::

   SYSFW-SWREV:= SEQUENCE
   {
      swrev INTEGER -- 32 bit value indicating the revision of the binary
   }


.. _sysfw_load_ext:

|sysfw| Load Extension
----------------------

|sysfw| uses the Load extension to determine where the image is loaded
as part of authentication. The load extension is identified by OID **1.3.6.1.4.1.294.1.35**. This is a new extension defined by |sysfw|.

::

   SYSFW-LOAD := SEQUENCE
   {
        destAddr OCTET STRING, -- Address to which the image accompanying this certificate
                               -- needs to be copied.
        auth_in_place INTEGER -- Controls if/how the authenticated binary is copied to a different
                              -- location. See below for more information.
   }

The load extension is decoded into the below structure.

::

   struct ti_load_info {
    u64 destAddr;
    u8  auth_in_place;
   };

Populating the certificate fields
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1. ``destAddr``

   - This is a 64 bit field indicating the address to which the data
     needs to be copied. The representation is big endian.

2. ``auth_in_place``

   - This is an integer field used to indicate whether the binary should be copied
     to the specified load address during authentication. The valid values for this
     field and their interpretation are described below.

     +----------+-----------------------------------------------------------------+
     | Value    | Action                                                          |
     +==========+=================================================================+
     | 0        | Normal operation. Binary is copied to load address.             |
     +----------+-----------------------------------------------------------------+
     | 1        | In place operation. Binary is not moved.                        |
     +----------+-----------------------------------------------------------------+
     | 2        | In place operation variant. Binary is moved to the beginning of |
     |          | the buffer i.e. binary now starts at the location where the     |
     |          | certificate started                                             |
     +----------+-----------------------------------------------------------------+
     | Any      | invalid operation                                               |
     | other    |                                                                 |
     | value    |                                                                 |
     +----------+-----------------------------------------------------------------+

.. _sysfw_encryption_ext:

|sysfw| Encryption Extension
----------------------------

|sysfw| reuses the Encryption extension/OID as defined by ROM as no
additional information is required. This is identified by OID
**1.3.6.1.4.1.294.1.4**.

::

   SYSFW-ENCRYPT := SEQUENCE
   {
      initalVector OCTET STRING,
      randomString OCTET STRING,
      iterationCnt INTEGER,
      salt OCTET STRING
   }

The encryption extension is decoded into the following data structure.

.. code-block:: c

   struct ti_enc_info {
    u8 initialVector[16];
    u8 randomString[32];
    u8 iterationCnt;
    u8 salt[32];
   };

Populating the certificate fields
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1. ``initialVector``

   - This is the 16 byte initialization vector to be used in AES-CBC
     decryption.

2. ``randomString``

   - This field indicates the random 32 byte string that was appended to the
     binary before encrypting the combined binary. |sysfw| will compare the last
     32 bytes of the decryption output against the ``randomString`` field from
     the X509 certificate to verify the success of decryption operation.

3. ``iterationCnt``

   - This field is reserved and must be initialized to zero.

4. ``salt``

   - This field is 32 bytes long. It is reserved and must be initialized to zero.

.. note::

   |sysfw| always loads the binary to the location specified by :ref:`sysfw_load_ext`
   before performing in-place decryption at the loaded location.


.. _sysfw_debug_ext:

|sysfw| Debug Extension
-----------------------

.. note::

   This extension is not yet finalized.

The custom extension field used for debug control is identified by the OID
**1.3.6.1.4.1.294.1.8**. The structure of the field is shown below in
ASN.1 notation.

::

    UID-Debug ::= SEQUENCE
    {
        uid OCTET STRING, -- unique ID of the device for which this certificate applies
        debugCtrl INTEGER, -- debug control information
        coreDbgEn INTEGER, -- Core IDs for which debug must be enabled
        coreDbgSecEn INTEGER, -- Core IDs for which secure debug must be enabled
    }

The debug control data is decoded as a structure below:

::

    struct sdbg_debug_ctrl {
        u16 debug_priv_level;
        u16 hw_key_hide_flags;
        u8 debug_core_sel[MAX_CPU_CORES];
        u8 sec_debug_core_sel[MAX_CPU_CORES];
    }

The table below shows the way **UID-Debug** fields are decoded into **struct sdbg_debug_ctrl**.

+------------------------+----------------------------------------------------------+
| sdbg_debug_ctrl member |         X.509 certificate debug extension field          |
+========================+==========================================================+
| debug_priv_level       |debugCtrl field is decoded as a u32 value and the lower 16|
|                        |bit value is picked up                                    |
+------------------------+----------------------------------------------------------+
| hw_key_hide_flags      |debugCtrl field is decoded as a u32 value and the upper 16|
|                        |bit value is picked up                                    |
+------------------------+----------------------------------------------------------+
| debug_core_sel         |coreDbgEn field is decoded as an array of u8 values of    |
|                        |host-IDs for which non-secure debug should be enabled     |
+------------------------+----------------------------------------------------------+
| sec_debug_core_sel     |coreDbgSecEn field is decoded as an array of u8 values of |
|                        |host-IDs for which secure debug should be enabled         |
+------------------------+----------------------------------------------------------+

The following table shows the enumeration of values for **debug_priv_level**:

+-------------------+-------+-------------------------------------------------------+
| Enumeration name  | Value |                                  Meaning              |
+===================+=======+=======================================================+
| DEBUG_DISABLE     | 0     | Disable debug                                         |
+-------------------+-------+-------------------------------------------------------+
| DEBUG_PRESERVE    | 1     | Preserve current setting by locking registers         |
+-------------------+-------+-------------------------------------------------------+
| DEBUG_PUBLIC      | 2     | Enable debug at public (non-secure) user and          |
|                   |       | privileged level                                      |
+-------------------+-------+-------------------------------------------------------+
| DEBUG_PUBLIC_USER | 3     | Enable debug at public (non-secure) user level only   |
+-------------------+-------+-------------------------------------------------------+
| DEBUG_FULL        | 4     | Enable full debug (both secure and non-secure         |
|                   |       | privileged and user levels)                           |
+-------------------+-------+-------------------------------------------------------+
| DEBUG_SECURE_USER | 5     | Enable debug for both secure and non-secure at user   |
|                   |       | level only                                            |
+-------------------+-------+-------------------------------------------------------+

The following table shows the enumeration of the bitfield **hw_key_hide_flags**:

+-------------------------+-------+---------------------------------------------------+
|    Enumeration name     | Value |                                Meaning            |
+=========================+=======+===================================================+
| CERT_KEY_FLAGS_KEK      | 1     | If this bit is set, the KEK must be hidden with a |
|                         |       | software KEK                                      |
+-------------------------+-------+---------------------------------------------------+
| CERT_KEY_FLAGS_CUST_SSK | 2     | If this bit is set, customer secret keys (SMPK &  |
|                         |       | BMPK) must be hidden                              |
+-------------------------+-------+---------------------------------------------------+

For an example, please refer to the section ``[ debug ]`` in :ref:`sysfw_x509_template_example`.

.. _sysfw_hs_bcfg_ext:

|sysfw| HS Board Configuration Extension
-------------------------------------------------

|sysfw| extends the Encryption extension/OID as defined by ROM for the purpose
of authenticating the board configurations on HS devices. The hashes of the 4
board configuration blobs

1. Core board configuration
2. PM board configurations
3. RM board configuration
4. Encrypted Security board configuration

and the encryption parameters of the security board configuration are encoded in
the board configuration extension of the |sysfw| outer certificate . This
extension is identified by OID **1.3.6.1.4.1.294.1.36**.

::

   SYSFW-HS-BCFG:= SEQUENCE
   {
      initalVector OCTET STRING,
      randomString OCTET STRING,
      iterationCnt INTEGER,
      salt OCTET STRING,
      secBoardCfgHash OCTET STRING,
      secBoardCfgVer INTEGER,
      pmBoardCfgHash OCTET STRING,
      rmBoardCfgHash OCTET STRING
      boardCfgHash OCTET STRING
   }

The extension is decoded into the following data structure.

.. code-block:: c

   struct ti_bcfg_info {
    u8 initialVector[16];
    u8 randomString[32];
    u8 iterationCnt;
    u8 salt[32];
    u8 secBoardCfgHash[64];
    u8 secBoardCfgVer;
    u8 pmBoardCfgHash[64];
    u8 rmBoardCfgHash[64];
    u8 boardCfgHash[64];
   };

Populating the certificate fields
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1. ``initialVector``

   - This is the 16 byte initialization vector to be used in AES-CBC
     decryption.

2. ``randomString``

   - This field indicates the random 32 byte string that was appended to the
     board configuration binary before encrypting the combined binary. |sysfw|
     will compare the last 32 bytes of the decryption output against the
     ``randomString`` field from the X509 certificate to verify the success of
     decryption operation.

3. ``iterationCnt``

   - This field is reserved and must be initialized to zero.

4. ``salt``

   - This field is 32 bytes long. It is reserved and must be initialized to
     zero.

5. ``secBoardCfgHash``

   - This is a 64 byte field containing the SHA2-512 hash of the encrypted |sec_bcfg|. 

6. ``secBoardCfgVer``

   - This field indicates the version of security board configuration and must be initialized
     to zero.

7. ``pmBoardCfgHash``

   - This is a 64 byte field containing the SHA2-512 hash of the PM board configuration.

8. ``rmBoardCfgHash``

   - This is a 64 byte field containing the SHA2-512 hash of the RM board configuration.

8. ``boardCfgHash``

   - This is a 64 byte field containing the SHA2-512 hash of the main board configuration
     structure.

.. _sysfw_x509_template_example:

Sample x509 template
---------------------

.. note::

   The template below shows all the X509 extensions supported by the |sysfw|
   ASN1 parser. Depending on the usecase, the certificate may contain only a few
   of these extensions.

   - For performing JTAG unlock, only Software revision (``swrv``) and
     Debug(``debug``) extensions are required.
   - For authenticating a binary, only the Load (``sysfw_image_load``) and
     Image integrity (``sysfw_image_integrity``) extensions are required.

.. code-block :: bash

    [ req ]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_ca
    prompt = no

    dirstring_type = nobmp

    # This information will be filled by the end user.
    # The current data is only a place holder.
    # System firmware does not make decisions based
    # on the contents of this distinguished name block.
    [ req_distinguished_name ]
    C = US
    ST = Texas
    L = Dallas
    O = Texas Instruments
    OU = K3
    CN = www.ti.com
    emailAddress = noreply@ti.com

    [ v3_ca ]
    basicConstraints = CA:true
    1.3.6.1.4.1.294.1.3=ASN1:SEQUENCE:swrv
    1.3.6.1.4.1.294.1.4=ASN1:SEQUENCE:encryption
    1.3.6.1.4.1.294.1.33=ASN1:SEQUENCE:sysfw_boot_seq
    1.3.6.1.4.1.294.1.34=ASN1:SEQUENCE:sysfw_image_integrity
    1.3.6.1.4.1.294.1.35=ASN1:SEQUENCE:sysfw_image_load
    1.3.6.1.4.1.294.1.36=ASN1:SEQUENCE:sysfw_hs_boardcfg

    [ sysfw_boot_seq ]
    bootCore = INTEGER:0x20
    bootCoreOpts_set = INTEGER:0x00000000
    bootCoreOpts_clr = INTEGER:0x00000000
    resetVec = FORMAT:HEX,OCT:41c02100
    flagsValid = INTEGER:0x00
    rsvd1 = INTEGER:0x00
    rsdv2 = INTEGER:0x00
    rsdv3 = INTEGER:0x00

    [ sysfw_image_integrity ]
    shaType = OID:2.16.840.1.101.3.4.2.3
    shaValue = FORMAT:HEX,OCT:TEST_IMAGE_SHA512
    # Replace TEST_IMAGE_LENGTH with actual image length
    imageSize = INTEGER:TEST_IMAGE_LENGTH

    [ sysfw_image_load ]
    destAddr = FORMAT:HEX,OCT:41c02100
    authInPlace = INTEGER:0

    [ swrv ]
    swrv = INTEGER:0

    [ debug ]
    debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000
    debugType = INTEGER:0x00010005
    coreDbgEn = INTEGER:0x20210102
    coreDbgSecEn = INTEGER:0x2223

    [ encryption ]
    initalVector =  FORMAT:HEX,OCT:TEST_IMAGE_ENC_IV
    randomString =  FORMAT:HEX,OCT:TEST_IMAGE_ENC_RS
    iterationCnt =  INTEGER:TEST_IMAGE_KEY_DERIVE_INDEX
    salt         =  FORMAT:HEX,OCT:TEST_IMAGE_KEY_DERIVE_SALT

    [ sysfw_hs_boardcfg ]
    initalVector    =  FORMAT:HEX,OCT:SEC_BCFG_ENC_IV
    randomString    =  FORMAT:HEX,OCT:SEC_BCFG_ENC_RS
    iterationCnt    =  INTEGER:SEC_BCFG_KEY_DERIVE_INDEX
    salt            =  FORMAT:HEX,OCT:SEC_BCFG_KEY_DERIVE_SALT
    secBoardcfgHash =  FORMAT:HEX,OCT:SEC_BCFG_HASH
    secBoardcfgVer  =  INTEGER:SEC_BCFG_VER
    pmBoardcfgHash  =  FORMAT:HEX,OCT:PM_BCFG_HASH
    rmBoardcfgHash  =  FORMAT:HEX,OCT:RM_BCFG_HASH
    boardcfgHash    =  FORMAT:HEX,OCT:BCFG_HASH
