Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/crypto/ccp/test_dbc.py
26285 views
1
#!/usr/bin/python3
2
# SPDX-License-Identifier: GPL-2.0
3
import unittest
4
import os
5
import time
6
import glob
7
import fcntl
8
try:
9
import ioctl_opt as ioctl
10
except ImportError:
11
ioctl = None
12
pass
13
from dbc import *
14
15
# Artificial delay between set commands
16
SET_DELAY = 0.5
17
18
19
class invalid_param(ctypes.Structure):
20
_fields_ = [
21
("data", ctypes.c_uint8),
22
]
23
24
25
def system_is_secured() -> bool:
26
fused_part = glob.glob("/sys/bus/pci/drivers/ccp/**/fused_part")[0]
27
if os.path.exists(fused_part):
28
with open(fused_part, "r") as r:
29
return int(r.read()) == 1
30
return True
31
32
33
class DynamicBoostControlTest(unittest.TestCase):
34
def __init__(self, data) -> None:
35
self.d = None
36
self.signature = b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
37
self.uid = b"1111111111111111"
38
super().__init__(data)
39
40
def setUp(self) -> None:
41
self.d = open(DEVICE_NODE)
42
return super().setUp()
43
44
def tearDown(self) -> None:
45
if self.d:
46
self.d.close()
47
return super().tearDown()
48
49
50
class TestUnsupportedSystem(DynamicBoostControlTest):
51
def setUp(self) -> None:
52
if os.path.exists(DEVICE_NODE):
53
self.skipTest("system is supported")
54
with self.assertRaises(FileNotFoundError) as error:
55
super().setUp()
56
self.assertEqual(error.exception.errno, 2)
57
58
def test_unauthenticated_nonce(self) -> None:
59
"""fetch unauthenticated nonce"""
60
with self.assertRaises(ValueError) as error:
61
get_nonce(self.d, None)
62
63
64
class TestInvalidIoctls(DynamicBoostControlTest):
65
def __init__(self, data) -> None:
66
self.data = invalid_param()
67
self.data.data = 1
68
super().__init__(data)
69
70
def setUp(self) -> None:
71
if not os.path.exists(DEVICE_NODE):
72
self.skipTest("system is unsupported")
73
if not ioctl:
74
self.skipTest("unable to test IOCTLs without ioctl_opt")
75
76
return super().setUp()
77
78
def test_invalid_nonce_ioctl(self) -> None:
79
"""tries to call get_nonce ioctl with invalid data structures"""
80
81
# 0x1 (get nonce), and invalid data
82
INVALID1 = ioctl.IOWR(ord("D"), 0x01, invalid_param)
83
with self.assertRaises(OSError) as error:
84
fcntl.ioctl(self.d, INVALID1, self.data, True)
85
self.assertEqual(error.exception.errno, 22)
86
87
def test_invalid_setuid_ioctl(self) -> None:
88
"""tries to call set_uid ioctl with invalid data structures"""
89
90
# 0x2 (set uid), and invalid data
91
INVALID2 = ioctl.IOW(ord("D"), 0x02, invalid_param)
92
with self.assertRaises(OSError) as error:
93
fcntl.ioctl(self.d, INVALID2, self.data, True)
94
self.assertEqual(error.exception.errno, 22)
95
96
def test_invalid_setuid_rw_ioctl(self) -> None:
97
"""tries to call set_uid ioctl with invalid data structures"""
98
99
# 0x2 as RW (set uid), and invalid data
100
INVALID3 = ioctl.IOWR(ord("D"), 0x02, invalid_param)
101
with self.assertRaises(OSError) as error:
102
fcntl.ioctl(self.d, INVALID3, self.data, True)
103
self.assertEqual(error.exception.errno, 22)
104
105
def test_invalid_param_ioctl(self) -> None:
106
"""tries to call param ioctl with invalid data structures"""
107
# 0x3 (param), and invalid data
108
INVALID4 = ioctl.IOWR(ord("D"), 0x03, invalid_param)
109
with self.assertRaises(OSError) as error:
110
fcntl.ioctl(self.d, INVALID4, self.data, True)
111
self.assertEqual(error.exception.errno, 22)
112
113
def test_invalid_call_ioctl(self) -> None:
114
"""tries to call the DBC ioctl with invalid data structures"""
115
# 0x4, and invalid data
116
INVALID5 = ioctl.IOWR(ord("D"), 0x04, invalid_param)
117
with self.assertRaises(OSError) as error:
118
fcntl.ioctl(self.d, INVALID5, self.data, True)
119
self.assertEqual(error.exception.errno, 22)
120
121
122
class TestInvalidSignature(DynamicBoostControlTest):
123
def setUp(self) -> None:
124
if not os.path.exists(DEVICE_NODE):
125
self.skipTest("system is unsupported")
126
if not system_is_secured():
127
self.skipTest("system is unfused")
128
return super().setUp()
129
130
def test_unauthenticated_nonce(self) -> None:
131
"""fetch unauthenticated nonce"""
132
get_nonce(self.d, None)
133
134
def test_multiple_unauthenticated_nonce(self) -> None:
135
"""ensure state machine always returns nonce"""
136
for count in range(0, 2):
137
get_nonce(self.d, None)
138
139
def test_authenticated_nonce(self) -> None:
140
"""fetch authenticated nonce"""
141
get_nonce(self.d, None)
142
with self.assertRaises(OSError) as error:
143
get_nonce(self.d, self.signature)
144
self.assertEqual(error.exception.errno, 22)
145
146
def test_set_uid(self) -> None:
147
"""set uid"""
148
get_nonce(self.d, None)
149
with self.assertRaises(OSError) as error:
150
set_uid(self.d, self.uid, self.signature)
151
self.assertEqual(error.exception.errno, 1)
152
153
def test_get_param(self) -> None:
154
"""fetch a parameter"""
155
with self.assertRaises(OSError) as error:
156
process_param(self.d, PARAM_GET_SOC_PWR_CUR, self.signature)
157
self.assertEqual(error.exception.errno, 11)
158
159
def test_set_param(self) -> None:
160
"""set a parameter"""
161
with self.assertRaises(OSError) as error:
162
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, 1000)
163
self.assertEqual(error.exception.errno, 11)
164
165
166
class TestUnFusedSystem(DynamicBoostControlTest):
167
def setup_identity(self) -> None:
168
"""sets up the identity of the caller"""
169
# if already authenticated these may fail
170
try:
171
get_nonce(self.d, None)
172
except PermissionError:
173
pass
174
try:
175
set_uid(self.d, self.uid, self.signature)
176
except BlockingIOError:
177
pass
178
try:
179
get_nonce(self.d, self.signature)
180
except PermissionError:
181
pass
182
183
def setUp(self) -> None:
184
if not os.path.exists(DEVICE_NODE):
185
self.skipTest("system is unsupported")
186
if system_is_secured():
187
self.skipTest("system is fused")
188
super().setUp()
189
self.setup_identity()
190
time.sleep(SET_DELAY)
191
192
def test_get_valid_param(self) -> None:
193
"""fetch all possible parameters"""
194
# SOC power
195
soc_power_max = process_param(self.d, PARAM_GET_SOC_PWR_MAX, self.signature)
196
soc_power_min = process_param(self.d, PARAM_GET_SOC_PWR_MIN, self.signature)
197
self.assertGreater(soc_power_max[0], soc_power_min[0])
198
199
# fmax
200
fmax_max = process_param(self.d, PARAM_GET_FMAX_MAX, self.signature)
201
fmax_min = process_param(self.d, PARAM_GET_FMAX_MIN, self.signature)
202
self.assertGreater(fmax_max[0], fmax_min[0])
203
204
# cap values
205
keys = {
206
"fmax-cap": PARAM_GET_FMAX_CAP,
207
"power-cap": PARAM_GET_PWR_CAP,
208
"current-temp": PARAM_GET_CURR_TEMP,
209
"soc-power-cur": PARAM_GET_SOC_PWR_CUR,
210
}
211
for k in keys:
212
result = process_param(self.d, keys[k], self.signature)
213
self.assertGreater(result[0], 0)
214
215
def test_get_invalid_param(self) -> None:
216
"""fetch an invalid parameter"""
217
try:
218
set_uid(self.d, self.uid, self.signature)
219
except OSError:
220
pass
221
with self.assertRaises(OSError) as error:
222
process_param(self.d, (0xF,), self.signature)
223
self.assertEqual(error.exception.errno, 22)
224
225
def test_set_fmax(self) -> None:
226
"""get/set fmax limit"""
227
# fetch current
228
original = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
229
230
# set the fmax
231
target = original[0] - 100
232
process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, target)
233
time.sleep(SET_DELAY)
234
new = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
235
self.assertEqual(new[0], target)
236
237
# revert back to current
238
process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, original[0])
239
time.sleep(SET_DELAY)
240
cur = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
241
self.assertEqual(cur[0], original[0])
242
243
def test_set_power_cap(self) -> None:
244
"""get/set power cap limit"""
245
# fetch current
246
original = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
247
248
# set the fmax
249
target = original[0] - 10
250
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, target)
251
time.sleep(SET_DELAY)
252
new = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
253
self.assertEqual(new[0], target)
254
255
# revert back to current
256
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, original[0])
257
time.sleep(SET_DELAY)
258
cur = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
259
self.assertEqual(cur[0], original[0])
260
261
def test_set_3d_graphics_mode(self) -> None:
262
"""set/get 3d graphics mode"""
263
# these aren't currently implemented but may be some day
264
# they are *expected* to fail
265
with self.assertRaises(OSError) as error:
266
process_param(self.d, PARAM_GET_GFX_MODE, self.signature)
267
self.assertEqual(error.exception.errno, 2)
268
269
time.sleep(SET_DELAY)
270
271
with self.assertRaises(OSError) as error:
272
process_param(self.d, PARAM_SET_GFX_MODE, self.signature, 1)
273
self.assertEqual(error.exception.errno, 2)
274
275
276
if __name__ == "__main__":
277
unittest.main()
278
279