wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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