3 * Copyright (C) 2006-2015 wolfSSL Inc.
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */
28 /* in case user set HAVE_ED25519 there */
29 #include <wolfssl/wolfcrypt/settings.h>
33 #include <wolfssl/wolfcrypt/ed25519.h>
34 #include <wolfssl/wolfcrypt/error-crypt.h>
36 #include <wolfssl/wolfcrypt/misc.h>
38 #include <wolfcrypt/src/misc.c>
43 generate an ed25519 key pair.
46 int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
52 if (rng == NULL || key == NULL)
55 /* ed25519 has 32 byte key sizes */
56 if (keySz != ED25519_KEY_SIZE)
60 ret |= wc_RNG_GenerateBlock(rng, key->k, 32);
61 ret |= wc_Sha512Hash(key->k, 32, az);
66 ge_scalarmult_base(&A, az);
67 ge_p3_tobytes(key->p, &A);
68 XMEMMOVE(key->k + 32, key->p, 32);
75 in contains the message to sign
76 inlen is the length of the message to sign
77 out is the buffer to write the signature
78 outlen [in/out] input size of out buf
79 output gets set as the final length of out
80 key is the ed25519 key to use when signing
83 int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
84 word32 *outlen, ed25519_key* key)
87 byte nonce[SHA512_DIGEST_SIZE];
88 byte hram[SHA512_DIGEST_SIZE];
94 /* sanity check on arguments */
95 if (in == NULL || out == NULL || outlen == NULL || key == NULL)
98 /* check and set up out length */
100 sigSz = wc_ed25519_sig_size(key);
105 /* step 1: create nonce to use where nonce is r in
106 r = H(h_b, ... ,h_2b-1,M) */
107 ret |= wc_Sha512Hash(key->k,32,az);
111 ret |= wc_InitSha512(&sha);
112 ret |= wc_Sha512Update(&sha, az + 32, 32);
113 ret |= wc_Sha512Update(&sha, in, inlen);
114 ret |= wc_Sha512Final(&sha, nonce);
117 /* step 2: computing R = rB where rB is the scalar multiplication of
119 ge_scalarmult_base(&R,nonce);
120 ge_p3_tobytes(out,&R);
122 /* step 3: hash R + public key + message getting H(R,A,M) then
123 creating S = (r + H(R,A,M)a) mod l */
124 ret |= wc_InitSha512(&sha);
125 ret |= wc_Sha512Update(&sha, out, 32);
126 ret |= wc_Sha512Update(&sha, key->p, 32);
127 ret |= wc_Sha512Update(&sha, in, inlen);
128 ret |= wc_Sha512Final(&sha, hram);
130 sc_muladd(out + 32, hram, az, nonce);
137 sig is array of bytes containing the signature
138 siglen is the length of sig byte array
139 msg the array of bytes containing the message
140 msglen length of msg array
141 stat will be 1 on successful verify and 0 on unsuccessful
143 int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg,
144 word32 msglen, int* stat, ed25519_key* key)
147 byte h[SHA512_DIGEST_SIZE];
154 /* sanity check on arguments */
155 if (sig == NULL || msg == NULL || stat == NULL || key == NULL)
160 sigSz = wc_ed25519_size(key);
162 /* check on basics needed to verify signature */
168 /* uncompress A (public key), test if valid, and negate it */
169 if (ge_frombytes_negate_vartime(&A, key->p) != 0)
172 /* find H(R,A,M) and store it as h */
173 ret |= wc_InitSha512(&sha);
174 ret |= wc_Sha512Update(&sha, sig, 32);
175 ret |= wc_Sha512Update(&sha, key->p, 32);
176 ret |= wc_Sha512Update(&sha, msg, msglen);
177 ret |= wc_Sha512Final(&sha, h);
181 Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
182 SB - H(R,A,M)A saving decompression of R
184 ret |= ge_double_scalarmult_vartime(&R, h, &A, sig + 32);
185 ge_tobytes(rcheck, &R);
187 /* comparison of R created to R in sig */
188 ret |= ConstantCompare(rcheck, sig, 32);
190 *stat = (ret == 0)? 1: 0;
196 /* initialize information and memory for key */
197 int wc_ed25519_init(ed25519_key* key)
202 XMEMSET(key, 0, sizeof(ed25519_key));
208 /* clear memory of key */
209 void wc_ed25519_free(ed25519_key* key)
214 ForceZero(key, sizeof(ed25519_key));
219 outLen should contain the size of out buffer when input. outLen is than set
220 to the final output length.
223 int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
227 /* sanity check on arguments */
228 if (key == NULL || out == NULL || outLen == NULL)
231 keySz = wc_ed25519_size(key);
232 if (*outLen < keySz) {
237 XMEMCPY(out, key->p, keySz);
244 Imports a compressed/uncompressed public key.
245 in the byte array containing the public key
246 inLen the length of the byte array being passed in
247 key ed25519 key struct to put the public key in
249 int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
254 /* sanity check on arguments */
255 if (in == NULL || key == NULL)
258 keySz = wc_ed25519_size(key);
263 /* compressed prefix according to draft
264 http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
266 /* key is stored in compressed format so just copy in */
267 XMEMCPY(key->p, (in + 1), keySz);
271 /* importing uncompressed public key */
273 /* pass in (x,y) and store compressed key */
274 ret = ge_compress_key(key->p, (in+1), (in+1+keySz), keySz);
278 /* if not specified compressed or uncompressed check key size
279 if key size is equal to compressed key size copy in key */
280 if (inLen == keySz) {
281 XMEMCPY(key->p, in, keySz);
285 /* bad public key format */
291 For importing a private key and its associated public key.
293 int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
294 const byte* pub, word32 pubSz, ed25519_key* key)
299 /* sanity check on arguments */
300 if (priv == NULL || pub == NULL || key == NULL)
303 keySz = wc_ed25519_size(key);
306 if (privSz < keySz || pubSz < keySz)
309 XMEMCPY(key->k, priv, keySz);
310 ret = wc_ed25519_import_public(pub, pubSz, key);
311 XMEMCPY((key->k + keySz), key->p, keySz);
318 outLen should contain the size of out buffer when input. outLen is than set
319 to the final output length.
322 int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
326 /* sanity checks on arguments */
327 if (key == NULL || out == NULL || outLen == NULL)
330 keySz = wc_ed25519_size(key);
331 if (*outLen < keySz) {
336 XMEMCPY(out, key->k, keySz);
342 /* is the compressed key size in bytes */
343 int wc_ed25519_size(ed25519_key* key)
350 keySz = ED25519_KEY_SIZE;
356 /* returns the size of signature in bytes */
357 int wc_ed25519_sig_size(ed25519_key* key)
364 sigSz = ED25519_SIG_SIZE;
369 #endif /* HAVE_ED25519 */