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 uint32_t zero[ROCKCHIP_OTP_RSA_HASH_SIZE] = { 0 }; 164 char __maybe_unused str[HASH_STRING_SIZE] = {}; 165 struct pta_rk_secure_boot_hash *hash = NULL; 166 TEE_Result res = TEE_SUCCESS; 167 uint32_t key_size_bits = 0; 168 uint32_t status = 0; 169 size_t hash_sz = 0; 170 171 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 172 TEE_PARAM_TYPE_VALUE_INPUT, 173 TEE_PARAM_TYPE_NONE, 174 TEE_PARAM_TYPE_NONE)) 175 return TEE_ERROR_BAD_PARAMETERS; 176 177 hash = params[0].memref.buffer; 178 hash_sz = params[0].memref.size; 179 if (!hash || hash_sz != sizeof(*hash)) 180 return TEE_ERROR_BAD_PARAMETERS; 181 memcpy(new_hash, hash->value, sizeof(new_hash)); 182 183 key_size_bits = params[1].value.a; 184 if (key_size_bits != 4096 && key_size_bits != 2048) { 185 EMSG("Invalid key size: %"PRId32, key_size_bits); 186 return TEE_ERROR_BAD_PARAMETERS; 187 } 188 189 res = rockchip_otp_read_secure(old_hash, 190 ROCKCHIP_OTP_RSA_HASH_INDEX, 191 ROCKCHIP_OTP_RSA_HASH_SIZE); 192 if (res) 193 return res; 194 195 /* If a hash is already set, ensure new hash matches the old hash. */ 196 if (memcmp(old_hash, zero, sizeof(zero)) && 197 memcmp(old_hash, new_hash, sizeof(new_hash))) { 198 EMSG("Refusing to burn hash %s", 199 otp_to_string(new_hash, str, sizeof(str))); 200 EMSG("OTP hash is %s", 201 otp_to_string(old_hash, str, sizeof(str))); 202 return TEE_ERROR_BAD_PARAMETERS; 203 } 204 205 /* 206 * Check if secure boot is already enabled after verifying the 207 * parameters for reporting the correct error if the command would 208 * result in the same state as the already fused board. 209 */ 210 res = rockchip_otp_read_secure(&status, 211 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 212 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 213 if (res) 214 return res; 215 if (test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 216 DMSG("Secure boot already enabled"); 217 return TEE_SUCCESS; 218 } 219 220 if (IS_ENABLED(CFG_RK_SECURE_BOOT_SIMULATION)) { 221 IMSG("Simulation mode: Skip burning hash %s, key size %"PRId32, 222 otp_to_string(new_hash, str, sizeof(str)), key_size_bits); 223 return TEE_SUCCESS; 224 } 225 226 res = write_hash(new_hash, ARRAY_SIZE(new_hash)); 227 if (res) { 228 EMSG("Failed to write hash"); 229 return res; 230 } 231 232 res = write_key_size(key_size_bits); 233 if (res) { 234 EMSG("Failed to write key size"); 235 return res; 236 } 237 238 return TEE_SUCCESS; 239 } 240 241 static TEE_Result lockdown_device(uint32_t param_types, 242 TEE_Param params[TEE_NUM_PARAMS] __unused) 243 { 244 uint32_t hash[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 245 uint32_t zero[ROCKCHIP_OTP_RSA_HASH_SIZE] = {}; 246 TEE_Result res = TEE_ERROR_GENERIC; 247 uint32_t status = 0; 248 249 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, 250 TEE_PARAM_TYPE_NONE, 251 TEE_PARAM_TYPE_NONE, 252 TEE_PARAM_TYPE_NONE)) 253 return TEE_ERROR_BAD_PARAMETERS; 254 255 res = rockchip_otp_read_secure(hash, 256 ROCKCHIP_OTP_RSA_HASH_INDEX, 257 ROCKCHIP_OTP_RSA_HASH_SIZE); 258 if (res) 259 return res; 260 if (!memcmp(zero, hash, sizeof(hash))) { 261 EMSG("OTP hash is all zeros. Refuse lockdown."); 262 return TEE_ERROR_GENERIC; 263 } 264 265 res = rockchip_otp_read_secure(&status, 266 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 267 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 268 if (res) 269 return res; 270 if (test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 271 DMSG("Secure boot already enabled"); 272 return TEE_SUCCESS; 273 } 274 275 status |= ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE; 276 277 if (IS_ENABLED(CFG_RK_SECURE_BOOT_SIMULATION)) { 278 IMSG("Simulation mode: Skip writing status: %"PRIx32, 279 status); 280 return TEE_SUCCESS; 281 } 282 283 IMSG("Writing secure boot status: %"PRIx32, status); 284 res = rockchip_otp_write_secure(&status, 285 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 286 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 287 if (res) 288 return res; 289 290 res = rockchip_otp_read_secure(&status, 291 ROCKCHIP_OTP_SECURE_BOOT_STATUS_INDEX, 292 ROCKCHIP_OTP_SECURE_BOOT_STATUS_SIZE); 293 if (res) 294 return res; 295 if (!test_bit_mask(status, ROCKCHIP_OTP_SECURE_BOOT_STATUS_ENABLE)) { 296 EMSG("Failed to write secure boot status"); 297 return TEE_ERROR_GENERIC; 298 } 299 300 return TEE_SUCCESS; 301 } 302 303 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 304 uint32_t param_types, 305 TEE_Param params[TEE_NUM_PARAMS]) 306 { 307 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 308 TEE_Param bparams[TEE_NUM_PARAMS] = { }; 309 TEE_Result res2 = TEE_ERROR_GENERIC; 310 TEE_Param *eparams = NULL; 311 312 res = to_bounce_params(param_types, params, bparams, &eparams); 313 if (res) 314 return res; 315 316 switch (cmd_id) { 317 case PTA_RK_SECURE_BOOT_GET_INFO: 318 res = get_info(param_types, eparams); 319 break; 320 case PTA_RK_SECURE_BOOT_BURN_HASH: 321 res = burn_hash(param_types, eparams); 322 break; 323 case PTA_RK_SECURE_BOOT_LOCKDOWN_DEVICE: 324 res = lockdown_device(param_types, eparams); 325 break; 326 default: 327 break; 328 } 329 330 res2 = from_bounce_params(param_types, params, bparams, eparams); 331 if (!res && res2) 332 res = res2; 333 334 return res; 335 } 336 337 pseudo_ta_register(.uuid = PTA_RK_SECURE_BOOT_UUID, 338 .name = PTA_NAME, 339 .flags = PTA_DEFAULT_FLAGS, 340 .invoke_command_entry_point = invoke_command); 341