-
Notifications
You must be signed in to change notification settings - Fork 518
/
Copy pathsecurity_mode.cpp
123 lines (109 loc) · 4.6 KB
/
security_mode.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* Copyright (c) 2024 Particle Industries, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "security_mode.h"
#include "flash_mal.h"
#include "system_error.h"
#include "check.h"
#include "scope_guard.h"
#include <algorithm>
#include "system_control.h"
#include "flash_device_hal.h"
namespace {
module_info_security_mode sSecurityMode = MODULE_INFO_SECURITY_MODE_NONE;
} // namespace
int security_mode_find_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* securityModeExt) {
module_info_t info = {};
int flashDevId = -1;
if (storageId == HAL_STORAGE_ID_INTERNAL_FLASH) {
flashDevId = FLASH_INTERNAL;
} else if (storageId == HAL_STORAGE_ID_EXTERNAL_FLASH) {
flashDevId = FLASH_SERIAL;
} else {
return SYSTEM_ERROR_INVALID_ARGUMENT;
}
uint32_t infoOffset = 0;
CHECK(FLASH_ModuleInfo(&info, flashDevId, start, &infoOffset));
(void)infoOffset;
// NOTE: this function should only be called for validated modules, just basic sanity checking
CHECK_TRUE(info.module_function == MODULE_FUNCTION_BOOTLOADER, SYSTEM_ERROR_BAD_DATA);
CHECK_TRUE((uintptr_t)info.module_start_address < (uintptr_t)info.module_end_address, SYSTEM_ERROR_BAD_DATA);
// XXX: security extension only in suffix
module_info_suffix_base_t suffix = {};
uintptr_t end = (uintptr_t)info.module_end_address - (uintptr_t)info.module_start_address + start;
uintptr_t suffixStart = end - sizeof(module_info_suffix_base_t);
CHECK(hal_storage_read(storageId, suffixStart, (uint8_t*)&suffix, sizeof(suffix)));
CHECK_TRUE(suffix.size > sizeof(module_info_suffix_base_t) + sizeof(module_info_extension_t) * 2, SYSTEM_ERROR_NOT_FOUND);
// There are some additional extensions in suffix
// FIXME: there should be a common way to parse the extensions, for now there are several places where the same thing is done
for (uintptr_t offset = end - suffix.size; offset < end;) {
module_info_extension_t ext = {};
CHECK(hal_storage_read(storageId, offset, (uint8_t*)&ext, sizeof(ext)));
SCOPE_GUARD({
offset += ext.length;
});
if (ext.type == MODULE_INFO_EXTENSION_SECURITY_MODE) {
module_info_security_mode_ext_t pext = {};
CHECK(hal_storage_read(storageId, offset, (uint8_t*)&pext, sizeof(pext)));
if (pext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) {
// The only supported value for now
if (securityModeExt) {
// TODO: cert
memcpy(securityModeExt, &pext, std::min<size_t>(sizeof(pext), securityModeExt->ext.length));
}
return 0;
}
} else if (ext.type == MODULE_INFO_EXTENSION_END) {
break;
}
}
return SYSTEM_ERROR_NOT_FOUND;
}
int security_mode_set(module_info_security_mode mode, void* reserved) {
if (sSecurityMode == MODULE_INFO_SECURITY_MODE_NONE) {
sSecurityMode = mode;
return 0;
}
return SYSTEM_ERROR_INVALID_STATE;
}
int security_mode_get(void* reserved) {
return sSecurityMode;
}
int security_mode_check_request(security_mode_transport transport, uint16_t id) {
if (security_mode_get(nullptr) != MODULE_INFO_SECURITY_MODE_PROTECTED) {
return 0;
}
if (transport == SECURITY_MODE_TRANSPORT_USB || transport == SECURITY_MODE_TRANSPORT_BLE) {
switch (id) {
case CTRL_REQUEST_SET_PROTECTED_STATE:
case CTRL_REQUEST_GET_PROTECTED_STATE:
case CTRL_REQUEST_DEVICE_ID:
case CTRL_REQUEST_APP_CUSTOM: {
return 0;
}
}
}
if (transport == SECURITY_MODE_TRANSPORT_BLE) {
switch (id) {
case CTRL_REQUEST_WIFI_SCAN_NETWORKS:
case CTRL_REQUEST_WIFI_JOIN_NEW_NETWORK:
case CTRL_REQUEST_WIFI_CLEAR_KNOWN_NETWORKS: {
return 0;
}
}
}
return SYSTEM_ERROR_PROTECTED;
}