// Secure serial link — convenience wrapper tying rs232 + packet + security // // This is the top-level API for the serial/networking stack. It composes // three layers into one: // rs232 — ISR-driven UART I/O with ring buffers // packet — HDLC framing + CRC-16 + Go-Back-N ARQ (reliable delivery) // security — DH key exchange + XTEA-CTR encryption // // Usage: // 1. secLinkOpen() — opens COM port, sets up packet framing // 2. secLinkHandshake() — DH key exchange (blocks until both sides complete) // 3. secLinkSend() — send data (optionally encrypted) on a channel // 4. secLinkPoll() — receive, decrypt if needed, deliver to callback // 5. secLinkClose() — tear everything down // // Channel multiplexing: // Each packet carries a one-byte header: bit 7 = encrypted flag, // bits 6..0 = channel number (0-127). This allows multiple logical streams // (e.g., terminal data, file transfer, control messages) over a single // serial link without needing separate framing or sequencing per stream. // The callback receives plaintext regardless of whether encryption was used. // // Mixed clear/encrypted traffic: // Unencrypted packets can be sent before or after the handshake. This // allows a startup protocol (e.g., version negotiation) before keys are // exchanged. Encrypted packets require a completed handshake. #ifndef SECLINK_H #define SECLINK_H #include #include // Error codes #define SECLINK_SUCCESS 0 #define SECLINK_ERR_PARAM -1 #define SECLINK_ERR_SERIAL -2 #define SECLINK_ERR_ALLOC -3 #define SECLINK_ERR_HANDSHAKE -4 #define SECLINK_ERR_NOT_READY -5 #define SECLINK_ERR_SEND -6 // Max plaintext payload per send (packet max minus 1-byte channel header) #define SECLINK_MAX_PAYLOAD 254 // Channel limits #define SECLINK_MAX_CHANNEL 127 // Receive callback — delivers plaintext with channel number typedef void (*SecLinkRecvT)(void *ctx, const uint8_t *data, int len, uint8_t channel); // Opaque handle typedef struct SecLinkS SecLinkT; // Open a secure serial link. Opens the COM port and packet layer. // Handshake must be called separately before sending encrypted data. SecLinkT *secLinkOpen(int com, int32_t bps, int dataBits, char parity, int stopBits, int handshake, SecLinkRecvT callback, void *ctx); // Close the link. Frees all resources and closes the COM port. void secLinkClose(SecLinkT *link); // Perform DH key exchange. Blocks until both sides have exchanged keys // and derived cipher keys. RNG must be seeded before calling this. int secLinkHandshake(SecLinkT *link); // Get number of unacknowledged packets in the transmit window. int secLinkGetPending(SecLinkT *link); // Returns true if handshake is complete and link is ready for data. bool secLinkIsReady(SecLinkT *link); // Poll for incoming data. Decrypts if needed and delivers to callback. // Returns number of packets delivered, or negative on error. int secLinkPoll(SecLinkT *link); // Send data on a channel. If encrypt is true, data is encrypted before // sending (requires completed handshake). Clear packets can be sent // without a handshake. len must be 1..SECLINK_MAX_PAYLOAD. // If block is true, waits for transmit window space. int secLinkSend(SecLinkT *link, const uint8_t *data, int len, uint8_t channel, bool encrypt, bool block); // Send an arbitrarily large buffer by splitting it into SECLINK_MAX_PAYLOAD // chunks. Always blocks until all data is sent. Returns SECLINK_SUCCESS // or the first error encountered. int secLinkSendBuf(SecLinkT *link, const uint8_t *data, int len, uint8_t channel, bool encrypt); #endif