int AESContext::cryptCFB8(State & state, mbedtls_aes_context * context){ Stack * stack = state.stack; if (stack->is<LUA_TNUMBER>(1) && stack->is<LUA_TSTRING>(2) && stack->is<LUA_TSTRING>(3)){ std::string ivStr = stack->toLString(2); std::string input = stack->toLString(3); size_t length = input.length(); if (((length % 16) == 0) && (ivStr.length() == 16)){ int mode = stack->to<int>(1); unsigned char iv[16]; unsigned char * output = new unsigned char[length]; memcpy(iv, ivStr.c_str(), 16); int result = mbedtls_aes_crypt_cfb8(context, mode, length, iv, reinterpret_cast<const unsigned char *>(input.c_str()), output); if (result == 0){ stack->pushLString(std::string(reinterpret_cast<char*>(iv), 16)); stack->pushLString(std::string(reinterpret_cast<char*>(output), length)); delete[] output; return 2; } else{ stack->push<int>(result); delete[] output; return 1; } } else{ stack->push<bool>(false); return 1; } } return 0; }
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; } }
void Java_net_md_15_bungee_jni_cipher_NativeCipherImpl_cipher(JNIEnv* env, jobject obj, jlong ctx, jlong in, jlong out, jint length) { crypto_context *crypto = (crypto_context*) ctx; mbedtls_aes_crypt_cfb8(&crypto->cipher, crypto->mode, length, crypto->key, (byte*) in, (byte*) out); }