656 lines
23 KiB

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