Advertisement
Guest User

Untitled

a guest
Dec 1st, 2015
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.56 KB | None | 0 0
  1. //! Proof of concept virtual machine with instructions in-line with memory
  2. //!
  3. //! TODO: Implement unions for lense and use that for handling everything correctly!
  4. //!
  5. //! The instructions are RISC with a few CISC commands to interact with the network and handle
  6. //! cryptography.
  7. //!
  8. //! Instruction set
  9. //! ---------------
  10. //!
  11. //! 0x0_ : Core VM management
  12. //!
  13. //! 0x00 Return up the stack
  14. //! 0x01 Define function : 0x__
  15. //! 0x02 Define variable : 0x__ len:u16
  16. //! 0x03* Slice into a memory region
  17. //!
  18. //! 0x0A Crypto_box: key, nonce, message, signature
  19. //! 0x0B Hexdump: region
  20. //!
  21. //! 0xA_ .. 0xE_
  22. //! : Pre-boot defined functions and statics
  23. //!
  24. //! 0xF_ : Runtime defined
  25. //!
  26. //! Implementation notes
  27. //! --------------------
  28. //!
  29. //! - The 0x0_ range may be used freely as *non-callable registers*
  30. //! - This is useful for slicing into memory regions
  31.  
  32. extern crate rand;
  33.  
  34. use rand::{ChaChaRng, SeedableRng, Rng};
  35.  
  36. macro_rules! vec_no_copy {
  37. [$expr:expr; $n:expr] => {{
  38. let mut tmp = Vec::with_capacity($n);
  39. for _ in 0..$n {
  40. tmp.push($expr)
  41. }
  42. tmp
  43. }}
  44. }
  45.  
  46. fn hex_dump(vec: &[u8]) {
  47. println!("Hexdump:");
  48. let mut m = 0;
  49. for bytes in vec.chunks(16) {
  50. let mut n = 0;
  51. println!("{:04x} {}", m * 16,
  52. bytes.iter()
  53. .map(|x| {
  54. n += 1;
  55. if n == 8 {
  56. format!("{:02x} ", x)
  57. } else {
  58. format!("{:02x}", x)
  59. }
  60. })
  61. .collect::<Vec<String>>()
  62. .join(" "));
  63. m += 1;
  64. }
  65. }
  66.  
  67. pub struct State<'a> {
  68. state: &'a mut [u8],
  69. cursor: u16,
  70. registers: Vec<Reg<'a>>,
  71. chacha: ChaChaRng,
  72. stack: Vec<u16>,
  73. lock_flags: bool,
  74. }
  75.  
  76. enum Reg<'a> {
  77. Exact(u16),
  78. Region(&'a mut [u8]),
  79. None,
  80. }
  81.  
  82. impl<'a> Reg<'a> {
  83. fn get_region(&self) -> Result<&[u8], ()> {
  84. match *self {
  85. Reg::Region(ref r) => Ok(r),
  86. _ => Err(()),
  87. }
  88. }
  89.  
  90. fn get_region_mut(&mut self) -> Result<&mut [u8], ()> {
  91. match *self {
  92. Reg::Region(ref mut r) => Ok(r),
  93. _ => Err(()),
  94. }
  95. }
  96. }
  97.  
  98. impl<'a> State<'a> {
  99. fn with_program(prog: &'a mut [u8]) -> Self {
  100. State {
  101. state: prog,
  102. cursor: 0,
  103. registers: vec_no_copy![Reg::None; 0xFF],
  104. chacha: ChaChaRng::new_unseeded(),
  105. stack: Vec::new(),
  106. lock_flags: false,
  107. }
  108. }
  109.  
  110. fn get_u8(&mut self) -> u8 {
  111. let ret = self.state[self.cursor as usize];
  112. self.cursor += 1;
  113. ret
  114. }
  115.  
  116. fn get_u16(&mut self) -> u16 {
  117. let ret = &self.state[self.cursor as usize..self.cursor as usize + 2];
  118. self.cursor += 2;
  119. (ret[0] as u16) << 8 | ret[1] as u16
  120. }
  121.  
  122. fn set_start(&mut self) {
  123. let reg = self.get_u8() as usize;
  124.  
  125. self.registers[reg] = Reg::Exact(self.cursor);
  126. }
  127.  
  128. fn seek(&mut self) {
  129. let pos = self.get_u8() as usize;
  130.  
  131. match self.registers[pos] {
  132. Reg::Exact(c) => self.cursor = c,
  133. _ => unimplemented!(),
  134. }
  135.  
  136. println!("Jump: {}", self.cursor)
  137. }
  138.  
  139. fn set_region(&mut self) {
  140. assert!(self.cursor % 2 == 1, "Set_region must be aligned to 2 bytes! {}",
  141. self.cursor % 2);
  142.  
  143. let (ins, len) = (self.get_u8() as usize, self.get_u16() as usize);
  144.  
  145. self.registers[ins as usize] = Reg::Region(unsafe {
  146. ::std::slice::from_raw_parts_mut(
  147. (self.state.as_mut_ptr() as *mut u8).offset(self.cursor as isize),
  148. len)
  149. });
  150.  
  151. self.cursor += len as u16;
  152. }
  153.  
  154. // Should be implemented in the language itself
  155. fn crypt(&mut self) -> Result<(), ()> {
  156. let (key, nonce, range) = (self.get_u8() as usize,
  157. self.get_u8() as usize,
  158. self.get_u8() as usize);
  159.  
  160. // TODO: use and update nonce
  161. {
  162. let key = try!(self.registers[key].get_region());
  163. assert!(key.len() == 32);
  164.  
  165. self.chacha.reseed(unsafe {
  166. ::std::slice::from_raw_parts(key.as_ptr() as *const u32, 4)
  167. });
  168. }
  169. let range = try!(self.registers[range].get_region_mut());
  170. self.chacha.fill_bytes(range);
  171.  
  172. Ok(())
  173. }
  174.  
  175. // Lock memory flags and disable setting exec functions and interrupts
  176. fn boot(&mut self) {
  177. if !self.lock_flags {
  178. self.lock_flags = true;
  179. } else {
  180. println!("Guest attempted to boot, but it is already running");
  181. }
  182. }
  183.  
  184. fn dump_region(&mut self) {
  185. let region = self.get_u8() as usize;
  186. if let Reg::Region(ref r) = self.registers[region] {
  187. hex_dump(r)
  188. }
  189. }
  190.  
  191. fn tick(&mut self) {
  192. println!("Cursor: {}", self.cursor);
  193. match self.get_u8() {
  194. 0x00 => match self.stack.pop() {
  195. Some(c) => self.cursor = c,
  196. None => println!("Cannot return upwards!"),
  197. },
  198. // Set function : u8
  199. 0x01 => self.set_start(),
  200. // Set region : (u8, u16)
  201. 0x02 => self.set_region(),
  202. // Encrypt a region : (u8, u8)
  203. 0x0A => { self.crypt().map_err(|_| println!("Invalid key!")); },
  204. // Dump a selected region : u8
  205. 0x0B => self.dump_region(),
  206. // Nop
  207. 0xFF => {},
  208. n =>
  209. match self.registers[n as usize] {
  210. Reg::Region(ref r) => hex_dump(r),
  211. Reg::Exact(c) => self.cursor = c,
  212. Reg::None => println!("Undefined function: {}", n),
  213. }
  214. }
  215. }
  216. }
  217.  
  218. impl<'a> Iterator for State<'a> {
  219. type Item = ();
  220.  
  221. #[inline]
  222. fn next(&mut self) -> Option<Self::Item> {
  223. if (self.cursor as usize) < self.state.len() {
  224. Some(self.tick())
  225. } else {
  226. None
  227. }
  228. }
  229. }
  230.  
  231. static mut Program: &'static mut [u64] = &mut [
  232.  
  233. // Compiled program
  234.  
  235. 0x1000A102FFA001FF, // nop, fn reset_nonce, nop, static nonce
  236. 0x0000000000000000, // nonce
  237. 0x0000000000000000, // nonce
  238. 0x2000A302FFA20100, // return, fn reset_key, nop, static key
  239. 0x0000000000000000, // key
  240. 0x0000000000000000, // key
  241. 0x0000000000000000, // key
  242. 0x0000000000000000, // key
  243. 0xA1A1A30AA3A1A30A, // crypt key, nonce, key. crypt key, nonce, nonce
  244. 0xFFA2A0A30BA10B00, // dump nonce, dump key, call reset_nonce, call reset_key, nop
  245.  
  246. // 8 * 4 = 32 bytes of instructions
  247. // 8 * 6 = 48 bytes of memory (nonce and key)
  248. // 32 + 48 = 80 byte program
  249.  
  250. // Hexdump:
  251. // 0000 ff 01 a0 ff 02 a1 00 10 00 00 00 00 00 00 00 00
  252. // 0010 00 00 00 00 00 00 00 00 00 01 a2 ff 02 a3 00 20
  253. // 0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  254. // 0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  255. // 0040 0a a3 a1 a3 0a a3 a1 a1 00 0b a1 0b a3 a0 a2 ff
  256.  
  257. // 0xFF, // Padding for fn 3 + ret offset correction
  258. // // Initialisation
  259. // // fn reset_nonce @ 0xA0 () {
  260. // 0x01, 0xA0, 0xFF,
  261. // // static mut nonce @ 0xA1 = [u8; 16];
  262. // 0x02, 0xA1, 0x00, 0x10,
  263. // // 16 byte nonce
  264. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  265. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  266. // // return
  267. // 0x00,
  268. // // }
  269.  
  270. // // fn init @ 0xA2 (mut nonce @ 0xA1) {
  271. // 0x01, 0xA2, 0xFF, // 0x01, 0xA1
  272. // // static mut key @ 0xA3 = [0u8; 32];
  273. // 0x02, 0xA3, 0x00, 0x20,
  274. // // 32 byte key
  275. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  277. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  278. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  279. // // crypt(key, nonce, key)
  280. // 0x0A, 0xA3, 0xA1, 0xA3,
  281. // // crypt(key, nonce, nonce)
  282. // 0x0A, 0xA3, 0xA1, 0xA1,
  283. // // return
  284. // 0x00,
  285. // // }
  286.  
  287. // // hex_dump(nonce)
  288. // 0x0B, 0xA1,
  289. // // hex_dump(key)
  290. // 0x0B, 0xA3,
  291.  
  292. // // Define and initialise statics 'nonce' and 'key'
  293. // // reset_nonce()
  294. // 0xA0,
  295. // // init()
  296. // 0xA2, // dead code due to not actually having the stack return from reset_nonce
  297. ];
  298.  
  299. #[test]
  300. fn print() {
  301. let program = unsafe {
  302. ::std::slice::from_raw_parts_mut(Program.as_mut_ptr() as *mut u8, Program.len() * 8)
  303. };
  304. let mut s = State::with_program(program);
  305. hex_dump(s.state);
  306.  
  307. for _ in 0..14 {
  308. s.tick()
  309. // Profiling, debugging, etc?
  310. }
  311.  
  312. hex_dump(s.state);
  313.  
  314. unreachable!() // Debugging, dump the state
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement