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-2017 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 <wolfcrypt/settings.h> 00031 00032 #ifdef HAVE_ED25519 00033 00034 #include <wolfcrypt/ed25519.h> 00035 #include <wolfcrypt/error-crypt.h> 00036 #include <wolfcrypt/hash.h> 00037 #ifdef NO_INLINE 00038 #include <wolfcrypt/misc.h> 00039 #else 00040 #define WOLFSSL_MISC_INCLUDED 00041 #include <wolfcrypt/src/misc.c> 00042 #endif 00043 00044 #ifdef FREESCALE_LTC_ECC 00045 #include <wolfcrypt/port/nxp/ksdk_port.h> 00046 #endif 00047 00048 /* generate an ed25519 key pair. 00049 * returns 0 on success 00050 */ 00051 int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) 00052 { 00053 byte az[ED25519_PRV_KEY_SIZE]; 00054 int ret; 00055 #if !defined(FREESCALE_LTC_ECC) 00056 ge_p3 A; 00057 #endif 00058 00059 if (rng == NULL || key == NULL) 00060 return BAD_FUNC_ARG; 00061 00062 /* ed25519 has 32 byte key sizes */ 00063 if (keySz != ED25519_KEY_SIZE) 00064 return BAD_FUNC_ARG; 00065 00066 ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); 00067 if (ret != 0) 00068 return ret; 00069 ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); 00070 if (ret != 0) { 00071 ForceZero(key->k, ED25519_KEY_SIZE); 00072 return ret; 00073 } 00074 00075 /* apply clamp */ 00076 az[0] &= 248; 00077 az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ 00078 az[31] |= 64; 00079 00080 #ifdef FREESCALE_LTC_ECC 00081 ltc_pkha_ecc_point_t publicKey = {0}; 00082 publicKey.X = key->pointX; 00083 publicKey.Y = key->pointY; 00084 LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az, ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */); 00085 LTC_PKHA_Ed25519_Compress(&publicKey, key->p); 00086 #else 00087 ge_scalarmult_base(&A, az); 00088 ge_p3_tobytes(key->p, &A); 00089 #endif 00090 /* put public key after private key, on the same buffer */ 00091 XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); 00092 00093 key->pubKeySet = 1; 00094 00095 return ret; 00096 } 00097 00098 00099 #ifdef HAVE_ED25519_SIGN 00100 /* 00101 in contains the message to sign 00102 inlen is the length of the message to sign 00103 out is the buffer to write the signature 00104 outLen [in/out] input size of out buf 00105 output gets set as the final length of out 00106 key is the ed25519 key to use when signing 00107 return 0 on success 00108 */ 00109 int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, 00110 word32 *outLen, ed25519_key* key) 00111 { 00112 #ifdef FREESCALE_LTC_ECC 00113 byte tempBuf[ED25519_PRV_KEY_SIZE]; 00114 #else 00115 ge_p3 R; 00116 #endif 00117 byte nonce[WC_SHA512_DIGEST_SIZE]; 00118 byte hram[WC_SHA512_DIGEST_SIZE]; 00119 byte az[ED25519_PRV_KEY_SIZE]; 00120 wc_Sha512 sha; 00121 int ret; 00122 00123 /* sanity check on arguments */ 00124 if (in == NULL || out == NULL || outLen == NULL || key == NULL) 00125 return BAD_FUNC_ARG; 00126 if (!key->pubKeySet) 00127 return BAD_FUNC_ARG; 00128 00129 /* check and set up out length */ 00130 if (*outLen < ED25519_SIG_SIZE) { 00131 *outLen = ED25519_SIG_SIZE; 00132 return BUFFER_E; 00133 } 00134 *outLen = ED25519_SIG_SIZE; 00135 00136 /* step 1: create nonce to use where nonce is r in 00137 r = H(h_b, ... ,h_2b-1,M) */ 00138 ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); 00139 if (ret != 0) 00140 return ret; 00141 00142 /* apply clamp */ 00143 az[0] &= 248; 00144 az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ 00145 az[31] |= 64; 00146 00147 ret = wc_InitSha512(&sha); 00148 if (ret != 0) 00149 return ret; 00150 ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); 00151 if (ret == 0) 00152 ret = wc_Sha512Update(&sha, in, inlen); 00153 if (ret == 0) 00154 ret = wc_Sha512Final(&sha, nonce); 00155 wc_Sha512Free(&sha); 00156 if (ret != 0) 00157 return ret; 00158 00159 #ifdef FREESCALE_LTC_ECC 00160 ltc_pkha_ecc_point_t ltcPoint = {0}; 00161 ltcPoint.X = &tempBuf[0]; 00162 ltcPoint.Y = &tempBuf[32]; 00163 LTC_PKHA_sc_reduce(nonce); 00164 LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, ED25519_KEY_SIZE, <cPoint, kLTC_Ed25519 /* result on Ed25519 */); 00165 LTC_PKHA_Ed25519_Compress(<cPoint, out); 00166 #else 00167 sc_reduce(nonce); 00168 00169 /* step 2: computing R = rB where rB is the scalar multiplication of 00170 r and B */ 00171 ge_scalarmult_base(&R,nonce); 00172 ge_p3_tobytes(out,&R); 00173 #endif 00174 00175 /* step 3: hash R + public key + message getting H(R,A,M) then 00176 creating S = (r + H(R,A,M)a) mod l */ 00177 ret = wc_InitSha512(&sha); 00178 if (ret != 0) 00179 return ret; 00180 ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2); 00181 if (ret == 0) 00182 ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); 00183 if (ret == 0) 00184 ret = wc_Sha512Update(&sha, in, inlen); 00185 if (ret == 0) 00186 ret = wc_Sha512Final(&sha, hram); 00187 wc_Sha512Free(&sha); 00188 if (ret != 0) 00189 return ret; 00190 00191 #ifdef FREESCALE_LTC_ECC 00192 LTC_PKHA_sc_reduce(hram); 00193 LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); 00194 #else 00195 sc_reduce(hram); 00196 sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); 00197 #endif 00198 00199 return ret; 00200 } 00201 00202 #endif /* HAVE_ED25519_SIGN */ 00203 00204 #ifdef HAVE_ED25519_VERIFY 00205 00206 /* 00207 sig is array of bytes containing the signature 00208 siglen is the length of sig byte array 00209 msg the array of bytes containing the message 00210 msglen length of msg array 00211 res will be 1 on successful verify and 0 on unsuccessful 00212 return 0 and res of 1 on success 00213 */ 00214 int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, 00215 word32 msglen, int* res, ed25519_key* key) 00216 { 00217 byte rcheck[ED25519_KEY_SIZE]; 00218 byte h[WC_SHA512_DIGEST_SIZE]; 00219 #ifndef FREESCALE_LTC_ECC 00220 ge_p3 A; 00221 ge_p2 R; 00222 #endif 00223 int ret; 00224 wc_Sha512 sha; 00225 00226 /* sanity check on arguments */ 00227 if (sig == NULL || msg == NULL || res == NULL || key == NULL) 00228 return BAD_FUNC_ARG; 00229 00230 /* set verification failed by default */ 00231 *res = 0; 00232 00233 /* check on basics needed to verify signature */ 00234 if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) 00235 return BAD_FUNC_ARG; 00236 00237 /* uncompress A (public key), test if valid, and negate it */ 00238 #ifndef FREESCALE_LTC_ECC 00239 if (ge_frombytes_negate_vartime(&A, key->p) != 0) 00240 return BAD_FUNC_ARG; 00241 #endif 00242 00243 /* find H(R,A,M) and store it as h */ 00244 ret = wc_InitSha512(&sha); 00245 if (ret != 0) 00246 return ret; 00247 ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2); 00248 if (ret == 0) 00249 ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); 00250 if (ret == 0) 00251 ret = wc_Sha512Update(&sha, msg, msglen); 00252 if (ret == 0) 00253 ret = wc_Sha512Final(&sha, h); 00254 wc_Sha512Free(&sha); 00255 if (ret != 0) 00256 return ret; 00257 00258 #ifdef FREESCALE_LTC_ECC 00259 LTC_PKHA_sc_reduce(h); 00260 LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key); 00261 #else 00262 sc_reduce(h); 00263 00264 /* 00265 Uses a fast single-signature verification SB = R + H(R,A,M)A becomes 00266 SB - H(R,A,M)A saving decompression of R 00267 */ 00268 ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2)); 00269 if (ret != 0) 00270 return ret; 00271 00272 ge_tobytes(rcheck, &R); 00273 #endif /* FREESCALE_LTC_ECC */ 00274 00275 /* comparison of R created to R in sig */ 00276 ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2); 00277 if (ret != 0) 00278 return SIG_VERIFY_E; 00279 00280 /* set the verification status */ 00281 *res = 1; 00282 00283 return ret; 00284 } 00285 00286 #endif /* HAVE_ED25519_VERIFY */ 00287 00288 00289 /* initialize information and memory for key */ 00290 int wc_ed25519_init(ed25519_key* key) 00291 { 00292 if (key == NULL) 00293 return BAD_FUNC_ARG; 00294 00295 XMEMSET(key, 0, sizeof(ed25519_key)); 00296 00297 #ifndef FREESCALE_LTC_ECC 00298 fe_init(); 00299 #endif 00300 00301 return 0; 00302 } 00303 00304 00305 /* clear memory of key */ 00306 void wc_ed25519_free(ed25519_key* key) 00307 { 00308 if (key == NULL) 00309 return; 00310 00311 ForceZero(key, sizeof(ed25519_key)); 00312 } 00313 00314 00315 #ifdef HAVE_ED25519_KEY_EXPORT 00316 00317 /* 00318 outLen should contain the size of out buffer when input. outLen is than set 00319 to the final output length. 00320 returns 0 on success 00321 */ 00322 int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) 00323 { 00324 /* sanity check on arguments */ 00325 if (key == NULL || out == NULL || outLen == NULL) 00326 return BAD_FUNC_ARG; 00327 00328 if (*outLen < ED25519_PUB_KEY_SIZE) { 00329 *outLen = ED25519_PUB_KEY_SIZE; 00330 return BUFFER_E; 00331 } 00332 00333 *outLen = ED25519_PUB_KEY_SIZE; 00334 XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE); 00335 00336 return 0; 00337 } 00338 00339 #endif /* HAVE_ED25519_KEY_EXPORT */ 00340 00341 00342 #ifdef HAVE_ED25519_KEY_IMPORT 00343 /* 00344 Imports a compressed/uncompressed public key. 00345 in the byte array containing the public key 00346 inLen the length of the byte array being passed in 00347 key ed25519 key struct to put the public key in 00348 */ 00349 int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) 00350 { 00351 int ret; 00352 00353 /* sanity check on arguments */ 00354 if (in == NULL || key == NULL) 00355 return BAD_FUNC_ARG; 00356 00357 if (inLen < ED25519_PUB_KEY_SIZE) 00358 return BAD_FUNC_ARG; 00359 00360 /* compressed prefix according to draft 00361 http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */ 00362 if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) { 00363 /* key is stored in compressed format so just copy in */ 00364 XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE); 00365 #ifdef FREESCALE_LTC_ECC 00366 /* recover X coordinate */ 00367 ltc_pkha_ecc_point_t pubKey; 00368 pubKey.X = key->pointX; 00369 pubKey.Y = key->pointY; 00370 LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); 00371 #endif 00372 key->pubKeySet = 1; 00373 return 0; 00374 } 00375 00376 /* importing uncompressed public key */ 00377 if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) { 00378 #ifdef FREESCALE_LTC_ECC 00379 /* reverse bytes for little endian byte order */ 00380 for (int i = 0; i < ED25519_KEY_SIZE; i++) 00381 { 00382 key->pointX[i] = *(in + ED25519_KEY_SIZE - i); 00383 key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i); 00384 } 00385 XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE); 00386 ret = 0; 00387 #else 00388 /* pass in (x,y) and store compressed key */ 00389 ret = ge_compress_key(key->p, in+1, 00390 in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE); 00391 #endif /* FREESCALE_LTC_ECC */ 00392 if (ret == 0) 00393 key->pubKeySet = 1; 00394 return ret; 00395 } 00396 00397 /* if not specified compressed or uncompressed check key size 00398 if key size is equal to compressed key size copy in key */ 00399 if (inLen == ED25519_PUB_KEY_SIZE) { 00400 XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE); 00401 #ifdef FREESCALE_LTC_ECC 00402 /* recover X coordinate */ 00403 ltc_pkha_ecc_point_t pubKey; 00404 pubKey.X = key->pointX; 00405 pubKey.Y = key->pointY; 00406 LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); 00407 #endif 00408 key->pubKeySet = 1; 00409 return 0; 00410 } 00411 00412 /* bad public key format */ 00413 return BAD_FUNC_ARG; 00414 } 00415 00416 00417 /* 00418 For importing a private key. 00419 */ 00420 int wc_ed25519_import_private_only(const byte* priv, word32 privSz, 00421 ed25519_key* key) 00422 { 00423 /* sanity check on arguments */ 00424 if (priv == NULL || key == NULL) 00425 return BAD_FUNC_ARG; 00426 00427 /* key size check */ 00428 if (privSz < ED25519_KEY_SIZE) 00429 return BAD_FUNC_ARG; 00430 00431 XMEMCPY(key->k, priv, ED25519_KEY_SIZE); 00432 00433 return 0; 00434 } 00435 00436 /* 00437 For importing a private key and its associated public key. 00438 */ 00439 int wc_ed25519_import_private_key(const byte* priv, word32 privSz, 00440 const byte* pub, word32 pubSz, ed25519_key* key) 00441 { 00442 int ret; 00443 00444 /* sanity check on arguments */ 00445 if (priv == NULL || pub == NULL || key == NULL) 00446 return BAD_FUNC_ARG; 00447 00448 /* key size check */ 00449 if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE) 00450 return BAD_FUNC_ARG; 00451 00452 /* import public key */ 00453 ret = wc_ed25519_import_public(pub, pubSz, key); 00454 if (ret != 0) 00455 return ret; 00456 00457 /* make the private key (priv + pub) */ 00458 XMEMCPY(key->k, priv, ED25519_KEY_SIZE); 00459 XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); 00460 00461 return ret; 00462 } 00463 00464 #endif /* HAVE_ED25519_KEY_IMPORT */ 00465 00466 00467 #ifdef HAVE_ED25519_KEY_EXPORT 00468 00469 /* 00470 export private key only (secret part so 32 bytes) 00471 outLen should contain the size of out buffer when input. outLen is than set 00472 to the final output length. 00473 returns 0 on success 00474 */ 00475 int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) 00476 { 00477 /* sanity checks on arguments */ 00478 if (key == NULL || out == NULL || outLen == NULL) 00479 return BAD_FUNC_ARG; 00480 00481 if (*outLen < ED25519_KEY_SIZE) { 00482 *outLen = ED25519_KEY_SIZE; 00483 return BUFFER_E; 00484 } 00485 00486 *outLen = ED25519_KEY_SIZE; 00487 XMEMCPY(out, key->k, ED25519_KEY_SIZE); 00488 00489 return 0; 00490 } 00491 00492 /* 00493 export private key, including public part 00494 outLen should contain the size of out buffer when input. outLen is than set 00495 to the final output length. 00496 returns 0 on success 00497 */ 00498 int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) 00499 { 00500 /* sanity checks on arguments */ 00501 if (key == NULL || out == NULL || outLen == NULL) 00502 return BAD_FUNC_ARG; 00503 00504 if (*outLen < ED25519_PRV_KEY_SIZE) { 00505 *outLen = ED25519_PRV_KEY_SIZE; 00506 return BUFFER_E; 00507 } 00508 00509 *outLen = ED25519_PRV_KEY_SIZE; 00510 XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE); 00511 00512 return 0; 00513 } 00514 00515 /* export full private key and public key 00516 return 0 on success 00517 */ 00518 int wc_ed25519_export_key(ed25519_key* key, 00519 byte* priv, word32 *privSz, 00520 byte* pub, word32 *pubSz) 00521 { 00522 int ret; 00523 00524 /* export 'full' private part */ 00525 ret = wc_ed25519_export_private(key, priv, privSz); 00526 if (ret != 0) 00527 return ret; 00528 00529 /* export public part */ 00530 ret = wc_ed25519_export_public(key, pub, pubSz); 00531 00532 return ret; 00533 } 00534 00535 #endif /* HAVE_ED25519_KEY_EXPORT */ 00536 00537 /* check the private and public keys match */ 00538 int wc_ed25519_check_key(ed25519_key* key) 00539 { 00540 /* TODO: Perform check of private and public key */ 00541 (void)key; 00542 00543 return 0; 00544 } 00545 00546 /* returns the private key size (secret only) in bytes */ 00547 int wc_ed25519_size(ed25519_key* key) 00548 { 00549 if (key == NULL) 00550 return BAD_FUNC_ARG; 00551 00552 return ED25519_KEY_SIZE; 00553 } 00554 00555 /* returns the private key size (secret + public) in bytes */ 00556 int wc_ed25519_priv_size(ed25519_key* key) 00557 { 00558 if (key == NULL) 00559 return BAD_FUNC_ARG; 00560 00561 return ED25519_PRV_KEY_SIZE; 00562 } 00563 00564 /* returns the compressed key size in bytes (public key) */ 00565 int wc_ed25519_pub_size(ed25519_key* key) 00566 { 00567 if (key == NULL) 00568 return BAD_FUNC_ARG; 00569 00570 return ED25519_PUB_KEY_SIZE; 00571 } 00572 00573 /* returns the size of signature in bytes */ 00574 int wc_ed25519_sig_size(ed25519_key* key) 00575 { 00576 if (key == NULL) 00577 return BAD_FUNC_ARG; 00578 00579 return ED25519_SIG_SIZE; 00580 } 00581 00582 #endif /* HAVE_ED25519 */ 00583 00584
Generated on Tue Jul 12 2022 16:58:05 by
1.7.2