Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ed25519.c Source File

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, &ltcPoint, kLTC_Ed25519 /* result on Ed25519 */);
00165     LTC_PKHA_Ed25519_Compress(&ltcPoint, 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