Seregon/zftpd

Zero-copy FTP/HTTP Daemon compatible with all POSIX systems

C/11.0 KB/No license
include/ftp_crypto.h
zftpd / include / ftp_crypto.h
1/*
2MIT License
3 
4Copyright (c) 2026 Seregon
5 
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12 
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15 
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24 
25/**
26 * @file ftp_crypto.h
27 * @brief Lightweight ChaCha20 stream cipher for FTP data encryption
28 *
29 * @author SeregonWar
30 * @version 1.0.0
31 * @date 2026-02-19
32 *
33 * CIPHER: ChaCha20 (RFC 7539)
34 *
35 * ┌────────────────────────────────────────────────────┐
36 * │ ChaCha20 Stream Cipher — How it works │
37 * │ │
38 * │ 256-bit key ──┐ │
39 * │ 96-bit nonce ─┤──► ChaCha20 Block ──► 64B stream │
40 * │ 32-bit ctr ───┘ │ │
41 * │ XOR │
42 * │ plaintext ─────────────────────────────► ciphertext│
43 * │ │
44 * │ decrypt = same XOR with same keystream │
45 * └────────────────────────────────────────────────────┘
46 *
47 * PERFORMANCE: ~3 GB/s on x86-64, ~1 GB/s on ARM (pure C)
48 * DEPENDENCIES: None (self-contained ARX operations)
49 */
50 
51#ifndef FTP_CRYPTO_H
52#define FTP_CRYPTO_H
53 
54#include "ftp_config.h"
55#include <stddef.h>
56#include <stdint.h>
57 
58#if FTP_ENABLE_CRYPTO
59 
60/*===========================================================================*
61 * CRYPTO CONTEXT
62 *===========================================================================*/
63 
64/**
65 * Per-session ChaCha20 crypto context
66 *
67 * Memory layout (statically embedded in ftp_session_t):
68 * ┌──────────────────────────┐
69 * │ state[16] 64 bytes │ ChaCha20 state matrix
70 * │ keystream[64] 64 bytes │ Current block output
71 * │ ks_offset 1 byte │ Position in keystream
72 * │ active 1 byte │ Encryption on/off
73 * │ _pad 2 bytes │ Alignment
74 * │ counter 4 bytes │ Block counter
75 * └──────────────────────────┘
76 * Total: 136 bytes per session
77 */
78typedef struct {
79 uint32_t state[16]; /**< ChaCha20 state matrix (key+nonce+ctr) */
80 uint8_t keystream[64]; /**< Current 64-byte keystream block */
81 uint8_t ks_offset; /**< Consumed bytes in current keystream */
82 uint8_t active; /**< 1 = encryption enabled for session */
83 uint8_t _pad[2]; /**< Alignment padding */
84 uint32_t counter; /**< Block counter (increments per 64B) */
85} ftp_crypto_ctx_t;
86 
87/*===========================================================================*
88 * API
89 *===========================================================================*/
90 
91/**
92 * @brief Initialize crypto context with key and nonce
93 *
94 * Sets up the ChaCha20 state matrix from a 256-bit key and 96-bit nonce.
95 * After this call, the context is ready for ftp_crypto_xor().
96 *
97 * @param ctx Crypto context to initialize
98 * @param key 256-bit (32 byte) encryption key
99 * @param nonce 96-bit (12 byte) unique per-session nonce
100 *
101 * @pre ctx != NULL, key != NULL, nonce != NULL
102 */
103void ftp_crypto_init(ftp_crypto_ctx_t *ctx, const uint8_t key[32],
104 const uint8_t nonce[12]);
105 
106/**
107 * @brief XOR data with ChaCha20 keystream (encrypt or decrypt)
108 *
109 * Operates in-place: encrypt(plaintext) = decrypt(ciphertext) = XOR.
110 * Generates keystream on demand in 64-byte blocks.
111 * Safe to call with any data length (handles partial blocks).
112 *
113 * @param ctx Initialized crypto context
114 * @param data Buffer to encrypt/decrypt in-place
115 * @param len Number of bytes to process
116 *
117 * @pre ctx != NULL, ctx->active == 1
118 * @pre data != NULL if len > 0
119 */
120void ftp_crypto_xor(ftp_crypto_ctx_t *ctx, void *data, size_t len);
121 
122/**
123 * @brief Securely reset crypto context (zeroes all key material)
124 *
125 * @param ctx Crypto context to clear
126 */
127void ftp_crypto_reset(ftp_crypto_ctx_t *ctx);
128 
129/**
130 * @brief Derive session key from PSK and nonce
131 *
132 * Simple key derivation: rotates PSK bytes mixed with nonce
133 * to produce a unique-per-session 256-bit key.
134 *
135 * @param psk Pre-shared key (32 bytes)
136 * @param nonce Session nonce (12 bytes)
137 * @param out_key Output derived key (32 bytes)
138 */
139void ftp_crypto_derive_key(const uint8_t psk[32], const uint8_t nonce[12],
140 uint8_t out_key[32]);
141 
142#else /* !FTP_ENABLE_CRYPTO */
143 
144/* Stub context when crypto is compiled out */
145typedef struct {
146 uint8_t active; /**< Always 0 when crypto disabled */
147} ftp_crypto_ctx_t;
148 
149#endif /* FTP_ENABLE_CRYPTO */
150 
151#endif /* FTP_CRYPTO_H */
152