void jswrap_i2c_writeTo(JsVar *parent, JsVar *addressVar, JsVar *args) { IOEventFlags device = jsiGetDeviceFromClass(parent); if (!DEVICE_IS_I2C(device)) return; bool sendStop = true; int address = i2c_get_address(addressVar, &sendStop); size_t l = (size_t)jsvIterateCallbackCount(args); if (l+256 > jsuGetFreeStack()) { jsExceptionHere(JSET_ERROR, "Not enough free stack to send this amount of data"); return; } unsigned char *data = (unsigned char *)alloca(l); jsvIterateCallbackToBytes(args, data, l); jshI2CWrite(device, (unsigned char)address, l, data, sendStop); }
static NO_INLINE JsVar *jswrap_crypto_AEScrypt(JsVar *message, JsVar *key, JsVar *options, bool encrypt) { int err; unsigned char iv[16]; // initialisation vector memset(iv, 0, 16); CryptoMode mode = CM_CBC; if (jsvIsObject(options)) { JsVar *ivVar = jsvObjectGetChild(options, "iv", 0); if (ivVar) { jsvIterateCallbackToBytes(ivVar, iv, sizeof(iv)); jsvUnLock(ivVar); } JsVar *modeVar = jsvObjectGetChild(options, "mode", 0); if (!jsvIsUndefined(modeVar)) mode = jswrap_crypto_getMode(modeVar); jsvUnLock(modeVar); if (mode == CM_NONE) return 0; } else if (!jsvIsUndefined(options)) { jsError("'options' must be undefined, or an Object"); return 0; } 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, (unsigned int)keyLen*8 ); else err = mbedtls_aes_setkey_dec( &aes, (unsigned char*)keyPtr, (unsigned int)keyLen*8 ); if (err) { jswrap_crypto_error(err); return 0; } char *outPtr = 0; JsVar *outVar = jsvNewArrayBufferWithPtr((unsigned int)messageLen, &outPtr); if (!outPtr) { jsError("Not enough memory for result"); return 0; } switch (mode) { case CM_CBC: err = mbedtls_aes_crypt_cbc( &aes, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, messageLen, iv, (unsigned char*)messagePtr, (unsigned char*)outPtr ); break; case CM_CFB: err = mbedtls_aes_crypt_cfb8( &aes, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, messageLen, iv, (unsigned char*)messagePtr, (unsigned char*)outPtr ); break; case CM_CTR: { size_t nc_off = 0; unsigned char nonce_counter[16]; unsigned char stream_block[16]; memset(nonce_counter, 0, sizeof(nonce_counter)); memset(stream_block, 0, sizeof(stream_block)); err = mbedtls_aes_crypt_ctr( &aes, messageLen, &nc_off, nonce_counter, stream_block, (unsigned char*)messagePtr, (unsigned char*)outPtr ); break; } case CM_ECB: { size_t i = 0; while (!err && i+15 < messageLen) { err = mbedtls_aes_crypt_ecb( &aes, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, (unsigned char*)&messagePtr[i], (unsigned char*)&outPtr[i] ); i += 16; } break; } default: err = MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; break; } mbedtls_aes_free( &aes ); if (!err) { return outVar; } else { jswrap_crypto_error(err); jsvUnLock(outVar); return 0; } }