blob: bb03513cc120648352f3265d24d22dc232919cc5 [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-Pal51b61982022-03-17 14:19:30 +010027KEYFILE_ALT = os.path.join(DATA_DIR, 'key-alt.pem')
28
Mate Toth-Pal51b61982022-03-17 14:19:30 +010029class TestIatVerifier(unittest.TestCase):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020030 """A class used for testing iat-verifier.
31
32 This class uses the claim and token definitions for PSA Attestation Token"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010033
34 def setUp(self):
35 self.config = VerifierConfiguration()
36
37 def test_validate_signature(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020038 """Testing Signature validation"""
39 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
40 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
Mate Toth-Pal51b61982022-03-17 14:19:30 +010041
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020042 signing_key = read_keyfile(KEYFILE, method)
43 verifier_good_sig = PSAIoTProfile1TokenVerifier(
44 method=method,
45 cose_alg=cose_alg,
46 signing_key=signing_key,
47 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020048 good_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_good_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010049
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020050 signing_key = read_keyfile(KEYFILE_ALT, method)
51 verifier_bad_sig = PSAIoTProfile1TokenVerifier(
52 method=method,
53 cose_alg=cose_alg,
54 signing_key=signing_key,
55 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020056 bad_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_bad_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010057
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020058 #dump_file_binary(good_sig)
59
60 with open(good_sig, 'rb') as wfh:
Mate Toth-Palc7404e92022-07-15 11:11:13 +020061 token_item = verifier_good_sig.parse_token(
62 token=wfh.read(),
63 check_p_header=False,
64 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 check_p_header=False,
72 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +020073 token_item.verify()
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020074
75 self.assertIn('Bad signature', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +010076
77 def test_validate_iat_structure(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020078 """Testing IAT structure validation"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010079 keep_going_conf = VerifierConfiguration(keep_going=True)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020080 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
81 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
82 signing_key = read_keyfile(KEYFILE, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010083 realm_token_key = read_keyfile(KEYFILE_CCA_REALM, method)
84 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))
94 create_and_read_iat(
95 DATA_DIR,
96 'valid-cca-token.yaml',
97 CCATokenVerifier(
98 realm_token_method=method,
99 realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
100 realm_token_key=realm_token_key,
101 platform_token_method=method,
102 platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
103 platform_token_key=platform_token_key,
104 configuration=self.config))
105
106 create_and_read_iat(
107 DATA_DIR,
108 'cca_platform_token.yaml',
109 CCAPlatformTokenVerifier(
110 method=method,
111 cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
112 signing_key=platform_token_key,
113 configuration=self.config,
114 necessity=AttestationClaim.MANDATORY))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100115
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200116 with self.assertRaises(ValueError) as test_ctx:
117 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200118 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200119 'invalid-profile-id.yaml',
120 PSAIoTProfile1TokenVerifier(method=method,
121 cose_alg=cose_alg,
122 signing_key=signing_key,
123 configuration=self.config))
124 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100125
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200126 with self.assertRaises(ValueError) as test_ctx:
127 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200128 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200129 'malformed.cbor',
130 PSAIoTProfile1TokenVerifier(method=method,
131 cose_alg=cose_alg,
132 signing_key=signing_key,
133 configuration=self.config))
134 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100135
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200136 with self.assertRaises(ValueError) as test_ctx:
137 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200138 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200139 'missing-claim.yaml',
140 PSAIoTProfile1TokenVerifier(method=method,
141 cose_alg=cose_alg,
142 signing_key=signing_key,
143 configuration=self.config))
144 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100145
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200146 with self.assertRaises(ValueError) as test_ctx:
147 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200148 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200149 'submod-missing-claim.yaml',
150 PSAIoTProfile1TokenVerifier(method=method,
151 cose_alg=cose_alg,
152 signing_key=signing_key,
153 configuration=self.config))
154 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100155
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200156 with self.assertRaises(ValueError) as test_ctx:
157 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200158 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200159 'missing-sw-comps.yaml',
160 PSAIoTProfile1TokenVerifier(method=method,
161 cose_alg=cose_alg,
162 signing_key=signing_key,
163 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100164 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200165 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.assertLogs() 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-signer-id.yaml',
171 PSAIoTProfile1TokenVerifier(method=method,
172 cose_alg=cose_alg,
173 signing_key=signing_key,
174 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200175 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200176 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100177
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200178 with self.assertLogs() as test_ctx:
179 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200180 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200181 'invalid-type-length.yaml',
182 PSAIoTProfile1TokenVerifier(method=method,
183 cose_alg=cose_alg,
184 signing_key=signing_key,
185 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100186 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200187 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100188 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200189 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100190 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200191 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100192 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200193 test_ctx.records[3].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-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200199 PSAIoTProfile1TokenVerifier(
200 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200201 cose_alg=cose_alg,
202 signing_key=signing_key,
203 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200204 self.assertIn("Invalid HARDWARE_VERSION length; "
205 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200206 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200207 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200208 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200209 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200210 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200211 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200212 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100213
214 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200215 """Test binary_string decoding"""
216 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
217 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
218 signing_key = read_keyfile(KEYFILE, method)
219 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200220 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200221 'valid-iat.yaml',
222 PSAIoTProfile1TokenVerifier(method=method,
223 cose_alg=cose_alg,
224 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200225 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100226 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')
227
228 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200229 """Test security lifecycle decoding"""
230 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
231 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
232 signing_key = read_keyfile(KEYFILE, method)
233 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200234 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200235 'valid-iat.yaml',
236 PSAIoTProfile1TokenVerifier(method=method,
237 cose_alg=cose_alg,
238 signing_key=signing_key,
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200239 configuration=self.config)).get_token_map()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100240 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')