You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

777 lines
29 KiB

  1. /**
  2. * A group of prime order, C++ wrapper.
  3. *
  4. * The Decaf library implements cryptographic operations on a an elliptic curve
  5. * group of prime order. It accomplishes this by using a twisted Edwards
  6. * curve (isogenous to $(iso_to)) and wiping out the cofactor.
  7. *
  8. * Most of the functions in this file run in constant time, can't fail
  9. * except for ubiquitous reasons like memory exhaustion, and contain no
  10. * data-dependend branches, timing or memory accesses. There are some
  11. * exceptions, which should be noted. Typically, decoding functions can
  12. * fail.
  13. */
  14. /** This code uses posix_memalign. */
  15. #ifndef _XOPEN_SOURCE
  16. #define _XOPEN_SOURCE 600
  17. #endif
  18. #include <stdlib.h>
  19. #include <string.h> /* for memcpy */
  20. #include <decaf/point_$(gf_bits).h>
  21. #include <decaf/ed$(gf_bits).h>
  22. #include <decaf/secure_buffer.hxx>
  23. #include <string>
  24. #include <sys/types.h>
  25. #include <limits.h>
  26. /** @cond internal */
  27. #if __cplusplus >= 201103L
  28. #define DECAF_NOEXCEPT noexcept
  29. #else
  30. #define DECAF_NOEXCEPT throw()
  31. #endif
  32. /** @endcond */
  33. namespace decaf {
  34. /**
  35. * $(iso_to)/Decaf instantiation of group.
  36. */
  37. struct $(cxx_ns) {
  38. /** The name of the curve */
  39. static inline const char *name() { return "$(name)"; }
  40. /** The name of the curve */
  41. static inline int bits() { return $(gf_bits); }
  42. /** The curve's cofactor (removed, but useful for testing) */
  43. static const int REMOVED_COFACTOR = $(cofactor);
  44. /** Residue class of field modulus: p == this mod 2*(this-1) */
  45. static const int FIELD_MODULUS_TYPE = $(modulus &~ (modulus-3));
  46. /** @cond internal */
  47. class Point;
  48. class Precomputed;
  49. /** @endcond */
  50. /**
  51. * A scalar modulo the curve order.
  52. * Supports the usual arithmetic operations, all in constant time.
  53. */
  54. class Scalar : public Serializable<Scalar> {
  55. public:
  56. /** wrapped C type */
  57. typedef $(c_ns)_scalar_t Wrapped;
  58. /** Size of a serialized element */
  59. static const size_t SER_BYTES = $(C_NS)_SCALAR_BYTES;
  60. /** access to the underlying scalar object */
  61. Wrapped s;
  62. /** @cond internal */
  63. /** Don't initialize. */
  64. inline Scalar(const NOINIT &) DECAF_NOEXCEPT {}
  65. /** @endcond */
  66. /** Set to an unsigned word */
  67. inline Scalar(uint64_t w) DECAF_NOEXCEPT { *this = w; }
  68. /** Set to a signed word */
  69. inline Scalar(int64_t w) DECAF_NOEXCEPT { *this = w; }
  70. /** Set to an unsigned word */
  71. inline Scalar(unsigned int w) DECAF_NOEXCEPT { *this = w; }
  72. /** Set to a signed word */
  73. inline Scalar(int w) DECAF_NOEXCEPT { *this = w; }
  74. /** Construct from RNG */
  75. inline explicit Scalar(Rng &rng) DECAF_NOEXCEPT {
  76. FixedArrayBuffer<SER_BYTES + 16> sb(rng);
  77. *this = sb;
  78. }
  79. /** Construct from decaf_scalar_t object. */
  80. inline Scalar(const Wrapped &t = $(c_ns)_scalar_zero) DECAF_NOEXCEPT { $(c_ns)_scalar_copy(s,t); }
  81. /** Copy constructor. */
  82. inline Scalar(const Scalar &x) DECAF_NOEXCEPT { *this = x; }
  83. /** Construct from arbitrary-length little-endian byte sequence. */
  84. inline Scalar(const Block &buffer) DECAF_NOEXCEPT { *this = buffer; }
  85. /** Serializable instance */
  86. inline size_t ser_size() const DECAF_NOEXCEPT { return SER_BYTES; }
  87. /** Serializable instance */
  88. inline void serialize_into(unsigned char *buffer) const DECAF_NOEXCEPT {
  89. $(c_ns)_scalar_encode(buffer, s);
  90. }
  91. /** Assignment. */
  92. inline Scalar& operator=(const Scalar &x) DECAF_NOEXCEPT { $(c_ns)_scalar_copy(s,x.s); return *this; }
  93. /** Assign from unsigned 64-bit integer. */
  94. inline Scalar& operator=(uint64_t w) DECAF_NOEXCEPT { $(c_ns)_scalar_set_unsigned(s,w); return *this; }
  95. /** Assign from signed int. */
  96. inline Scalar& operator=(int64_t w) DECAF_NOEXCEPT {
  97. Scalar t(-(uint64_t)INT_MIN);
  98. $(c_ns)_scalar_set_unsigned(s,(uint64_t)w - (uint64_t)INT_MIN);
  99. *this -= t;
  100. return *this;
  101. }
  102. /** Assign from unsigned int. */
  103. inline Scalar& operator=(unsigned int w) DECAF_NOEXCEPT { return *this = (uint64_t)w; }
  104. /** Assign from signed int. */
  105. inline Scalar& operator=(int w) DECAF_NOEXCEPT { return *this = (int64_t)w; }
  106. /** Destructor securely zeorizes the scalar. */
  107. inline ~Scalar() DECAF_NOEXCEPT { $(c_ns)_scalar_destroy(s); }
  108. /** Assign from arbitrary-length little-endian byte sequence in a Block. */
  109. inline Scalar &operator=(const Block &bl) DECAF_NOEXCEPT {
  110. $(c_ns)_scalar_decode_long(s,bl.data(),bl.size()); return *this;
  111. }
  112. /**
  113. * Decode from correct-length little-endian byte sequence.
  114. * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q.
  115. */
  116. static inline decaf_error_t DECAF_WARN_UNUSED decode (
  117. Scalar &sc, const FixedBlock<SER_BYTES> buffer
  118. ) DECAF_NOEXCEPT {
  119. return $(c_ns)_scalar_decode(sc.s,buffer.data());
  120. }
  121. /** Add. */
  122. inline Scalar operator+ (const Scalar &q) const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_add(r.s,s,q.s); return r; }
  123. /** Add to this. */
  124. inline Scalar &operator+=(const Scalar &q) DECAF_NOEXCEPT { $(c_ns)_scalar_add(s,s,q.s); return *this; }
  125. /** Subtract. */
  126. inline Scalar operator- (const Scalar &q) const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,s,q.s); return r; }
  127. /** Subtract from this. */
  128. inline Scalar &operator-=(const Scalar &q) DECAF_NOEXCEPT { $(c_ns)_scalar_sub(s,s,q.s); return *this; }
  129. /** Multiply */
  130. inline Scalar operator* (const Scalar &q) const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_mul(r.s,s,q.s); return r; }
  131. /** Multiply into this. */
  132. inline Scalar &operator*=(const Scalar &q) DECAF_NOEXCEPT { $(c_ns)_scalar_mul(s,s,q.s); return *this; }
  133. /** Negate */
  134. inline Scalar operator- () const DECAF_NOEXCEPT { Scalar r((NOINIT())); $(c_ns)_scalar_sub(r.s,$(c_ns)_scalar_zero,s); return r; }
  135. /** Return 1/this.
  136. * @throw CryptoException if this is 0.
  137. */
  138. inline Scalar inverse() const /*throw(CryptoException)*/ {
  139. Scalar r;
  140. if (DECAF_SUCCESS != $(c_ns)_scalar_invert(r.s,s)) {
  141. throw CryptoException();
  142. }
  143. return r;
  144. }
  145. /** Invert with Fermat's Little Theorem (slow!). If *this == 0, set r=0
  146. * and return DECAF_FAILURE. */
  147. inline decaf_error_t DECAF_WARN_UNUSED
  148. inverse_noexcept(Scalar &r) const DECAF_NOEXCEPT {
  149. return $(c_ns)_scalar_invert(r.s,s);
  150. }
  151. /** Return this/q. @throw CryptoException if q == 0. */
  152. inline Scalar operator/ (const Scalar &q) const /*throw(CryptoException)*/ { return *this * q.inverse(); }
  153. /** Set this to this/q. @throw CryptoException if q == 0. */
  154. inline Scalar &operator/=(const Scalar &q) /*throw(CryptoException)*/ { return *this *= q.inverse(); }
  155. /** Return half this scalar. Much faster than /2. */
  156. inline Scalar half() const { Scalar out; $(c_ns)_scalar_halve(out.s,s); return out; }
  157. /** Compare in constant time */
  158. inline bool operator!=(const Scalar &q) const DECAF_NOEXCEPT { return !(*this == q); }
  159. /** Compare in constant time */
  160. inline bool operator==(const Scalar &q) const DECAF_NOEXCEPT { return !!$(c_ns)_scalar_eq(s,q.s); }
  161. /** Scalarmul with scalar on left. */
  162. inline Point operator* (const Point &q) const DECAF_NOEXCEPT { return q * (*this); }
  163. /** Scalarmul-precomputed with scalar on left. */
  164. inline Point operator* (const Precomputed &q) const DECAF_NOEXCEPT { return q * (*this); }
  165. /** Direct scalar multiplication.
  166. * @throw CryptoException if the input didn't decode.
  167. */
  168. inline SecureBuffer direct_scalarmul (
  169. const FixedBlock<SER_BYTES> &in,
  170. decaf_bool_t allow_identity=DECAF_FALSE,
  171. decaf_bool_t short_circuit=DECAF_TRUE
  172. ) const /*throw(CryptoException)*/;
  173. /** Direct scalar multiplication. */
  174. inline decaf_error_t DECAF_WARN_UNUSED direct_scalarmul_noexcept(
  175. FixedBuffer<SER_BYTES> &out,
  176. const FixedBlock<SER_BYTES> &in,
  177. decaf_bool_t allow_identity=DECAF_FALSE,
  178. decaf_bool_t short_circuit=DECAF_TRUE
  179. ) const DECAF_NOEXCEPT;
  180. };
  181. /** Element of prime-order elliptic curve group. */
  182. class Point : public Serializable<Point> {
  183. public:
  184. /** Wrapped C type */
  185. typedef $(c_ns)_point_t Wrapped;
  186. /** Size of a serialized element */
  187. static const size_t SER_BYTES = $(C_NS)_SER_BYTES;
  188. /** Bytes required for hash */
  189. static const size_t HASH_BYTES = $(C_NS)_HASH_BYTES;
  190. /** Bytes required for EdDSA encoding */
  191. static const size_t EDDSA_BYTES = DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES;
  192. /** Bytes required for EdDSA encoding */
  193. static const size_t LADDER_BYTES = DECAF_X$(gf_shortname)_PUBLIC_BYTES;
  194. /** Ratio due to EdDSA encoding */
  195. static const int EDDSA_ENCODE_RATIO = $(C_NS)_EDDSA_ENCODE_RATIO;
  196. /** Ratio due to EdDSA decoding */
  197. static const int EDDSA_DECODE_RATIO = $(C_NS)_EDDSA_DECODE_RATIO;
  198. /** Ratio due to ladder decoding */
  199. static const int LADDER_ENCODE_RATIO = DECAF_X$(gf_shortname)_ENCODE_RATIO;
  200. /** Size of a steganographically-encoded curve element. If the point is random, the encoding
  201. * should look statistically close to a uniformly-random sequnece of STEG_BYTES bytes.
  202. */
  203. static const size_t STEG_BYTES = HASH_BYTES * 2;
  204. /** Number of bits in invert_elligator which are actually used. */
  205. static const unsigned int INVERT_ELLIGATOR_WHICH_BITS = $(C_NS)_INVERT_ELLIGATOR_WHICH_BITS;
  206. /** The c-level object. */
  207. Wrapped p;
  208. /** @cond internal */
  209. /** Don't initialize. */
  210. inline Point(const NOINIT &) DECAF_NOEXCEPT {}
  211. /** @endcond */
  212. /** Constructor sets to identity by default. */
  213. inline Point(const Wrapped &q = $(c_ns)_point_identity) DECAF_NOEXCEPT { $(c_ns)_point_copy(p,q); }
  214. /** Copy constructor. */
  215. inline Point(const Point &q) DECAF_NOEXCEPT { *this = q; }
  216. /** Assignment. */
  217. inline Point& operator=(const Point &q) DECAF_NOEXCEPT { $(c_ns)_point_copy(p,q.p); return *this; }
  218. /** Destructor securely zeorizes the point. */
  219. inline ~Point() DECAF_NOEXCEPT { $(c_ns)_point_destroy(p); }
  220. /** Construct from RNG */
  221. inline explicit Point(Rng &rng, bool uniform = true) DECAF_NOEXCEPT {
  222. if (uniform) {
  223. FixedArrayBuffer<2*HASH_BYTES> b(rng);
  224. set_to_hash(b);
  225. } else {
  226. FixedArrayBuffer<HASH_BYTES> b(rng);
  227. set_to_hash(b);
  228. }
  229. }
  230. /**
  231. * Initialize from a fixed-length byte string.
  232. * The all-zero string maps to the identity.
  233. *
  234. * @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
  235. * or was the identity and allow_identity was DECAF_FALSE.
  236. */
  237. inline explicit Point(const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true)
  238. /*throw(CryptoException)*/ {
  239. if (DECAF_SUCCESS != decode(buffer,allow_identity ? DECAF_TRUE : DECAF_FALSE)) {
  240. throw CryptoException();
  241. }
  242. }
  243. /**
  244. * Initialize from C++ fixed-length byte string.
  245. * The all-zero string maps to the identity.
  246. *
  247. * @retval DECAF_SUCCESS the string was successfully decoded.
  248. * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point,
  249. * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
  250. */
  251. inline decaf_error_t DECAF_WARN_UNUSED decode (
  252. const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true
  253. ) DECAF_NOEXCEPT {
  254. return $(c_ns)_point_decode(p,buffer.data(),allow_identity ? DECAF_TRUE : DECAF_FALSE);
  255. }
  256. /**
  257. * Initialize from C++ fixed-length byte string, like EdDSA.
  258. * The all-zero string maps to the identity.
  259. *
  260. * @retval DECAF_SUCCESS the string was successfully decoded.
  261. * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point.
  262. * Contents of the point are undefined.
  263. */
  264. inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_mul_by_ratio_noexcept (
  265. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer
  266. ) DECAF_NOEXCEPT {
  267. return $(c_ns)_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data());
  268. }
  269. /**
  270. * Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any
  271. * remaining cofactor information.
  272. * @throw CryptoException if the input point was invalid.
  273. */
  274. inline void decode_like_eddsa_and_mul_by_ratio(
  275. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &buffer
  276. ) /*throw(CryptoException)*/ {
  277. if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException());
  278. }
  279. /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */
  280. inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const {
  281. SecureBuffer ret(DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES);
  282. $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p);
  283. return ret;
  284. }
  285. /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */
  286. inline void mul_by_ratio_and_encode_like_eddsa(
  287. FixedBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &out
  288. ) const {
  289. $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p);
  290. }
  291. /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */
  292. inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const {
  293. SecureBuffer ret(LADDER_BYTES);
  294. $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(ret.data(),p);
  295. return ret;
  296. }
  297. /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */
  298. inline void mul_by_ratio_and_encode_like_ladder(FixedBuffer<LADDER_BYTES> &out) const {
  299. $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(out.data(),p);
  300. }
  301. /**
  302. * Map uniformly to the curve from a hash buffer.
  303. * The empty or all-zero string maps to the identity, as does the string "\\x01".
  304. * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform,
  305. * but the buffer will be zero-padded on the right.
  306. */
  307. static inline Point from_hash ( const Block &s ) DECAF_NOEXCEPT {
  308. Point p((NOINIT())); p.set_to_hash(s); return p;
  309. }
  310. /**
  311. * Map to the curve from a hash buffer.
  312. * The empty or all-zero string maps to the identity, as does the string "\\x01".
  313. * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform,
  314. * but the buffer will be zero-padded on the right.
  315. */
  316. inline void set_to_hash( const Block &s ) DECAF_NOEXCEPT {
  317. if (s.size() < HASH_BYTES) {
  318. SecureBuffer b(HASH_BYTES);
  319. memcpy(b.data(), s.data(), s.size());
  320. $(c_ns)_point_from_hash_nonuniform(p,b.data());
  321. } else if (s.size() == HASH_BYTES) {
  322. $(c_ns)_point_from_hash_nonuniform(p,s.data());
  323. } else if (s.size() < 2*HASH_BYTES) {
  324. SecureBuffer b(2*HASH_BYTES);
  325. memcpy(b.data(), s.data(), s.size());
  326. $(c_ns)_point_from_hash_uniform(p,b.data());
  327. } else {
  328. $(c_ns)_point_from_hash_uniform(p,s.data());
  329. }
  330. }
  331. /** Encode to string. The identity encodes to the all-zero string. */
  332. inline operator SecureBuffer() const {
  333. SecureBuffer buffer(SER_BYTES);
  334. $(c_ns)_point_encode(buffer.data(), p);
  335. return buffer;
  336. }
  337. /** Serializable instance */
  338. inline size_t ser_size() const DECAF_NOEXCEPT { return SER_BYTES; }
  339. /** Serializable instance */
  340. inline void serialize_into(unsigned char *buffer) const DECAF_NOEXCEPT {
  341. $(c_ns)_point_encode(buffer, p);
  342. }
  343. /** Point add. */
  344. inline Point operator+ (const Point &q) const DECAF_NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_add(r.p,p,q.p); return r; }
  345. /** Point add. */
  346. inline Point &operator+=(const Point &q) DECAF_NOEXCEPT { $(c_ns)_point_add(p,p,q.p); return *this; }
  347. /** Point subtract. */
  348. inline Point operator- (const Point &q) const DECAF_NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_sub(r.p,p,q.p); return r; }
  349. /** Point subtract. */
  350. inline Point &operator-=(const Point &q) DECAF_NOEXCEPT { $(c_ns)_point_sub(p,p,q.p); return *this; }
  351. /** Point negate. */
  352. inline Point operator- () const DECAF_NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_negate(r.p,p); return r; }
  353. /** Double the point out of place. */
  354. inline Point times_two () const DECAF_NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_double(r.p,p); return r; }
  355. /** Double the point in place. */
  356. inline Point &double_in_place() DECAF_NOEXCEPT { $(c_ns)_point_double(p,p); return *this; }
  357. /** Constant-time compare. */
  358. inline bool operator!=(const Point &q) const DECAF_NOEXCEPT { return ! $(c_ns)_point_eq(p,q.p); }
  359. /** Constant-time compare. */
  360. inline bool operator==(const Point &q) const DECAF_NOEXCEPT { return !!$(c_ns)_point_eq(p,q.p); }
  361. /** Scalar multiply. */
  362. inline Point operator* (const Scalar &s) const DECAF_NOEXCEPT { Point r((NOINIT())); $(c_ns)_point_scalarmul(r.p,p,s.s); return r; }
  363. /** Scalar multiply in place. */
  364. inline Point &operator*=(const Scalar &s) DECAF_NOEXCEPT { $(c_ns)_point_scalarmul(p,p,s.s); return *this; }
  365. /** Multiply by s.inverse(). If s=0, maps to the identity. */
  366. inline Point operator/ (const Scalar &s) const /*throw(CryptoException)*/ { return (*this) * s.inverse(); }
  367. /** Multiply by s.inverse(). If s=0, maps to the identity. */
  368. inline Point &operator/=(const Scalar &s) /*throw(CryptoException)*/ { return (*this) *= s.inverse(); }
  369. /** Validate / sanity check */
  370. inline bool validate() const DECAF_NOEXCEPT { return $(c_ns)_point_valid(p); }
  371. /** Double-scalar multiply, equivalent to q*qs + r*rs but faster. */
  372. static inline Point double_scalarmul (
  373. const Point &q, const Scalar &qs, const Point &r, const Scalar &rs
  374. ) DECAF_NOEXCEPT {
  375. Point p((NOINIT())); $(c_ns)_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
  376. }
  377. /** Dual-scalar multiply, equivalent to this*r1, this*r2 but faster. */
  378. inline void dual_scalarmul (
  379. Point &q1, Point &q2, const Scalar &r1, const Scalar &r2
  380. ) const DECAF_NOEXCEPT {
  381. $(c_ns)_point_dual_scalarmul(q1.p,q2.p,p,r1.s,r2.s);
  382. }
  383. /**
  384. * Double-scalar multiply, equivalent to q*qs + r*rs but faster.
  385. * For those who like their scalars before the point.
  386. */
  387. static inline Point double_scalarmul (
  388. const Scalar &qs, const Point &q, const Scalar &rs, const Point &r
  389. ) DECAF_NOEXCEPT {
  390. return double_scalarmul(q,qs,r,rs);
  391. }
  392. /**
  393. * Double-scalar multiply: this point by the first scalar and base by the second scalar.
  394. * @warning This function takes variable time, and may leak the scalars (or points, but currently
  395. * it doesn't).
  396. */
  397. inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) DECAF_NOEXCEPT {
  398. Point r((NOINIT())); $(c_ns)_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r;
  399. }
  400. /** Return a point equal to *this, whose internal data is rotated by a torsion element. */
  401. inline Point debugging_torque() const DECAF_NOEXCEPT {
  402. Point q;
  403. $(c_ns)_point_debugging_torque(q.p,p);
  404. return q;
  405. }
  406. /** Return a point equal to *this, whose internal data has a modified representation. */
  407. inline Point debugging_pscale(const FixedBlock<SER_BYTES> factor) const DECAF_NOEXCEPT {
  408. Point q;
  409. $(c_ns)_point_debugging_pscale(q.p,p,factor.data());
  410. return q;
  411. }
  412. /** Return a point equal to *this, whose internal data has a randomized representation. */
  413. inline Point debugging_pscale(Rng &r) const DECAF_NOEXCEPT {
  414. FixedArrayBuffer<SER_BYTES> sb(r);
  415. return debugging_pscale(sb);
  416. }
  417. /**
  418. * Modify buffer so that Point::from_hash(Buffer) == *this, and return DECAF_SUCCESS;
  419. * or leave buf unmodified and return DECAF_FAILURE.
  420. */
  421. inline decaf_error_t invert_elligator (
  422. Buffer buf, uint32_t hint
  423. ) const DECAF_NOEXCEPT {
  424. unsigned char buf2[2*HASH_BYTES];
  425. memset(buf2,0,sizeof(buf2));
  426. memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
  427. decaf_bool_t ret;
  428. if (buf.size() > HASH_BYTES) {
  429. ret = decaf_successful($(c_ns)_invert_elligator_uniform(buf2, p, hint));
  430. } else {
  431. ret = decaf_successful($(c_ns)_invert_elligator_nonuniform(buf2, p, hint));
  432. }
  433. if (buf.size() < HASH_BYTES) {
  434. ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size());
  435. }
  436. for (size_t i=0; i<buf.size() && i<HASH_BYTES; i++) {
  437. buf[i] = (buf[i] & ~ret) | (buf2[i] &ret);
  438. }
  439. decaf_bzero(buf2,sizeof(buf2));
  440. return decaf_succeed_if(ret);
  441. }
  442. /** Steganographically encode this */
  443. inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const /*throw(std::bad_alloc, LengthException)*/ {
  444. if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException();
  445. SecureBuffer out(STEG_BYTES);
  446. decaf_error_t done;
  447. do {
  448. rng.read(Buffer(out).slice(HASH_BYTES-4,STEG_BYTES-HASH_BYTES+1));
  449. uint32_t hint = 0;
  450. for (int i=0; i<4; i++) { hint |= uint32_t(out[HASH_BYTES-4+i])<<(8*i); }
  451. done = invert_elligator(out, hint);
  452. } while (!decaf_successful(done));
  453. return out;
  454. }
  455. /** Return the base point of the curve. */
  456. static inline const Point base() DECAF_NOEXCEPT { return Point($(c_ns)_point_base); }
  457. /** Return the identity point of the curve. */
  458. static inline const Point identity() DECAF_NOEXCEPT { return Point($(c_ns)_point_identity); }
  459. };
  460. /**
  461. * Precomputed table of points.
  462. * Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is.
  463. * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to
  464. * stack-allocate a 15kiB object anyway.
  465. */
  466. /** @cond internal */
  467. typedef $(c_ns)_precomputed_s Precomputed_U;
  468. /** @endcond */
  469. class Precomputed
  470. /** @cond internal */
  471. : protected OwnedOrUnowned<Precomputed,Precomputed_U>
  472. /** @endcond */
  473. {
  474. public:
  475. /** Destructor securely zeorizes the memory. */
  476. inline ~Precomputed() DECAF_NOEXCEPT { clear(); }
  477. /**
  478. * Initialize from underlying type, declared as a reference to prevent
  479. * it from being called with 0, thereby breaking override.
  480. *
  481. * The underlying object must remain valid throughout the lifetime of this one.
  482. *
  483. * By default, initializes to the table for the base point.
  484. *
  485. * @warning The empty initializer makes this equal to base, unlike the empty
  486. * initializer for points which makes this equal to the identity.
  487. */
  488. inline Precomputed (
  489. const Precomputed_U &yours = *$(c_ns)_precomputed_base
  490. ) DECAF_NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>(yours) {}
  491. #if __cplusplus >= 201103L
  492. /** Move-assign operator */
  493. inline Precomputed &operator=(Precomputed &&it) DECAF_NOEXCEPT {
  494. OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it);
  495. return *this;
  496. }
  497. /** Move constructor */
  498. inline Precomputed(Precomputed &&it) DECAF_NOEXCEPT : OwnedOrUnowned<Precomputed,Precomputed_U>() {
  499. *this = it;
  500. }
  501. /** Undelete copy operator */
  502. inline Precomputed &operator=(const Precomputed &it) DECAF_NOEXCEPT {
  503. OwnedOrUnowned<Precomputed,Precomputed_U>::operator= (it);
  504. return *this;
  505. }
  506. #endif
  507. /**
  508. * Initilaize from point. Must allocate memory, and may throw.
  509. */
  510. inline Precomputed &operator=(const Point &it) /*throw(std::bad_alloc)*/ {
  511. alloc();
  512. $(c_ns)_precompute(ours.mine,it.p);
  513. return *this;
  514. }
  515. /**
  516. * Copy constructor.
  517. */
  518. inline Precomputed(const Precomputed &it) /*throw(std::bad_alloc)*/
  519. : OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; }
  520. /**
  521. * Constructor which initializes from point.
  522. */
  523. inline explicit Precomputed(const Point &it) /*throw(std::bad_alloc)*/
  524. : OwnedOrUnowned<Precomputed,Precomputed_U>() { *this = it; }
  525. /** Fixed base scalarmul. */
  526. inline Point operator* (const Scalar &s) const DECAF_NOEXCEPT { Point r; $(c_ns)_precomputed_scalarmul(r.p,get(),s.s); return r; }
  527. /** Multiply by s.inverse(). If s=0, maps to the identity. */
  528. inline Point operator/ (const Scalar &s) const /*throw(CryptoException)*/ { return (*this) * s.inverse(); }
  529. /** Return the table for the base point. */
  530. static inline const Precomputed base() DECAF_NOEXCEPT { return Precomputed(); }
  531. public:
  532. /** @cond internal */
  533. friend class OwnedOrUnowned<Precomputed,Precomputed_U>;
  534. static inline size_t size() DECAF_NOEXCEPT { return $(c_ns)_sizeof_precomputed_s; }
  535. static inline size_t alignment() DECAF_NOEXCEPT { return $(c_ns)_alignof_precomputed_s; }
  536. static inline const Precomputed_U * default_value() DECAF_NOEXCEPT { return $(c_ns)_precomputed_base; }
  537. /** @endcond */
  538. };
  539. /** X-only Diffie-Hellman ladder functions */
  540. struct DhLadder {
  541. public:
  542. /** Bytes in an X$(gf_shortname) public key. */
  543. static const size_t PUBLIC_BYTES = DECAF_X$(gf_shortname)_PUBLIC_BYTES;
  544. /** Bytes in an X$(gf_shortname) private key. */
  545. static const size_t PRIVATE_BYTES = DECAF_X$(gf_shortname)_PRIVATE_BYTES;
  546. /** Base point for a scalar multiplication. */
  547. static const FixedBlock<PUBLIC_BYTES> base_point() DECAF_NOEXCEPT {
  548. return FixedBlock<PUBLIC_BYTES>(decaf_x$(gf_shortname)_base_point);
  549. }
  550. /** Calculate and return a shared secret with public key. */
  551. static inline SecureBuffer shared_secret(
  552. const FixedBlock<PUBLIC_BYTES> &pk,
  553. const FixedBlock<PRIVATE_BYTES> &scalar
  554. ) /*throw(std::bad_alloc,CryptoException)*/ {
  555. SecureBuffer out(PUBLIC_BYTES);
  556. if (DECAF_SUCCESS != decaf_x$(gf_shortname)(out.data(), pk.data(), scalar.data())) {
  557. throw CryptoException();
  558. }
  559. return out;
  560. }
  561. /** Calculate and write into out a shared secret with public key, noexcept version. */
  562. static inline decaf_error_t DECAF_WARN_UNUSED
  563. shared_secret_noexcept (
  564. FixedBuffer<PUBLIC_BYTES> &out,
  565. const FixedBlock<PUBLIC_BYTES> &pk,
  566. const FixedBlock<PRIVATE_BYTES> &scalar
  567. ) DECAF_NOEXCEPT {
  568. return decaf_x$(gf_shortname)(out.data(), pk.data(), scalar.data());
  569. }
  570. /** Calculate and return a public key; equivalent to shared_secret(base_point(),scalar)
  571. * but possibly faster.
  572. * @deprecated Renamed to derive_public_key.
  573. */
  574. static inline SecureBuffer DECAF_DEPRECATED("Renamed to derive_public_key")
  575. generate_key(
  576. const FixedBlock<PRIVATE_BYTES> &scalar
  577. ) /*throw(std::bad_alloc)*/ {
  578. SecureBuffer out(PUBLIC_BYTES);
  579. decaf_x$(gf_shortname)_derive_public_key(out.data(), scalar.data());
  580. return out;
  581. }
  582. /** Calculate and return a public key; equivalent to shared_secret(base_point(),scalar)
  583. * but possibly faster.
  584. */
  585. static inline SecureBuffer derive_public_key(
  586. const FixedBlock<PRIVATE_BYTES> &scalar
  587. ) /*throw(std::bad_alloc)*/ {
  588. SecureBuffer out(PUBLIC_BYTES);
  589. decaf_x$(gf_shortname)_derive_public_key(out.data(), scalar.data());
  590. return out;
  591. }
  592. /** Calculate and return a public key into a fixed buffer;
  593. * equivalent to shared_secret(base_point(),scalar) but possibly faster.
  594. */
  595. static inline void
  596. derive_public_key_noexcept (
  597. FixedBuffer<PUBLIC_BYTES> &out,
  598. const FixedBlock<PRIVATE_BYTES> &scalar
  599. ) DECAF_NOEXCEPT {
  600. decaf_x$(gf_shortname)_derive_public_key(out.data(), scalar.data());
  601. }
  602. /** Calculate and return a public key into a fixed buffer;
  603. * equivalent to shared_secret(base_point(),scalar) but possibly faster.
  604. * @deprecated Renamed to derive_public_key_noexcept.
  605. */
  606. static inline void
  607. DECAF_DEPRECATED("Renamed to derive_public_key_noexcept")
  608. generate_key_noexcept (
  609. FixedBuffer<PUBLIC_BYTES> &out,
  610. const FixedBlock<PRIVATE_BYTES> &scalar
  611. ) DECAF_NOEXCEPT {
  612. decaf_x$(gf_shortname)_derive_public_key(out.data(), scalar.data());
  613. }
  614. };
  615. }; /* struct $(cxx_ns) */
  616. /** @cond internal */
  617. inline SecureBuffer $(cxx_ns)::Scalar::direct_scalarmul (
  618. const FixedBlock<$(cxx_ns)::Point::SER_BYTES> &in,
  619. decaf_bool_t allow_identity,
  620. decaf_bool_t short_circuit
  621. ) const /*throw(CryptoException)*/ {
  622. SecureBuffer out($(cxx_ns)::Point::SER_BYTES);
  623. if (DECAF_SUCCESS !=
  624. $(c_ns)_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit)
  625. ) {
  626. throw CryptoException();
  627. }
  628. return out;
  629. }
  630. inline decaf_error_t $(cxx_ns)::Scalar::direct_scalarmul_noexcept (
  631. FixedBuffer<$(cxx_ns)::Point::SER_BYTES> &out,
  632. const FixedBlock<$(cxx_ns)::Point::SER_BYTES> &in,
  633. decaf_bool_t allow_identity,
  634. decaf_bool_t short_circuit
  635. ) const DECAF_NOEXCEPT {
  636. return $(c_ns)_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit);
  637. }
  638. /** @endcond */
  639. $("/** Alternative name for %s, for backwards compatibility */\ntypedef %s %s;\n" % (cxx_ns,cxx_ns,altname) if altname else "")
  640. #undef DECAF_NOEXCEPT
  641. } /* namespace decaf */