Initial Attestation Verifier

This is a set of utility scripts for working with PSA Initial Attestation Token, the structure of which is described here:

The following utilities are provided:

check_iat

Verifies the structure, and optionally the signature, of a token.

compile_token

Creates a (optionally, signed) token from a YAML descriptions of the claims.

decompile_token

Generates a YAML descriptions of the claims contained within a token. (Note: this description can then be compiled back into a token using compile_token.)

Installation

You can install the script using pip:

# Inside the directory containg this README
pip3 install .

This should automatically install all the required dependencies. Please see setup.py for the list of said dependencies.

Usage

Note

You can use -h flag with any of the scripts to see their usage help.

check_iat

After installing, you should have check_iat script in your PATH. The script expects a single parameter – a path to the signed IAT in COSE format.

You can find an example in the “sample” directory.

The script will extract the COSE payload and make sure that it is a valid IAT (i.e. all mandatory fields are present, and all known fields have correct size/type):

$ check_iat sample/cbor/iat.cbor
Token format OK

If you want the script to verify the signature, you need to specify the file containing the signing key in PEM format using -k option. The key used to sign sample/iat.cbor is inside sample/key.pem.

$ check_iat -k sample/key.pem  sample/cbor/iat.cbor
Signature OK
Token format OK

You can add a -p flag to the invocation in order to have the script print out the decoded IAT in JSON format. It should look something like this:

{
    "INSTANCE_ID": "\u0001\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
    "IMPLEMENTATION_ID": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
    "CHALLEGE": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
    "CLIENT_ID": 2,
    "SECURITY_LIFECYCLE": 2,
    "VERSION": 1,
        "BOOT_SEED": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018"
    "SUBMOD": [
    {
        "SUBMOD_NAME": "BL",
        "SIGNER_ID": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
        "SUBMOD_VERSION": "3.4.2",
        "MEASUREMENT": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018"
    },
    {
        "SUBMOD_NAME": "M1",
        "SIGNER_ID": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
        "SUBMOD_VERSION": "3.4.2",
        "MEASUREMENT": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018"
    },
    {
        "SUBMOD_NAME": "M2",
        "SIGNER_ID": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
        "SUBMOD_VERSION": "3.4.2",
        "MEASUREMENT": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018"
    },
    {
        "SUBMOD_NAME": "M3",
        "SIGNER_ID": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018",
        "SUBMOD_VERSION": "3.4.2",
        "MEASUREMENT": "\u0007\u0006\u0005\u0004\u0003\u0002\u0001\u0000\u000f\u000e\r\f\u000b\n\t\b\u0017\u0016\u0015\u0014\u0013\u0012\u0011\u0010\u001f\u001e\u001d\u001c\u001b\u001a\u0019\u0018"
    }
    ]
}

compile_token

You can use this script to compile a YAML claims description into a COSE-wrapped CBOR token:

$ compile_token -k sample/key.pem sample/yaml/iat.yaml > sample_token.cbor

No validation is performed as part of this, so there is no guarantee that a valid IAT will be produced.

You can omit the -k option, in which case, the resulting token will not be signed, however it will still be wrapped in COSE “envelope”. If you would like to produce a pure CBOR encoding of the claims without a COSE wrapper, you can use -r flag.

decompile_token

Decompile an IAT (or any COSE-wrapped CBOR object – no validation is performed as part of this) into a YAML description of its claims.

$decompile_token  sample/cbor/iat.cbor
boot_seed: !!binary |
  BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
challenge: !!binary |
  BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
client_id: 2
implementation_id: !!binary |
  BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
instance_id: !!binary |
  AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY
profile_id: http://example.com
security_lifecycle: SL_SECURED
sw_components:
- measurement_description: TF-M_SHA256MemPreXIP
  measurement_value: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  signer_id: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  sw_component_type: BL
  sw_component_version: 3.4.2
- measurement_value: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  signer_id: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  sw_component_type: M1
  sw_component_version: 1.2
- measurement_value: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  signer_id: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  sw_component_type: M2
  sw_component_version: 1.2.3
- measurement_value: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  signer_id: !!binary |
    BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=
  sw_component_type: M3
  sw_component_version: 1

This description can then be compiled back into CBOR using compile_token.

Mac0Message

By default, the expectation is that the message will be wrapped using Sign1Message COSE structure, however, the alternative Mac0Message structure that uses HMAC with SHA256 algorithm rather than a signature is supported via the -m mac flag:

$ check_iat -m mac -k sample/hmac.key sample/iat-hmac.cbor
Signature OK
Token format OK

Testing

Tests can be run using nose2:

pip install nose2

Then run by executing nose2 in the root directory.

Development Scripts

The following utility scripts are contained within dev_scripts subdirectory and were utilized in development of this tool. They are not need to use the iat-verifier script, and can generally be ignored.

./dev_scripts/generate-key.py OUTFILE

Generate an ECDSA (NIST256p curve) signing key and write it in PEM format to the specified file.

./dev_scripts/generate-sample-iat.py KEYFILE OUTFILE

Generate a sample token, signing it with the specified key, and writing the output to the specified file.

Note

This script is deprecated – use compile_token (see above) instead.


Copyright (c) 2019-2020, Arm Limited. All rights reserved.