blob: 8f64be8a4d6b2963baf650060083ac9696ba1746 [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(),
Mate Toth-Palc7404e92022-07-15 11:11:13 +020064 lower_case_key=False)
65 token_item.verify()
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020066
67 with self.assertRaises(ValueError) as test_ctx:
68 with open(bad_sig, 'rb') as wfh:
Mate Toth-Palc7404e92022-07-15 11:11:13 +020069 token_item = verifier_good_sig.parse_token(
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020070 token=wfh.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020071 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +020072 token_item.verify()
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020073
74 self.assertIn('Bad signature', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +010075
76 def test_validate_iat_structure(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020077 """Testing IAT structure validation"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010078 keep_going_conf = VerifierConfiguration(keep_going=True)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020079 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
80 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
81 signing_key = read_keyfile(KEYFILE, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010082 realm_token_key = read_keyfile(KEYFILE_CCA_REALM, method)
Mate Toth-Palb21ae522022-09-01 12:02:21 +020083 realm_token_key2 = read_keyfile(KEYFILE_CCA_REALM2, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010084 platform_token_key = read_keyfile(KEYFILE_CCA_PLAT, method)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010085
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020086 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +020087 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088 'valid-iat.yaml',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010089 PSAIoTProfile1TokenVerifier(
90 method=method,
91 cose_alg=cose_alg,
92 signing_key=signing_key,
93 configuration=self.config))
Mate Toth-Palb21ae522022-09-01 12:02:21 +020094
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010095 create_and_read_iat(
96 DATA_DIR,
97 'valid-cca-token.yaml',
98 CCATokenVerifier(
99 realm_token_method=method,
100 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
101 realm_token_key=realm_token_key,
102 platform_token_method=method,
103 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
104 platform_token_key=platform_token_key,
105 configuration=self.config))
106
107 create_and_read_iat(
108 DATA_DIR,
109 'cca_platform_token.yaml',
110 CCAPlatformTokenVerifier(
111 method=method,
112 cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
113 signing_key=platform_token_key,
114 configuration=self.config,
115 necessity=AttestationClaim.MANDATORY))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100116
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200117 with self.assertRaises(ValueError) as test_ctx:
118 create_and_read_iat(
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200119 DATA_DIR,
Mate Toth-Palc5dbad02022-09-01 22:17:26 +0200120 'cca-invalid-plat-challenge.yaml',
121 CCATokenVerifier(
122 realm_token_method=method,
123 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
124 realm_token_key=realm_token_key,
125 platform_token_method=method,
126 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
127 platform_token_key=platform_token_key,
128 configuration=self.config))
129 self.assertIn("Invalid CCA_PLATFORM_CHALLENGE byte at 16: 0x00 instead of 0xe4", test_ctx.exception.args[0])
130
131 with self.assertRaises(ValueError) as test_ctx:
132 create_and_read_iat(
133 DATA_DIR,
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200134 'valid-cca-token.yaml',
135 CCATokenVerifier(
136 realm_token_method=method,
137 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
138 realm_token_key=realm_token_key2,
139 platform_token_method=method,
140 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
141 platform_token_key=platform_token_key,
142 configuration=self.config))
143 self.assertIn("Realm signature doesn't match Realm Public Key claim in Realm token", test_ctx.exception.args[0])
144
145 with self.assertRaises(ValueError) as test_ctx:
146 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200147 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200148 'invalid-profile-id.yaml',
149 PSAIoTProfile1TokenVerifier(method=method,
150 cose_alg=cose_alg,
151 signing_key=signing_key,
152 configuration=self.config))
153 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100154
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200155 with self.assertRaises(ValueError) as test_ctx:
156 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200157 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200158 'malformed.cbor',
159 PSAIoTProfile1TokenVerifier(method=method,
160 cose_alg=cose_alg,
161 signing_key=signing_key,
162 configuration=self.config))
163 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100164
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200165 with self.assertRaises(ValueError) as test_ctx:
166 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200167 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200168 'missing-claim.yaml',
169 PSAIoTProfile1TokenVerifier(method=method,
170 cose_alg=cose_alg,
171 signing_key=signing_key,
172 configuration=self.config))
173 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100174
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200175 with self.assertRaises(ValueError) as test_ctx:
176 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200177 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200178 'submod-missing-claim.yaml',
179 PSAIoTProfile1TokenVerifier(method=method,
180 cose_alg=cose_alg,
181 signing_key=signing_key,
182 configuration=self.config))
183 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100184
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200185 with self.assertRaises(ValueError) as test_ctx:
186 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200187 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200188 'missing-sw-comps.yaml',
189 PSAIoTProfile1TokenVerifier(method=method,
190 cose_alg=cose_alg,
191 signing_key=signing_key,
192 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100193 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200194 test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100195
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200196 with self.assertLogs() as test_ctx:
197 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200198 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200199 'missing-signer-id.yaml',
200 PSAIoTProfile1TokenVerifier(method=method,
201 cose_alg=cose_alg,
202 signing_key=signing_key,
203 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200204 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200205 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100206
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200207 with self.assertLogs() as test_ctx:
208 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200209 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200210 'invalid-type-length.yaml',
211 PSAIoTProfile1TokenVerifier(method=method,
212 cose_alg=cose_alg,
213 signing_key=signing_key,
214 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100215 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200216 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100217 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200218 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100219 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200220 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100221 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200222 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100223
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200224 with self.assertLogs() as test_ctx:
225 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200226 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200227 'invalid-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200228 PSAIoTProfile1TokenVerifier(
229 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200230 cose_alg=cose_alg,
231 signing_key=signing_key,
232 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200233 self.assertIn("Invalid HARDWARE_VERSION length; "
234 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200235 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200236 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200237 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200238 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200239 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200240 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200241 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100242
243 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200244 """Test binary_string decoding"""
245 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
246 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
247 signing_key = read_keyfile(KEYFILE, method)
248 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200249 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200250 'valid-iat.yaml',
251 PSAIoTProfile1TokenVerifier(method=method,
252 cose_alg=cose_alg,
253 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200254 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100255 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')
256
257 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200258 """Test security lifecycle decoding"""
259 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
260 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
261 signing_key = read_keyfile(KEYFILE, method)
262 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200263 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200264 'valid-iat.yaml',
265 PSAIoTProfile1TokenVerifier(method=method,
266 cose_alg=cose_alg,
267 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200268 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100269 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')