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-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
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2