Created
March 7, 2022 16:13
-
-
Save bmatusiak/a1ac4b31cf5fd4c2c4ac2a9b0fd377ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef USE_ECDH | |
#include "mbedtls/include/mbedtls/ecdh.h" | |
static NO_INLINE JsVar *jswrap_crypto_ecdh(JsVar *message, JsVar *key, JsVar *options, bool genSecret ) { | |
int ret; | |
JSV_GET_AS_CHAR_ARRAY(msgPtr, msgLen, message); | |
if (!msgPtr) return 0; | |
mbedtls_ecdh_context ecdh_ctx; | |
mbedtls_ecdh_init( &ecdh_ctx ); | |
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_SECP256R1; | |
unsigned int is_CURVE25519 = 0; | |
if (jsvIsObject(options)) { | |
//curve option | |
JsVar *curveVar = jsvObjectGetChild(options, "curve", 0); | |
if (!jsvIsUndefined(curveVar) && jsvIsString(curveVar)){ | |
if(jsvIsStringEqual(curveVar, "curve25519")){ | |
curve_id = MBEDTLS_ECP_DP_CURVE25519; | |
jsvUnLock(curveVar); | |
is_CURVE25519 = 1; | |
}else{ | |
size_t curveLen = (jsvGetStringLength(curveVar) + 1); | |
char curve[curveLen]; | |
jsvGetString( curveVar, curve , curveLen); | |
jsvUnLock(curveVar); | |
const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_info_from_name( (const char *)curve ); | |
if (curve_info == NULL){ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError( " failed\n ! mbedtls_ecp_curve_info_from_name returned NULL" ); | |
return 0; | |
} | |
curve_id = curve_info->grp_id; | |
} | |
} | |
} else if (!jsvIsUndefined(options)) { | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError("'options' must be undefined, or an Object"); | |
return 0; | |
} | |
ret = mbedtls_ecp_group_load( &ecdh_ctx.grp, curve_id ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); | |
return 0; | |
} | |
//build private key from sha256 hash | |
unsigned char d[32]; | |
mbedtls_sha256((unsigned char *)msgPtr, msgLen, (unsigned char *)d, false/*256*/); | |
mbedtls_mpi_read_binary(&ecdh_ctx.d, d, sizeof(d)); | |
if(is_CURVE25519 == 1){ | |
size_t b; | |
mbedtls_mpi *dd = &ecdh_ctx.d; | |
mbedtls_ecp_group *d_grp = &ecdh_ctx.grp; | |
/* Make sure the most significant bit is nbits */ | |
b = mbedtls_mpi_bitlen( dd ) - 1; /* mbedtls_mpi_bitlen is one-based */ | |
if( b > d_grp->nbits ) | |
mbedtls_mpi_shift_r( dd, b - d_grp->nbits ); | |
else | |
mbedtls_mpi_set_bit( dd, d_grp->nbits, 1 ); | |
/* Make sure the last three bits are unset */ | |
mbedtls_mpi_set_bit( dd, 0, 0 ); | |
mbedtls_mpi_set_bit( dd, 1, 0 ); | |
mbedtls_mpi_set_bit( dd, 2, 0 ); | |
} | |
ret = mbedtls_ecp_check_privkey(&ecdh_ctx.grp, &ecdh_ctx.d); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError( " failed\n ! mbedtls_ecp_check_privkey returned %d\n", ret ); | |
return 0; | |
} | |
ret = mbedtls_ecp_mul( &ecdh_ctx.grp, &ecdh_ctx.Q, &ecdh_ctx.d, &(ecdh_ctx.grp.G), NULL, NULL ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError( " failed\n ! mbedtls_ecp_mul returned %d\n", ret ); | |
return 0; | |
} | |
ret = mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *)&ecdh_ctx, (const mbedtls_ecp_keypair *)&ecdh_ctx); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsError( " failed\n ! mbedtls_ecp_check_pub_priv returned %d\n", ret ); | |
return 0; | |
} | |
int bufferSize = 32; | |
char *outPtr = 0; | |
JsVar *outArr; | |
if(!genSecret){ | |
if(is_CURVE25519 == 0) | |
bufferSize = 64; | |
outArr = jsvNewArrayBufferWithPtr((unsigned int)bufferSize, &outPtr); | |
if (!outPtr) { | |
jsError("Not enough memory for result"); | |
return 0; | |
} | |
// outPtr[0] = 4; | |
ret = mbedtls_mpi_write_binary( &ecdh_ctx.Q.X, (unsigned char *)&outPtr[0], 32 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_write_binary X returned %d\n", ret ); | |
return 0; | |
} | |
if( is_CURVE25519 == 0){ | |
ret = mbedtls_mpi_write_binary( &ecdh_ctx.Q.Y, (unsigned char *)&outPtr[32], 32 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_write_binary Y returned %d\n", ret ); | |
return 0; | |
} | |
} | |
}else{ | |
bufferSize = 32; | |
outArr = jsvNewArrayBufferWithPtr((unsigned int)bufferSize, &outPtr); | |
if (!outPtr) { | |
jsError("Not enough memory for result"); | |
return 0; | |
} | |
JSV_GET_AS_CHAR_ARRAY(keyPtr, keyLen, key); | |
if (!keyPtr) { | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
return 0; | |
} | |
ret = mbedtls_mpi_lset( &ecdh_ctx.Qp.Z, 1 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); | |
return 0; | |
} | |
ret = mbedtls_mpi_read_binary( &ecdh_ctx.Qp.X, (unsigned char *)&keyPtr[0], 32 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); | |
return 0; | |
} | |
if( is_CURVE25519 == 0){ | |
ret = mbedtls_mpi_read_binary( &ecdh_ctx.Qp.Y, (unsigned char *)&keyPtr[32], 32 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); | |
return 0; | |
} | |
} | |
ret = mbedtls_ecdh_compute_shared( &ecdh_ctx.grp, &ecdh_ctx.z, | |
&ecdh_ctx.Qp, &ecdh_ctx.d, | |
NULL, NULL ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); | |
return 0; | |
} | |
ret = mbedtls_mpi_write_binary( &ecdh_ctx.z, (unsigned char *)outPtr, 32 ); | |
if( ret != 0 ) | |
{ | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
jsvUnLock(outArr); | |
jsError( " failed\n ! mbedtls_mpi_write_binary X returned %d\n", ret ); | |
return 0; | |
} | |
} | |
mbedtls_ecdh_free( &ecdh_ctx ); | |
return outArr; | |
} | |
/*JSON{ | |
"type" : "class", | |
"library" : "crypto", | |
"class" : "ECDH", | |
"ifdef" : "USE_ECDH" | |
} | |
Class containing ECDH | |
**Note:** This library is currently only included in builds for boards where there is space. For other boards there is `crypto.js` which implements SHA1 in JS. | |
*/ | |
/*JSON{ | |
"type" : "staticproperty", | |
"class" : "crypto", | |
"name" : "ECDH", | |
"generate_full" : "jspNewBuiltin(\"ECDH\");", | |
"return" : ["JsVar"], | |
"return_object" : "ECDH", | |
"ifdef" : "USE_ECDH" | |
} | |
Class containing ECDH | |
*/ | |
/*JSON{ | |
"type" : "staticmethod", | |
"class" : "ECDH", | |
"name" : "genpublic", | |
"generate" : "jswrap_crypto_ecdh_genpublic", | |
"params" : [ | |
["message","JsVar","Message to genpublic"], | |
["options","JsVar","options for ecdh"] | |
], | |
"return" : ["JsVar","Returns an ArrayBuffer"], | |
"return_object" : "ArrayBuffer", | |
"ifdef" : "USE_ECDH" | |
} | |
*/ | |
JsVar *jswrap_crypto_ecdh_genpublic(JsVar *message, JsVar *options) { | |
return jswrap_crypto_ecdh(message, NULL, options, false); | |
} | |
/*JSON{ | |
"type" : "staticmethod", | |
"class" : "ECDH", | |
"name" : "gensecret", | |
"generate" : "jswrap_crypto_ecdh_gensecret", | |
"params" : [ | |
["message","JsVar","Message to gensecret"], | |
["key","JsVar","key to gensecret"], | |
["options","JsVar","options for ecdh"] | |
], | |
"return" : ["JsVar","Returns an ArrayBuffer"], | |
"return_object" : "ArrayBuffer", | |
"ifdef" : "USE_ECDH" | |
} | |
*/ | |
JsVar *jswrap_crypto_ecdh_gensecret(JsVar *message, JsVar *key, JsVar *options) { | |
return jswrap_crypto_ecdh(message, key,options, true); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef USE_ECDH | |
JsVar *jswrap_crypto_ecdh_genpublic(JsVar *message, JsVar *options); | |
JsVar *jswrap_crypto_ecdh_gensecret(JsVar *message, JsVar *key, JsVar *options); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment