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