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