1 /* 2 * Copyright 2018-2021 NXP 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 #ifndef FSL_SSCP_H 8 #define FSL_SSCP_H 9 10 #include <stddef.h> 11 #include "fsl_sscp_commands.h" 12 13 /*! 14 @defgroup sscp Security Subsystem Communication Protocol (SSCP) 15 16 # SSCP protocol description 17 18 SSCP is very simple remote procedure call protocol. 19 Function parameters are described by one or multiple SSCP operation descriptor(s). 20 One parameter descriptor describes up to 7 function parameters as contexts, buffers, values or aggregates. 21 Multiple parameter descriptors can be linked by the aggregate parameter type (kSSCP_ParamType_Aggregate). 22 23 Function arguments are described as a buffer (address and size), a value (a tuple of two words), 24 a context (pointer and type id) or an aggregate. 25 If the parameter is the aggregate (kSSCP_ParamType_Aggregate type), then it will contain a pointer to another 26 sscp_operation_t. This allows to link additional sscp_operation_t. 27 28 The protocol allows for remote calling by a copy of all arguments (including buffer contents), 29 that is, to remote call to a sub-system having no physical access to Host CPU memory. 30 If a sub-system has access to Host CPU memory, the SSCP transport implementation can decide to transfer 31 only the buffer descriptor (pointer and size) without physically transmitting the buffer content, 32 as the buffer content can be accessed by the sub-system when the remote function executes. 33 The same holds for the context descriptor (pointer and type id). The actual SSCP implementation 34 can transfer only pointer to a sub-system, if the sub-system has access to the memory, where the context data 35 structure is located, and if it has an application level knowledge of the context data structure 36 layout (either based on the command id or the context type id). 37 38 Byte length (for void* and uintptr_t) and endianess is inherited from the host CPU. 39 40 # SSCP operation descriptors 41 42 A remote function is invoked by transmitting a command id (unique identifier to specify a remote function), 43 followed by SSCP operation descriptors ::sscp_operation_t. There is always one descriptor and optionally 44 it can link another descriptor, if the number of ::sscp_operation_t params is not sufficient 45 to described all function parameters. In the example below, the last params[n-1] on the left side is an aggregate 46 that links secondary descriptor. 47 48 @code 49 command 50 paramTypes 51 params[0] 52 ... 53 params[n-1] ------------- paramTypes 54 params[0] 55 ... 56 params[n-1] 57 @endcode 58 59 where n = 1, 2, ..., 7. 60 61 These operation descriptors serve as an input to ::sscp_invoke_command() function. 62 The serialization to the communication system is implementation specific. 63 For example, implementations may decide to transfer only pointers and values (without payloads), 64 because security sub-system has access to memory, so it can read and write payloads on its own during function 65 execution. Other implementations may need to serialize everything to a communication bus. 66 67 This implementation specific data transfer is implemented by an invoke() function. 68 During implementation specific initialization of the SSCP transfer, sscp_<Implementation>_init() function, 69 a pointer to implementation specific invoke() function is stored in the sscp_<Implementation>_context_t. 70 71 @code 72 sscp_mu_init(ctx, invoke = sscp_mu_invoke_command) 73 ... 74 ctx->invoke() 75 ... 76 ctx->invoke() 77 ... 78 sscp_deinit(ctx) 79 @endcode 80 81 # Example for SSCP protocol implementation with ELEMU 82 83 The ::sscp_invoke_command() implementation for the ELEMU (Sentinel), ::sscp_mu_invoke_command(), 84 builds up the serial message as follows: 85 86 word 0 | word 1 | word 2 | word 3 | ... | word (n*2 + 1) 87 -------|-----------|-------------|-------------|-----|--------------- 88 CMD |paramTypes | params[0].a | params[0].b | ... | params[n-1].b 89 90 where the n value is CMD specific and it is present in the CMD word. 91 Passing this message through ELEMU to the ELE sub-system is done by simply moving the 16 words into ELEMU Tx A 92 registers. 93 94 # Example with the SSS API 95 96 @code 97 sss_status_t sss_aead_one_go(sss_aead_t *context, 98 const uint8_t *srcData, 99 uint8_t *destData, 100 size_t size, 101 uint8_t *nonce, 102 size_t nonceLen, 103 const uint8_t *aad, 104 size_t aadLen, 105 uint8_t *tag, 106 size_t tagLen); 107 108 uint32_t cmd = kSSCP_CMD_SSS_AeadOneGo(n=6); 109 110 sscp_operation_t op = (0); 111 sscp_status_t status = kStatus_SSCP_Fail; 112 uint32_t ret = 0; 113 114 if (context->mode == Encrypt) 115 { 116 op.paramTypes = SSCP_OP_SET_PARAM(kSSCP_ParamType_ContextReference, 117 kSSCP_ParamType_MemrefInput, 118 kSSCP_ParamType_MemrefOutput, 119 kSSCP_ParamType_MemrefInput, 120 kSSCP_ParamType_MemrefInput, 121 kSSCP_ParamType_MemrefOutput, 122 kSSCP_ParamType_None); 123 } 124 else 125 { 126 op.paramTypes = SSCP_OP_SET_PARAM(kSSCP_ParamType_ContextReference, 127 kSSCP_ParamType_MemrefInput, 128 kSSCP_ParamType_MemrefOutput, 129 kSSCP_ParamType_MemrefInput, 130 kSSCP_ParamType_MemrefInput, 131 kSSCP_ParamType_MemrefInput, 132 kSSCP_ParamType_None); 133 } 134 135 ... context is an aggregate data type ... 136 ... implementation specific sscp_operation_t to serialize the context data ... 137 op.params[0].context.ptr = context; 138 op.params[0].context.type = kSSCP_ParamContextType_SSS_Aead; 139 140 ... function parameters ... 141 op.params[1].memref.buffer = srcData; 142 op.params[1].memref.size = size; 143 144 op.params[2].memref.buffer = destData; 145 op.params[2].memref.size = size; 146 147 op.params[3].memref.buffer = nonce; 148 op.params[3].memref.size = nonceLen; 149 150 op.params[4].memref.buffer = aad; 151 op.params[4].memref.size = aadLen; 152 153 op.params[5].memref.buffer = tag; 154 op.params[5].memref.size = tagLen; 155 156 ... Serialize to the link ... 157 status = context->session->sscp->invoke(context->sscpSession, cmd, &op, &ret); 158 if (status != kStatus_SSCP_Success) 159 { 160 return kStatus_SSS_Fail; 161 } 162 163 return (sss_status_t)ret; 164 165 @endcode 166 167 # Example with the TEE Client API 168 169 @code 170 TEEC_Result TEEC_InvokeCommand(TEEC_Session *sessionTEEC, 171 uint32_t commandID, 172 TEEC_Operation *operation, 173 uint32_t *returnOrigin); 174 175 176 uint32_t cmd = kSSCP_CMD_TEEC_InvokeCommand; 177 178 sscp_operation_t op = {0}; 179 sscp_status_t status = kStatus_SSCP_Fail; 180 uint32_t ret = 0; 181 182 op.paramTypes = SSCP_OP_SET_PARAM(kSSCP_ParamType_ContextReference, 183 kSSCP_ParamType_ValueInput, 184 kSSCP_ParamType_ContextReference, 185 kSSCP_ParamType_MemrefOutput, 186 kSSCP_ParamType_None, 187 kSSCP_ParamType_None, 188 kSSCP_ParamType_None); 189 190 op.params[0].context.ptr = sessionTEEC; 191 op.params[0].context.type = kSSCP_ParamContextType_TEEC_Session; 192 193 op.params[1].value.a = commandID; 194 op.params[1].value.b = 0; 195 196 op.params[2].context.ptr = operation; 197 op.params[2].context.type = kSSCP_ParamContextType_TEEC_Operation; 198 199 op.params[3].memref.buffer = returnOrigin; 200 op.params[3].memref.size = sizeof(*returnOrigin); 201 202 @endcode 203 */ 204 205 /*! 206 * @addtogroup sscp 207 * @{ 208 */ 209 210 /*! @brief Maximum number of parameters to be supported in one sscp_operation_t */ 211 #define SSCP_OPERATION_PARAM_COUNT (7u) 212 #define SSCP_OPERATION_RESULTS_COUNT (2u) 213 214 /*! @brief Default SSCP context is a pointer to memory. */ 215 #ifndef SSCP_MAX_CONTEXT_SIZE 216 #define SSCP_MAX_CONTEXT_SIZE (sizeof(void *)) 217 #endif 218 219 /*! @brief Set parameter types for the SSCP operation. Each param type is encoded into 4-bits bit field. */ 220 #define SSCP_OP_SET_PARAM(p0, p1, p2, p3, p4, p5, p6) \ 221 (((uint32_t)(p0)&0xFu) << 0) | (((uint32_t)(p1)&0xFu) << 4) | (((uint32_t)(p2)&0xFu) << 8) | \ 222 (((uint32_t)(p3)&0xFu) << 12) | (((uint32_t)(p4)&0xFu) << 16) | (((uint32_t)(p5)&0xFu) << 20) | \ 223 (((uint32_t)(p6)&0xFu) << 24) 224 225 /*! @brief Set parameter types for the SSCP operation. Each param type is encoded into 4-bits bit field. */ 226 #define SSCP_OP_SET_RESULT(p0) (((uint32_t)(p0)&0xFu) << 0) 227 228 /*! @brief Decode i-th parameter as 4-bit unsigned integer. */ 229 #define SSCP_OP_GET_PARAM(i, paramTypes) ((((uint32_t)(paramTypes)) >> (i)*4u) & 0xFu) 230 231 /*! @brief Compile time sizeof() check */ 232 #if 0 233 #define SSCP_BUILD_ASSURE(condition, msg) extern int(msg)[1 - 2 * (!(condition))] __attribute__((unused)) 234 #else 235 #define SSCP_BUILD_ASSURE(condition, msg) 236 #endif 237 238 /** 239 * @brief Definitions with return values from SSCP functions 240 */ 241 typedef uint32_t sscp_status_t; 242 #define kStatus_SSCP_Success ((sscp_status_t)0x10203040u) 243 #define kStatus_SSCP_Fail ((sscp_status_t)0x40302010u) 244 #define kStatus_SSCP_ResourceBusy ((sscp_status_t)0x40302020u) 245 246 typedef struct sscp_context sscp_context_t; 247 248 /** 249 * @brief SSCP operation descriptor 250 * 251 */ 252 typedef struct sscp_operation sscp_operation_t; 253 254 /*! @brief Typedef for a function that sends a command and associated parameters to security sub-system 255 * 256 * The commandID and operation content is serialized and sent over to the selected security sub-system. 257 * This is implementation specific function. 258 * The function can invoke both blocking and non-blocking secure functions in the selected security sub-system. 259 * 260 * @param context Initialized SSCP context 261 * @param commandID Command - an id of a remote secure function to be invoked 262 * @param op Description of function arguments as a sequence of buffers, values, context references and aggregates 263 * @param ret Return code of the remote secure function (application layer return value) 264 * 265 * @returns Status of the operation 266 * @retval kStatus_SSCP_Success A blocking command has completed or a non-blocking command has been accepted. 267 * @retval kStatus_SSCP_Fail Operation failure, for example hardware fail. 268 * @retval kStatus_SSCP_InvalidArgument One of the arguments is invalid for the function to execute. 269 */ 270 typedef sscp_status_t (*fn_sscp_invoke_command_t)(sscp_context_t *context, 271 sscp_command_t commandID, 272 sscp_operation_t *op, 273 uint32_t *ret); 274 275 /** 276 * struct _sscp_context - SSCP context struct 277 * 278 * This data type is used to keep context of the SSCP link. 279 * It has one mandatory member - pointer to invoke() function. 280 * Otherwise it is completely implementation specific. 281 * 282 * @param invoke Pointer to implementation specific invoke() function 283 * @param context Container for the implementation specific data. 284 */ 285 struct sscp_context 286 { 287 fn_sscp_invoke_command_t invoke; 288 /*sscp_status_t (*sscp_invoke_command)(sscp_context_t *context, uint32_t commandID, sscp_operation_t *op);*/ 289 290 /*! Implementation specific part */ 291 struct 292 { 293 uint8_t data[SSCP_MAX_CONTEXT_SIZE]; 294 } context; 295 }; 296 297 /** 298 * struct _sscp_memref - Buffer 299 * 300 * This data type is used to describe a function argument as a buffer. 301 * 302 * @param buffer Memory address 303 * @param size Length of the buffer in bytes 304 */ 305 typedef struct 306 { 307 uintptr_t buffer; 308 size_t size; 309 } sscp_memref_t; 310 311 /** 312 * struct sscp_value_t - Small raw data 313 * 314 * This data type is used to describe a function argument as a tuple of two 32-bit values. 315 * 316 * @param a First 32-bit data value. 317 * @param b Second 32-bit data value. 318 */ 319 typedef struct 320 { 321 uint32_t a; 322 uint32_t b; 323 } sscp_value_t; 324 325 /** 326 * @brief SSCP descriptor for an aggregate 327 * 328 * This data type is used to link additional SSCP operation. 329 * 330 * @param op Pointer to sscp_operation_t. 331 */ 332 typedef struct 333 { 334 sscp_operation_t *op; 335 } sscp_aggregate_operation_t; 336 337 /** 338 * @brief SSCP descriptor for a context struct 339 * 340 * This data type is used pass context struct to SSCP by reference 341 * 342 * @param ptr Pointer to a data structure 343 * @param type 32-bit identifier specifying context struct type 344 */ 345 typedef struct 346 { 347 void *ptr; 348 uint32_t type; 349 } sscp_context_reference_t; 350 351 /** 352 * @brief Data structure representing a function argument. 353 * 354 * Either the client uses a shared memory reference, or a small raw 355 * data container. 356 * 357 * @param value Small raw data container 358 * @param memref Memory reference 359 * @param aggregate Reference to another SSCP descriptor 360 * @param context Pointer to a data struct to be passed to SSCP by reference 361 */ 362 typedef union 363 { 364 sscp_value_t value; 365 sscp_memref_t memref; 366 sscp_aggregate_operation_t aggregate; 367 sscp_context_reference_t context; 368 } sscp_parameter_t; 369 370 /** 371 * @brief Data structure describing function arguments. 372 * Function argument are described as a sequence of buffers, values, context references and aggregates. 373 * It serves as an input to ::sscp_invoke_command(), an implementation specific serialization function. 374 * 375 * @param paramTypes Type of data passed. 376 * @param params Array of parameters of type sscp_parameter_t. 377 * 378 */ 379 struct sscp_operation 380 { 381 uint32_t paramTypes; 382 sscp_parameter_t params[SSCP_OPERATION_PARAM_COUNT]; 383 uint32_t resultTypes; 384 uint32_t resultCount; 385 sscp_parameter_t result[SSCP_OPERATION_RESULTS_COUNT]; 386 }; 387 388 /** 389 * @brief Enum with SSCP operation parameters. 390 */ 391 typedef uint32_t sscp_param_types_t; 392 #define kSSCP_ParamType_None ((sscp_param_types_t)0x0u) /*! Parameter not in use */ 393 #define kSSCP_ParamType_Aggregate ((sscp_param_types_t)0x1u) /*! Link to another ::sscp_operation_t */ 394 #define kSSCP_ParamType_ContextReference \ 395 ((sscp_param_types_t)0x2u) /*! Reference to a context structure - pointer and type */ 396 #define kSSCP_ParamType_MemrefInputNoSize \ 397 ((sscp_param_types_t)0x3u) /*! Reference to a memory buffer - input to remote function or service, no size \ 398 specified */ 399 #define kSSCP_ParamType_MemrefOutputNoSize \ 400 ((sscp_param_types_t)0x4u) /*! Reference to a memory buffer - output by remote function or service, no size \ 401 specified.*/ 402 #define kSSCP_ParamType_MemrefInput \ 403 ((sscp_param_types_t)0x5u) /*! Reference to a memory buffer - input to remote function or service */ 404 #define kSSCP_ParamType_MemrefOutput \ 405 ((sscp_param_types_t)0x6u) /*! Reference to a memory buffer - output by remote function or service. \ 406 Implementations shall update the size member of the ::sscp_memref_t with the \ 407 actual number of bytes written. */ 408 #define kSSCP_ParamType_MemrefInOut \ 409 ((sscp_param_types_t)0x7u) /*! Reference to a memory buffer - input to and ouput from remote function or service \ 410 */ 411 #define kSSCP_ParamType_ValueInputTuple \ 412 ((sscp_param_types_t)0x8u) /*! Tuple of two 32-bit integers - input to remote function or service */ 413 #define kSSCP_ParamType_ValueOutputTuple \ 414 ((sscp_param_types_t)0x9u) /*! Tuple of two 32-bit integers - output by remote function or service */ 415 #define kSSCP_ParamType_ValueInputSingle \ 416 ((sscp_param_types_t)0xau) /*! One 32-bit integers - input to remote function or service */ 417 #define kSSCP_ParamType_ValueOutputSingle \ 418 ((sscp_param_types_t)0xbu) /*! One 32-bit integers - output by remote function or service */ 419 420 /******************************************************************************* 421 * API 422 ******************************************************************************/ 423 #if defined(__cplusplus) 424 extern "C" { 425 #endif 426 427 /*! @brief Sends a command and associated parameters to security sub-system 428 * 429 * The commandID and operation content is serialized and sent over to the selected security sub-system. 430 * This is implementation specific function. 431 * The function can invoke both blocking and non-blocking secure functions in the selected security sub-system. 432 * 433 * @param context Initialized SSCP context 434 * @param commandID Command - an id of a remote secure function to be invoked 435 * @param op Description of function arguments as a sequence of buffers and values 436 * @param ret Return code of the remote secure function (application layer return value) 437 * 438 * @returns Status of the operation 439 * @retval kStatus_SSCP_Success A blocking command has completed or a non-blocking command has been accepted. 440 * @retval kStatus_SSCP_Fail Operation failure, for example hardware fail. 441 * @retval kStatus_SSCP_InvalidArgument One of the arguments is invalid for the function to execute. 442 */ 443 sscp_status_t sscp_invoke_command(sscp_context_t *context, uint32_t commandID, sscp_operation_t *op, uint32_t *ret); 444 445 #if defined(__cplusplus) 446 } 447 #endif 448 449 /*! 450 *@} 451 */ /* end of sscp */ 452 453 #endif /* FSL_SSCP_H */ 454