ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
sntrup761.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file sntrup761.h
6 * @brief Streamlined NTRU Prime sntrup761 KEM - responder (encapsulation) only.
7 *
8 * The second post-quantum KEM OpenSSH ships (alongside ML-KEM-768), used by the
9 * sntrup761x25519-sha512@openssh.com hybrid key exchange. Both KEM roles are provided:
10 * - Encapsulation (SSH server / responder): given the peer's public key, produce a ciphertext
11 * and a shared secret.
12 * - KeyGen + Decapsulation (the reverse-SSH client / initiator): generate a keypair, send the
13 * public key, then recover the shared secret from the server's ciphertext.
14 *
15 * Streamlined NTRU Prime, parameter set sntrup761 (p=761, q=4591, w=286): a lattice KEM over
16 * the ring Z_q[x]/(x^761 - x - 1). The algorithm and the byte encodings match OpenSSH's embedded
17 * sntrup761 reference (public domain; D. J. Bernstein et al.) so the ciphertext this produces
18 * decapsulates byte-for-byte on a real OpenSSH peer. Zero heap; SHA-512 via the SSH sha512 seam,
19 * randomness via ssh_rng_fill.
20 */
21
22#ifndef PROTOCORE_SNTRUP761_H
23#define PROTOCORE_SNTRUP761_H
24
25#include "protocore_config.h"
26
27#if PC_ENABLE_SSH_SNTRUP761
28
29#include <stddef.h>
30#include <stdint.h>
31
32#define PC_SNTRUP761_PK_BYTES 1158 ///< public key (Rq-encoded h)
33#define PC_SNTRUP761_SK_BYTES 1763 ///< secret key (f, 1/g, pk, rho, cache)
34#define PC_SNTRUP761_CT_BYTES 1039 ///< ciphertext (Rounded-encoded c || 32-byte Confirm)
35#define PC_SNTRUP761_SS_BYTES 32 ///< shared secret (session key)
36#define PC_SNTRUP761_SK_PK_OFFSET \
37 382 ///< the public key is embedded in sk at this offset (2*Small_bytes); the KEM initiator reconstructs
38 ///< its C_INIT and the exchange hash from sk rather than storing pk twice
39
40/**
41 * @brief sntrup761 key generation (initiator). Produces a public/secret keypair; the caller sends
42 * @p pk and holds @p sk until the peer's ciphertext arrives (then pc_sntrup761_dec).
43 */
44void pc_sntrup761_keypair(uint8_t pk[PC_SNTRUP761_PK_BYTES], uint8_t sk[PC_SNTRUP761_SK_BYTES]);
45
46/**
47 * @brief sntrup761 Encapsulation (responder). Draws a fresh short polynomial via ssh_rng_fill,
48 * encrypts it under @p pk, and derives the session key.
49 * @param pk the peer's public key (PC_SNTRUP761_PK_BYTES).
50 * @param ct out: the ciphertext (PC_SNTRUP761_CT_BYTES).
51 * @param ss out: the shared secret (PC_SNTRUP761_SS_BYTES).
52 */
53void pc_sntrup761_enc(const uint8_t pk[PC_SNTRUP761_PK_BYTES], uint8_t ct[PC_SNTRUP761_CT_BYTES],
54 uint8_t ss[PC_SNTRUP761_SS_BYTES]);
55
56/**
57 * @brief sntrup761 Decapsulation (initiator). Recovers the shared secret from the peer's ciphertext
58 * using the secret key from pc_sntrup761_keypair. Implicit-rejection (FO): on a bad
59 * ciphertext it returns a deterministic pseudo-random secret rather than failing.
60 */
61void pc_sntrup761_dec(const uint8_t sk[PC_SNTRUP761_SK_BYTES], const uint8_t ct[PC_SNTRUP761_CT_BYTES],
62 uint8_t ss[PC_SNTRUP761_SS_BYTES]);
63
64#endif // PC_ENABLE_SSH_SNTRUP761
65
66#endif // PROTOCORE_SNTRUP761_H
User-facing configuration for ProtoCore.