1 /* 2 * Copyright (c) 2026, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #ifndef __SFCP_H__ 9 #define __SFCP_H__ 10 11 #include <stdbool.h> 12 #include <stddef.h> 13 #include <stdint.h> 14 15 #include <drivers/arm/sfcp_link_defs.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /** 22 * \brief Minimum buffer size (in bytes) required for any SFCP packet. 23 * 24 * \details 25 * This constant defines the smallest valid buffer size that can be passed to 26 * SFCP send/receive/init functions. It accounts for the packet header, 27 * required metadata fields, and any alignment requirements, but does not 28 * include any additional payload space. 29 * 30 * Buffers smaller than this size are guaranteed to be rejected with 31 * ::SFCP_ERROR_BUFFER_TOO_SMALL. 32 * 33 * This macro is intended for compile-time allocation checks or for ensuring 34 * that dynamically allocated buffers meet the protocol's minimum size 35 * requirements before calling SFCP APIs. 36 */ 37 #define SFCP_BUFFER_MINIMUM_SIZE (40) 38 39 /** 40 * \brief Library return codes for the SFCP API. 41 * 42 * Notes: 43 * - Polling receives SHOULD use the *_NO_MSG_AVAILABLE / *_NO_REPLY_AVAILABLE codes 44 * when nothing is ready to read (non-fatal “no data” condition). 45 * - If a provided buffer is too small to hold the packet header + metadata, 46 * the call MUST return SFCP_ERROR_BUFFER_TOO_SMALL. 47 */ 48 enum sfcp_error_t { 49 SFCP_ERROR_SUCCESS = 0, 50 SFCP_ERROR_INVALID_POINTER, 51 SFCP_ERROR_INVALID_SENDER_ID, 52 SFCP_ERROR_INVALID_PACKET, 53 SFCP_ERROR_MESSAGE_TOO_SMALL, 54 SFCP_ERROR_BUFFER_TOO_SMALL, 55 SFCP_ERROR_INVALID_LEGACY_FORMAT_CONFIGURATION, 56 SFCP_ERROR_PAYLOAD_TOO_LARGE, 57 SFCP_ERROR_CRYPTOGRAPHY_NOT_SUPPORTED, 58 SFCP_ERROR_TRUSTED_SUBNET_MUST_BE_MANUALLY_SELECTED, 59 SFCP_ERROR_PAYLOAD_INVALID_ALIGNMENT, 60 SFCP_ERROR_ENCRYPTION_FAILED, 61 SFCP_ERROR_DECRYPTION_FAILED, 62 SFCP_ERROR_GENERATE_IV_FAILED, 63 SFCP_ERROR_GENERATE_SESSION_KEY_SEED_FAILED, 64 SFCP_ERROR_INVALID_TRUSTED_SUBNET_ID, 65 SFCP_ERROR_TRUSTED_SUBNET_ALREADY_REGISTERED, 66 SFCP_ERROR_INVALID_TRUSTED_SUBNET_NODE_ID, 67 SFCP_ERROR_INVALID_TRUSTED_SUBNET_NODE_AMOUNT, 68 SFCP_ERROR_INVALID_REPLY, 69 SFCP_ERROR_INVALID_MSG, 70 SFCP_ERROR_INVALID_NODE, 71 SFCP_ERROR_NO_MSG_AVAILABLE, 72 SFCP_ERROR_NO_REPLY_AVAILABLE, 73 SFCP_ERROR_SEND_MSG_AGAIN, 74 SFCP_ERROR_SEND_MSG_BUS_BUSY, 75 SFCP_ERROR_INVALID_PROTOCOL_VERSION, 76 SFCP_ERROR_INVALID_APPLICATION_ID, 77 SFCP_ERROR_INVALID_CLIENT_ID, 78 SFCP_ERROR_INVALID_CRYPTO_MODE, 79 SFCP_ERROR_INVALID_MSG_TYPE, 80 SFCP_ERROR_INVALID_SEQUENCE_NUMBER, 81 SFCP_ERROR_INVALID_PACKET_SIZE, 82 SFCP_ERROR_HANDLER_TABLE_FULL, 83 SFCP_ERROR_INVALID_BUFFER_HANDLE, 84 SFCP_ERROR_INVALID_TRUSTED_SUBNET_STATE, 85 SFCP_ERROR_INTERNAL_HANDSHAKE_FAILURE, 86 SFCP_ERROR_HANDSHAKE_GENERATE_RANDOM_FAILURE, 87 SFCP_ERROR_HANDSHAKE_HASH_FAILURE, 88 SFCP_ERROR_HANDSHAKE_HASH_ALG_UNSUPPORTED, 89 SFCP_ERROR_HANDSHAKE_SETUP_SESSION_KEY_FAILURE, 90 SFCP_ERROR_HANDSHAKE_REKEY_SESSION_KEY_FAILURE, 91 SFCP_ERROR_HANDSHAKE_INVALIDATE_SESSION_KEY_FAILURE, 92 SFCP_ERROR_HANDSHAKE_INVALID_RECEIVED_IV, 93 SFCP_ERROR_HANDSHAKE_INVALID_RE_KEY_MSG, 94 SFCP_ERROR_HANDSHAKE_INVALID_MUTUAL_AUTH_MSG, 95 SFCP_ERROR_ALLOCATE_BUFFER_TOO_LARGE, 96 SFCP_ERROR_ALLOCATE_BUFFER_FAILED, 97 SFCP_ERROR_POP_BUFFER_FAILED, 98 SFCP_ERROR_MSG_ALREADY_RECEIVED, 99 SFCP_ERROR_MSG_OUT_OF_ORDER_TEMPORARY_FAILURE, 100 SFCP_ERROR_PROTOCOL_ERROR, 101 SFCP_ERROR_SEND_PACKET_BUS_BUSY, 102 SFCP_ERROR_HAL_ERROR_BASE, 103 SFCP_ERROR_HAL_ERROR_MAX = SFCP_ERROR_HAL_ERROR_BASE + 0x100, 104 SFCP_ERROR_FORCE_UINT32T_MAX = UINT32_MAX, 105 }; 106 107 struct sfcp_packet_t; 108 109 /** 110 * \brief Metadata captured at send time to match a future reply. 111 * 112 * \details 113 * The sender MUST NOT reuse a sequence number until the reply for the message 114 * using that sequence number has been received. If the ID extension is used, the 115 * (message_id, client_id) pair MUST remain unique among in-flight messages. 116 * If a timeout-retry mechanism is used, the sender MUST increment sequence numbers 117 * between messages and keep metadata for all outstanding messages to handle delayed 118 * replies. 119 */ 120 struct sfcp_reply_metadata_t { 121 sfcp_node_id_t receiver; /**< Intended receiver node ID. */ 122 bool uses_cryptography; /**< Whether crypto/auth is used for this exchange. 123 Replies MUST mirror this bit (except error replies, 124 which are never encrypted). */ 125 uint16_t client_id; /**< Client ID (0 if ID extension not used). */ 126 uint16_t application_id; /**< Application ID (0 if ID extension not used). */ 127 uint8_t message_id; /**< Message ID for matching. */ 128 uint8_t trusted_subnet_id; /**< Trusted subnet ID (only if uses_cryptography). */ 129 }; 130 131 /** 132 * \brief Metadata captured at receive time to initialize a reply. 133 * 134 * \details 135 * A reply MUST use the same client ID and application ID as the original message, 136 * so it routes back to the correct caller/handler. 137 * The reply MUST also mirror the message’s uses_cryptography bit (except 138 * for protocol error replies, which cannot be encrypted). 139 */ 140 struct sfcp_msg_metadata_t { 141 sfcp_node_id_t 142 sender; /**< Original sender node ID (now the reply receiver). */ 143 bool uses_cryptography; /**< Whether the original message used crypto/auth. */ 144 uint16_t client_id; /**< Client ID from the original message (or 0). */ 145 uint16_t application_id; /**< Application ID from the original message (or 0). */ 146 uint8_t message_id; /**< Message ID from the original message. */ 147 uint8_t trusted_subnet_id; /**< Trusted subnet ID from the original message. */ 148 }; 149 150 /** 151 * \brief Opaque handle for an entry in the internal message/reply buffer. 152 * 153 * \details 154 * A value of this type is passed to handler callbacks and later used with the 155 * *_pop_* functions to retrieve the corresponding packet from the internal 156 * buffer. The concrete encoding is implementation-defined. 157 */ 158 typedef uint32_t sfcp_buffer_handle_t; 159 160 /** 161 * \brief Prototype for asynchronous handler functions (message or reply). 162 * 163 * \details 164 * The handler is invoked from the IRQ/deferred context with a buffer handle. 165 * The handler typically enqueues the handle and returns quickly; later, the 166 * consumer calls the appropriate *_pop_* routine to copy data out. 167 * 168 * \param[in] buffer_handle Handle for the buffered packet to process. 169 * 170 * \return SFCP_ERROR_SUCCESS if the handle was accepted/queued; an error 171 * code otherwise. 172 */ 173 typedef enum sfcp_error_t (*sfcp_handler_t)(sfcp_buffer_handle_t buffer_handle); 174 175 /** 176 * \brief Initializes the RSE communications layer. 177 * 178 * \details 179 * Initializes the transport/link integration used by the SFCP library. 180 * 181 * \return SFCP_ERROR_SUCCESS on success; otherwise a translated HAL error. 182 */ 183 enum sfcp_error_t sfcp_init(void); 184 185 /** 186 * \brief Prepare a message packet and payload buffer for sending. 187 * 188 * \param[in] buf Caller-provided buffer that will hold the entire packet 189 * (header + optional ID/crypto metadata + payload). 190 * \param[in] buf_size Size of \p buf. 191 * \param[in] receiver Destination node ID. 192 * \param[in] application_id Application ID at the receiver (0 means the receiver node itself). 193 * \param[in] client_id Client ID on behalf of which the sender is acting (0 means the sender node). 194 * \param[in] needs_reply If true, the packet type is MSG_NEEDS_REPLY; otherwise MSG_NO_REPLY. 195 * For MSG_NO_REPLY, the receiver MUST NOT send any reply. 196 * \param[in] manually_specify_ts_id If true, use the provided trusted_subnet_id; otherwise auto-select. 197 * \param[in] trusted_subnet_id Trusted subnet ID to use (only if manually_specify_ts_id is true). 198 * \param[out] payload Pointer within \p buf where the caller writes plaintext payload. 199 * \param[out] payload_len Capacity of the payload area (bytes). Caller MUST NOT exceed this. 200 * \param[out] msg Pointer to the prepared packet structure within \p buf. 201 * \param[out] msg_size Total packet size (header + metadata + payload capacity) to pass to send. 202 * \param[out] metadata Populated with values needed to match a future reply. 203 * 204 * \return SFCP_ERROR_SUCCESS on success; 205 * SFCP_ERROR_CRYPTOGRAPHY_NOT_SUPPORTED if crypto is requested but unsupported; 206 * SFCP_ERROR_INVALID_BUFFER / SFCP_ERROR_BUFFER_TOO_SMALL on buffer issues; 207 * SFCP_ERROR_INVALID_NODE for invalid destination. 208 */ 209 enum sfcp_error_t sfcp_init_msg(uint8_t *buf, size_t buf_size, 210 sfcp_node_id_t receiver, 211 uint16_t application_id, uint16_t client_id, 212 bool needs_reply, bool manually_specify_ts_id, 213 uint8_t trusted_subnet_id, uint8_t **payload, 214 size_t *payload_len, struct sfcp_packet_t **msg, 215 size_t *msg_size, 216 struct sfcp_reply_metadata_t *metadata); 217 218 /** 219 * \brief Transmit a prepared message packet. 220 * 221 * \param[in] msg Pointer to packet prepared by sfcp_init_msg (unaltered). 222 * \param[in] msg_size Total size of the packet buffer. 223 * \param[in] payload_size Number of bytes of the payload area actually used. 224 * 225 * \return SFCP_ERROR_SUCCESS on success; 226 * SFCP_ERROR_INVALID_PACKET / SFCP_ERROR_MESSAGE_TOO_SMALL / 227 * SFCP_ERROR_PAYLOAD_TOO_LARGE if the packet is malformed or sizes mismatch; 228 * SFCP_ERROR_INVALID_NODE if routing fails; 229 * a translated HAL error on transport failure. 230 * 231 * \note The application supplies plaintext in the payload; the library performs any required 232 * encryption/authentication transparently before sending. 233 */ 234 enum sfcp_error_t sfcp_send_msg(struct sfcp_packet_t *msg, size_t msg_size, 235 size_t payload_size); 236 237 /** 238 * \brief Prepare a reply packet and payload buffer corresponding to a received message. 239 * 240 * \param[in] buf Caller-provided buffer for the entire reply packet. 241 * \param[in] buf_size Size of \p buf. 242 * \param[in] metadata Metadata captured when the message was received; the reply will: 243 * - mirror uses_cryptography (except protocol error replies, 244 * which cannot be encrypted), and 245 * - use the same client_id, application_id, and message_id. 246 * \param[out] payload Pointer within \p buf where the caller writes the plaintext reply payload. 247 * \param[out] payload_len Capacity of the reply payload area (bytes). 248 * \param[out] reply Pointer to the prepared reply packet within \p buf. 249 * \param[out] reply_size Total packet size to pass to sfcp_send_reply. 250 * 251 * \return SFCP_ERROR_SUCCESS on success; *_BUFFER_TOO_SMALL if \p buf is insufficient; or a 252 * translated HAL error if local node ID cannot be obtained. 253 */ 254 enum sfcp_error_t sfcp_init_reply(uint8_t *buf, size_t buf_size, 255 struct sfcp_msg_metadata_t metadata, 256 uint8_t **payload, size_t *payload_len, 257 struct sfcp_packet_t **reply, 258 size_t *reply_size); 259 260 /** 261 * \brief Transmit a prepared reply packet. 262 * 263 * \param[in] reply Pointer to packet prepared by sfcp_init_reply (unaltered). 264 * \param[in] reply_size Total size of the packet buffer. 265 * \param[in] payload_size Number of bytes of the payload area actually used. 266 * 267 * \return SFCP_ERROR_SUCCESS on success; the same validation/routing/transport errors as send_msg. 268 * 269 * \note Normal replies MUST mirror the message’s uses_cryptography bit. 270 * Protocol error replies are never encrypted. 271 */ 272 enum sfcp_error_t sfcp_send_reply(struct sfcp_packet_t *reply, 273 size_t reply_size, size_t payload_size); 274 275 /** 276 * \brief Receive a message (polling mode). 277 * 278 * \details 279 * Retrieves the next available message destined for \p sender (by route), validates it, 280 * and exposes the plaintext payload pointer and capacity. If nothing is available, returns 281 * SFCP_ERROR_NO_MSG_AVAILABLE (non-fatal). 282 * 283 * Validation rules enforced include: 284 * - Packet type MUST be MSG_NEEDS_REPLY or MSG_NO_REPLY. 285 * - Protocol version MUST equal 0b10. 286 * - If ID extension not present, receiver MUST treat client_id/application_id as 0; 287 * otherwise, they MUST be read from their fields. 288 * - Receiver MUST route handling based on application_id; if out of range, return 289 * INVALID_APPLICATION_ID (sender of MSG_NEEDS_REPLY will receive an error reply). 290 * - If message crypto setting doesn’t match the expected uses_cryptography, return INVALID_CRYPTO_MODE. 291 * - For MSG_NO_REPLY, the receiver MUST NOT send a reply even on failure. 292 * 293 * \param[in] buf Buffer to receive the packet. 294 * \param[in] buf_size Size of \p buf. 295 * \param[in] any_sender Message can come from any known sender, if set \p sender must be 0 296 * \param[in] sender Expected sender node ID. 297 * \param[in] application_id Application ID this receiver instance handles (0 for node handler). 298 * \param[out] client_id Client ID extracted from the message (0 if no ID extension). 299 * \param[out] payload Pointer within \p buf to the plaintext payload. 300 * \param[out] payload_len Capacity of \p payload (bytes). 301 * \param[out] metadata Set to values needed to initialize a reply. 302 * 303 * \return SFCP_ERROR_SUCCESS on success; 304 * SFCP_ERROR_NO_MSG_AVAILABLE if nothing to read; 305 * SFCP_ERROR_BUFFER_TOO_SMALL / *_INVALID_* for validation failures. 306 * 307 * \note Decryption/authentication MUST be performed before returning payload to the caller 308 * when crypto is used. 309 */ 310 enum sfcp_error_t sfcp_receive_msg(uint8_t *buf, size_t buf_size, 311 bool any_sender, sfcp_node_id_t sender, 312 uint16_t application_id, uint16_t *client_id, 313 uint8_t **payload, size_t *payload_len, 314 struct sfcp_msg_metadata_t *metadata); 315 316 /** 317 * \brief Receive a reply (polling mode). 318 * 319 * \details 320 * Retrieves the next available reply corresponding to \p metadata (by route), validates it, 321 * and exposes the plaintext payload pointer and capacity. If nothing is available, returns 322 * SFCP_ERROR_NO_REPLY_AVAILABLE (non-fatal). 323 * 324 * Validation rules enforced include: 325 * - Packet type MUST be REPLY (normal) or PROTOCOL_ERROR_REPLY (protocol error). 326 * Error replies are never encrypted. 327 * - If the message used ID extension, the reply MUST carry the same client_id and application_id. 328 * - uses_cryptography MUST mirror the original message for normal replies. 329 * 330 * \param[in] buf Buffer to receive the packet. 331 * \param[in] buf_size Size of \p buf. 332 * \param[in] metadata Reply metadata captured at send time. 333 * \param[out] payload Pointer within \p buf to the plaintext payload (if any). 334 * \param[out] payload_len Capacity of \p payload (bytes). 335 * 336 * \return SFCP_ERROR_SUCCESS on success; 337 * SFCP_ERROR_NO_REPLY_AVAILABLE if nothing to read; 338 * SFCP_ERROR_BUFFER_TOO_SMALL / *_INVALID_* for validation failures. 339 * 340 * \note Decryption/authentication MUST be performed before returning payload to the caller 341 * when crypto is used. 342 */ 343 enum sfcp_error_t sfcp_receive_reply(uint8_t *buf, size_t buf_size, 344 struct sfcp_reply_metadata_t metadata, 345 uint8_t **payload, size_t *payload_len); 346 347 /** 348 * \brief Look up the registered message handler for an Application ID. 349 * 350 * \param[in] application_id Application ID to route messages to (0 for the 351 * node-wide/default handler). 352 * \param[out] handler On success, set to the registered handler. 353 * 354 * \return SFCP_ERROR_SUCCESS on success; 355 * SFCP_ERROR_INVALID_APPLICATION_ID if no handler exists; 356 * other errors as appropriate. 357 */ 358 enum sfcp_error_t sfcp_get_msg_handler(uint16_t application_id, 359 sfcp_handler_t *handler); 360 361 /** 362 * \brief Register (or replace) the message handler for an Application ID. 363 * 364 * \param[in] application_id Application ID to associate with \p handler 365 * (0 for the node-wide/default handler). 366 * \param[in] handler Callback to invoke when a message for this 367 * Application ID is received. 368 * 369 * \return SFCP_ERROR_SUCCESS on success; an error code otherwise. 370 */ 371 enum sfcp_error_t sfcp_register_msg_handler(uint16_t application_id, 372 sfcp_handler_t handler); 373 374 /** 375 * \brief Copy a buffered Message out of the internal queue (handler mode). 376 * 377 * \details 378 * On success this function: 379 * - Performs any required decryption, authentication, and access-control checks 380 * before exposing data to the caller. 381 * - Copies the plaintext payload into \p payload (if \p payload_len >= size). 382 * - Fills \p sender, \p client_id, \p needs_reply, and \p metadata so a reply 383 * can be constructed later. 384 * - Removes the Message from the internal buffer. 385 * 386 * On failure, the Message MUST NOT be removed from the buffer. 387 * 388 * \param[in] buffer_handle Handle previously delivered to a message handler. 389 * \param[out] sender Set to the Sender node ID. 390 * \param[out] client_id Set to the Client ID (0 if ID extension not used). 391 * \param[out] needs_reply Set true if the Message requests a reply. 392 * \param[out] payload Destination buffer for the plaintext payload 393 * (may be NULL if \p payload_len is 0). 394 * \param[in] payload_len Size in bytes of \p payload. 395 * \param[out] payload_size Set to the number of payload bytes available. 396 * \param[out] metadata Filled with values needed to initialize a reply. 397 * 398 * \return SFCP_ERROR_SUCCESS on success; 399 * SFCP_ERROR_PAYLOAD_TOO_LARGE if \p payload is too small (Message 400 * is retained internally); 401 * SFCP_ERROR_INVALID_PACKET / *_INVALID_* on validation failure 402 * (Message is retained); 403 * other errors as appropriate. 404 */ 405 enum sfcp_error_t 406 sfcp_pop_msg_from_buffer(sfcp_buffer_handle_t buffer_handle, 407 sfcp_node_id_t *sender, uint16_t *client_id, 408 bool *needs_reply, uint8_t *payload, 409 size_t payload_len, size_t *payload_size, 410 struct sfcp_msg_metadata_t *metadata); 411 412 /** 413 * \brief Look up the registered reply handler for a client identifier. 414 * 415 * \param[in] client_id Client identifier used to route replies (0 when the 416 * ID extension is not used). 417 * \param[out] handler On success, set to the registered handler. 418 * 419 * \return SFCP_ERROR_SUCCESS on success; 420 * SFCP_ERROR_INVALID_CLIENT_ID if no handler exists; 421 * other errors as appropriate. 422 */ 423 enum sfcp_error_t sfcp_get_reply_handler(uint16_t client_id, 424 sfcp_handler_t *handler); 425 426 /** 427 * \brief Register (or replace) the reply handler for an identifier. 428 * 429 * \details 430 * The identifier selects which replies are delivered to \p handler. In systems 431 * using the ID extension this is typically the \b client_id; otherwise it may be 432 * a single global handler registered with identifier 0. 433 * 434 * \param[in] application_id Identifier used by the implementation to select 435 * the reply handler (commonly the client_id). 436 * \param[in] handler Callback to invoke when a matching reply arrives. 437 * 438 * \return SFCP_ERROR_SUCCESS on success; an error code otherwise. 439 */ 440 enum sfcp_error_t sfcp_register_reply_handler(uint16_t application_id, 441 sfcp_handler_t handler); 442 443 /** 444 * \brief Copy a buffered Reply out of the internal queue (handler mode). 445 * 446 * \details 447 * On success this function: 448 * - Performs any required decryption, authentication, and access-control checks 449 * before exposing data to the caller. 450 * - Copies the plaintext payload into \p payload (if \p payload_len >= size). 451 * - Fills \p metadata so the caller can match the Reply to the original Message. 452 * - Removes the Reply from the internal buffer. 453 * 454 * On failure, the Reply MUST NOT be removed from the buffer. 455 * 456 * \param[in] buffer_handle Handle previously delivered to a reply handler. 457 * \param[out] payload Destination buffer for the plaintext payload 458 * (may be NULL if \p payload_len is 0). 459 * \param[in] payload_len Size in bytes of \p payload. 460 * \param[out] payload_size Set to the number of payload bytes available. 461 * \param[out] metadata Filled with the reply metadata (ids, message_id, flags). 462 * 463 * \return SFCP_ERROR_SUCCESS on success; 464 * SFCP_ERROR_PAYLOAD_TOO_LARGE if \p payload is too small (Reply 465 * is retained internally); 466 * SFCP_ERROR_INVALID_PACKET / *_INVALID_* on validation failure 467 * (Reply is retained); 468 * other errors as appropriate. 469 */ 470 enum sfcp_error_t 471 sfcp_pop_reply_from_buffer(sfcp_buffer_handle_t buffer_handle, uint8_t *payload, 472 size_t payload_len, size_t *payload_size, 473 struct sfcp_reply_metadata_t *metadata); 474 475 #ifdef __cplusplus 476 } 477 #endif 478 479 #endif /* __SFCP_H__ */ 480