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