wolfSSL SSL/TLS library, support up to TLS1.3
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
curve25519.c
00001 /* curve25519.c 00002 * 00003 * Copyright (C) 2006-2020 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 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 /* Check the public key value (big or little endian) 00261 * 00262 * pub Public key bytes. 00263 * pubSz Size of public key in bytes. 00264 * endian Public key bytes passed in as big-endian or little-endian. 00265 * returns BAD_FUNC_ARGS when pub is NULL, 00266 * BUFFER_E when size of public key is zero; 00267 * ECC_OUT_OF_RANGE_E if the high bit is set; 00268 * ECC_BAD_ARG_E if key length is not 32 bytes, public key value is 00269 * zero or one; and 00270 * 0 otherwise. 00271 */ 00272 int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian) 00273 { 00274 word32 i; 00275 00276 if (pub == NULL) 00277 return BAD_FUNC_ARG; 00278 00279 /* Check for empty key data */ 00280 if (pubSz == 0) 00281 return BUFFER_E; 00282 00283 /* Check key length */ 00284 if (pubSz != CURVE25519_KEYSIZE) 00285 return ECC_BAD_ARG_E; 00286 00287 00288 if (endian == EC25519_LITTLE_ENDIAN) { 00289 /* Check for value of zero or one */ 00290 for (i = pubSz - 1; i > 0; i--) { 00291 if (pub[i] != 0) 00292 break; 00293 } 00294 if (i == 0 && (pub[0] == 0 || pub[0] == 1)) 00295 return ECC_BAD_ARG_E; 00296 00297 /* Check high bit set */ 00298 if (pub[CURVE25519_KEYSIZE-1] & 0x80) 00299 return ECC_OUT_OF_RANGE_E; 00300 } 00301 else { 00302 /* Check for value of zero or one */ 00303 for (i = 0; i < pubSz-1; i++) { 00304 if (pub[i] != 0) 00305 break; 00306 } 00307 if (i == pubSz - 1 && (pub[i] == 0 || pub[i] == 1)) 00308 return ECC_BAD_ARG_E; 00309 00310 /* Check high bit set */ 00311 if (pub[0] & 0x80) 00312 return ECC_OUT_OF_RANGE_E; 00313 } 00314 00315 return 0; 00316 } 00317 00318 #endif /* HAVE_CURVE25519_KEY_IMPORT */ 00319 00320 00321 #ifdef HAVE_CURVE25519_KEY_EXPORT 00322 00323 /* export curve25519 private key only raw (Big endian) 00324 * outLen is in/out size 00325 * return 0 on success */ 00326 int wc_curve25519_export_private_raw(curve25519_key* key, byte* out, 00327 word32* outLen) 00328 { 00329 return wc_curve25519_export_private_raw_ex(key, out, outLen, 00330 EC25519_BIG_ENDIAN); 00331 } 00332 00333 /* export curve25519 private key only raw (Big or Little endian) 00334 * outLen is in/out size 00335 * return 0 on success */ 00336 int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, 00337 word32* outLen, int endian) 00338 { 00339 /* sanity check */ 00340 if (key == NULL || out == NULL || outLen == NULL) 00341 return BAD_FUNC_ARG; 00342 00343 /* check size of outgoing buffer */ 00344 if (*outLen < CURVE25519_KEYSIZE) { 00345 *outLen = CURVE25519_KEYSIZE; 00346 return ECC_BAD_ARG_E; 00347 } 00348 *outLen = CURVE25519_KEYSIZE; 00349 00350 if (endian == EC25519_BIG_ENDIAN) { 00351 int i; 00352 00353 /* put the key in Big Endian format */ 00354 for (i = 0; i < CURVE25519_KEYSIZE; i++) 00355 out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1]; 00356 } 00357 else 00358 XMEMCPY(out, key->k.point, CURVE25519_KEYSIZE); 00359 00360 return 0; 00361 } 00362 00363 /* curve25519 key pair export (Big or Little endian) 00364 * return 0 on success */ 00365 int wc_curve25519_export_key_raw(curve25519_key* key, 00366 byte* priv, word32 *privSz, 00367 byte* pub, word32 *pubSz) 00368 { 00369 return wc_curve25519_export_key_raw_ex(key, priv, privSz, 00370 pub, pubSz, EC25519_BIG_ENDIAN); 00371 } 00372 00373 /* curve25519 key pair export (Big or Little endian) 00374 * return 0 on success */ 00375 int wc_curve25519_export_key_raw_ex(curve25519_key* key, 00376 byte* priv, word32 *privSz, 00377 byte* pub, word32 *pubSz, 00378 int endian) 00379 { 00380 int ret; 00381 00382 /* export private part */ 00383 ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian); 00384 if (ret != 0) 00385 return ret; 00386 00387 /* export public part */ 00388 return wc_curve25519_export_public_ex(key, pub, pubSz, endian); 00389 } 00390 00391 #endif /* HAVE_CURVE25519_KEY_EXPORT */ 00392 00393 #ifdef HAVE_CURVE25519_KEY_IMPORT 00394 00395 /* curve25519 private key import (Big endian) 00396 * Public key to match private key needs to be imported too 00397 * return 0 on success */ 00398 int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, 00399 const byte* pub, word32 pubSz, 00400 curve25519_key* key) 00401 { 00402 return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz, 00403 key, EC25519_BIG_ENDIAN); 00404 } 00405 00406 /* curve25519 private key import (Big or Little endian) 00407 * Public key to match private key needs to be imported too 00408 * return 0 on success */ 00409 int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz, 00410 const byte* pub, word32 pubSz, 00411 curve25519_key* key, int endian) 00412 { 00413 int ret; 00414 00415 /* import private part */ 00416 ret = wc_curve25519_import_private_ex(priv, privSz, key, endian); 00417 if (ret != 0) 00418 return ret; 00419 00420 /* import public part */ 00421 return wc_curve25519_import_public_ex(pub, pubSz, key, endian); 00422 } 00423 00424 /* curve25519 private key import only. (Big endian) 00425 * return 0 on success */ 00426 int wc_curve25519_import_private(const byte* priv, word32 privSz, 00427 curve25519_key* key) 00428 { 00429 return wc_curve25519_import_private_ex(priv, privSz, 00430 key, EC25519_BIG_ENDIAN); 00431 } 00432 00433 /* curve25519 private key import only. (Big or Little endian) 00434 * return 0 on success */ 00435 int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, 00436 curve25519_key* key, int endian) 00437 { 00438 /* sanity check */ 00439 if (key == NULL || priv == NULL) 00440 return BAD_FUNC_ARG; 00441 00442 /* check size of incoming keys */ 00443 if ((int)privSz != CURVE25519_KEYSIZE) 00444 return ECC_BAD_ARG_E; 00445 00446 if (endian == EC25519_BIG_ENDIAN) { 00447 int i; 00448 00449 /* read the key in Big Endian format */ 00450 for (i = 0; i < CURVE25519_KEYSIZE; i++) 00451 key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1]; 00452 } 00453 else 00454 XMEMCPY(key->k.point, priv, CURVE25519_KEYSIZE); 00455 00456 key->dp = &curve25519_sets[0]; 00457 00458 /* Clamp the key */ 00459 key->k.point[0] &= 248; 00460 key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */ 00461 key->k.point[privSz-1] |= 64; 00462 00463 return 0; 00464 } 00465 00466 #endif /* HAVE_CURVE25519_KEY_IMPORT */ 00467 00468 00469 int wc_curve25519_init(curve25519_key* key) 00470 { 00471 if (key == NULL) 00472 return BAD_FUNC_ARG; 00473 00474 XMEMSET(key, 0, sizeof(*key)); 00475 00476 /* currently the format for curve25519 */ 00477 key->dp = &curve25519_sets[0]; 00478 00479 #ifndef FREESCALE_LTC_ECC 00480 fe_init(); 00481 #endif 00482 00483 return 0; 00484 } 00485 00486 00487 /* Clean the memory of a key */ 00488 void wc_curve25519_free(curve25519_key* key) 00489 { 00490 if (key == NULL) 00491 return; 00492 00493 key->dp = NULL; 00494 ForceZero(key->p.point, sizeof(key->p.point)); 00495 ForceZero(key->k.point, sizeof(key->k.point)); 00496 #ifdef FREESCALE_LTC_ECC 00497 ForceZero(key->p.point, sizeof(key->p.pointY)); 00498 ForceZero(key->k.point, sizeof(key->k.pointY)); 00499 #endif 00500 } 00501 00502 00503 /* get key size */ 00504 int wc_curve25519_size(curve25519_key* key) 00505 { 00506 if (key == NULL) 00507 return 0; 00508 00509 return key->dp->size; 00510 } 00511 00512 #endif /*HAVE_CURVE25519*/ 00513 00514
Generated on Tue Jul 12 2022 20:58:34 by 1.7.2