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.
 
 
 
 
 

287 lines
12 KiB

  1. /**
  2. * @file decaf.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 Ed448-Goldilocks) and wiping out the cofactor.
  14. *
  15. * The formulas are all complete and have no special cases, except that
  16. * decaf_448_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_448_base_double_scalarmul_non_secret.
  21. */
  22. #ifndef __DECAF_448_HXX__
  23. #define __DECAF_448_HXX__ 1
  24. #define _XOPEN_SOURCE 600 /* for posix_memalign */
  25. #include <stdlib.h>
  26. #include <string.h> /* for memcpy */
  27. #include "decaf.h"
  28. #include <string>
  29. #include <sys/types.h>
  30. #include <limits.h>
  31. /* TODO: document */
  32. /* TODO: This is incomplete */
  33. /* TODO: attribute nonnull */
  34. #if __cplusplus >= 201103L
  35. #define NOEXCEPT noexcept
  36. #define EXPLICIT_CON explicit
  37. #define GET_DATA(str) ((const unsigned char *)&(str)[0])
  38. #else
  39. #define NOEXCEPT throw()
  40. #define EXPLICIT_CON
  41. #define GET_DATA(str) ((const unsigned char *)((str).data()))
  42. #endif
  43. namespace decaf {
  44. void really_bzero(void *data, size_t size);
  45. template<unsigned int bits = 448> struct decaf;
  46. template<> struct decaf<448> {
  47. class CryptoException : public std::exception {
  48. public:
  49. CryptoException() {}
  50. virtual ~CryptoException() NOEXCEPT {}
  51. virtual const char * what() const NOEXCEPT { return "CryptoException"; }
  52. };
  53. class Point;
  54. class Precomputed;
  55. class Scalar {
  56. public:
  57. decaf_448_scalar_t s;
  58. inline Scalar() NOEXCEPT {}
  59. inline Scalar(const decaf_word_t w) NOEXCEPT { decaf_448_scalar_set(s,w); }
  60. inline Scalar(const int w) NOEXCEPT {
  61. Scalar t(-(decaf_word_t)INT_MIN);
  62. decaf_448_scalar_set(s,(decaf_word_t)w - (decaf_word_t)INT_MIN);
  63. *this -= t;
  64. }
  65. inline Scalar(const decaf_448_scalar_t &t) NOEXCEPT { decaf_448_scalar_copy(s,t); }
  66. inline Scalar(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); }
  67. inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; }
  68. inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); }
  69. /* Initialize from buffer */
  70. inline Scalar &operator=(const std::string &str) NOEXCEPT {
  71. decaf_448_scalar_decode_long(s,GET_DATA(str),str.length()); return *this;
  72. }
  73. inline explicit Scalar(const std::string &str) NOEXCEPT { *this = str; }
  74. inline Scalar(const unsigned char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,buffer,n); }
  75. inline Scalar(const char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); }
  76. inline Scalar(const void *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); }
  77. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  78. Scalar &sc, const unsigned char buffer[DECAF_448_SCALAR_BYTES]
  79. ) NOEXCEPT {
  80. return decaf_448_scalar_decode(sc.s,buffer);
  81. }
  82. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  83. Scalar &sc, const std::string buffer
  84. ) NOEXCEPT {
  85. if (buffer.size() != DECAF_448_SCALAR_BYTES) return DECAF_FAILURE;
  86. return decaf_448_scalar_decode(sc.s,GET_DATA(buffer));
  87. }
  88. inline EXPLICIT_CON operator std::string() const NOEXCEPT {
  89. unsigned char buffer[DECAF_448_SCALAR_BYTES];
  90. decaf_448_scalar_encode(buffer, s);
  91. return std::string((char*)buffer,sizeof(buffer));
  92. }
  93. inline void encode(unsigned char buffer[DECAF_448_SCALAR_BYTES]) const NOEXCEPT{
  94. decaf_448_scalar_encode(buffer, s);
  95. }
  96. /* Arithmetic */
  97. inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_add(r.s,s,q.s); return r; }
  98. inline Scalar operator+=(const Scalar &q) NOEXCEPT { decaf_448_scalar_add(s,s,q.s); return *this; }
  99. inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_sub(r.s,s,q.s); return r; }
  100. inline Scalar operator-=(const Scalar &q) NOEXCEPT { decaf_448_scalar_sub(s,s,q.s); return *this; }
  101. inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_mul(r.s,s,q.s); return r; }
  102. inline Scalar operator*=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.s); return *this; }
  103. inline Scalar inverse() const NOEXCEPT { Scalar r; decaf_448_scalar_invert(r.s,s); return r; }
  104. inline Scalar operator/ (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_mul(r.s,s,q.inverse().s); return r; }
  105. inline Scalar operator/=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.inverse().s); return *this; }
  106. inline Scalar operator- () const NOEXCEPT { Scalar r; decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; }
  107. inline bool operator!=(const Scalar &q) const NOEXCEPT { return ! decaf_448_scalar_eq(s,q.s); }
  108. inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_448_scalar_eq(s,q.s); }
  109. inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); }
  110. inline Point operator* (const Precomputed &q) const NOEXCEPT { return q * (*this); }
  111. };
  112. class Point {
  113. public:
  114. decaf_448_point_t p;
  115. inline Point() {}
  116. inline Point(const decaf_448_point_t &q) { decaf_448_point_copy(p,q); } /* TODO: not memcpy? */
  117. inline Point(const Point &q) { decaf_448_point_copy(p,q.p); }
  118. inline Point& operator=(const Point &q) { decaf_448_point_copy(p,q.p); return *this; }
  119. inline ~Point() { decaf_448_point_destroy(p); }
  120. inline explicit Point(const std::string &s, decaf_bool_t allow_identity=DECAF_TRUE) throw(CryptoException) {
  121. if (!decode(*this,s,allow_identity)) throw CryptoException();
  122. }
  123. inline explicit Point(const unsigned char buffer[DECAF_448_SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE)
  124. throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
  125. /* serialize / deserialize */
  126. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  127. Point &p, const unsigned char buffer[DECAF_448_SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE
  128. ) NOEXCEPT {
  129. return decaf_448_point_decode(p.p,buffer,allow_identity);
  130. }
  131. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  132. Point &p, const std::string &buffer, decaf_bool_t allow_identity=DECAF_TRUE
  133. ) NOEXCEPT {
  134. if (buffer.size() != DECAF_448_SER_BYTES) return DECAF_FAILURE;
  135. return decaf_448_point_decode(p.p,GET_DATA(buffer),allow_identity);
  136. }
  137. static inline Point from_hash_nonuniform ( const unsigned char buffer[DECAF_448_SER_BYTES] ) NOEXCEPT {
  138. Point p; decaf_448_point_from_hash_nonuniform(p.p,buffer); return p;
  139. }
  140. static inline Point from_hash_nonuniform ( const std::string &s ) NOEXCEPT {
  141. std::string t = s;
  142. if (t.size() < DECAF_448_SER_BYTES) t.insert(t.size(),DECAF_448_SER_BYTES-t.size(),0);
  143. Point p; decaf_448_point_from_hash_nonuniform(p.p,GET_DATA(t)); return p;
  144. }
  145. static inline Point from_hash ( const unsigned char buffer[2*DECAF_448_SER_BYTES] ) NOEXCEPT {
  146. Point p; decaf_448_point_from_hash_uniform(p.p,buffer); return p;
  147. }
  148. static inline Point from_hash ( const std::string &s ) NOEXCEPT {
  149. std::string t = s;
  150. if (t.size() < DECAF_448_SER_BYTES) return from_hash_nonuniform(s);
  151. if (t.size() < 2*DECAF_448_SER_BYTES) t.insert(t.size(),2*DECAF_448_SER_BYTES-t.size(),0);
  152. Point p; decaf_448_point_from_hash_uniform(p.p,GET_DATA(t)); return p;
  153. }
  154. inline EXPLICIT_CON operator std::string() const NOEXCEPT {
  155. unsigned char buffer[DECAF_448_SER_BYTES];
  156. decaf_448_point_encode(buffer, p);
  157. return std::string((char*)buffer,sizeof(buffer));
  158. }
  159. inline void encode(unsigned char buffer[DECAF_448_SER_BYTES]) const NOEXCEPT{
  160. decaf_448_point_encode(buffer, p);
  161. }
  162. /* Point/point arithmetic */
  163. inline Point operator+ (const Point &q) const NOEXCEPT { Point r; decaf_448_point_add(r.p,p,q.p); return r; }
  164. inline Point operator+=(const Point &q) NOEXCEPT { decaf_448_point_add(p,p,q.p); return *this; }
  165. inline Point operator- (const Point &q) const NOEXCEPT { Point r; decaf_448_point_sub(r.p,p,q.p); return r; }
  166. inline Point operator-=(const Point &q) NOEXCEPT { decaf_448_point_sub(p,p,q.p); return *this; }
  167. inline Point operator- () const NOEXCEPT { Point r; decaf_448_point_negate(r.p,p); return r; }
  168. inline Point times_two () const NOEXCEPT { Point r; decaf_448_point_double(r.p,p); return r; }
  169. inline Point &double_in_place() NOEXCEPT { decaf_448_point_double(p,p); return *this; }
  170. inline bool operator!=(const Point &q) const NOEXCEPT { return ! decaf_448_point_eq(p,q.p); }
  171. inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_448_point_eq(p,q.p); }
  172. /* Scalarmul */
  173. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_point_scalarmul(r.p,p,s.s); return r; }
  174. inline Point operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; }
  175. inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
  176. static inline Point double_scalar_mul (
  177. const Point &q, const Scalar &qs, const Point &r, const Scalar &rs
  178. ) NOEXCEPT {
  179. Point p; decaf_448_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
  180. }
  181. /* FIXME: are these defined to be correct? */
  182. static inline const Point &base() NOEXCEPT { return *(const Point *)decaf_448_point_base; }
  183. static inline const Point &identity() NOEXCEPT { return *(const Point *)decaf_448_point_identity; }
  184. };
  185. class Precomputed {
  186. public:
  187. union {
  188. decaf_448_precomputed_s *mine;
  189. const decaf_448_precomputed_s *yours;
  190. } ours;
  191. bool isMine;
  192. private:
  193. inline void clear() NOEXCEPT {
  194. if (isMine) {
  195. decaf_448_precomputed_destroy(ours.mine);
  196. free(ours.mine);
  197. ours.yours = decaf_448_precomputed_base;
  198. isMine = false;
  199. }
  200. }
  201. inline void alloc() {
  202. if (isMine) return;
  203. int ret = posix_memalign((void**)&ours.mine, alignof_decaf_448_precomputed_s,sizeof_decaf_448_precomputed_s);
  204. if (ret || !ours.mine) {
  205. isMine = false;
  206. throw std::bad_alloc();
  207. }
  208. isMine = true;
  209. }
  210. inline const decaf_448_precomputed_s *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; }
  211. public:
  212. inline ~Precomputed() NOEXCEPT { clear(); }
  213. inline Precomputed(const decaf_448_precomputed_s &yours = *decaf_448_precomputed_base) NOEXCEPT {
  214. ours.yours = &yours;
  215. isMine = false;
  216. }
  217. inline Precomputed &operator=(const Precomputed &it) {
  218. if (this == &it) return *this;
  219. if (it.isMine) {
  220. alloc();
  221. memcpy(ours.mine,it.ours.mine,sizeof_decaf_448_precomputed_s);
  222. } else {
  223. clear();
  224. ours.yours = it.ours.yours;
  225. }
  226. isMine = it.isMine;
  227. return *this;
  228. }
  229. inline Precomputed &operator=(const Point &it) {
  230. alloc();
  231. decaf_448_precompute(ours.mine,it.p);
  232. return *this;
  233. }
  234. inline Precomputed(const Precomputed &it) NOEXCEPT : isMine(false) { *this = it; }
  235. inline explicit Precomputed(const Point &it) NOEXCEPT : isMine(false) { *this = it; }
  236. #if __cplusplus >= 201103L
  237. inline Precomputed &operator=(Precomputed &&it) NOEXCEPT {
  238. if (this == &it) return *this;
  239. clear();
  240. ours = it.ours;
  241. isMine = it.isMine;
  242. it.isMine = false;
  243. it.ours.yours = decaf_448_precomputed_base;
  244. return *this;
  245. }
  246. inline Precomputed(Precomputed &&it) NOEXCEPT : isMine(false) { *this = it; }
  247. #endif
  248. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; }
  249. inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); }
  250. static inline const Precomputed base() NOEXCEPT { return Precomputed(*decaf_448_precomputed_base); }
  251. };
  252. }; /* struct decaf<448> */
  253. #undef NOEXCEPT
  254. } /* namespace decaf */
  255. #endif /* __DECAF_448_HXX__ */