23#ifndef DETERMINISTICESPASYNCWEBSERVER_SSH_FE25519_H
24#define DETERMINISTICESPASYNCWEBSERVER_SSH_FE25519_H
34#if defined(ARDUINO) && defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_IDF_TARGET_ESP32S3
35#define DETWS_FE25519_MPI_HW 1
38#ifdef DETWS_FE25519_MPI_HW
40#include "soc/hwcrypto_reg.h"
45 void esp_mpi_enable_hardware_hw_op(
void);
46 void esp_mpi_disable_hardware_hw_op(
void);
49#define SSH_RSA_REG(a) (*(volatile uint32_t *)(a))
52typedef uint32_t fe[8];
57static const uint32_t FE_MOD_MPRIME = 0x286bca1bu;
58static const uint32_t FE_MOD_P[8] = {0xffffffedu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
59 0xffffffffu, 0xffffffffu, 0xffffffffu, 0x7fffffffu};
60static const uint32_t FE_MOD_R2[8] = {0x000005a4u, 0, 0, 0, 0, 0, 0, 0};
63static inline void ssh_fe_hw_enable(
void)
65 esp_mpi_enable_hardware_hw_op();
66 SSH_RSA_REG(RSA_INTERRUPT_REG) = 0;
68static inline void ssh_fe_hw_disable(
void)
70 esp_mpi_disable_hardware_hw_op();
74static inline void fe_mul(fe z,
const fe x,
const fe y)
76 volatile uint32_t *M = (
volatile uint32_t *)RSA_MEM_M_BLOCK_BASE;
77 volatile uint32_t *X = (
volatile uint32_t *)RSA_MEM_X_BLOCK_BASE;
78 volatile uint32_t *Y = (
volatile uint32_t *)RSA_MEM_Y_BLOCK_BASE;
79 volatile uint32_t *Z = (
volatile uint32_t *)RSA_MEM_Z_BLOCK_BASE;
80 SSH_RSA_REG(RSA_LENGTH_REG) = 8 - 1;
81 SSH_RSA_REG(RSA_M_DASH_REG) = FE_MOD_MPRIME;
82 for (
int i = 0; i < 8; i++)
89 SSH_RSA_REG(RSA_CLEAR_INTERRUPT_REG) = 1;
90 SSH_RSA_REG(RSA_MOD_MULT_START_REG) = 1;
91 while (SSH_RSA_REG(RSA_QUERY_INTERRUPT_REG) == 0)
93 SSH_RSA_REG(RSA_CLEAR_INTERRUPT_REG) = 1;
94 for (
int i = 0; i < 8; i++)
97static inline void fe_sq(fe o,
const fe x)
102static inline void fe_copy(fe o,
const fe a)
104 for (
int i = 0; i < 8; i++)
107static inline void fe_0(fe o)
109 for (
int i = 0; i < 8; i++)
112static inline void fe_1(fe o)
115 for (
int i = 1; i < 8; i++)
119static inline void fe_reduce_once(fe o)
123 for (
int i = 0; i < 8; i++)
125 b += (int64_t)o[i] - (int64_t)FE_MOD_P[i];
129 uint32_t keep = (uint32_t)b;
130 for (
int i = 0; i < 8; i++)
131 o[i] = (o[i] & keep) | (t[i] & ~keep);
133static inline void fe_add(fe o,
const fe x,
const fe y)
136 for (
int i = 0; i < 8; i++)
138 c += (uint64_t)x[i] + y[i];
144static inline void fe_sub(fe o,
const fe x,
const fe y)
148 for (
int i = 0; i < 8; i++)
150 b += (int64_t)x[i] - (int64_t)y[i];
154 uint32_t borrow = (uint32_t)b;
156 for (
int i = 0; i < 8; i++)
158 c += (uint64_t)t[i] + (FE_MOD_P[i] & borrow);
163static inline void fe_cswap(fe x, fe y, uint32_t swap)
165 uint32_t mask = (uint32_t)(-(int32_t)swap);
166 for (
int i = 0; i < 8; i++)
168 uint32_t t = mask & (x[i] ^ y[i]);
173static inline void fe_frombytes(fe o,
const uint8_t b[32])
175 for (
int i = 0; i < 8; i++)
176 o[i] = (uint32_t)b[4 * i] | ((uint32_t)b[4 * i + 1] << 8) | ((uint32_t)b[4 * i + 2] << 16) |
177 ((uint32_t)b[4 * i + 3] << 24);
181static inline void fe_tobytes(uint8_t b[32],
const fe a)
186 for (
int i = 0; i < 8; i++)
188 b[4 * i] = (uint8_t)t[i];
189 b[4 * i + 1] = (uint8_t)(t[i] >> 8);
190 b[4 * i + 2] = (uint8_t)(t[i] >> 16);
191 b[4 * i + 3] = (uint8_t)(t[i] >> 24);
195static inline void fe_invert(fe o,
const fe a)
199 for (
int i = 253; i >= 0; i--)
202 if (i != 2 && i != 4)
208static inline void fe_pow2523(fe o,
const fe a)
212 for (
int i = 250; i >= 0; i--)
221static inline int fe_parity(
const fe a)
228static inline int fe_neq(
const fe a,
const fe b)
235 for (
int i = 0; i < 32; i++)
236 diff |= (
unsigned)(c[i] ^ d[i]);
237 return (
int)((1 & ((diff - 1) >> 8)) - 1);