blob: 2f45d66c5f29f1e284ee975e9dd1d3628fad9842 [file] [log] [blame]
Mate Toth-Pal51b61982022-03-17 14:19:30 +01001# -----------------------------------------------------------------------------
2# Copyright (c) 2019-2022, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6# -----------------------------------------------------------------------------
7
Mate Toth-Palb9057ff2022-04-29 16:03:21 +02008"""Unittests for iat-verifier using PSAIoTProfile1TokenVerifier"""
9
Mate Toth-Pal51b61982022-03-17 14:19:30 +010010import os
Mate Toth-Pal51b61982022-03-17 14:19:30 +010011import unittest
12
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020013from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010014from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
Mate Toth-Palb2508d52022-04-30 14:10:06 +020015from iatverifier.util import read_keyfile
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010016from iatverifier.attest_token_verifier import AttestationClaim, VerifierConfiguration
17from iatverifier.attest_token_verifier import AttestationTokenVerifier
Mate Toth-Palb2508d52022-04-30 14:10:06 +020018from test_utils import create_and_read_iat, read_iat, create_token_tmp_file
Mate Toth-Pal51b61982022-03-17 14:19:30 +010019
20
21THIS_DIR = os.path.dirname(__file__)
22
23DATA_DIR = os.path.join(THIS_DIR, 'data')
24KEYFILE = os.path.join(DATA_DIR, 'key.pem')
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010025KEYFILE_CCA_PLAT = os.path.join(DATA_DIR, 'cca_platform.pem')
26KEYFILE_CCA_REALM = os.path.join(DATA_DIR, 'cca_realm.pem')
Mate Toth-Palb21ae522022-09-01 12:02:21 +020027KEYFILE_CCA_REALM2= os.path.join(DATA_DIR, 'cca_realm2.pem')
Mate Toth-Pal51b61982022-03-17 14:19:30 +010028KEYFILE_ALT = os.path.join(DATA_DIR, 'key-alt.pem')
29
Mate Toth-Pal51b61982022-03-17 14:19:30 +010030class TestIatVerifier(unittest.TestCase):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020031 """A class used for testing iat-verifier.
32
33 This class uses the claim and token definitions for PSA Attestation Token"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010034
35 def setUp(self):
36 self.config = VerifierConfiguration()
37
38 def test_validate_signature(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020039 """Testing Signature validation"""
40 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
41 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
Mate Toth-Pal51b61982022-03-17 14:19:30 +010042
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020043 signing_key = read_keyfile(KEYFILE, method)
44 verifier_good_sig = PSAIoTProfile1TokenVerifier(
45 method=method,
46 cose_alg=cose_alg,
47 signing_key=signing_key,
48 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020049 good_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_good_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010050
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020051 signing_key = read_keyfile(KEYFILE_ALT, method)
52 verifier_bad_sig = PSAIoTProfile1TokenVerifier(
53 method=method,
54 cose_alg=cose_alg,
55 signing_key=signing_key,
56 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020057 bad_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_bad_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010058
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020059 #dump_file_binary(good_sig)
60
61 with open(good_sig, 'rb') as wfh:
Mate Toth-Palc7404e92022-07-15 11:11:13 +020062 token_item = verifier_good_sig.parse_token(
63 token=wfh.read(),
64 check_p_header=False,
65 lower_case_key=False)
66 token_item.verify()
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020067
68 with self.assertRaises(ValueError) as test_ctx:
69 with open(bad_sig, 'rb') as wfh:
Mate Toth-Palc7404e92022-07-15 11:11:13 +020070 token_item = verifier_good_sig.parse_token(
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020071 token=wfh.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020072 check_p_header=False,
73 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +020074 token_item.verify()
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020075
76 self.assertIn('Bad signature', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +010077
78 def test_validate_iat_structure(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020079 """Testing IAT structure validation"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010080 keep_going_conf = VerifierConfiguration(keep_going=True)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020081 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
82 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
83 signing_key = read_keyfile(KEYFILE, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010084 realm_token_key = read_keyfile(KEYFILE_CCA_REALM, method)
Mate Toth-Palb21ae522022-09-01 12:02:21 +020085 realm_token_key2 = read_keyfile(KEYFILE_CCA_REALM2, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010086 platform_token_key = read_keyfile(KEYFILE_CCA_PLAT, method)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010087
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +020089 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020090 'valid-iat.yaml',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010091 PSAIoTProfile1TokenVerifier(
92 method=method,
93 cose_alg=cose_alg,
94 signing_key=signing_key,
95 configuration=self.config))
Mate Toth-Palb21ae522022-09-01 12:02:21 +020096
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010097 create_and_read_iat(
98 DATA_DIR,
99 'valid-cca-token.yaml',
100 CCATokenVerifier(
101 realm_token_method=method,
102 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
103 realm_token_key=realm_token_key,
104 platform_token_method=method,
105 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
106 platform_token_key=platform_token_key,
107 configuration=self.config))
108
109 create_and_read_iat(
110 DATA_DIR,
111 'cca_platform_token.yaml',
112 CCAPlatformTokenVerifier(
113 method=method,
114 cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
115 signing_key=platform_token_key,
116 configuration=self.config,
117 necessity=AttestationClaim.MANDATORY))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100118
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200119 with self.assertRaises(ValueError) as test_ctx:
120 create_and_read_iat(
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200121 DATA_DIR,
122 'valid-cca-token.yaml',
123 CCATokenVerifier(
124 realm_token_method=method,
125 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
126 realm_token_key=realm_token_key2,
127 platform_token_method=method,
128 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
129 platform_token_key=platform_token_key,
130 configuration=self.config))
131 self.assertIn("Realm signature doesn't match Realm Public Key claim in Realm token", test_ctx.exception.args[0])
132
133 with self.assertRaises(ValueError) as test_ctx:
134 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200135 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200136 'invalid-profile-id.yaml',
137 PSAIoTProfile1TokenVerifier(method=method,
138 cose_alg=cose_alg,
139 signing_key=signing_key,
140 configuration=self.config))
141 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100142
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200143 with self.assertRaises(ValueError) as test_ctx:
144 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200145 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200146 'malformed.cbor',
147 PSAIoTProfile1TokenVerifier(method=method,
148 cose_alg=cose_alg,
149 signing_key=signing_key,
150 configuration=self.config))
151 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100152
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200153 with self.assertRaises(ValueError) as test_ctx:
154 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200155 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200156 'missing-claim.yaml',
157 PSAIoTProfile1TokenVerifier(method=method,
158 cose_alg=cose_alg,
159 signing_key=signing_key,
160 configuration=self.config))
161 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100162
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200163 with self.assertRaises(ValueError) as test_ctx:
164 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200165 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200166 'submod-missing-claim.yaml',
167 PSAIoTProfile1TokenVerifier(method=method,
168 cose_alg=cose_alg,
169 signing_key=signing_key,
170 configuration=self.config))
171 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100172
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200173 with self.assertRaises(ValueError) as test_ctx:
174 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200175 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200176 'missing-sw-comps.yaml',
177 PSAIoTProfile1TokenVerifier(method=method,
178 cose_alg=cose_alg,
179 signing_key=signing_key,
180 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100181 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200182 test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100183
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200184 with self.assertLogs() as test_ctx:
185 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200186 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200187 'missing-signer-id.yaml',
188 PSAIoTProfile1TokenVerifier(method=method,
189 cose_alg=cose_alg,
190 signing_key=signing_key,
191 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200192 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200193 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100194
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200195 with self.assertLogs() as test_ctx:
196 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200197 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200198 'invalid-type-length.yaml',
199 PSAIoTProfile1TokenVerifier(method=method,
200 cose_alg=cose_alg,
201 signing_key=signing_key,
202 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100203 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200204 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100205 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200206 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100207 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200208 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100209 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200210 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100211
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200212 with self.assertLogs() as test_ctx:
213 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200214 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200215 'invalid-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200216 PSAIoTProfile1TokenVerifier(
217 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200218 cose_alg=cose_alg,
219 signing_key=signing_key,
220 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200221 self.assertIn("Invalid HARDWARE_VERSION length; "
222 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200223 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200224 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200225 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200226 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200227 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200228 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200229 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100230
231 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200232 """Test binary_string decoding"""
233 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
234 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
235 signing_key = read_keyfile(KEYFILE, method)
236 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200237 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200238 'valid-iat.yaml',
239 PSAIoTProfile1TokenVerifier(method=method,
240 cose_alg=cose_alg,
241 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200242 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100243 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')
244
245 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200246 """Test security lifecycle decoding"""
247 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
248 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
249 signing_key = read_keyfile(KEYFILE, method)
250 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200251 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200252 'valid-iat.yaml',
253 PSAIoTProfile1TokenVerifier(method=method,
254 cose_alg=cose_alg,
255 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200256 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100257 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')