Renesas / SecureDweet
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     #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