blob: 5f8380e3547687824e868e5113c5026dfaa6618d [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-Palb2508d52022-04-30 14:10:06 +020014from iatverifier.util import read_keyfile
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020015from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
Mate Toth-Palb2508d52022-04-30 14:10:06 +020016from test_utils import create_and_read_iat, read_iat, create_token_tmp_file
Mate Toth-Pal51b61982022-03-17 14:19:30 +010017
18
19THIS_DIR = os.path.dirname(__file__)
20
21DATA_DIR = os.path.join(THIS_DIR, 'data')
22KEYFILE = os.path.join(DATA_DIR, 'key.pem')
23KEYFILE_ALT = os.path.join(DATA_DIR, 'key-alt.pem')
24
Mate Toth-Pal51b61982022-03-17 14:19:30 +010025class TestIatVerifier(unittest.TestCase):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020026 """A class used for testing iat-verifier.
27
28 This class uses the claim and token definitions for PSA Attestation Token"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010029
30 def setUp(self):
31 self.config = VerifierConfiguration()
32
33 def test_validate_signature(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020034 """Testing Signature validation"""
35 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
36 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
Mate Toth-Pal51b61982022-03-17 14:19:30 +010037
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020038 signing_key = read_keyfile(KEYFILE, method)
39 verifier_good_sig = PSAIoTProfile1TokenVerifier(
40 method=method,
41 cose_alg=cose_alg,
42 signing_key=signing_key,
43 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020044 good_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_good_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010045
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020046 signing_key = read_keyfile(KEYFILE_ALT, method)
47 verifier_bad_sig = PSAIoTProfile1TokenVerifier(
48 method=method,
49 cose_alg=cose_alg,
50 signing_key=signing_key,
51 configuration=self.config)
Mate Toth-Palb2508d52022-04-30 14:10:06 +020052 bad_sig = create_token_tmp_file(DATA_DIR, 'valid-iat.yaml', verifier_bad_sig)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010053
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020054 #dump_file_binary(good_sig)
55
56 with open(good_sig, 'rb') as wfh:
57 verifier_good_sig.parse_token(
58 token=wfh.read(),
59 verify=True,
60 check_p_header=False,
61 lower_case_key=False)
62
63
64 with self.assertRaises(ValueError) as test_ctx:
65 with open(bad_sig, 'rb') as wfh:
66 verifier_good_sig.parse_token(
67 token=wfh.read(),
68 verify=True,
69 check_p_header=False,
70 lower_case_key=False)
71
72 self.assertIn('Bad signature', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +010073
74 def test_validate_iat_structure(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020075 """Testing IAT structure validation"""
Mate Toth-Pal51b61982022-03-17 14:19:30 +010076 keep_going_conf = VerifierConfiguration(keep_going=True)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020077 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
78 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
79 signing_key = read_keyfile(KEYFILE, method)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010080
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020081 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +020082 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020083 'valid-iat.yaml',
84 PSAIoTProfile1TokenVerifier(method=method,
85 cose_alg=cose_alg,
86 signing_key=signing_key,
87 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +010088
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020089 with self.assertRaises(ValueError) as test_ctx:
90 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +020091 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020092 'invalid-profile-id.yaml',
93 PSAIoTProfile1TokenVerifier(method=method,
94 cose_alg=cose_alg,
95 signing_key=signing_key,
96 configuration=self.config))
97 self.assertIn('Invalid PROFILE_ID', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +010098
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020099 with self.assertRaises(ValueError) as test_ctx:
100 read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200101 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200102 'malformed.cbor',
103 PSAIoTProfile1TokenVerifier(method=method,
104 cose_alg=cose_alg,
105 signing_key=signing_key,
106 configuration=self.config))
107 self.assertIn('Bad COSE', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100108
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200109 with self.assertRaises(ValueError) as test_ctx:
110 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200111 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200112 'missing-claim.yaml',
113 PSAIoTProfile1TokenVerifier(method=method,
114 cose_alg=cose_alg,
115 signing_key=signing_key,
116 configuration=self.config))
117 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
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-Palb2508d52022-04-30 14:10:06 +0200121 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200122 'submod-missing-claim.yaml',
123 PSAIoTProfile1TokenVerifier(method=method,
124 cose_alg=cose_alg,
125 signing_key=signing_key,
126 configuration=self.config))
127 self.assertIn('missing MANDATORY claim', test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100128
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200129 with self.assertRaises(ValueError) as test_ctx:
130 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200131 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200132 'missing-sw-comps.yaml',
133 PSAIoTProfile1TokenVerifier(method=method,
134 cose_alg=cose_alg,
135 signing_key=signing_key,
136 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100137 self.assertIn('NO_MEASUREMENTS claim is not present',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200138 test_ctx.exception.args[0])
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100139
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200140 with self.assertLogs() as test_ctx:
141 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200142 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200143 'missing-signer-id.yaml',
144 PSAIoTProfile1TokenVerifier(method=method,
145 cose_alg=cose_alg,
146 signing_key=signing_key,
147 configuration=self.config))
Mate Toth-Pald10a9142022-04-28 15:34:13 +0200148 self.assertIn('Missing RECOMMENDED claim "SIGNER_ID" from SW_COMPONENTS',
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200149 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100150
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200151 with self.assertLogs() as test_ctx:
152 create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200153 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200154 'invalid-type-length.yaml',
155 PSAIoTProfile1TokenVerifier(method=method,
156 cose_alg=cose_alg,
157 signing_key=signing_key,
158 configuration=keep_going_conf))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100159 self.assertIn("Invalid PROFILE_ID: must be a(n) <class 'str'>: found <class 'int'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200160 test_ctx.records[0].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100161 self.assertIn("Invalid SIGNER_ID: must be a(n) <class 'bytes'>: found <class 'str'>",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200162 test_ctx.records[1].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100163 self.assertIn("Invalid SIGNER_ID length: must be at least 32 bytes, found 12 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200164 test_ctx.records[2].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100165 self.assertIn("Invalid MEASUREMENT length: must be at least 32 bytes, found 28 bytes",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200166 test_ctx.records[3].getMessage())
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 'invalid-hw-version.yaml',
Tamas Ban8ac8d172022-07-04 13:01:08 +0200172 PSAIoTProfile1TokenVerifier(
173 method=method,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200174 cose_alg=cose_alg,
175 signing_key=signing_key,
176 configuration=keep_going_conf))
Tamas Ban8ac8d172022-07-04 13:01:08 +0200177 self.assertIn("Invalid HARDWARE_VERSION length; "
178 "must be 19 characters, found 10 characters",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200179 test_ctx.records[0].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200180 self.assertIn("Invalid character at position 1",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200181 test_ctx.records[1].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200182 self.assertIn("Invalid character - at position 4",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200183 test_ctx.records[2].getMessage())
Tamas Ban8ac8d172022-07-04 13:01:08 +0200184 self.assertIn("Invalid character a at position 10",
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200185 test_ctx.records[3].getMessage())
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100186
187 def test_binary_string_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200188 """Test binary_string decoding"""
189 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
190 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
191 signing_key = read_keyfile(KEYFILE, method)
192 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200193 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200194 'valid-iat.yaml',
195 PSAIoTProfile1TokenVerifier(method=method,
196 cose_alg=cose_alg,
197 signing_key=signing_key,
198 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100199 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')
200
201 def test_security_lifecycle_decoding(self):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200202 """Test security lifecycle decoding"""
203 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
204 cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
205 signing_key = read_keyfile(KEYFILE, method)
206 iat = create_and_read_iat(
Mate Toth-Palb2508d52022-04-30 14:10:06 +0200207 DATA_DIR,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200208 'valid-iat.yaml',
209 PSAIoTProfile1TokenVerifier(method=method,
210 cose_alg=cose_alg,
211 signing_key=signing_key,
212 configuration=self.config))
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100213 self.assertEqual(iat['SECURITY_LIFECYCLE'], 'SL_SECURED')