1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2025, Pengutronix, Michael Tretter <entwicklung@pengutronix.de> 4 */ 5 6 #include <config.h> 7 #include <drivers/rockchip_otp.h> 8 #include <kernel/pseudo_ta.h> 9 #include <kernel/tee_misc.h> 10 #include <tee/uuid.h> 11 #include <utee_defines.h> 12 #include <stdio.h> 13 #include <string.h> 14 #include <platform_config.h> 15 16 #include <pta_rk_secure_boot.h> 17 18 #define PTA_NAME "rk_secure_boot.pta" 19 20 /* 21 * The hash is stored in OTP in little endian. The PTA assumes that OP-TEE is 22 * in little endian and may copy the hash from memory to OTP without ensuring 23 * the byte order. 24 */ 25 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); 26 27 static inline bool test_bit_mask(uint32_t value, uint32_t mask) 28 { 29 return (value & mask) == mask; 30 } 31 32 #define HASH_STRING_SIZE 88 33 static_assert(ROCKCHIP_OTP_RSA_HASH_SIZE == 8); 34 static __maybe_unused char *otp_to_string(uint32_t *otp, 35 char *str, size_t str_size) 36 { 37 snprintf(str, str_size, 38 "0x%"PRIx32" 0x%"PRIx32" 0x%"PRIx32" 0x%"PRIx32 39 " 0x%"PRIx32" 0x%"PRIx32" 0x%"PRIx32" 0x%"PRIx32, 40 otp[0], otp[1], otp[2], otp[3], 41 otp[4], otp[5], otp[6], otp[7]); 42 43 return str; 44 } 45 46 static TEE_Result write_key_size(uint32_t key_size_bits) 47 { 48 uint32_t idx = ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX; 49 uint32_t sz = ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE; 50 TEE_Result res = TEE_SUCCESS; 51 uint32_t status = 0; 52 53 IMSG("Setting key size to %"PRId32, key_size_bits); 54 55 switch (key_size_bits) { 56 case 4096: 57 status |= ROCKCHIP_OTP_SECURE_BOOT_STATUS_RSA4096; 58 59 res = rockchip_otp_write_secure(&status, idx, sz); 60 if (res) 61 return res; 62 63 res = rockchip_otp_read_secure(&status, idx, sz); 64 if (res) 65 return res; 66 if (!test_bit_mask(status, 67 ROCKCHIP_OTP_SECURE_BOOT_STATUS_RSA4096)) 68 return TEE_ERROR_GENERIC; 69 break; 70 case 2048: 71 /* Nothing to do */ 72 break; 73 default: 74 res = TEE_ERROR_BAD_PARAMETERS; 75 break; 76 } 77 78 return res; 79 } 80 81 static TEE_Result write_hash(uint32_t *hash, size_t size) 82 { 83 char __maybe_unused str[HASH_STRING_SIZE] = {}; 84 uint32_t tmp[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 85 TEE_Result res = TEE_SUCCESS; 86 87 if (size != ROCKCHIP_OTP_RSA_HASH_SIZE) 88 return TEE_ERROR_GENERIC; 89 90 IMSG("Burning hash %s", otp_to_string(hash, str, sizeof(str))); 91 92 res = rockchip_otp_write_secure(hash, 93 ROCKCHIP_OTP_RSA_HASH_INDEX, 94 ROCKCHIP_OTP_RSA_HASH_SIZE); 95 if (res) 96 return res; 97 98 res = rockchip_otp_read_secure(tmp, 99 ROCKCHIP_OTP_RSA_HASH_INDEX, 100 ROCKCHIP_OTP_RSA_HASH_SIZE); 101 if (res) 102 return res; 103 if (memcmp(tmp, hash, sizeof(tmp))) { 104 EMSG("Failed to burn hash. OTP is %s", 105 otp_to_string(tmp, str, sizeof(str))); 106 return res; 107 } 108 109 return res; 110 } 111 112 static TEE_Result get_info(uint32_t param_types, 113 TEE_Param params[TEE_NUM_PARAMS]) 114 { 115 uint32_t hash[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 116 char __maybe_unused str[HASH_STRING_SIZE] = {}; 117 struct pta_rk_secure_boot_info *info = NULL; 118 TEE_Result res = TEE_ERROR_GENERIC; 119 uint32_t status = 0; 120 121 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 122 TEE_PARAM_TYPE_NONE, 123 TEE_PARAM_TYPE_NONE, 124 TEE_PARAM_TYPE_NONE)) 125 return TEE_ERROR_BAD_PARAMETERS; 126 127 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*info))) 128 return TEE_ERROR_BAD_PARAMETERS; 129 130 info = params[0].memref.buffer; 131 if (!info || params[0].memref.size != sizeof(*info)) 132 return TEE_ERROR_BAD_PARAMETERS; 133 134 memset(info, 0, sizeof(*info)); 135 136 res = rockchip_otp_read_secure(&status, 137 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 138 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 139 if (res) 140 return res; 141 142 res = rockchip_otp_read_secure(hash, 143 ROCKCHIP_OTP_RSA_HASH_INDEX, 144 ROCKCHIP_OTP_RSA_HASH_SIZE); 145 if (res) 146 return res; 147 148 DMSG("Current hash: %s", otp_to_string(hash, str, sizeof(str))); 149 150 info->enabled = test_bit_mask(status, 151 ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE); 152 info->simulation = IS_ENABLED(CFG_RK_SECURE_BOOT_SIMULATION); 153 memcpy(info->hash.value, hash, sizeof(info->hash.value)); 154 155 return TEE_SUCCESS; 156 } 157 158 static TEE_Result burn_hash(uint32_t param_types, 159 TEE_Param params[TEE_NUM_PARAMS]) 160 { 161 uint32_t new_hash[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 162 uint32_t old_hash[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 163 char __maybe_unused str[HASH_STRING_SIZE] = {}; 164 struct pta_rk_secure_boot_hash *hash = NULL; 165 TEE_Result res = TEE_SUCCESS; 166 uint32_t key_size_bits = 0; 167 uint32_t status = 0; 168 size_t hash_sz = 0; 169 170 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 171 TEE_PARAM_TYPE_VALUE_INPUT, 172 TEE_PARAM_TYPE_NONE, 173 TEE_PARAM_TYPE_NONE)) 174 return TEE_ERROR_BAD_PARAMETERS; 175 176 hash = params[0].memref.buffer; 177 hash_sz = params[0].memref.size; 178 if (!hash || hash_sz != sizeof(*hash)) 179 return TEE_ERROR_BAD_PARAMETERS; 180 memcpy(new_hash, hash->value, sizeof(new_hash)); 181 182 key_size_bits = params[1].value.a; 183 if (key_size_bits != 4096 && key_size_bits != 2048) { 184 EMSG("Invalid key size: %"PRId32, key_size_bits); 185 return TEE_ERROR_BAD_PARAMETERS; 186 } 187 188 res = rockchip_otp_read_secure(old_hash, 189 ROCKCHIP_OTP_RSA_HASH_INDEX, 190 ROCKCHIP_OTP_RSA_HASH_SIZE); 191 if (res) 192 return res; 193 if (memcmp(old_hash, new_hash, sizeof(new_hash))) { 194 EMSG("Refusing to burn hash %s", 195 otp_to_string(new_hash, str, sizeof(str))); 196 EMSG("OTP hash is %s", 197 otp_to_string(old_hash, str, sizeof(str))); 198 return res; 199 } 200 201 /* 202 * Check if secure boot is already enabled after verifying the 203 * parameters for reporting the correct error if the command would 204 * result in the same state as the already fused board. 205 */ 206 res = rockchip_otp_read_secure(&status, 207 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 208 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 209 if (res) 210 return res; 211 if (test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 212 DMSG("Secure boot already enabled"); 213 return TEE_SUCCESS; 214 } 215 216 if (IS_ENABLED(CFG_RK_SECURE_BOOT_SIMULATION)) { 217 IMSG("Simulation mode: Skip burning hash %s, key size %"PRId32, 218 otp_to_string(new_hash, str, sizeof(str)), key_size_bits); 219 return TEE_SUCCESS; 220 } 221 222 res = write_hash(new_hash, ARRAY_SIZE(new_hash)); 223 if (res) { 224 EMSG("Failed to write hash"); 225 return res; 226 } 227 228 res = write_key_size(key_size_bits); 229 if (res) { 230 EMSG("Failed to write key size"); 231 return res; 232 } 233 234 return TEE_SUCCESS; 235 } 236 237 static TEE_Result lockdown_device(uint32_t param_types, 238 TEE_Param params[TEE_NUM_PARAMS] __unused) 239 { 240 uint32_t hash[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 241 uint32_t zero[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 242 TEE_Result res = TEE_ERROR_GENERIC; 243 uint32_t status = 0; 244 245 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, 246 TEE_PARAM_TYPE_NONE, 247 TEE_PARAM_TYPE_NONE, 248 TEE_PARAM_TYPE_NONE)) 249 return TEE_ERROR_BAD_PARAMETERS; 250 251 res = rockchip_otp_read_secure(hash, 252 ROCKCHIP_OTP_RSA_HASH_INDEX, 253 ROCKCHIP_OTP_RSA_HASH_SIZE); 254 if (res) 255 return res; 256 if (!memcmp(zero, hash, sizeof(hash))) { 257 EMSG("OTP hash is all zeros. Refuse lockdown."); 258 return TEE_ERROR_GENERIC; 259 } 260 261 res = rockchip_otp_read_secure(&status, 262 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 263 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 264 if (res) 265 return res; 266 if (test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 267 DMSG("Secure boot already enabled"); 268 return TEE_SUCCESS; 269 } 270 271 status = ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE; 272 273 if (IS_ENABLED(CFG_RK_SECURE_BOOT_SIMULATION)) { 274 IMSG("Simulation mode: Skip writing status: %"PRIx32, 275 status); 276 return TEE_SUCCESS; 277 } 278 279 IMSG("Writing secure boot status: %"PRIx32, status); 280 res = rockchip_otp_write_secure(&status, 281 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 282 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 283 if (res) 284 return res; 285 286 res = rockchip_otp_read_secure(&status, 287 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 288 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 289 if (res) 290 return res; 291 if (test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 292 EMSG("Failed to write secure boot status"); 293 return TEE_ERROR_GENERIC; 294 } 295 296 return TEE_SUCCESS; 297 } 298 299 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 300 uint32_t param_types, 301 TEE_Param params[TEE_NUM_PARAMS]) 302 { 303 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 304 TEE_Param bparams[TEE_NUM_PARAMS] = { }; 305 TEE_Result res2 = TEE_ERROR_GENERIC; 306 TEE_Param *eparams = NULL; 307 308 res = to_bounce_params(param_types, params, bparams, &eparams); 309 if (res) 310 return res; 311 312 switch (cmd_id) { 313 case PTA_RK_SECURE_BOOT_GET_INFO: 314 res = get_info(param_types, eparams); 315 break; 316 case PTA_RK_SECURE_BOOT_BURN_HASH: 317 res = burn_hash(param_types, eparams); 318 break; 319 case PTA_RK_SECURE_BOOT_LOCKDOWN_DEVICE: 320 res = lockdown_device(param_types, eparams); 321 break; 322 default: 323 break; 324 } 325 326 res2 = from_bounce_params(param_types, params, bparams, eparams); 327 if (!res && res2) 328 res = res2; 329 330 return res; 331 } 332 333 pseudo_ta_register(.uuid = PTA_RK_SECURE_BOOT_UUID, 334 .name = PTA_NAME, 335 .flags = PTA_DEFAULT_FLAGS, 336 .invoke_command_entry_point = invoke_command); 337