blob: 2ea1b5e5da48e8f0d804d89412834ed69addd3bc [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,
Mate Toth-Palc5dbad02022-09-01 22:17:26 +0200122 'cca-invalid-plat-challenge.yaml',
123 CCATokenVerifier(
124 realm_token_method=method,
125 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
126 realm_token_key=realm_token_key,
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("Invalid CCA_PLATFORM_CHALLENGE byte at 16: 0x00 instead of 0xe4", test_ctx.exception.args[0])
132
133 with self.assertRaises(ValueError) as test_ctx:
134 create_and_read_iat(
135 DATA_DIR,
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200136 'valid-cca-token.yaml',
137 CCATokenVerifier(
138 realm_token_method=method,
139 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
140 realm_token_key=realm_token_key2,
141 platform_token_method=method,
142 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
143 platform_token_key=platform_token_key,
144 configuration=self.config))
145 self.assertIn("Realm signature doesn't match Realm Public Key claim in Realm token", test_ctx.exception.args[0])
146
147 with self.assertRaises(ValueError) as test_ctx:
148 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200149 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200150 'invalid-profile-id.yaml',
151 PSAIoTProfile1TokenVerifier(method=method,
152 cose_alg=cose_alg,
153 signing_key=signing_key,
154 configuration=self.config))
155 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100156
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200157 with self.assertRaises(ValueError) as test_ctx:
158 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200159 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200160 'malformed.cbor',
161 PSAIoTProfile1TokenVerifier(method=method,
162 cose_alg=cose_alg,
163 signing_key=signing_key,
164 configuration=self.config))
165 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100166
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200167 with self.assertRaises(ValueError) as test_ctx:
168 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200169 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200170 'missing-claim.yaml',
171 PSAIoTProfile1TokenVerifier(method=method,
172 cose_alg=cose_alg,
173 signing_key=signing_key,
174 configuration=self.config))
175 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100176
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200177 with self.assertRaises(ValueError) as test_ctx:
178 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200179 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200180 'submod-missing-claim.yaml',
181 PSAIoTProfile1TokenVerifier(method=method,
182 cose_alg=cose_alg,
183 signing_key=signing_key,
184 configuration=self.config))
185 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100186
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200187 with self.assertRaises(ValueError) as test_ctx:
188 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200189 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200190 'missing-sw-comps.yaml',
191 PSAIoTProfile1TokenVerifier(method=method,
192 cose_alg=cose_alg,
193 signing_key=signing_key,
194 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100195 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200196 test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100197
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200198 with self.assertLogs() as test_ctx:
199 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200200 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200201 'missing-signer-id.yaml',
202 PSAIoTProfile1TokenVerifier(method=method,
203 cose_alg=cose_alg,
204 signing_key=signing_key,
205 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200206 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200207 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100208
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200209 with self.assertLogs() as test_ctx:
210 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200211 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200212 'invalid-type-length.yaml',
213 PSAIoTProfile1TokenVerifier(method=method,
214 cose_alg=cose_alg,
215 signing_key=signing_key,
216 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100217 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200218 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100219 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200220 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100221 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200222 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100223 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200224 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100225
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200226 with self.assertLogs() as test_ctx:
227 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200228 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200229 'invalid-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200230 PSAIoTProfile1TokenVerifier(
231 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200232 cose_alg=cose_alg,
233 signing_key=signing_key,
234 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200235 self.assertIn("Invalid HARDWARE_VERSION length; "
236 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200237 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200238 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200239 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200240 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200241 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200242 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200243 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100244
245 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200246 """Test binary_string 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')
258
259 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200260 """Test security lifecycle decoding"""
261 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
262 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
263 signing_key = read_keyfile(KEYFILE, method)
264 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200265 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200266 'valid-iat.yaml',
267 PSAIoTProfile1TokenVerifier(method=method,
268 cose_alg=cose_alg,
269 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200270 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100271 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')