Basic WebAssembly support with minimal Javascript API #615. Currently 6/12 crypto functions supported. Tested in browser with all default features disabled.

This commit is contained in:
Rujia Liu
2023-09-08 17:27:22 +08:00
parent a0b5a24853
commit b6ce6b7cdb
9 changed files with 184 additions and 32 deletions

View File

@@ -4742,18 +4742,22 @@ impl Machine {
self.crypto_password_hash();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallCryptoDataEncrypt => {
self.crypto_data_encrypt();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteCryptoDataEncrypt => {
self.crypto_data_encrypt();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallCryptoDataDecrypt => {
self.crypto_data_decrypt();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteCryptoDataDecrypt => {
self.crypto_data_decrypt();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
@@ -4766,34 +4770,42 @@ impl Machine {
self.crypto_curve_scalar_mult();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallEd25519Sign => {
self.ed25519_sign();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteEd25519Sign => {
self.ed25519_sign();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallEd25519Verify => {
self.ed25519_verify();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteEd25519Verify => {
self.ed25519_verify();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallEd25519NewKeyPair => {
self.ed25519_new_key_pair();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteEd25519NewKeyPair => {
self.ed25519_new_key_pair();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
#[cfg(feature = "crypto-full")]
&Instruction::CallEd25519KeyPairPublicKey => {
self.ed25519_key_pair_public_key();
step_or_fail!(self, self.machine_st.p += 1);
}
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteEd25519KeyPairPublicKey => {
self.ed25519_key_pair_public_key();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);

View File

@@ -332,6 +332,19 @@ impl Machine {
self.load_file(file.into(), stream);
self.user_output.bytes().map(|b| b.unwrap()).collect()
}
pub fn test_load_string(&mut self, code: &str) -> Vec<u8> {
use std::io::Read;
let stream = Stream::from_owned_string(
code.to_owned(),
&mut self.machine_st.arena,
);
self.load_file("<stdin>".into(), stream);
self.user_output.bytes().map(|b| b.unwrap()).collect()
}
}
#[cfg(test)]

View File

@@ -453,9 +453,9 @@ impl Machine {
let user_output = Stream::stdout(&mut machine_st.arena);
let user_error = Stream::stderr(&mut machine_st.arena);
#[cfg(not(target_os = "wasi"))]
#[cfg(not(target_arch = "wasm32"))]
let runtime = tokio::runtime::Runtime::new().unwrap();
#[cfg(target_os = "wasi")]
#[cfg(target_arch = "wasm32")]
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()

View File

@@ -60,7 +60,7 @@ use std::process;
use std::str::FromStr;
use chrono::{offset::Local, DateTime};
#[cfg(not(target_os = "wasi"))]
#[cfg(not(target_arch = "wasm32"))]
use cpu_time::ProcessTime;
use std::time::{Duration, SystemTime};
@@ -71,8 +71,11 @@ use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use blake2::{Blake2b, Blake2s};
use ring::rand::{SecureRandom, SystemRandom};
use ring::{digest, hkdf, pbkdf2};
#[cfg(feature = "crypto-full")]
use ring::{
aead, digest, hkdf, pbkdf2,
aead,
signature::{self, KeyPair},
};
use ripemd160::{Digest, Ripemd160};
@@ -4290,7 +4293,7 @@ impl Machine {
self.machine_st.fail = result;
}
#[cfg(not(target_os = "wasi"))]
#[cfg(not(target_arch = "wasm32"))]
#[inline(always)]
pub(crate) fn cpu_now(&mut self) {
let secs = ProcessTime::now().as_duration().as_secs_f64();
@@ -4300,7 +4303,7 @@ impl Machine {
.unify_f64(secs, self.machine_st.registers[1]);
}
#[cfg(target_os = "wasi")]
#[cfg(target_arch = "wasm32")]
#[inline(always)]
pub(crate) fn cpu_now(&mut self) {
// TODO
@@ -7382,6 +7385,7 @@ impl Machine {
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn crypto_data_encrypt(&mut self) {
let encoding = cell_as_atom!(self.deref_register(3));
@@ -7430,6 +7434,7 @@ impl Machine {
);
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn crypto_data_decrypt(&mut self) {
let data = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
@@ -7508,6 +7513,7 @@ impl Machine {
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn ed25519_new_key_pair(&mut self) {
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
@@ -7520,6 +7526,7 @@ impl Machine {
)
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn ed25519_key_pair_public_key(&mut self) {
let bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
@@ -7541,6 +7548,7 @@ impl Machine {
);
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn ed25519_sign(&mut self) {
let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
@@ -7567,6 +7575,7 @@ impl Machine {
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
}
#[cfg(feature = "crypto-full")]
#[inline(always)]
pub(crate) fn ed25519_verify(&mut self) {
let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));