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.
 
 
 
 
 

231 lines
9.6 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. /* TODO: document */
  30. /* TODO: This is incomplete */
  31. /* TODO: attribute nonnull */
  32. #if __cplusplus >= 201103L
  33. #define NOEXCEPT noexcept
  34. #define EXPLICIT_CON explicit
  35. #define GET_DATA(str) ((const unsigned char *)&(str)[0])
  36. #else
  37. #define NOEXCEPT
  38. #define EXPLICIT_CON
  39. #define GET_DATA(str) ((const unsigned char *)((str).data()))
  40. #endif
  41. namespace decaf {
  42. void really_bzero(void *data, size_t size);
  43. template<unsigned int bits = 448> struct decaf;
  44. template<> struct decaf<448> {
  45. class Scalar {
  46. public:
  47. decaf_448_scalar_t s;
  48. inline Scalar() NOEXCEPT {}
  49. inline Scalar(const decaf_word_t w) NOEXCEPT { decaf_448_scalar_set(s,w); }
  50. inline Scalar(const decaf_448_scalar_t &t) NOEXCEPT { decaf_448_scalar_copy(s,t); }
  51. inline Scalar(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); }
  52. inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; }
  53. inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); }
  54. /* Initialize from buffer */
  55. inline explicit Scalar(const std::string &str) NOEXCEPT { decaf_448_scalar_decode_long(s,GET_DATA(str),str.length()); }
  56. inline Scalar(const unsigned char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,buffer,n); }
  57. inline Scalar(const char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); }
  58. inline Scalar(const void *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); }
  59. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  60. Scalar &sc, const unsigned char buffer[DECAF_448_SCALAR_BYTES]
  61. ) NOEXCEPT {
  62. return decaf_448_scalar_decode(sc.s,buffer);
  63. }
  64. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  65. Scalar &sc, const std::string buffer
  66. ) NOEXCEPT {
  67. if (buffer.size() != DECAF_448_SCALAR_BYTES) return DECAF_FAILURE;
  68. return decaf_448_scalar_decode(sc.s,GET_DATA(buffer));
  69. }
  70. inline EXPLICIT_CON operator std::string() const NOEXCEPT {
  71. unsigned char buffer[DECAF_448_SCALAR_BYTES];
  72. decaf_448_scalar_encode(buffer, s);
  73. return std::string((char*)buffer,sizeof(buffer));
  74. }
  75. inline void write_to_buffer(unsigned char buffer[DECAF_448_SCALAR_BYTES]) const NOEXCEPT{
  76. decaf_448_scalar_encode(buffer, s);
  77. }
  78. /* Arithmetic */
  79. inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_add(r.s,s,q.s); return r; }
  80. inline Scalar operator+=(const Scalar &q) NOEXCEPT { decaf_448_scalar_add(s,s,q.s); return *this; }
  81. inline Scalar operator- (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_sub(r.s,s,q.s); return r; }
  82. inline Scalar operator-=(const Scalar &q) NOEXCEPT { decaf_448_scalar_sub(s,s,q.s); return *this; }
  83. inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_mul(r.s,s,q.s); return r; }
  84. inline Scalar operator*=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.s); return *this; }
  85. inline Scalar operator- () const NOEXCEPT { Scalar r; decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; }
  86. inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_448_scalar_eq(s,q.s); }
  87. };
  88. class Point {
  89. public:
  90. decaf_448_point_t p;
  91. inline Point() {}
  92. inline Point(const decaf_448_point_t &q) { decaf_448_point_copy(p,q); } /* TODO: not memcpy? */
  93. inline Point(const Point &q) { decaf_448_point_copy(p,q.p); }
  94. inline Point& operator=(const Point &q) { decaf_448_point_copy(p,q.p); return *this; }
  95. inline ~Point() { decaf_448_point_destroy(p); }
  96. /* serialize / deserialize */
  97. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  98. Point &p, const unsigned char buffer[DECAF_448_SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE
  99. ) NOEXCEPT {
  100. return decaf_448_point_decode(p.p,buffer,allow_identity);
  101. }
  102. static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
  103. Point &p, const std::string &buffer, decaf_bool_t allow_identity=DECAF_TRUE
  104. ) NOEXCEPT {
  105. if (buffer.size() != DECAF_448_SER_BYTES) return DECAF_FAILURE;
  106. return decaf_448_point_decode(p.p,GET_DATA(buffer),allow_identity);
  107. }
  108. inline EXPLICIT_CON operator std::string() const NOEXCEPT {
  109. unsigned char buffer[DECAF_448_SER_BYTES];
  110. decaf_448_point_encode(buffer, p);
  111. return std::string((char*)buffer,sizeof(buffer));
  112. }
  113. inline void write_to_buffer(unsigned char buffer[DECAF_448_SER_BYTES]) const NOEXCEPT{
  114. decaf_448_point_encode(buffer, p);
  115. }
  116. /* Point/point arithmetic */
  117. inline Point operator+ (const Point &q) const NOEXCEPT { Point r; decaf_448_point_add(r.p,p,q.p); return r; }
  118. inline Point operator+=(const Point &q) NOEXCEPT { decaf_448_point_add(p,p,q.p); return *this; }
  119. inline Point operator- (const Point &q) const NOEXCEPT { Point r; decaf_448_point_sub(r.p,p,q.p); return r; }
  120. inline Point operator-=(const Point &q) NOEXCEPT { decaf_448_point_sub(p,p,q.p); return *this; }
  121. inline Point operator- () const NOEXCEPT { Point r; decaf_448_point_negate(r.p,p); return r; }
  122. inline Point times_two () const NOEXCEPT { Point r; decaf_448_point_double(r.p,p); return r; }
  123. inline Point &double_in_place() NOEXCEPT { decaf_448_point_double(p,p); return *this; }
  124. inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_448_point_eq(p,q.p); }
  125. /* Scalarmul */
  126. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_point_scalarmul(r.p,p,s.s); return r; }
  127. inline Point operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; }
  128. static inline Point double_scalar_mul (
  129. const Point &q, const Scalar &qs, const Point &r, const Scalar &rs
  130. ) NOEXCEPT {
  131. Point p; decaf_448_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p;
  132. }
  133. /* FIXME: are these defined to be correct? */
  134. static inline const Point &base() NOEXCEPT { return (const Point &)decaf_448_point_base; }
  135. static inline const Point &identity() NOEXCEPT { return (const Point &)decaf_448_point_identity; }
  136. };
  137. class Precomputed {
  138. public:
  139. union {
  140. decaf_448_precomputed_s *mine;
  141. const decaf_448_precomputed_s *yours;
  142. } ours;
  143. bool isMine;
  144. private:
  145. inline void clear() NOEXCEPT {
  146. if (isMine) {
  147. decaf_448_precomputed_destroy(ours.mine);
  148. free(ours.mine);
  149. ours.yours = decaf_448_precomputed_base;
  150. isMine = false;
  151. }
  152. }
  153. inline void alloc() {
  154. if (isMine) return;
  155. int ret = posix_memalign((void**)&ours.mine, alignof_decaf_448_precomputed_s,sizeof_decaf_448_precomputed_s);
  156. if (ret || !ours.mine) {
  157. isMine = false;
  158. throw std::bad_alloc();
  159. }
  160. isMine = true;
  161. }
  162. inline const decaf_448_precomputed_s *get() const NOEXCEPT { return isMine ? ours.mine : ours.yours; }
  163. public:
  164. inline ~Precomputed() NOEXCEPT { clear(); }
  165. inline Precomputed(const decaf_448_precomputed_s *yours = decaf_448_precomputed_base) NOEXCEPT {
  166. ours.yours = yours;
  167. isMine = false;
  168. }
  169. inline Precomputed &operator=(const Precomputed &it) {
  170. if (this == &it) return *this;
  171. if (it.isMine) {
  172. alloc();
  173. memcpy(ours.mine,it.ours.mine,sizeof_decaf_448_precomputed_s);
  174. } else {
  175. clear();
  176. ours.yours = it.ours.yours;
  177. }
  178. isMine = it.isMine;
  179. return *this;
  180. }
  181. inline Precomputed &operator=(const Point &it) {
  182. alloc();
  183. decaf_448_precompute(ours.mine,it.p);
  184. return *this;
  185. }
  186. inline Precomputed(const Precomputed &it) NOEXCEPT : isMine(false) { *this = it; }
  187. inline Precomputed(const Point &it) NOEXCEPT : isMine(false) { *this = it; }
  188. #if __cplusplus >= 201103L
  189. inline Precomputed &operator=(Precomputed &&it) NOEXCEPT {
  190. if (this == &it) return *this;
  191. clear();
  192. ours = it.ours;
  193. isMine = it.isMine;
  194. it.isMine = false;
  195. it.ours.yours = decaf_448_precomputed_base;
  196. return *this;
  197. }
  198. inline Precomputed(Precomputed &&it) NOEXCEPT : isMine(false) { *this = it; }
  199. #endif
  200. inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; }
  201. static inline const Precomputed base() NOEXCEPT { return Precomputed(decaf_448_precomputed_base); }
  202. };
  203. #undef NOEXCEPT
  204. }; /* struct decaf<448> */
  205. }; /* namespace decaf */
  206. #endif /* __DECAF_448_HXX__ */