blob: ed3a725817c2163f104a9b4b95dc7b89c0b6db58 [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:
61 verifier_good_sig.parse_token(
62 token=wfh.read(),
63 verify=True,
64 check_p_header=False,
65 lower_case_key=False)
66
67
68 with self.assertRaises(ValueError) as test_ctx:
69 with open(bad_sig, 'rb') as wfh:
70 verifier_good_sig.parse_token(
71 token=wfh.read(),
72 verify=True,
73 check_p_header=False,
74 lower_case_key=False)
75
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)
85 platform_token_key = read_keyfile(KEYFILE_CCA_PLAT, method)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010086
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020087 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +020088 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020089 'valid-iat.yaml',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010090 PSAIoTProfile1TokenVerifier(
91 method=method,
92 cose_alg=cose_alg,
93 signing_key=signing_key,
94 configuration=self.config))
95 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-Palb2508d52022-04-30 14:10:06 +0200119 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200120 'invalid-profile-id.yaml',
121 PSAIoTProfile1TokenVerifier(method=method,
122 cose_alg=cose_alg,
123 signing_key=signing_key,
124 configuration=self.config))
125 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100126
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200127 with self.assertRaises(ValueError) as test_ctx:
128 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200129 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200130 'malformed.cbor',
131 PSAIoTProfile1TokenVerifier(method=method,
132 cose_alg=cose_alg,
133 signing_key=signing_key,
134 configuration=self.config))
135 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100136
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200137 with self.assertRaises(ValueError) as test_ctx:
138 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200139 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200140 'missing-claim.yaml',
141 PSAIoTProfile1TokenVerifier(method=method,
142 cose_alg=cose_alg,
143 signing_key=signing_key,
144 configuration=self.config))
145 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100146
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200147 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 'submod-missing-claim.yaml',
151 PSAIoTProfile1TokenVerifier(method=method,
152 cose_alg=cose_alg,
153 signing_key=signing_key,
154 configuration=self.config))
155 self.assertIn('missing MANDATORY claim', 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 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200159 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200160 'missing-sw-comps.yaml',
161 PSAIoTProfile1TokenVerifier(method=method,
162 cose_alg=cose_alg,
163 signing_key=signing_key,
164 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100165 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200166 test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100167
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200168 with self.assertLogs() as test_ctx:
169 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200170 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200171 'missing-signer-id.yaml',
172 PSAIoTProfile1TokenVerifier(method=method,
173 cose_alg=cose_alg,
174 signing_key=signing_key,
175 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200176 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200177 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100178
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200179 with self.assertLogs() as test_ctx:
180 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200181 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200182 'invalid-type-length.yaml',
183 PSAIoTProfile1TokenVerifier(method=method,
184 cose_alg=cose_alg,
185 signing_key=signing_key,
186 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100187 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200188 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100189 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200190 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100191 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200192 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100193 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200194 test_ctx.records[3].getMessage())
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 'invalid-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200200 PSAIoTProfile1TokenVerifier(
201 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200202 cose_alg=cose_alg,
203 signing_key=signing_key,
204 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200205 self.assertIn("Invalid HARDWARE_VERSION length; "
206 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200207 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200208 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200209 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200210 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200211 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200212 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200213 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100214
215 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200216 """Test binary_string decoding"""
217 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
218 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
219 signing_key = read_keyfile(KEYFILE, method)
220 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200221 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200222 'valid-iat.yaml',
223 PSAIoTProfile1TokenVerifier(method=method,
224 cose_alg=cose_alg,
225 signing_key=signing_key,
226 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100227 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')
228
229 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200230 """Test security lifecycle decoding"""
231 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
232 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
233 signing_key = read_keyfile(KEYFILE, method)
234 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200235 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200236 'valid-iat.yaml',
237 PSAIoTProfile1TokenVerifier(method=method,
238 cose_alg=cose_alg,
239 signing_key=signing_key,
240 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100241 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')