1 // donna.h - written and placed in public domain by Jeffrey Walton
2 //           Crypto++ specific implementation wrapped around Andrew
3 //           Moon's public domain curve25519-donna and ed25519-donna,
4 //           https://github.com/floodyberry/curve25519-donna and
5 //           https://github.com/floodyberry/ed25519-donna.
6 
7 // The curve25519 and ed25519 source files multiplex different repos and
8 // architectures using namespaces. The repos are Andrew Moon's
9 // curve25519-donna and ed25519-donna. The architectures are 32-bit, 64-bit
10 // and SSE. For example, 32-bit x25519 uses symbols from Donna::X25519 and
11 // Donna::Arch32.
12 
13 // If needed, see Moon's commit "Go back to ignoring 256th bit [sic]",
14 // https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658
15 
16 /// \file donna.h
17 /// \details Functions for curve25519 and ed25519 operations
18 /// \details This header provides the entry points into Andrew Moon's
19 ///   curve25519 and ed25519 curve functions. The Crypto++ classes x25519
20 ///   and ed25519 use the functions. The functions are in the <tt>Donna</tt>
21 ///   namespace and are curve25519_mult(), ed25519_publickey(),
22 ///   ed25519_sign() and ed25519_sign_open().
23 /// \details At the moment the hash function for signing is fixed at
24 ///   SHA512.
25 
26 #ifndef CRYPTOPP_DONNA_H
27 #define CRYPTOPP_DONNA_H
28 
29 #include "cryptlib.h"
30 #include "stdcpp.h"
31 
32 NAMESPACE_BEGIN(CryptoPP)
33 NAMESPACE_BEGIN(Donna)
34 
35 //***************************** curve25519 *****************************//
36 
37 /// \brief Generate a public key
38 /// \param publicKey byte array for the public key
39 /// \param secretKey byte array with the private key
40 /// \return 0 on success, non-0 otherwise
41 /// \details curve25519_mult() generates a public key from an existing
42 ///   secret key. Internally curve25519_mult() performs a scalar
43 ///   multiplication using the base point and writes the result to
44 ///   <tt>pubkey</tt>.
45 int curve25519_mult(byte publicKey[32], const byte secretKey[32]);
46 
47 /// \brief Generate a shared key
48 /// \param sharedKey byte array for the shared secret
49 /// \param secretKey byte array with the private key
50 /// \param othersKey byte array with the peer's public key
51 /// \return 0 on success, non-0 otherwise
52 /// \details curve25519_mult() generates a shared key from an existing
53 ///   secret key and the other party's public key. Internally
54 ///   curve25519_mult() performs a scalar multiplication using the two keys
55 ///   and writes the result to <tt>sharedKey</tt>.
56 int curve25519_mult(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]);
57 
58 //******************************* ed25519 *******************************//
59 
60 /// \brief Creates a public key from a secret key
61 /// \param publicKey byte array for the public key
62 /// \param secretKey byte array with the private key
63 /// \return 0 on success, non-0 otherwise
64 /// \details ed25519_publickey() generates a public key from a secret key.
65 ///   Internally ed25519_publickey() performs a scalar multiplication
66 ///   using the secret key and then writes the result to <tt>publicKey</tt>.
67 int ed25519_publickey(byte publicKey[32], const byte secretKey[32]);
68 
69 /// \brief Creates a signature on a message
70 /// \param message byte array with the message
71 /// \param messageLength size of the message, in bytes
72 /// \param publicKey byte array with the public key
73 /// \param secretKey byte array with the private key
74 /// \param signature byte array for the signature
75 /// \return 0 on success, non-0 otherwise
76 /// \details ed25519_sign() generates a signature on a message using
77 ///   the public and private keys. The various buffers can be exact
78 ///   sizes, and do not require extra space like when using the
79 ///   NaCl library functions.
80 /// \details At the moment the hash function for signing is fixed at
81 ///   SHA512.
82 int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
83 
84 /// \brief Creates a signature on a message
85 /// \param stream std::istream derived class
86 /// \param publicKey byte array with the public key
87 /// \param secretKey byte array with the private key
88 /// \param signature byte array for the signature
89 /// \return 0 on success, non-0 otherwise
90 /// \details ed25519_sign() generates a signature on a message using
91 ///   the public and private keys. The various buffers can be exact
92 ///   sizes, and do not require extra space like when using the
93 ///   NaCl library functions.
94 /// \details This ed25519_sign() overload handles large streams. It
95 ///   was added for signing and verifying files that are too large
96 ///   for a memory allocation.
97 /// \details At the moment the hash function for signing is fixed at
98 ///   SHA512.
99 int ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
100 
101 /// \brief Verifies a signature on a message
102 /// \param message byte array with the message
103 /// \param messageLength size of the message, in bytes
104 /// \param publicKey byte array with the public key
105 /// \param signature byte array with the signature
106 /// \return 0 on success, non-0 otherwise
107 /// \details ed25519_sign_open() verifies a signature on a message using
108 ///   the public key. The various buffers can be exact sizes, and do not
109 ///   require extra space like when using the NaCl library functions.
110 /// \details At the moment the hash function for signing is fixed at
111 ///   SHA512.
112 int
113 ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]);
114 
115 /// \brief Verifies a signature on a message
116 /// \param stream std::istream derived class
117 /// \param publicKey byte array with the public key
118 /// \param signature byte array with the signature
119 /// \return 0 on success, non-0 otherwise
120 /// \details ed25519_sign_open() verifies a signature on a message using
121 ///   the public key. The various buffers can be exact sizes, and do not
122 ///   require extra space like when using the NaCl library functions.
123 /// \details This ed25519_sign_open() overload handles large streams. It
124 ///   was added for signing and verifying files that are too large
125 ///   for a memory allocation.
126 /// \details At the moment the hash function for signing is fixed at
127 ///   SHA512.
128 int
129 ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]);
130 
131 //****************************** Internal ******************************//
132 
133 #ifndef CRYPTOPP_DOXYGEN_PROCESSING
134 
135 // CRYPTOPP_WORD128_AVAILABLE mostly depends upon GCC support for
136 // __SIZEOF_INT128__. If __SIZEOF_INT128__ is not available then Moon
137 // provides routines for MSC and GCC. It should cover most platforms,
138 // but there are gaps like MS ARM64 and XLC. We tried to enable the
139 // 64-bit path for SunCC from 12.5 but we got the dreaded compile
140 // error "The operand ___LCM cannot be assigned to".
141 
142 #if defined(CRYPTOPP_WORD128_AVAILABLE) || \
143    (defined(_MSC_VER) && defined(_M_X64))
144 # define CRYPTOPP_CURVE25519_64BIT 1
145 #else
146 # define CRYPTOPP_CURVE25519_32BIT 1
147 #endif
148 
149 // Benchmarking on a modern 64-bit Core i5-6400 @2.7 GHz shows SSE2 on Linux
150 // is not profitable. Here are the numbers in milliseconds/operation:
151 //
152 //   * Langley, C++, 0.050
153 //   * Moon, C++: 0.040
154 //   * Moon, SSE2: 0.061
155 //   * Moon, native: 0.045
156 //
157 // However, a modern 64-bit Core i5-3200 @2.5 GHz shows SSE2 is profitable
158 // for MS compilers. Here are the numbers in milliseconds/operation:
159 //
160 //   * x86, no SSE2, 0.294
161 //   * x86, SSE2, 0.097
162 //   * x64, no SSE2, 0.081
163 //   * x64, SSE2, 0.071
164 
165 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) && defined(_MSC_VER)
166 # define CRYPTOPP_CURVE25519_SSE2 1
167 #endif
168 
169 #if (CRYPTOPP_CURVE25519_SSE2)
170   extern int curve25519_mult_SSE2(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]);
171 #endif
172 
173 #endif  // CRYPTOPP_DOXYGEN_PROCESSING
174 
175 NAMESPACE_END  // Donna
176 NAMESPACE_END  // CryptoPP
177 
178 #endif  // CRYPTOPP_DONNA_H
179