mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
working PBKDF2, and AES doing something, but not tested
This commit is contained in:
parent
2805ce4f84
commit
26f965510a
7
Makefile
7
Makefile
@ -975,10 +975,15 @@ ifdef USE_CRYPTO
|
||||
INCLUDE += -I$(ROOT)/libs/crypto/mbedtls/include
|
||||
WRAPPERSOURCES += libs/crypto/jswrap_crypto.c
|
||||
SOURCES += \
|
||||
libs/crypto/mbedtls/library/aes.c \
|
||||
libs/crypto/mbedtls/library/asn1parse.c \
|
||||
libs/crypto/mbedtls/library/cipher.c \
|
||||
libs/crypto/mbedtls/library/cipher_wrap.c \
|
||||
libs/crypto/mbedtls/library/md.c \
|
||||
libs/crypto/mbedtls/library/md_wrap.c \
|
||||
libs/crypto/mbedtls/library/oid.c \
|
||||
libs/crypto/mbedtls/library/pkcs5.c
|
||||
libs/crypto/mbedtls/library/pkcs5.c \
|
||||
libs/crypto/mbedtls/library/sha1.c
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "jsvariterator.h"
|
||||
#include "jswrap_crypto.h"
|
||||
|
||||
#include "mbedtls/include/mbedtls/aes.h"
|
||||
#include "mbedtls/include/mbedtls/pkcs5.h"
|
||||
|
||||
|
||||
@ -30,19 +31,16 @@ Cryptographic functions
|
||||
For other boards you will have to make build your own firmware.
|
||||
*/
|
||||
|
||||
mbedtls_md_context_t tls_md_ctx;
|
||||
bool tls_md_ctx_init = false;
|
||||
|
||||
mbedtls_md_context_t *jswrap_crypto_getContext() {
|
||||
if (!tls_md_ctx_init) {
|
||||
// FIXME
|
||||
tls_md_ctx_init = true;
|
||||
mbedtls_md_init( &tls_md_ctx );
|
||||
void jswrap_crypto_error(int err) {
|
||||
const char *e = 0;
|
||||
switch(err) {
|
||||
case MBEDTLS_ERR_MD_BAD_INPUT_DATA: e="Bad Input Data"; break;
|
||||
case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: e="Invalid input length"; break;
|
||||
}
|
||||
return &tls_md_ctx;
|
||||
if (e) jsError(e);
|
||||
else jsError("Unknown error: -0x%x", -err);
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"library" : "crypto",
|
||||
@ -55,16 +53,16 @@ A structure containing an array of 32 bit words
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"library" : "crypto",
|
||||
"class" : "crypto",
|
||||
"name" : "PBKDF2",
|
||||
"generate" : "jswrap_crypto_PBKDF2",
|
||||
"params" : [
|
||||
["passphrase","JsVar",""],
|
||||
["passphrase","JsVar","Passphrase"],
|
||||
["salt","JsVar","Salt for turning passphrase into a key"],
|
||||
["options","JsVar","Object of Options, `{ keySize: 8, iterations: 10 }`"]
|
||||
],
|
||||
"return" : ["JsVar","Returns a WordArray structure"],
|
||||
"return_object" : "WordArray"
|
||||
"return" : ["JsVar","Returns an ArrayBuffer"],
|
||||
"return_object" : "ArrayBuffer"
|
||||
}
|
||||
|
||||
Password-Based Key Derivation Function 2 algorithm.
|
||||
@ -74,35 +72,125 @@ JsVar *jswrap_crypto_PBKDF2(JsVar *passphrase, JsVar *salt, JsVar *options) {
|
||||
int keySize = 128/32;
|
||||
if (jsvIsObject(options)) {
|
||||
keySize = jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "keySize", 0));
|
||||
if (keySize<1) keySize=1;
|
||||
if (keySize<128/32) keySize=128/32;
|
||||
iterations = jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "iterations", 0));
|
||||
if (iterations<1) iterations = 1;
|
||||
} else if (!jsvIsUndefined(options))
|
||||
jsError("Options should be an object or undefined, got %t", options);
|
||||
|
||||
JSV_GET_AS_CHAR_ARRAY(passPtr, passLen, passphrase);
|
||||
if (!passPtr) return 0;
|
||||
JSV_GET_AS_CHAR_ARRAY(saltPtr, saltLen, salt);
|
||||
if (!saltPtr) return 0;
|
||||
|
||||
mbedtls_md_context_t *ctx = jswrap_crypto_getContext();
|
||||
int err;
|
||||
mbedtls_md_context_t ctx;
|
||||
|
||||
JsVar *keyStr = jsvNewFlatStringOfLength(keySize*4);
|
||||
if (!jsvIsFlatString(keyStr)) {
|
||||
jsError("Not enough memory");
|
||||
jsvUnLock(keyStr);
|
||||
mbedtls_md_init( &ctx );
|
||||
err = mbedtls_md_setup( &ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ), 1 );
|
||||
assert(err==0)
|
||||
|
||||
char *keyPtr = 0;
|
||||
JsVar *keyArr = jsvNewArrayBufferWithPtr((unsigned)keySize*4, &keyPtr);
|
||||
if (!keyPtr) {
|
||||
jsError("Not enough memory for result");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err = mbedtls_pkcs5_pbkdf2_hmac( ctx, passPtr, passLen,
|
||||
saltPtr, saltLen,
|
||||
iterations,
|
||||
keySize*4, jsvGetFlatStringPointer(keyStr) );
|
||||
err = mbedtls_pkcs5_pbkdf2_hmac( &ctx,
|
||||
(unsigned char*)passPtr, passLen,
|
||||
(unsigned char*)saltPtr, saltLen,
|
||||
(unsigned)iterations,
|
||||
(unsigned)keySize*4, (unsigned char*)keyPtr );
|
||||
|
||||
if (!err) {
|
||||
// TODO: not WordArray
|
||||
return keyStr;
|
||||
return keyArr;
|
||||
} else {
|
||||
jsError("Cryto: err %d", err);
|
||||
jsvUnLock(keyStr);
|
||||
jswrap_crypto_error(err);
|
||||
jsvUnLock(keyArr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static NO_INLINE JsVar *jswrap_crypto_AES_crypt(JsVar *message, JsVar *key, bool encrypt) {
|
||||
int err;
|
||||
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init( &aes );
|
||||
|
||||
JSV_GET_AS_CHAR_ARRAY(messagePtr, messageLen, message);
|
||||
if (!messagePtr) return 0;
|
||||
|
||||
JSV_GET_AS_CHAR_ARRAY(keyPtr, keyLen, key);
|
||||
if (!keyPtr) return 0;
|
||||
|
||||
if (encrypt)
|
||||
err = mbedtls_aes_setkey_enc( &aes, (unsigned char*)keyPtr, keyLen*8 );
|
||||
else
|
||||
err = mbedtls_aes_setkey_dec( &aes, (unsigned char*)keyPtr, keyLen*8 );
|
||||
if (err) {
|
||||
jswrap_crypto_error(err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *outPtr = 0;
|
||||
JsVar *outVar = jsvNewArrayBufferWithPtr(messageLen, &outPtr);
|
||||
if (!outPtr) {
|
||||
jsError("Not enough memory for result");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char iv[16]; // initialisation vector
|
||||
memset(iv, 0, 16);
|
||||
|
||||
err = mbedtls_aes_crypt_cbc( &aes,
|
||||
encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT,
|
||||
messageLen,
|
||||
iv,
|
||||
messagePtr,
|
||||
outPtr );
|
||||
|
||||
mbedtls_aes_free( &aes );
|
||||
if (!err) {
|
||||
return outVar;
|
||||
} else {
|
||||
jswrap_crypto_error(err);
|
||||
jsvUnLock(outVar);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "crypto",
|
||||
"name" : "AES_encrypt",
|
||||
"generate" : "jswrap_crypto_AES_encrypt",
|
||||
"params" : [
|
||||
["passphrase","JsVar","Message to encrypt"],
|
||||
["key","JsVar","Key to encrypt message - must be an ArrayBuffer of 128, 192, or 256 BITS"]
|
||||
],
|
||||
"return" : ["JsVar","Returns an ArrayBuffer"],
|
||||
"return_object" : "ArrayBuffer"
|
||||
}
|
||||
*/
|
||||
JsVar *jswrap_crypto_AES_encrypt(JsVar *message, JsVar *key) {
|
||||
return jswrap_crypto_AES_crypt(message, key, true);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "crypto",
|
||||
"name" : "AES_decrypt",
|
||||
"generate" : "jswrap_crypto_AES_decrypt",
|
||||
"params" : [
|
||||
["passphrase","JsVar","Message to decrypt"],
|
||||
["key","JsVar","Key to encrypt message - must be an ArrayBuffer of 128, 192, or 256 BITS"]
|
||||
],
|
||||
"return" : ["JsVar","Returns an ArrayBuffer"],
|
||||
"return_object" : "ArrayBuffer"
|
||||
}
|
||||
*/
|
||||
JsVar *jswrap_crypto_AES_decrypt(JsVar *message, JsVar *key) {
|
||||
return jswrap_crypto_AES_crypt(message, key, false);
|
||||
}
|
||||
|
||||
@ -16,3 +16,6 @@
|
||||
#include "jsvar.h"
|
||||
|
||||
JsVar *jswrap_crypto_PBKDF2(JsVar *passphrase, JsVar *salt, JsVar *options);
|
||||
|
||||
JsVar *jswrap_crypto_AES_encrypt(JsVar *message, JsVar *key);
|
||||
JsVar *jswrap_crypto_AES_decrypt(JsVar *message, JsVar *key);
|
||||
|
||||
@ -37,22 +37,23 @@
|
||||
*/
|
||||
|
||||
/* mbed TLS feature support */
|
||||
/*
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
/*
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||
*/
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PKCS5_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
|
||||
/*
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
|
||||
@ -66,7 +67,7 @@
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
|
||||
15
src/jsvar.c
15
src/jsvar.c
@ -3068,3 +3068,18 @@ JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length) {
|
||||
jsvUnLock(lenVar);
|
||||
return array;
|
||||
}
|
||||
|
||||
JsVar *jsvNewArrayBufferWithPtr(unsigned int length, char **ptr) {
|
||||
assert(ptr);
|
||||
*ptr=0;
|
||||
JsVar *backingString = jsvNewFlatStringOfLength(length);
|
||||
if (!backingString) return 0;
|
||||
JsVar *arr = jsvNewArrayBufferFromString(backingString, length);
|
||||
if (!arr) {
|
||||
jsvUnLock(backingString);
|
||||
return 0;
|
||||
}
|
||||
*ptr = jsvGetFlatStringPointer(backingString);
|
||||
jsvUnLock(backingString);
|
||||
return arr;
|
||||
}
|
||||
|
||||
11
src/jsvar.h
11
src/jsvar.h
@ -669,6 +669,11 @@ bool jsvReadConfigObject(JsVar *object, jsvConfigObject *configs, int nConfigs);
|
||||
/// Create a new typed array of the given type and length
|
||||
JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length);
|
||||
|
||||
/** Create a new arraybuffer of the given type and length, also return a pointer
|
||||
* to the contiguous memory area containing it. Returns 0 if it was unable to
|
||||
* allocate it. */
|
||||
JsVar *jsvNewArrayBufferWithPtr(unsigned int length, char **ptr);
|
||||
|
||||
/** Get the given JsVar as a character array. If it's a flat string, return a
|
||||
* pointer to it, or if it isn't allocate data on the stack and copy the data.
|
||||
*
|
||||
@ -676,7 +681,7 @@ JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length);
|
||||
* the data will be lost when we return. */
|
||||
#define JSV_GET_AS_CHAR_ARRAY(TARGET_PTR, TARGET_LENGTH, DATA) \
|
||||
size_t TARGET_LENGTH = 0; \
|
||||
unsigned char *TARGET_PTR = 0; \
|
||||
char *TARGET_PTR = 0; \
|
||||
if (jsvIsFlatString(DATA)) { \
|
||||
TARGET_LENGTH = jsvGetStringLength(DATA); \
|
||||
TARGET_PTR = jsvGetFlatStringPointer(DATA); \
|
||||
@ -685,8 +690,8 @@ JsVar *jsvNewTypedArray(JsVarDataArrayBufferViewType type, JsVarInt length);
|
||||
if (TARGET_LENGTH+256 > jsuGetFreeStack()) { \
|
||||
jsExceptionHere(JSET_ERROR, "Not enough stack memory to decode data"); \
|
||||
} else { \
|
||||
unsigned char *TARGET_PTR = (unsigned char *)alloca(TARGET_LENGTH); \
|
||||
jsvIterateCallbackToBytes(DATA, TARGET_PTR, (unsigned int)TARGET_LENGTH); \
|
||||
TARGET_PTR = (char *)alloca(TARGET_LENGTH); \
|
||||
jsvIterateCallbackToBytes(DATA, (unsigned char *)TARGET_PTR, (unsigned int)TARGET_LENGTH); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user