Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ed25519.c
00001 /* ed25519.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ 00024 00025 #ifdef HAVE_CONFIG_H 00026 #include <config.h> 00027 #endif 00028 00029 /* in case user set HAVE_ED25519 there */ 00030 #include <wolfssl/wolfcrypt/settings.h> 00031 00032 #ifdef HAVE_ED25519 00033 00034 #include <wolfssl/wolfcrypt/ed25519.h> 00035 #include <wolfssl/wolfcrypt/error-crypt.h> 00036 #include <wolfssl/wolfcrypt/hash.h> 00037 #ifdef NO_INLINE 00038 #include <wolfssl/wolfcrypt/misc.h> 00039 #else 00040 #include <wolfcrypt/src/misc.c> 00041 #endif 00042 00043 /* generate an ed25519 key pair. 00044 * returns 0 on success 00045 */ 00046 int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) 00047 { 00048 byte az[ED25519_PRV_KEY_SIZE]; 00049 int ret; 00050 ge_p3 A; 00051 00052 if (rng == NULL || key == NULL) 00053 return BAD_FUNC_ARG; 00054 00055 /* ed25519 has 32 byte key sizes */ 00056 if (keySz != ED25519_KEY_SIZE) 00057 return BAD_FUNC_ARG; 00058 00059 ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); 00060 if (ret != 0) 00061 return ret; 00062 ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); 00063 if (ret != 0) { 00064 ForceZero(key->k, ED25519_KEY_SIZE); 00065 return ret; 00066 } 00067 00068 /* apply clamp */ 00069 az[0] &= 248; 00070 az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ 00071 az[31] |= 64; 00072 00073 ge_scalarmult_base(&A, az); 00074 ge_p3_tobytes(key->p, &A); 00075 00076 /* put public key after private key, on the same buffer */ 00077 XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); 00078 00079 return ret; 00080 } 00081 00082 00083 #ifdef HAVE_ED25519_SIGN 00084 /* 00085 in contains the message to sign 00086 inlen is the length of the message to sign 00087 out is the buffer to write the signature 00088 outLen [in/out] input size of out buf 00089 output gets set as the final length of out 00090 key is the ed25519 key to use when signing 00091 return 0 on success 00092 */ 00093 int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, 00094 word32 *outLen, ed25519_key* key) 00095 { 00096 ge_p3 R; 00097 byte nonce[SHA512_DIGEST_SIZE]; 00098 byte hram[SHA512_DIGEST_SIZE]; 00099 byte az[ED25519_PRV_KEY_SIZE]; 00100 Sha512 sha; 00101 int ret; 00102 00103 /* sanity check on arguments */ 00104 if (in == NULL || out == NULL || outLen == NULL || key == NULL) 00105 return BAD_FUNC_ARG; 00106 00107 /* check and set up out length */ 00108 if (*outLen < ED25519_SIG_SIZE) { 00109 *outLen = ED25519_SIG_SIZE; 00110 return BUFFER_E; 00111 } 00112 *outLen = ED25519_SIG_SIZE; 00113 00114 /* step 1: create nonce to use where nonce is r in 00115 r = H(h_b, ... ,h_2b-1,M) */ 00116 ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); 00117 if (ret != 0) 00118 return ret; 00119 00120 /* apply clamp */ 00121 az[0] &= 248; 00122 az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ 00123 az[31] |= 64; 00124 00125 ret = wc_InitSha512(&sha); 00126 if (ret != 0) 00127 return ret; 00128 ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); 00129 if (ret != 0) 00130 return ret; 00131 ret = wc_Sha512Update(&sha, in, inlen); 00132 if (ret != 0) 00133 return ret; 00134 ret = wc_Sha512Final(&sha, nonce); 00135 if (ret != 0) 00136 return ret; 00137 00138 sc_reduce(nonce); 00139 00140 /* step 2: computing R = rB where rB is the scalar multiplication of 00141 r and B */ 00142 ge_scalarmult_base(&R,nonce); 00143 ge_p3_tobytes(out,&R); 00144 00145 /* step 3: hash R + public key + message getting H(R,A,M) then 00146 creating S = (r + H(R,A,M)a) mod l */ 00147 ret = wc_InitSha512(&sha); 00148 if (ret != 0) 00149 return ret; 00150 ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2); 00151 if (ret != 0) 00152 return ret; 00153 ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); 00154 if (ret != 0) 00155 return ret; 00156 ret = wc_Sha512Update(&sha, in, inlen); 00157 if (ret != 0) 00158 return ret; 00159 ret = wc_Sha512Final(&sha, hram); 00160 if (ret != 0) 00161 return ret; 00162 00163 sc_reduce(hram); 00164 sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); 00165 00166 return ret; 00167 } 00168 00169 #endif /* HAVE_ED25519_SIGN */ 00170 00171 #ifdef HAVE_ED25519_VERIFY 00172 00173 /* 00174 sig is array of bytes containing the signature 00175 siglen is the length of sig byte array 00176 msg the array of bytes containing the message 00177 msglen length of msg array 00178 stat will be 1 on successful verify and 0 on unsuccessful 00179 return 0 and stat of 1 on success 00180 */ 00181 int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, 00182 word32 msglen, int* stat, ed25519_key* key) 00183 { 00184 byte rcheck[ED25519_KEY_SIZE]; 00185 byte h[SHA512_DIGEST_SIZE]; 00186 ge_p3 A; 00187 ge_p2 R; 00188 int ret; 00189 Sha512 sha; 00190 00191 /* sanity check on arguments */ 00192 if (sig == NULL || msg == NULL || stat == NULL || key == NULL) 00193 return BAD_FUNC_ARG; 00194 00195 /* set verification failed by default */ 00196 *stat = 0; 00197 00198 /* check on basics needed to verify signature */ 00199 if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) 00200 return BAD_FUNC_ARG; 00201 00202 /* uncompress A (public key), test if valid, and negate it */ 00203 if (ge_frombytes_negate_vartime(&A, key->p) != 0) 00204 return BAD_FUNC_ARG; 00205 00206 /* find H(R,A,M) and store it as h */ 00207 ret = wc_InitSha512(&sha); 00208 if (ret != 0) 00209 return ret; 00210 ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2); 00211 if (ret != 0) 00212 return ret; 00213 ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); 00214 if (ret != 0) 00215 return ret; 00216 ret = wc_Sha512Update(&sha, msg, msglen); 00217 if (ret != 0) 00218 return ret; 00219 ret = wc_Sha512Final(&sha, h); 00220 if (ret != 0) 00221 return ret; 00222 00223 sc_reduce(h); 00224 00225 /* 00226 Uses a fast single-signature verification SB = R + H(R,A,M)A becomes 00227 SB - H(R,A,M)A saving decompression of R 00228 */ 00229 ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2)); 00230 if (ret != 0) 00231 return ret; 00232 00233 ge_tobytes(rcheck, &R); 00234 00235 /* comparison of R created to R in sig */ 00236 ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2); 00237 if (ret != 0) 00238 return SIG_VERIFY_E; 00239 00240 /* set the verification status */ 00241 *stat = 1; 00242 00243 return ret; 00244 } 00245 00246 #endif /* HAVE_ED25519_VERIFY */ 00247 00248 00249 /* initialize information and memory for key */ 00250 int wc_ed25519_init(ed25519_key* key) 00251 { 00252 if (key == NULL) 00253 return BAD_FUNC_ARG; 00254 00255 XMEMSET(key, 0, sizeof(ed25519_key)); 00256 00257 return 0; 00258 } 00259 00260 00261 /* clear memory of key */ 00262 void wc_ed25519_free(ed25519_key* key) 00263 { 00264 if (key == NULL) 00265 return; 00266 00267 ForceZero(key, sizeof(ed25519_key)); 00268 } 00269 00270 00271 #ifdef HAVE_ED25519_KEY_EXPORT 00272 00273 /* 00274 outLen should contain the size of out buffer when input. outLen is than set 00275 to the final output length. 00276 returns 0 on success 00277 */ 00278 int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) 00279 { 00280 /* sanity check on arguments */ 00281 if (key == NULL || out == NULL || outLen == NULL) 00282 return BAD_FUNC_ARG; 00283 00284 if (*outLen < ED25519_PUB_KEY_SIZE) { 00285 *outLen = ED25519_PUB_KEY_SIZE; 00286 return BUFFER_E; 00287 } 00288 00289 *outLen = ED25519_PUB_KEY_SIZE; 00290 XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE); 00291 00292 return 0; 00293 } 00294 00295 #endif /* HAVE_ED25519_KEY_EXPORT */ 00296 00297 00298 #ifdef HAVE_ED25519_KEY_IMPORT 00299 /* 00300 Imports a compressed/uncompressed public key. 00301 in the byte array containing the public key 00302 inLen the length of the byte array being passed in 00303 key ed25519 key struct to put the public key in 00304 */ 00305 int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) 00306 { 00307 int ret; 00308 00309 /* sanity check on arguments */ 00310 if (in == NULL || key == NULL) 00311 return BAD_FUNC_ARG; 00312 00313 if (inLen < ED25519_PUB_KEY_SIZE) 00314 return BAD_FUNC_ARG; 00315 00316 /* compressed prefix according to draft 00317 http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */ 00318 if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) { 00319 /* key is stored in compressed format so just copy in */ 00320 XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE); 00321 return 0; 00322 } 00323 00324 /* importing uncompressed public key */ 00325 if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) { 00326 /* pass in (x,y) and store compressed key */ 00327 ret = ge_compress_key(key->p, in+1, 00328 in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE); 00329 return ret; 00330 } 00331 00332 /* if not specified compressed or uncompressed check key size 00333 if key size is equal to compressed key size copy in key */ 00334 if (inLen == ED25519_PUB_KEY_SIZE) { 00335 XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE); 00336 return 0; 00337 } 00338 00339 /* bad public key format */ 00340 return BAD_FUNC_ARG; 00341 } 00342 00343 00344 /* 00345 For importing a private key and its associated public key. 00346 */ 00347 int wc_ed25519_import_private_key(const byte* priv, word32 privSz, 00348 const byte* pub, word32 pubSz, ed25519_key* key) 00349 { 00350 int ret; 00351 00352 /* sanity check on arguments */ 00353 if (priv == NULL || pub == NULL || key == NULL) 00354 return BAD_FUNC_ARG; 00355 00356 /* key size check */ 00357 if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE) 00358 return BAD_FUNC_ARG; 00359 00360 /* import public key */ 00361 ret = wc_ed25519_import_public(pub, pubSz, key); 00362 if (ret != 0) 00363 return ret; 00364 00365 /* make the private key (priv + pub) */ 00366 XMEMCPY(key->k, priv, ED25519_KEY_SIZE); 00367 XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); 00368 00369 return ret; 00370 } 00371 00372 #endif /* HAVE_ED25519_KEY_IMPORT */ 00373 00374 00375 #ifdef HAVE_ED25519_KEY_EXPORT 00376 00377 /* 00378 export private key only (secret part so 32 bytes) 00379 outLen should contain the size of out buffer when input. outLen is than set 00380 to the final output length. 00381 returns 0 on success 00382 */ 00383 int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) 00384 { 00385 /* sanity checks on arguments */ 00386 if (key == NULL || out == NULL || outLen == NULL) 00387 return BAD_FUNC_ARG; 00388 00389 if (*outLen < ED25519_KEY_SIZE) { 00390 *outLen = ED25519_KEY_SIZE; 00391 return BUFFER_E; 00392 } 00393 00394 *outLen = ED25519_KEY_SIZE; 00395 XMEMCPY(out, key->k, ED25519_KEY_SIZE); 00396 00397 return 0; 00398 } 00399 00400 /* 00401 export private key, including public part 00402 outLen should contain the size of out buffer when input. outLen is than set 00403 to the final output length. 00404 returns 0 on success 00405 */ 00406 int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) 00407 { 00408 /* sanity checks on arguments */ 00409 if (key == NULL || out == NULL || outLen == NULL) 00410 return BAD_FUNC_ARG; 00411 00412 if (*outLen < ED25519_PRV_KEY_SIZE) { 00413 *outLen = ED25519_PRV_KEY_SIZE; 00414 return BUFFER_E; 00415 } 00416 00417 *outLen = ED25519_PRV_KEY_SIZE; 00418 XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE); 00419 00420 return 0; 00421 } 00422 00423 /* export full private key and public key 00424 return 0 on success 00425 */ 00426 int wc_ed25519_export_key(ed25519_key* key, 00427 byte* priv, word32 *privSz, 00428 byte* pub, word32 *pubSz) 00429 { 00430 int ret; 00431 00432 /* export 'full' private part */ 00433 ret = wc_ed25519_export_private(key, priv, privSz); 00434 if (ret != 0) 00435 return ret; 00436 00437 /* export public part */ 00438 ret = wc_ed25519_export_public(key, pub, pubSz); 00439 00440 return ret; 00441 } 00442 00443 #endif /* HAVE_ED25519_KEY_EXPORT */ 00444 00445 00446 /* returns the private key size (secret only) in bytes */ 00447 int wc_ed25519_size(ed25519_key* key) 00448 { 00449 if (key == NULL) 00450 return BAD_FUNC_ARG; 00451 00452 return ED25519_KEY_SIZE; 00453 } 00454 00455 /* returns the private key size (secret + public) in bytes */ 00456 int wc_ed25519_priv_size(ed25519_key* key) 00457 { 00458 if (key == NULL) 00459 return BAD_FUNC_ARG; 00460 00461 return ED25519_PRV_KEY_SIZE; 00462 } 00463 00464 /* returns the compressed key size in bytes (public key) */ 00465 int wc_ed25519_pub_size(ed25519_key* key) 00466 { 00467 if (key == NULL) 00468 return BAD_FUNC_ARG; 00469 00470 return ED25519_PUB_KEY_SIZE; 00471 } 00472 00473 /* returns the size of signature in bytes */ 00474 int wc_ed25519_sig_size(ed25519_key* key) 00475 { 00476 if (key == NULL) 00477 return BAD_FUNC_ARG; 00478 00479 return ED25519_SIG_SIZE; 00480 } 00481 00482 #endif /* HAVE_ED25519 */ 00483 00484
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2