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.
 
 
 
 
 

593 lines
22 KiB

  1. /**
  2. * @file decaf_255.hxx
  3. * @author Mike Hamburg
  4. *
  5. * @copyright
  6. * Copyright (c) 2015 Cryptography Research, Inc. \n
  7. * Released under the MIT License. See LICENSE.txt for license information.
  8. *
  9. * @brief A group of prime order p, C++ wrapper.
  10. *
  11. * The Decaf library implements cryptographic operations on a an elliptic curve
  12. * group of prime order p. It accomplishes this by using a twisted Edwards
  13. * curve (isogenous to Ed255-Goldilocks) and wiping out the cofactor.
  14. *
  15. * The formulas are all complete and have no special cases, except that
  16. * decaf_255_decode can fail because not every sequence of bytes is a valid group
  17. * element.
  18. *
  19. * The formulas contain no data-dependent branches, timing or memory accesses,
  20. * except for decaf_255_base_double_scalarmul_non_secret.
  21. */
  22. #ifndef __DECAF_255_HXX__
  23. #define __DECAF_255_HXX__ 1
  24. /** This code uses posix_memalign. */
  25. #define _XOPEN_SOURCE 600
  26. #include <stdlib.h>
  27. #include <string.h> /* for memcpy */
  28. #include "decaf.h"
  29. #include "secure_buffer.hxx"
  30. #include <string>
  31. #include <sys/types.h>
  32. #include <limits.h>
  33. /* TODO: attribute nonnull */
  34. /** @cond internal */
  35. #if __cplusplus >= 201103L
  36. #define NOEXCEPT noexcept
  37. #else
  38. #define NOEXCEPT throw()
  39. #endif
  40. /** @endcond */
  41. namespace decaf {
  42. /**
  43. * @brief Ed255-Goldilocks/Decaf instantiation of group.
  44. */
  45. struct Ed255 {
  46. /** @cond internal */
  47. class Point;
  48. class Precomputed;
  49. /** @endcond */
  50. /**
  51. * @brief A scalar modulo the curve order.
  52. * Supports the usual arithmetic operations, all in constant time.
  53. */
  54. class Scalar {
  55. public:
  56. /** @brief Size of a serialized element */
  57. static const size_t SER_BYTES = DECAF_255_SCALAR_BYTES;
  58. /** @brief access to the underlying scalar object */
  59. decaf_255_scalar_t s;
  60. /** @brief Don't initialize. */
  61. inline Scalar(const NOINIT &) NOEXCEPT {}
  62. /** @brief Set to an unsigned word */
  63. inline Scalar(const decaf_word_t w) NOEXCEPT { *this = w; }
  64. /** @brief Set to a signed word */
  65. inline Scalar(const int w) NOEXCEPT { *this = w; }
  66. /** @brief Construct from RNG */
  67. inline explicit Scalar(Rng &rng) NOEXCEPT {
  68. StackBuffer<SER_BYTES> sb(rng);
  69. *this = sb;
  70. }
  71. /** @brief Construct from decaf_scalar_t object. */
  72. inline Scalar(const decaf_255_scalar_t &t = decaf_255_scalar_zero) NOEXCEPT { decaf_255_scalar_copy(s,t); }
  73. /** @brief Copy constructor. */
  74. inline Scalar(const Scalar &x) NOEXCEPT { *this = x; }
  75. /** @brief Construct from arbitrary-length little-endian byte sequence. */
  76. inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; }
  77. /** @brief Assignment. */
  78. inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_255_scalar_copy(s,x.s); return *this; }
  79. /** @brief Assign from unsigned word. */
  80. inline Scalar& operator=(decaf_word_t w) NOEXCEPT { decaf_255_scalar_set_unsigned(s,w); return *this; }
  81. /** @brief Assign from signed int. */
  82. inline Scalar& operator=(int w) NOEXCEPT {
  83. Scalar t(-(decaf_word_t)INT_MIN);
  84. decaf_255_scalar_set_unsigned(s,(decaf_word_t)w - (decaf_word_t)INT_MIN);
  85. *this -= t;
  86. return *this;
  87. }
  88. /** Destructor securely zeorizes the scalar. */
  89. inline ~Scalar() NOEXCEPT { decaf_255_scalar_destroy(s); }
  90. /** @brief Assign from arbitrary-length little-endian byte sequence in a Block. */
  91. inline Scalar &operator=(const Block &bl) NOEXCEPT {
  92. decaf_255_scalar_decode_long(s,bl.data(),bl.size()); return *this;
  93. }
  94. /**
  95. * @brief Decode from correct-length little-endian byte sequence.
  96. * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q.
  97. */
  98. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  99. Scalar &sc, const unsigned char buffer[SER_BYTES]
  100. ) NOEXCEPT {
  101. return decaf_255_scalar_decode(sc.s,buffer);
  102. }
  103. /** @brief Decode from correct-length little-endian byte sequence in C++ string. */
  104. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  105. Scalar &sc, const Block &buffer
  106. ) NOEXCEPT {
  107. if (buffer.size() != SER_BYTES) return DECAF_FAILURE;
  108. return decaf_255_scalar_decode(sc.s,buffer);
  109. }
  110. /** @brief Encode to fixed-length string */
  111. inline operator SecureBuffer() const NOEXCEPT {
  112. SecureBuffer buf(SER_BYTES); decaf_255_scalar_encode(buf,s); return buf;
  113. }
  114. /** @brief Encode to fixed-length buffer */
  115. inline void encode(unsigned char buffer[SER_BYTES]) const NOEXCEPT{
  116. decaf_255_scalar_encode(buffer, s);
  117. }
  118. /** Add. */
  119. inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_add(r.s,s,q.s); return r; }
  120. /** Add to this. */
  121. inline Scalar &operator+=(const Scalar &q) NOEXCEPT { decaf_255_scalar_add(s,s,q.s); return *this; }
  122. /** Subtract. */
  123. inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,s,q.s); return r; }
  124. /** Subtract from this. */
  125. inline Scalar &operator-=(const Scalar &q) NOEXCEPT { decaf_255_scalar_sub(s,s,q.s); return *this; }
  126. /** Multiply */
  127. inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_mul(r.s,s,q.s); return r; }
  128. /** Multiply into this. */
  129. inline Scalar &operator*=(const Scalar &q) NOEXCEPT { decaf_255_scalar_mul(s,s,q.s); return *this; }
  130. /** Negate */
  131. inline Scalar operator- () const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_sub(r.s,decaf_255_scalar_zero,s); return r; }
  132. /** @brief Invert with Fermat's Little Theorem (slow!). If *this == 0, return 0. */
  133. inline Scalar inverse() const NOEXCEPT { Scalar r; decaf_255_scalar_invert(r.s,s); return r; }
  134. /** @brief Divide by inverting q. If q == 0, return 0. */
  135. inline Scalar operator/ (const Scalar &q) const NOEXCEPT { return *this * q.inverse(); }
  136. /** @brief Divide by inverting q. If q == 0, return 0. */
  137. inline Scalar &operator/=(const Scalar &q) NOEXCEPT { return *this *= q.inverse(); }
  138. /** @brief Compare in constant time */
  139. inline bool operator!=(const Scalar &q) const NOEXCEPT { return !(*this == q); }
  140. /** @brief Compare in constant time */
  141. inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_255_scalar_eq(s,q.s); }
  142. /** @brief Scalarmul with scalar on left. */
  143. inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); }
  144. /** @brief Scalarmul-precomputed with scalar on left. */
  145. inline Point operator* (const Precomputed &q) const NOEXCEPT { return q * (*this); }
  146. /** @brief Direct scalar multiplication. */
  147. inline SecureBuffer direct_scalarmul(
  148. const Block &in,
  149. decaf_bool_t allow_identity=DECAF_FALSE,
  150. decaf_bool_t short_circuit=DECAF_TRUE
  151. ) const throw(CryptoException) {
  152. SecureBuffer out(/*FIXME Point::*/SER_BYTES);
  153. if (!decaf_255_direct_scalarmul(out, in.data(), s, allow_identity, short_circuit))
  154. throw CryptoException();
  155. return out;
  156. }
  157. };
  158. /**
  159. * @brief Element of prime-order group.
  160. */
  161. class Point {
  162. public:
  163. /** @brief Size of a serialized element */
  164. static const size_t SER_BYTES = DECAF_255_SER_BYTES;
  165. /** @brief Size of a stegged element */
  166. static const size_t STEG_BYTES = DECAF_255_SER_BYTES + 8;
  167. /** @brief Bytes required for hash */
  168. static const size_t HASH_BYTES = DECAF_255_SER_BYTES;
  169. /** The c-level object. */
  170. decaf_255_point_t p;
  171. /** @brief Don't initialize. */
  172. inline Point(const NOINIT &) NOEXCEPT {}
  173. /** @brief Constructor sets to identity by default. */
  174. inline Point(const decaf_255_point_t &q = decaf_255_point_identity) NOEXCEPT { decaf_255_point_copy(p,q); }
  175. /** @brief Copy constructor. */
  176. inline Point(const Point &q) NOEXCEPT { *this = q; }
  177. /** @brief Assignment. */
  178. inline Point& operator=(const Point &q) NOEXCEPT { decaf_255_point_copy(p,q.p); return *this; }
  179. /** @brief Destructor securely zeorizes the point. */
  180. inline ~Point() NOEXCEPT { decaf_255_point_destroy(p); }
  181. /** @brief Construct from RNG */
  182. inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT {
  183. if (uniform) {
  184. StackBuffer<2*HASH_BYTES> b(rng);
  185. set_to_hash(b);
  186. } else {
  187. StackBuffer<HASH_BYTES> b(rng);
  188. set_to_hash(b);
  189. }
  190. }
  191. /**
  192. * @brief Initialize from C++ fixed-length byte string.
  193. * The all-zero string maps to the identity.
  194. *
  195. * @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
  196. * or was the identity and allow_identity was DECAF_FALSE.
  197. */
  198. inline explicit Point(const Block &s, decaf_bool_t allow_identity=DECAF_TRUE) throw(CryptoException) {
  199. if (!decode(*this,s,allow_identity)) throw CryptoException();
  200. }
  201. /**
  202. * @brief Initialize from C fixed-length byte string.
  203. * The all-zero string maps to the identity.
  204. *
  205. * @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
  206. * or was the identity and allow_identity was DECAF_FALSE.
  207. */
  208. inline explicit Point(const unsigned char buffer[SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE)
  209. throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
  210. /**
  211. * @brief Initialize from C fixed-length byte string.
  212. * The all-zero string maps to the identity.
  213. *
  214. * @retval DECAF_SUCCESS the string was successfully decoded.
  215. * @return DECAF_FAILURE the string wasn't the encoding of a point, or was the identity
  216. * and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
  217. */
  218. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  219. Point &p, const unsigned char buffer[SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE
  220. ) NOEXCEPT {
  221. return decaf_255_point_decode(p.p,buffer,allow_identity);
  222. }
  223. /**
  224. * @brief Initialize from C++ fixed-length byte string.
  225. * The all-zero string maps to the identity.
  226. *
  227. * @retval DECAF_SUCCESS the string was successfully decoded.
  228. * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point,
  229. * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
  230. */
  231. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  232. Point &p, const Block &buffer, decaf_bool_t allow_identity=DECAF_TRUE
  233. ) NOEXCEPT {
  234. if (buffer.size() != SER_BYTES) return DECAF_FAILURE;
  235. return decaf_255_point_decode(p.p,buffer.data(),allow_identity);
  236. }
  237. /**
  238. * @brief Map uniformly to the curve from a hash buffer.
  239. * The empty or all-zero string maps to the identity, as does the string "\x01".
  240. * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform,
  241. * but the buffer will be zero-padded on the right.
  242. */
  243. static inline Point from_hash ( const Block &s ) NOEXCEPT {
  244. Point p((NOINIT())); p.set_to_hash(s); return p;
  245. }
  246. /**
  247. * @brief Map to the curve from a hash buffer.
  248. * The empty or all-zero string maps to the identity, as does the string "\x01".
  249. * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform,
  250. * but the buffer will be zero-padded on the right.
  251. */
  252. inline void set_to_hash( const Block &s ) NOEXCEPT {
  253. if (s.size() < HASH_BYTES) {
  254. SecureBuffer b(HASH_BYTES);
  255. memcpy(b.data(), s.data(), s.size());
  256. decaf_255_point_from_hash_nonuniform(p,b);
  257. } else if (s.size() == HASH_BYTES) {
  258. decaf_255_point_from_hash_nonuniform(p,s);
  259. } else if (s.size() < 2*HASH_BYTES) {
  260. SecureBuffer b(2*HASH_BYTES);
  261. memcpy(b.data(), s.data(), s.size());
  262. decaf_255_point_from_hash_uniform(p,b);
  263. } else {
  264. decaf_255_point_from_hash_uniform(p,s);
  265. }
  266. }
  267. /**
  268. * @brief Encode to string. The identity encodes to the all-zero string.
  269. */
  270. inline operator SecureBuffer() const NOEXCEPT {
  271. SecureBuffer buffer(SER_BYTES);
  272. decaf_255_point_encode(buffer, p);
  273. return buffer;
  274. }
  275. /**
  276. * @brief Encode to a C buffer. The identity encodes to all zeros.
  277. */
  278. inline void encode(unsigned char buffer[SER_BYTES]) const NOEXCEPT{
  279. decaf_255_point_encode(buffer, p);
  280. }
  281. /** @brief Point add. */
  282. inline Point operator+ (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_add(r.p,p,q.p); return r; }
  283. /** @brief Point add. */
  284. inline Point &operator+=(const Point &q) NOEXCEPT { decaf_255_point_add(p,p,q.p); return *this; }
  285. /** @brief Point subtract. */
  286. inline Point operator- (const Point &q) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_sub(r.p,p,q.p); return r; }
  287. /** @brief Point subtract. */
  288. inline Point &operator-=(const Point &q) NOEXCEPT { decaf_255_point_sub(p,p,q.p); return *this; }
  289. /** @brief Point negate. */
  290. inline Point operator- () const NOEXCEPT { Point r((NOINIT())); decaf_255_point_negate(r.p,p); return r; }
  291. /** @brief Double the point out of place. */
  292. inline Point times_two () const NOEXCEPT { Point r((NOINIT())); decaf_255_point_double(r.p,p); return r; }
  293. /** @brief Double the point in place. */
  294. inline Point &double_in_place() NOEXCEPT { decaf_255_point_double(p,p); return *this; }
  295. /** @brief Constant-time compare. */
  296. inline bool operator!=(const Point &q) const NOEXCEPT { return ! decaf_255_point_eq(p,q.p); }
  297. /** @brief Constant-time compare. */
  298. inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_255_point_eq(p,q.p); }
  299. /** @brief Scalar multiply. */
  300. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r((NOINIT())); decaf_255_point_scalarmul(r.p,p,s.s); return r; }
  301. /** @brief Scalar multiply in place. */
  302. inline Point &operator*=(const Scalar &s) NOEXCEPT { decaf_255_point_scalarmul(p,p,s.s); return *this; }
  303. /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
  304. inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
  305. /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
  306. inline Point &operator/=(const Scalar &s) NOEXCEPT { return (*this) *= s.inverse(); }
  307. /** @brief Validate / sanity check */
  308. inline bool validate() const NOEXCEPT { return !!decaf_255_point_valid(p); }
  309. /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */
  310. static inline Point double_scalarmul (
  311. const Point &q, const Scalar &qs, const Point &r, const Scalar &rs
  312. ) NOEXCEPT {
  313. Point p((NOINIT())); decaf_255_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
  314. }
  315. /**
  316. * @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster.
  317. * For those who like their scalars before the point.
  318. */
  319. static inline Point double_scalarmul (
  320. const Scalar &qs, const Point &q, const Scalar &rs, const Point &r
  321. ) NOEXCEPT {
  322. Point p((NOINIT())); decaf_255_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
  323. }
  324. /**
  325. * @brief Double-scalar multiply: this point by the first scalar and base by the second scalar.
  326. * @warning This function takes variable time, and may leak the scalars (or points, but currently
  327. * it doesn't).
  328. */
  329. inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) NOEXCEPT {
  330. Point r((NOINIT())); decaf_255_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r;
  331. }
  332. /** @brief Return a point equal to *this, whose internal data is rotated by a torsion element. */
  333. inline Point debugging_torque() const NOEXCEPT {
  334. Point q;
  335. decaf_255_point_debugging_torque(q.p,p);
  336. return q;
  337. }
  338. /** @brief Return a point equal to *this, whose internal data has a modified representation. */
  339. inline Point debugging_pscale(const uint8_t factor[/*SER_BYTES*/]) const NOEXCEPT {
  340. Point q;
  341. decaf_255_point_debugging_pscale(q.p,p,factor);
  342. return q;
  343. }
  344. /** @brief Return a point equal to *this, whose internal data has a randomized representation. */
  345. inline Point debugging_pscale(Rng &r) const NOEXCEPT {
  346. StackBuffer<SER_BYTES> sb(r);
  347. return debugging_pscale(sb);
  348. }
  349. /**
  350. * Modify buffer so that Point::from_hash(Buffer) == *this, and return true;
  351. * or leave buf unmodified and return false.
  352. */
  353. inline bool invert_elligator (
  354. Buffer &buf, uint16_t hint
  355. ) const NOEXCEPT {
  356. unsigned char buf2[2*HASH_BYTES];
  357. memset(buf2,0,sizeof(buf2));
  358. memcpy(buf2,buf,(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
  359. decaf_bool_t ret;
  360. if (buf.size() > HASH_BYTES) {
  361. ret = decaf_255_invert_elligator_uniform(buf2, p, hint);
  362. } else {
  363. ret = decaf_255_invert_elligator_nonuniform(buf2, p, hint);
  364. }
  365. if (buf.size() < HASH_BYTES) {
  366. ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size());
  367. }
  368. if (ret) {
  369. /* TODO: make this constant time?? */
  370. memcpy(buf,buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
  371. }
  372. decaf_bzero(buf2,sizeof(buf2));
  373. return !!ret;
  374. }
  375. /** @brief Steganographically encode this */
  376. inline SecureBuffer steg_encode(Rng &rng) const throw(std::bad_alloc) {
  377. SecureBuffer out(STEG_BYTES);
  378. bool done;
  379. do {
  380. rng.read(out.slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1));
  381. done = invert_elligator(out, out[HASH_BYTES-1]);
  382. } while (!done);
  383. return out;
  384. }
  385. /** @brief Return the base point */
  386. static inline const Point base() NOEXCEPT { return Point(decaf_255_point_base); }
  387. /** @brief Return the identity point */
  388. static inline const Point identity() NOEXCEPT { return Point(decaf_255_point_identity); }
  389. };
  390. /**
  391. * @brief Precomputed table of points.
  392. * Minor difficulties arise here because the decaf API doesn't expose, as a constant, how big such an object is.
  393. * Therefore we have to call malloc() or friends, but that's probably for the best, because you don't want to
  394. * stack-allocate a 15kiB object anyway.
  395. */
  396. class Precomputed {
  397. private:
  398. /** @cond internal */
  399. union {
  400. decaf_255_precomputed_s *mine;
  401. const decaf_255_precomputed_s *yours;
  402. } ours;
  403. bool isMine;
  404. inline void clear() NOEXCEPT {
  405. if (isMine) {
  406. decaf_255_precomputed_destroy(ours.mine);
  407. free(ours.mine);
  408. ours.yours = decaf_255_precomputed_base;
  409. isMine = false;
  410. }
  411. }
  412. inline void alloc() throw(std::bad_alloc) {
  413. if (isMine) return;
  414. int ret = posix_memalign((void**)&ours.mine, alignof_decaf_255_precomputed_s,sizeof_decaf_255_precomputed_s);
  415. if (ret || !ours.mine) {
  416. isMine = false;
  417. throw std::bad_alloc();
  418. }
  419. isMine = true;
  420. }
  421. inline const decaf_255_precomputed_s *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; }
  422. /** @endcond */
  423. public:
  424. /** Destructor securely zeorizes the memory. */
  425. inline ~Precomputed() NOEXCEPT { clear(); }
  426. /**
  427. * @brief Initialize from underlying type, declared as a reference to prevent
  428. * it from being called with 0, thereby breaking override.
  429. *
  430. * The underlying object must remain valid throughout the lifetime of this one.
  431. *
  432. * By default, initializes to the table for the base point.
  433. *
  434. * @warning The empty initializer makes this equal to base, unlike the empty
  435. * initializer for points which makes this equal to the identity.
  436. */
  437. inline Precomputed(
  438. const decaf_255_precomputed_s &yours = *decaf_255_precomputed_base
  439. ) NOEXCEPT {
  440. ours.yours = &yours;
  441. isMine = false;
  442. }
  443. /**
  444. * @brief Assign. This may require an allocation and memcpy.
  445. */
  446. inline Precomputed &operator=(const Precomputed &it) throw(std::bad_alloc) {
  447. if (this == &it) return *this;
  448. if (it.isMine) {
  449. alloc();
  450. memcpy(ours.mine,it.ours.mine,sizeof_decaf_255_precomputed_s);
  451. } else {
  452. clear();
  453. ours.yours = it.ours.yours;
  454. }
  455. isMine = it.isMine;
  456. return *this;
  457. }
  458. /**
  459. * @brief Initilaize from point. Must allocate memory, and may throw.
  460. */
  461. inline Precomputed &operator=(const Point &it) throw(std::bad_alloc) {
  462. alloc();
  463. decaf_255_precompute(ours.mine,it.p);
  464. return *this;
  465. }
  466. /**
  467. * @brief Copy constructor.
  468. */
  469. inline Precomputed(const Precomputed &it) throw(std::bad_alloc) : isMine(false) { *this = it; }
  470. /**
  471. * @brief Constructor which initializes from point.
  472. */
  473. inline explicit Precomputed(const Point &it) throw(std::bad_alloc) : isMine(false) { *this = it; }
  474. #if __cplusplus >= 201103L
  475. inline Precomputed &operator=(Precomputed &&it) NOEXCEPT {
  476. if (this == &it) return *this;
  477. clear();
  478. ours = it.ours;
  479. isMine = it.isMine;
  480. it.isMine = false;
  481. it.ours.yours = decaf_255_precomputed_base;
  482. return *this;
  483. }
  484. inline Precomputed(Precomputed &&it) NOEXCEPT : isMine(false) { *this = it; }
  485. #endif
  486. /** @brief Fixed base scalarmul. */
  487. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_255_precomputed_scalarmul(r.p,get(),s.s); return r; }
  488. /** @brief Multiply by s.inverse(). If s=0, maps to the identity. */
  489. inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
  490. /** @brief Return the table for the base point. */
  491. static inline const Precomputed base() NOEXCEPT { return Precomputed(*decaf_255_precomputed_base); }
  492. };
  493. }; /* struct Decaf255 */
  494. #undef NOEXCEPT
  495. } /* namespace decaf */
  496. #endif /* __DECAF_255_HXX__ */