Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers curve25519.c Source File

curve25519.c

00001 /* curve25519.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 curve25519 Public Domain ref10 work. */
00024 
00025 
00026 #ifdef HAVE_CONFIG_H
00027     #include <config.h>
00028 #endif
00029 
00030 #include <wolfssl/wolfcrypt/settings.h>
00031 
00032 #ifdef HAVE_CURVE25519
00033 
00034 #include <wolfssl/wolfcrypt/curve25519.h>
00035 #include <wolfssl/wolfcrypt/error-crypt.h>
00036 #ifdef NO_INLINE
00037     #include <wolfssl/wolfcrypt/misc.h>
00038 #else
00039     #include <wolfcrypt/src/misc.c>
00040 #endif
00041 
00042 const curve25519_set_type curve25519_sets[] = {
00043     {
00044         32,
00045         "CURVE25519",
00046     }
00047 };
00048 
00049 
00050 int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
00051 {
00052     unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
00053     int  ret;
00054 
00055     if (key == NULL || rng == NULL)
00056         return BAD_FUNC_ARG;
00057 
00058     /* currently only a key size of 32 bytes is used */
00059     if (keysize != CURVE25519_KEYSIZE)
00060         return ECC_BAD_ARG_E;
00061 
00062     /* random number for private key */
00063     ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize);
00064     if (ret != 0)
00065         return ret;
00066 
00067     /* Clamp the private key */
00068     key->k.point[0] &= 248;
00069     key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */
00070     key->k.point[CURVE25519_KEYSIZE-1] |= 64;
00071 
00072     /* compute public key */
00073     ret = curve25519(key->p.point, key->k.point, basepoint);
00074     if (ret != 0) {
00075         ForceZero(key->k.point, keysize);
00076         ForceZero(key->p.point, keysize);
00077         return ret;
00078     }
00079 
00080     return ret;
00081 }
00082 
00083 #ifdef HAVE_CURVE25519_SHARED_SECRET
00084 
00085 int wc_curve25519_shared_secret(curve25519_key* private_key,
00086                                 curve25519_key* public_key,
00087                                 byte* out, word32* outlen)
00088 {
00089     return wc_curve25519_shared_secret_ex(private_key, public_key,
00090                                           out, outlen, EC25519_BIG_ENDIAN);
00091 }
00092 
00093 int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
00094                                    curve25519_key* public_key,
00095                                    byte* out, word32* outlen, int endian)
00096 {
00097     unsigned char o[CURVE25519_KEYSIZE];
00098     int ret = 0;
00099 
00100     /* sanity check */
00101     if (private_key == NULL || public_key == NULL ||
00102         out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE)
00103         return BAD_FUNC_ARG;
00104 
00105     /* avoid implementation fingerprinting */
00106     if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F)
00107         return ECC_BAD_ARG_E;
00108 
00109     ret = curve25519(o, private_key->k.point, public_key->p.point);
00110     if (ret != 0) {
00111         ForceZero(o, CURVE25519_KEYSIZE);
00112         return ret;
00113     }
00114 
00115     if (endian == EC25519_BIG_ENDIAN) {
00116         int i;
00117         /* put shared secret key in Big Endian format */
00118         for (i = 0; i < CURVE25519_KEYSIZE; i++)
00119             out[i] = o[CURVE25519_KEYSIZE - i -1];
00120     }
00121     else /* put shared secret key in Little Endian format */
00122         XMEMCPY(out, o, CURVE25519_KEYSIZE);
00123 
00124     *outlen = CURVE25519_KEYSIZE;
00125 
00126     ForceZero(o, sizeof(o));
00127 
00128     return ret;
00129 }
00130 
00131 #endif /* HAVE_CURVE25519_SHARED_SECRET */
00132 
00133 #ifdef HAVE_CURVE25519_KEY_EXPORT
00134 
00135 /* export curve25519 public key (Big endian)
00136  * return 0 on success */
00137 int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
00138 {
00139     return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
00140 }
00141 
00142 /* export curve25519 public key (Big or Little endian)
00143  * return 0 on success */
00144 int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
00145                                    word32* outLen, int endian)
00146 {
00147     word32 keySz;
00148 
00149     if (key == NULL || out == NULL || outLen == NULL)
00150         return BAD_FUNC_ARG;
00151 
00152     /* check size of outgoing key */
00153     keySz  = wc_curve25519_size(key);
00154 
00155     /* check and set outgoing key size */
00156     if (*outLen < keySz) {
00157         *outLen = keySz;
00158         return ECC_BAD_ARG_E;
00159     }
00160     *outLen = keySz;
00161 
00162     if (endian == EC25519_BIG_ENDIAN) {
00163         int i;
00164 
00165         /* read keys in Big Endian format */
00166         for (i = 0; i < CURVE25519_KEYSIZE; i++)
00167             out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1];
00168     }
00169     else
00170         XMEMCPY(out, key->p.point, keySz);
00171 
00172     return 0;
00173 }
00174 
00175 #endif /* HAVE_CURVE25519_KEY_EXPORT */
00176 
00177 #ifdef HAVE_CURVE25519_KEY_IMPORT
00178 
00179 /* import curve25519 public key (Big endian)
00180  *  return 0 on success */
00181 int wc_curve25519_import_public(const byte* in, word32 inLen,
00182                                 curve25519_key* key)
00183 {
00184     return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
00185 }
00186 
00187 /* import curve25519 public key (Big or Little endian)
00188  * return 0 on success */
00189 int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
00190                                 curve25519_key* key, int endian)
00191 {
00192     word32 keySz;
00193 
00194     /* sanity check */
00195     if (key == NULL || in == NULL)
00196         return BAD_FUNC_ARG;
00197 
00198     /* check size of incoming keys */
00199     keySz = wc_curve25519_size(key);
00200     if (inLen != keySz)
00201        return ECC_BAD_ARG_E;
00202 
00203     if (endian == EC25519_BIG_ENDIAN) {
00204         int i;
00205 
00206         /* read keys in Big Endian format */
00207         for (i = 0; i < CURVE25519_KEYSIZE; i++)
00208             key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1];
00209     }
00210     else
00211         XMEMCPY(key->p.point, in, inLen);
00212 
00213     key->dp = &curve25519_sets[0];
00214 
00215     return 0;
00216 }
00217 
00218 #endif /* HAVE_CURVE25519_KEY_IMPORT */
00219 
00220 
00221 #ifdef HAVE_CURVE25519_KEY_EXPORT
00222 
00223 /* export curve25519 private key only raw (Big endian)
00224  * outLen is in/out size
00225  * return 0 on success */
00226 int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
00227                                      word32* outLen)
00228 {
00229     return wc_curve25519_export_private_raw_ex(key, out, outLen,
00230                                                EC25519_BIG_ENDIAN);
00231 }
00232 
00233 /* export curve25519 private key only raw (Big or Little endian)
00234  * outLen is in/out size
00235  * return 0 on success */
00236 int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
00237                                         word32* outLen, int endian)
00238 {
00239     word32 keySz;
00240 
00241     /* sanity check */
00242     if (key == NULL || out == NULL || outLen == NULL)
00243         return BAD_FUNC_ARG;
00244 
00245     /* check size of outgoing buffer */
00246     keySz = wc_curve25519_size(key);
00247     if (*outLen < keySz) {
00248         *outLen = keySz;
00249         return ECC_BAD_ARG_E;
00250     }
00251     *outLen = keySz;
00252 
00253     if (endian == EC25519_BIG_ENDIAN) {
00254         int i;
00255 
00256         /* put the key in Big Endian format */
00257         for (i = 0; i < CURVE25519_KEYSIZE; i++)
00258             out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1];
00259     }
00260     else
00261         XMEMCPY(out, key->k.point, keySz);
00262 
00263     return 0;
00264 }
00265 
00266 /* curve25519 key pair export (Big or Little endian)
00267  * return 0 on success */
00268 int wc_curve25519_export_key_raw(curve25519_key* key,
00269                                  byte* priv, word32 *privSz,
00270                                  byte* pub, word32 *pubSz)
00271 {
00272     return wc_curve25519_export_key_raw_ex(key, priv, privSz,
00273                                            pub, pubSz, EC25519_BIG_ENDIAN);
00274 }
00275 
00276 /* curve25519 key pair export (Big or Little endian)
00277  * return 0 on success */
00278 int wc_curve25519_export_key_raw_ex(curve25519_key* key,
00279                                     byte* priv, word32 *privSz,
00280                                     byte* pub, word32 *pubSz,
00281                                     int endian)
00282 {
00283     int ret;
00284 
00285     /* export private part */
00286     ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
00287     if (ret != 0)
00288         return ret;
00289 
00290     /* export public part */
00291     return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
00292 }
00293 
00294 #endif /* HAVE_CURVE25519_KEY_EXPORT */
00295 
00296 #ifdef HAVE_CURVE25519_KEY_IMPORT
00297 
00298 /* curve25519 private key import (Big endian)
00299  * Public key to match private key needs to be imported too
00300  * return 0 on success */
00301 int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
00302                                      const byte* pub, word32 pubSz,
00303                                      curve25519_key* key)
00304 {
00305     return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
00306                                                key, EC25519_BIG_ENDIAN);
00307 }
00308 
00309 /* curve25519 private key import (Big or Little endian)
00310  * Public key to match private key needs to be imported too
00311  * return 0 on success */
00312 int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
00313                                         const byte* pub, word32 pubSz,
00314                                         curve25519_key* key, int endian)
00315 {
00316     int ret;
00317 
00318     /* import private part */
00319     ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
00320     if (ret != 0)
00321         return ret;
00322 
00323     /* import public part */
00324     return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
00325 }
00326 
00327 /* curve25519 private key import only. (Big endian)
00328  * return 0 on success */
00329 int wc_curve25519_import_private(const byte* priv, word32 privSz,
00330                                  curve25519_key* key)
00331 {
00332     return wc_curve25519_import_private_ex(priv, privSz,
00333                                            key, EC25519_BIG_ENDIAN);
00334 }
00335 
00336 /* curve25519 private key import only. (Big or Little endian)
00337  * return 0 on success */
00338 int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
00339                                     curve25519_key* key, int endian)
00340 {
00341     /* sanity check */
00342     if (key == NULL || priv == NULL)
00343         return BAD_FUNC_ARG;
00344 
00345     /* check size of incoming keys */
00346     if ((int)privSz != wc_curve25519_size(key))
00347         return ECC_BAD_ARG_E;
00348 
00349     if (endian == EC25519_BIG_ENDIAN) {
00350         int i;
00351 
00352         /* read the key in Big Endian format */
00353         for (i = 0; i < CURVE25519_KEYSIZE; i++)
00354             key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1];
00355     }
00356     else
00357         XMEMCPY(key->k.point, priv, privSz);
00358 
00359     key->dp = &curve25519_sets[0];
00360 
00361     /* Clamp the key */
00362     key->k.point[0] &= 248;
00363     key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */
00364     key->k.point[privSz-1] |= 64;
00365 
00366     return 0;
00367 }
00368 
00369 #endif /* HAVE_CURVE25519_KEY_IMPORT */
00370 
00371 
00372 int wc_curve25519_init(curve25519_key* key)
00373 {
00374     if (key == NULL)
00375        return BAD_FUNC_ARG;
00376 
00377     /* currently the format for curve25519 */
00378     key->dp = &curve25519_sets[0];
00379 
00380     XMEMSET(key->k.point, 0, key->dp->size);
00381     XMEMSET(key->p.point, 0, key->dp->size);
00382 
00383     return 0;
00384 }
00385 
00386 
00387 /* Clean the memory of a key */
00388 void wc_curve25519_free(curve25519_key* key)
00389 {
00390    if (key == NULL)
00391        return;
00392 
00393    key->dp = NULL;
00394    ForceZero(key->p.point, sizeof(key->p.point));
00395    ForceZero(key->k.point, sizeof(key->k.point));
00396 }
00397 
00398 
00399 /* get key size */
00400 int wc_curve25519_size(curve25519_key* key)
00401 {
00402     if (key == NULL)
00403         return 0;
00404 
00405     return key->dp->size;
00406 }
00407 
00408 #endif /*HAVE_CURVE25519*/
00409 
00410