/** * @file se050_session.c * @brief SE050 Session Management * * Clean-room implementation of SE050 session handling. * Supports Platform SCP03 secure channel. * * License: MIT (Clean-room implementation) */ #include "se050_i2c_hal.h" #include "se050_session_internal.h" #include "se050_wireguard.h" #include "se050_crypto_utils.h" #include #include #include /* SCP03 status codes */ #define SCP03_SW_SUCCESS 0x9000 #define SCP03_SW_FAIL 0x6F00 /* ============================================================================ * Session Management * ============================================================================ */ se050_status_t se050_session_create(se050_session_ctx_t **ctx, se050_i2c_hal_t *hal) { se050_session_ctx_t *session; static uint32_t session_counter = 0; if (!ctx || !hal) { return SE050_ERR_INVALID_ARG; } /* Allocate session context */ session = (se050_session_ctx_t *)calloc(1, sizeof(*session)); if (!session) { return SE050_ERR_FAIL; } /* Initialize session */ session->hal = hal; session->state = SESSION_STATE_CREATED; session->session_id = ++session_counter; session->session_key_len = 0; session->scp03 = NULL; /* Zeroize session key on allocation */ memzero_explicit(session->session_key, sizeof(session->session_key)); *ctx = session; return SE050_OK; } se050_status_t se050_session_open(se050_session_ctx_t *ctx) { uint8_t cmd[64]; uint8_t rsp[64]; int ret; size_t cmd_len, rsp_len; if (!ctx) { return SE050_ERR_INVALID_ARG; } if (ctx->state != SESSION_STATE_CREATED) { return SE050_ERR_SESSION; } /* Build OPEN_SESSION APDU */ /* CLA INS P1 P2 LC DATA LE */ cmd[0] = 0x80; /* CLA */ cmd[1] = 0x70; /* INS - OPEN_SESSION */ cmd[2] = 0x00; /* P1 */ cmd[3] = 0x00; /* P2 */ cmd[4] = 0x00; /* LC */ cmd[5] = 0x00; /* LE */ cmd_len = 6; /* Send command */ ret = se050_i2c_write(ctx->hal, cmd, (int)cmd_len); if (ret < 0) { return SE050_ERR_I2C; } /* Receive response */ rsp_len = sizeof(rsp); ret = se050_i2c_read(ctx->hal, rsp, (int)rsp_len); if (ret < 0) { return SE050_ERR_I2C; } rsp_len = (size_t)ret; /* Check response status */ if (rsp_len < 2) { return SE050_ERR_SESSION; } uint16_t sw = (uint16_t)((rsp[rsp_len - 2] << 8) | rsp[rsp_len - 1]); if (sw != 0x9000) { return SE050_ERR_SESSION; } ctx->state = SESSION_STATE_OPENED; return SE050_OK; } void se050_session_close(se050_session_ctx_t *ctx) { uint8_t cmd[64]; uint8_t rsp[64]; int ret; if (!ctx) { return; } if (ctx->state != SESSION_STATE_OPENED) { return; } /* Build CLOSE_SESSION APDU */ cmd[0] = 0x80; /* CLA */ cmd[1] = 0x71; /* INS - CLOSE_SESSION */ cmd[2] = 0x00; /* P1 */ cmd[3] = 0x00; /* P2 */ cmd[4] = 0x00; /* LC */ cmd[5] = 0x00; /* LE */ ret = se050_i2c_write(ctx->hal, cmd, 6); if (ret >= 0) { se050_i2c_read(ctx->hal, rsp, sizeof(rsp)); } ctx->state = SESSION_STATE_CLOSED; } void se050_session_delete(se050_session_ctx_t *ctx) { if (!ctx) { return; } /* Close SCP03 secure channel if initialized */ if (ctx->scp03) { se050_scp03_free(ctx->scp03); ctx->scp03 = NULL; } /* Securely zeroize session key */ if (ctx->session_key_len > 0) { memzero_explicit(ctx->session_key, ctx->session_key_len); ctx->session_key_len = 0; } /* Free session context */ free(ctx); } /* ============================================================================ * SCP03 Secure Channel Integration * ============================================================================ */ /** * @brief Initialize SCP03 secure channel for this session * @param ctx Session context * @return SE050_OK on success */ se050_status_t se050_session_scp03_init(se050_session_ctx_t *ctx) { if (!ctx) { return SE050_ERR_INVALID_ARG; } if (ctx->state != SESSION_STATE_CREATED && ctx->state != SESSION_STATE_OPENED) { return SE050_ERR_SESSION; } /* Create SCP03 context */ return se050_scp03_init(&ctx->scp03, ctx); } /** * @brief Set SCP03 keys for PlatformSCP03 authentication * @param ctx Session context * @param enc_key Encryption key (16 bytes) * @param mac_key MAC key (16 bytes) * @param dek_key Data Encryption Key (16 bytes) * @return SE050_OK on success */ se050_status_t se050_session_scp03_set_keys(se050_session_ctx_t *ctx, const uint8_t *enc_key, const uint8_t *mac_key, const uint8_t *dek_key) { if (!ctx || !ctx->scp03) { return SE050_ERR_SESSION; } return se050_scp03_set_keys(ctx->scp03, enc_key, mac_key, dek_key); } /** * @brief Encrypt command using SCP03 * @param ctx Session context * @param cmd Command buffer * @param cmd_len Command length * @return SE050_OK on success */ se050_status_t se050_session_scp03_encrypt(se050_session_ctx_t *ctx, uint8_t *cmd, size_t *cmd_len) { if (!ctx || !ctx->scp03) { return SE050_ERR_SESSION; } return se050_scp03_encrypt_command(ctx->scp03, cmd, cmd_len); } /** * @brief Decrypt response using SCP03 * @param ctx Session context * @param cmd_len Original command length * @param rsp Response buffer * @param rsp_len Response length * @return Status word (0x9000 on success) */ uint16_t se050_session_scp03_decrypt(se050_session_ctx_t *ctx, size_t cmd_len, uint8_t *rsp, size_t *rsp_len) { if (!ctx || !ctx->scp03) { return SCP03_SW_FAIL; } return se050_scp03_decrypt_response(ctx->scp03, cmd_len, rsp, rsp_len); }