diff --git a/Cargo.lock b/Cargo.lock
index 588a760f0358bc32cda32fb55124334a86baeb0f..a2225c6934f5bb15bd99137a714b7464695ed167 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,17 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "aes"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfe0133578c0986e1fe3dfcd4af1cc5b2dd6c3dbf534d69916ce16a2701d40ba"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.19"
@@ -32,6 +43,12 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "ascii"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
+
 [[package]]
 name = "atomic-polyfill"
 version = "0.1.10"
@@ -83,6 +100,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
 
+[[package]]
+name = "base64ct"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474"
+
 [[package]]
 name = "bit_field"
 version = "0.10.1"
@@ -101,18 +124,77 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array 0.14.6",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array 0.14.6",
+]
+
 [[package]]
 name = "byteorder"
 version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
+[[package]]
+name = "caprand"
+version = "0.1.0"
+dependencies = [
+ "cortex-m",
+ "critical-section 1.1.1",
+ "embassy-rp",
+ "embassy-time",
+ "getrandom",
+ "log",
+ "rand_chacha",
+ "sha2 0.10.5",
+]
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "chacha20"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "cipher"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
+
 [[package]]
 name = "cortex-m"
 version = "0.7.6"
@@ -146,6 +228,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "cpufeatures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "critical-section"
 version = "0.2.7"
@@ -164,6 +255,38 @@ version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
 
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array 0.14.6",
+ "typenum",
+]
+
+[[package]]
+name = "ctr"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d14f329cfbaf5d0e06b5e87fff7e265d2673c5ea7d2c27691a2c107db1442a0"
+dependencies = [
+ "cipher",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "subtle",
+ "zeroize",
+]
+
 [[package]]
 name = "cyw43"
 version = "0.1.0"
@@ -176,7 +299,7 @@ dependencies = [
  "embassy-net",
  "embassy-sync",
  "embassy-time",
- "embedded-hal 1.0.0-alpha.8",
+ "embedded-hal 1.0.0-alpha.9",
  "embedded-hal-async",
  "futures",
  "num_enum",
@@ -257,32 +380,65 @@ dependencies = [
 ]
 
 [[package]]
-name = "door-picow"
-version = "0.1.0"
+name = "der"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
 dependencies = [
- "atomic-polyfill 0.1.10",
- "cortex-m",
- "cortex-m-rt",
- "cyw43",
- "defmt",
- "defmt-rtt",
- "embassy-executor",
- "embassy-net",
- "embassy-rp",
- "embassy-time",
- "embedded-hal 1.0.0-alpha.8",
- "embedded-hal-async",
- "embedded-io",
- "futures",
- "heapless",
- "panic-probe",
- "static_cell",
+ "const-oid",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array 0.14.6",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+dependencies = [
+ "block-buffer 0.10.3",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "ed25519"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
+dependencies = [
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519",
+ "sha2 0.9.9",
+ "zeroize",
 ]
 
 [[package]]
 name = "embassy-cortex-m"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "atomic-polyfill 1.0.1",
  "cfg-if",
@@ -297,11 +453,11 @@ dependencies = [
 [[package]]
 name = "embassy-embedded-hal"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "embassy-sync",
  "embedded-hal 0.2.7",
- "embedded-hal 1.0.0-alpha.8",
+ "embedded-hal 1.0.0-alpha.9",
  "embedded-hal-async",
  "embedded-storage",
  "embedded-storage-async",
@@ -311,7 +467,7 @@ dependencies = [
 [[package]]
 name = "embassy-executor"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "atomic-polyfill 1.0.1",
  "cfg-if",
@@ -326,12 +482,12 @@ dependencies = [
 [[package]]
 name = "embassy-futures"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 
 [[package]]
 name = "embassy-hal-common"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "num-traits",
 ]
@@ -339,7 +495,7 @@ dependencies = [
 [[package]]
 name = "embassy-macros"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "darling",
  "proc-macro2",
@@ -350,7 +506,7 @@ dependencies = [
 [[package]]
 name = "embassy-net"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "as-slice 0.2.1",
  "atomic-polyfill 1.0.1",
@@ -358,8 +514,6 @@ dependencies = [
  "defmt",
  "embassy-sync",
  "embassy-time",
- "embedded-io",
- "embedded-nal-async",
  "futures",
  "generic-array 0.14.6",
  "heapless",
@@ -371,7 +525,7 @@ dependencies = [
 [[package]]
 name = "embassy-rp"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "atomic-polyfill 1.0.1",
  "cfg-if",
@@ -382,12 +536,17 @@ dependencies = [
  "embassy-cortex-m",
  "embassy-embedded-hal",
  "embassy-executor",
+ "embassy-futures",
  "embassy-hal-common",
  "embassy-sync",
  "embassy-time",
+ "embassy-usb-driver",
  "embedded-hal 0.2.7",
- "embedded-hal 1.0.0-alpha.8",
+ "embedded-hal 1.0.0-alpha.9",
  "embedded-hal-async",
+ "embedded-hal-nb",
+ "embedded-io",
+ "embedded-storage",
  "futures",
  "nb 1.0.0",
  "rp2040-pac2",
@@ -396,7 +555,7 @@ dependencies = [
 [[package]]
 name = "embassy-sync"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "atomic-polyfill 1.0.1",
  "cfg-if",
@@ -409,15 +568,24 @@ dependencies = [
 [[package]]
 name = "embassy-time"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/embassy?rev=cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b#cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
 dependencies = [
  "atomic-polyfill 1.0.1",
  "cfg-if",
  "critical-section 1.1.1",
  "defmt",
- "embassy-macros",
+ "embassy-sync",
  "embedded-hal 0.2.7",
  "futures-util",
+ "heapless",
+]
+
+[[package]]
+name = "embassy-usb-driver"
+version = "0.1.0"
+source = "git+https://github.com/embassy-rs/embassy?rev=e7fdd500d8354a03fcd105c8298cf7b4798a4107#e7fdd500d8354a03fcd105c8298cf7b4798a4107"
+dependencies = [
+ "defmt",
 ]
 
 [[package]]
@@ -432,52 +600,36 @@ dependencies = [
 
 [[package]]
 name = "embedded-hal"
-version = "1.0.0-alpha.8"
+version = "1.0.0-alpha.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3babfc7fd332142a0b11aebf592992f211f4e01b6222fb04b03aba1bd80018d"
-dependencies = [
- "nb 1.0.0",
-]
+checksum = "129b101ddfee640565f7c07b301a31d95aa21e5acef21a491c307139f5fa4c91"
 
 [[package]]
 name = "embedded-hal-async"
-version = "0.1.0-alpha.1"
+version = "0.1.0-alpha.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "022249738afde9b2b755a28a367ae20c9367e8e9c24b9aaf60bcc9255a255ec5"
+checksum = "c913f631bd08c253b85fdf0077061c64763d70e27803b04da5a49c5fb2a65057"
 dependencies = [
- "embedded-hal 1.0.0-alpha.8",
-]
-
-[[package]]
-name = "embedded-io"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36673b79844ff4ec0e3f00aeca0b2cfff564ff6739ab9801d13f45a8ec6cc1c7"
-dependencies = [
- "defmt",
+ "embedded-hal 1.0.0-alpha.9",
 ]
 
 [[package]]
-name = "embedded-nal"
-version = "0.6.0"
+name = "embedded-hal-nb"
+version = "1.0.0-alpha.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db9efecb57ab54fa918730f2874d7d37647169c50fa1357fecb81abee840b113"
+checksum = "7e0760ec0a3bf76859d5e33f39542af103f157d5b2ecfb00ace56dd461472e3a"
 dependencies = [
- "heapless",
+ "embedded-hal 1.0.0-alpha.9",
  "nb 1.0.0",
- "no-std-net",
 ]
 
 [[package]]
-name = "embedded-nal-async"
-version = "0.2.0"
+name = "embedded-io"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be6ff4a100fe482c345744cb854ac1c8237ea17be2579c92d9441c0c5b0f6c82"
+checksum = "33dfba9e6c113f2fd8537c943780a7345945e66c86972e356b1152e19481bcf5"
 dependencies = [
- "embedded-io",
- "embedded-nal",
- "heapless",
- "no-std-net",
+ "defmt",
 ]
 
 [[package]]
@@ -602,6 +754,17 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "hash32"
 version = "0.2.1"
@@ -624,18 +787,48 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.3",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array 0.14.6",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
+[[package]]
+name = "libc"
+version = "0.2.132"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+
 [[package]]
 name = "lock_api"
 version = "0.4.8"
@@ -646,6 +839,15 @@ dependencies = [
  "scopeguard",
 ]
 
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "managed"
 version = "0.8.0"
@@ -674,10 +876,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
 
 [[package]]
-name = "no-std-net"
-version = "0.5.0"
+name = "no-panic"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152"
+checksum = "3b884e0f4a7a80970539a7757902675ce503d98615f5b564564b4bd0236f7f36"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "num-traits"
@@ -708,6 +915,12 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
 [[package]]
 name = "panic-probe"
 version = "0.3.0"
@@ -718,6 +931,15 @@ dependencies = [
  "defmt",
 ]
 
+[[package]]
+name = "pem-rfc7468"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
+dependencies = [
+ "base64ct",
+]
+
 [[package]]
 name = "pin-project-lite"
 version = "0.2.9"
@@ -730,6 +952,29 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
+[[package]]
+name = "poly1305"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
+dependencies = [
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "pretty-hex"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5"
+
 [[package]]
 name = "proc-macro-error"
 version = "1.0.4"
@@ -772,6 +1017,40 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
 [[package]]
 name = "regex"
 version = "1.6.0"
@@ -813,7 +1092,7 @@ dependencies = [
 [[package]]
 name = "rp2040-pac2"
 version = "0.1.0"
-source = "git+https://github.com/embassy-rs/rp2040-pac2?rev=9ad7223a48a065e612bc7dc7be5bf5bd0b41cfc4#9ad7223a48a065e612bc7dc7be5bf5bd0b41cfc4"
+source = "git+https://github.com/embassy-rs/rp2040-pac2?rev=017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364#017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364"
 dependencies = [
  "cortex-m",
  "cortex-m-rt",
@@ -837,12 +1116,33 @@ dependencies = [
  "semver 1.0.14",
 ]
 
+[[package]]
+name = "salty"
+version = "0.2.0"
+source = "git+https://github.com/mkj/salty?branch=parts#856c2ca9f491cdb776dcf20350a77da5ec0aaa23"
+dependencies = [
+ "digest 0.10.3",
+ "ed25519",
+ "subtle",
+ "zeroize",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "sec1"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
+dependencies = [
+ "der",
+ "generic-array 0.14.6",
+]
+
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -864,6 +1164,36 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.3",
+]
+
+[[package]]
+name = "signature"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e90531723b08e4d6d71b791108faf51f03e1b4a7784f96b2b87f852ebc247228"
+
 [[package]]
 name = "smoltcp"
 version = "0.8.0"
@@ -877,6 +1207,28 @@ dependencies = [
  "managed",
 ]
 
+[[package]]
+name = "snafu"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5177903bf45656592d9eb5c0e22f408fc023aae51dbe2088889b71633ba451f2"
+dependencies = [
+ "doc-comment",
+ "snafu-derive",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "410b26ed97440d90ced3e2488c868d56a86e2064f5d7d6f417909b286afe25e5"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "spin"
 version = "0.9.4"
@@ -886,6 +1238,21 @@ dependencies = [
  "lock_api",
 ]
 
+[[package]]
+name = "ssh-key"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e09d8b0ff2fca365c89ad535055c17adbd9fb0a5daf338299049882e95b6931"
+dependencies = [
+ "base64ct",
+ "ed25519-dalek",
+ "pem-rfc7468",
+ "rand_core 0.6.4",
+ "sec1",
+ "sha2 0.10.5",
+ "zeroize",
+]
+
 [[package]]
 name = "stable_deref_trait"
 version = "1.2.0"
@@ -907,6 +1274,75 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "sunset"
+version = "0.1.0"
+dependencies = [
+ "aes",
+ "ascii",
+ "chacha20",
+ "ctr",
+ "digest 0.10.3",
+ "heapless",
+ "hmac",
+ "log",
+ "no-panic",
+ "poly1305",
+ "pretty-hex",
+ "rand",
+ "rand_core 0.6.4",
+ "salty",
+ "sha2 0.10.5",
+ "signature",
+ "snafu",
+ "ssh-key",
+ "sunset-sshwire-derive",
+]
+
+[[package]]
+name = "sunset-picow"
+version = "0.1.0"
+dependencies = [
+ "atomic-polyfill 0.1.10",
+ "caprand",
+ "cortex-m",
+ "cortex-m-rt",
+ "critical-section 1.1.1",
+ "cyw43",
+ "defmt",
+ "defmt-rtt",
+ "embassy-executor",
+ "embassy-net",
+ "embassy-rp",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-hal 1.0.0-alpha.9",
+ "embedded-hal-async",
+ "embedded-io",
+ "futures",
+ "getrandom",
+ "heapless",
+ "panic-probe",
+ "pin-utils",
+ "rand",
+ "sha2 0.10.5",
+ "static_cell",
+ "sunset",
+]
+
+[[package]]
+name = "sunset-sshwire-derive"
+version = "0.1.0"
+dependencies = [
+ "virtue",
+]
+
 [[package]]
 name = "syn"
 version = "1.0.99"
@@ -918,6 +1354,18 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
 [[package]]
 name = "typenum"
 version = "1.15.0"
@@ -930,6 +1378,22 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
 
+[[package]]
+name = "unicode-xid"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+
+[[package]]
+name = "universal-hash"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
+dependencies = [
+ "generic-array 0.14.6",
+ "subtle",
+]
+
 [[package]]
 name = "vcell"
 version = "0.1.3"
@@ -942,6 +1406,12 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "virtue"
+version = "0.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef1af909ca048161652d5a24e037d5e6190a9f6798c222594a721b9ba0ba53f1"
+
 [[package]]
 name = "void"
 version = "1.0.2"
@@ -956,3 +1426,30 @@ checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
 dependencies = [
  "vcell",
 ]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "zeroize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 42b461728cbf128e50b0a5fcc51310b0af061458..280178105303d0e1385052b1f3a7177340d3f7d2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "door-picow"
+name = "sunset-picow"
 version = "0.1.0"
 edition = "2021"
 
@@ -11,6 +11,7 @@ embassy-executor = { version = "0.1.0",  features = ["defmt", "integrated-timers
 embassy-time = { version = "0.1.0",  features = ["defmt", "defmt-timestamp-uptime"] }
 embassy-rp = { version = "0.1.0",  features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
 embassy-net = { version = "0.1.0", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
+embassy-sync = { version = "0.1.0" }
 atomic-polyfill = "0.1.5"
 static_cell = "1.0"
 
@@ -23,18 +24,28 @@ cortex-m-rt = "0.7.0"
 futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] }
 
 embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
-embedded-hal-async = { version = "0.1.0-alpha.1" }
+embedded-hal-async = { version = "0.1.0-alpha.2" }
 embedded-io = { version = "0.3.0", features = ["async", "defmt"] }
 heapless = "0.7.15"
 
+sunset = { path = "../sunset" }
+getrandom = { version = "0.2", default-features = false, features = ["custom"]}
+pin-utils = "0.1"
+
+caprand = { path = "../caprand" }
+
+critical-section = "1.1"
+rand = { version = "0.8", default-features = false, features = ["getrandom"] }
+sha2 = { version = "0.10", default-features = false }
 
 [patch.crates-io]
-embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
-embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
-embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
-embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
-embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
-embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "cb9f0ef5b800ce4a22cde1805e0eb88425f1e07b" }
+embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "e7fdd500d8354a03fcd105c8298cf7b4798a4107" }
+# embassy-net = { path = "/home/matt/3rd/rs/embassy/embassy-net" }
 
 [profile.dev]
 debug = 2
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 0fa7cf7bf6e7d152f0fdffa79773cbe3cdcd5389..a35a11b82158a63714cf5cf8adfb4127073429af 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,7 +1,7 @@
 # Before upgrading check that everything is available on all tier1 targets here:
 # https://rust-lang.github.io/rustup-components-history
 [toolchain]
-channel = "nightly-2022-07-13"
+channel = "nightly-2022-09-22"
 components = [ "rust-src", "rustfmt" ]
 targets = [
     "thumbv6m-none-eabi",
diff --git a/src/embassy_sunset.rs b/src/embassy_sunset.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5eb32651d02a868733e6aec8e0d62e7d0b72fa54
--- /dev/null
+++ b/src/embassy_sunset.rs
@@ -0,0 +1,93 @@
+use core::future::poll_fn;
+use core::task::Poll;
+
+use embassy_sync::waitqueue::AtomicWaker;
+use embassy_sync::mutex::Mutex;
+use embassy_sync::blocking_mutex::raw::NoopRawMutex;
+use embassy_sync::signal::Signal;
+
+use sunset::{Runner, Result, Behaviour};
+
+pub(crate) struct Inner<'a> {
+    pub runner: Runner<'a>,
+}
+
+pub struct EmbassySunset<'a> {
+    pub(crate) inner: Mutex<NoopRawMutex, Inner<'a>>,
+
+    progress_notify: Signal<NoopRawMutex, ()>,
+
+    read_waker: AtomicWaker,
+    write_waker: AtomicWaker,
+}
+
+impl<'a> EmbassySunset<'a> {
+    pub fn new(runner: Runner<'a>) -> Self {
+        let inner = Inner {
+            runner,
+        };
+        let inner = Mutex::new(inner);
+
+        let progress_notify = Signal::new();
+
+        Self {
+            inner,
+            progress_notify,
+            read_waker: AtomicWaker::new(),
+            write_waker: AtomicWaker::new(),
+         }
+    }
+
+    pub async fn progress(&mut self,
+        b: &mut Behaviour<'_>)
+        -> Result<()> {
+            let mut inner = self.inner.lock().await;
+            inner.runner.progress(b).await
+    }
+
+    pub async fn read(&self, buf: &mut [u8]) -> Result<usize> {
+        poll_fn(|cx| {
+            let r = match self.inner.try_lock() {
+                Ok(mut inner) => {
+                    match inner.runner.output(buf) {
+                        Ok(0) => Poll::Pending,
+                        Ok(n) => Poll::Ready(Ok(n)),
+                        Err(e) => Poll::Ready(Err(e)),
+                    }
+                }
+                Err(_) => Poll::Pending,
+            };
+
+            if r.is_pending() {
+                self.read_waker.register(cx.waker())
+            }
+            r
+        })
+        .await
+    }
+
+    pub async fn write(&self, buf: &[u8]) -> Result<usize> {
+        poll_fn(|cx| {
+            let r = match self.inner.try_lock() {
+                Ok(mut inner) => {
+                    if inner.runner.ready_input() {
+                        match inner.runner.input(buf) {
+                            Ok(0) => Poll::Pending,
+                            Ok(n) => Poll::Ready(Ok(n)),
+                            Err(e) => Poll::Ready(Err(e)),
+                        }
+                    } else {
+                        Poll::Pending
+                    }
+                }
+                Err(_) => Poll::Pending,
+            };
+
+            if r.is_pending() {
+                self.write_waker.register(cx.waker())
+            }
+            r
+        })
+        .await
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index b7c2bcdbc96e73b47f9186e09ec5aeee08894020..12f9bd09516afabbc2a24979356df3b780efbd0e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,22 +1,40 @@
 #![no_std]
 #![no_main]
-#![feature(generic_associated_types, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
-use core::convert::Infallible;
 use core::future::Future;
 
+use core::todo;
 use defmt::*;
 use embassy_executor::Spawner;
 use embassy_net::tcp::TcpSocket;
 use embassy_net::{Stack, StackResources};
 use embassy_rp::gpio::{Flex, Level, Output};
 use embassy_rp::peripherals::{PIN_23, PIN_24, PIN_25, PIN_29};
-use embedded_hal_1::spi::ErrorType;
 use embedded_hal_async::spi::{ExclusiveDevice, SpiBusFlush, SpiBusRead, SpiBusWrite};
 use embedded_io::asynch::{Read, Write};
 use static_cell::StaticCell;
 use {defmt_rtt as _, panic_probe as _};
 
+use core::str::FromStr;
+use core::cell::RefCell;
+use core::num::NonZeroU32;
+use futures::{task::noop_waker_ref,pending};
+use core::task::{Context,Poll,Waker,RawWaker,RawWakerVTable};
+use pin_utils::{pin_mut,unsafe_pinned};
+use core::pin::Pin;
+
+use rand::rngs::OsRng;
+use rand::RngCore;
+
+use sunset::*;
+
+mod wifi;
+mod server;
+mod embassy_sunset;
+
+const NUM_LISTENERS: usize = 4;
+
 macro_rules! singleton {
     ($val:expr) => {{
         type T = impl Sized;
@@ -25,12 +43,29 @@ macro_rules! singleton {
     }};
 }
 
-#[embassy_executor::task]
-async fn wifi_task(
-    runner: cyw43::Runner<'static, Output<'static, PIN_23>, ExclusiveDevice<MySpi, Output<'static, PIN_25>>>,
-) -> ! {
-    runner.run().await
-}
+// fn run() -> sunset::Result<()> {
+//     let mut x = [0u8; 500];
+
+//     let mut inbuf = [0u8; 1000];
+//     let mut outbuf = [0u8; 1000];
+//     let mut runner = sunset::Runner::new_server(&mut inbuf, &mut outbuf)?;
+//     let mut cli = SSHClient {};
+//     let mut cli = sunset::Behaviour::new_client(&mut cli);
+
+//     let mut pollctx = Context::from_waker(noop_waker_ref());
+
+//         runner.input(&x)?;
+//         let l = runner.progress(&mut cli);
+//         pin_mut!(l);
+//         let _ = l.poll(&mut pollctx);
+//         // runner.output(&mut x).unwrap();
+
+//         // tx.write(b'x').unwrap();
+//         // write!(tx, "{}", x[0]);
+
+//     Ok(())
+// }
+
 
 #[embassy_executor::task]
 async fn net_task(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! {
@@ -41,7 +76,12 @@ async fn net_task(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! {
 async fn main(spawner: Spawner) {
     info!("Hello World!");
 
-    let p = embassy_rp::init(Default::default());
+    let mut p = embassy_rp::init(Default::default());
+
+    caprand::setup(&mut p.PIN_25).unwrap();
+    getrandom::register_custom_getrandom!(caprand::random);
+
+    // TODO: move this to wifi mod
 
     // Include the WiFi firmware and Country Locale Matrix (CLM) blobs.
     let fw = include_bytes!("../firmware/43439A0.bin");
@@ -61,18 +101,19 @@ async fn main(spawner: Spawner) {
     dio.set_low();
     dio.set_as_output();
 
-    let bus = MySpi { clk, dio };
+    let bus = wifi::MySpi { clk, dio };
     let spi = ExclusiveDevice::new(bus, cs);
 
     let state = singleton!(cyw43::State::new());
     let (mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
 
-    spawner.spawn(wifi_task(runner)).unwrap();
+    spawner.spawn(wifi::wifi_task(runner)).unwrap();
 
     let net_device = control.init(clm).await;
 
     //control.join_open(env!("WIFI_NETWORK")).await;
-    control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await;
+    // control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await;
+    control.join_wpa2("WIFI_NETWORK", "WIFI_PASSWORD").await;
 
     let config = embassy_net::ConfigStrategy::Dhcp;
     //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config {
@@ -81,148 +122,189 @@ async fn main(spawner: Spawner) {
     //    gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
     //});
 
-    // Generate random seed
-    let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
+    let seed = OsRng.next_u64();
 
     // Init network stack
     let stack = &*singleton!(Stack::new(
         net_device,
         config,
-        singleton!(StackResources::<1, 2, 8>::new()),
+        singleton!(StackResources::<1, 10, 8>::new()),
         seed
     ));
 
     unwrap!(spawner.spawn(net_task(stack)));
 
-    // And now we can use it!
+    for _ in 0..NUM_LISTENERS {
+        spawner.spawn(listener(stack)).unwrap();
+    }
+}
 
+#[embassy_executor::task]
+async fn listener(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! {
     let mut rx_buffer = [0; 4096];
     let mut tx_buffer = [0; 4096];
-    let mut buf = [0; 4096];
 
     loop {
         let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
         socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10)));
 
-        info!("Listening on TCP:1234...");
-        if let Err(e) = socket.accept(1234).await {
+        info!("Listening on TCP:22...");
+        if let Err(e) = socket.accept(22).await {
             warn!("accept error: {:?}", e);
             continue;
         }
 
-        info!("Received connection from {:?}", socket.remote_endpoint());
-
-        loop {
-            let n = match socket.read(&mut buf).await {
-                Ok(0) => {
-                    warn!("read EOF");
-                    break;
-                }
-                Ok(n) => n,
-                Err(e) => {
-                    warn!("read error: {:?}", e);
-                    break;
-                }
-            };
-
-            info!("rxd {:02x}", &buf[..n]);
-
-            match socket.write_all(&buf[..n]).await {
-                Ok(()) => {}
-                Err(e) => {
-                    warn!("write error: {:?}", e);
-                    break;
-                }
-            };
+        let r = session(&mut socket).await;
+        if let Err(e) = r {
+            // warn!("Ended with error: {:?}", e);
+            warn!("Ended with error");
         }
     }
 }
 
-struct MySpi {
-    /// SPI clock
-    clk: Output<'static, PIN_29>,
+struct DemoServer {
+    // keys: Vec<SignKey>,
 
-    /// 4 signals, all in one!!
-    /// - SPI MISO
-    /// - SPI MOSI
-    /// - IRQ
-    /// - strap to set to gSPI mode on boot.
-    dio: Flex<'static, PIN_24>,
+    sess: Option<u32>,
+    want_shell: bool,
+    shell_started: bool,
 }
 
-impl ErrorType for MySpi {
-    type Error = Infallible;
+impl DemoServer {
+    fn new() -> Result<Self> {
+        // let keys = keyfiles.iter().map(|f| {
+        //     read_key(f).with_context(|| format!("loading key {f}"))
+        // }).collect::<Result<Vec<SignKey>>>()?;
+
+        Ok(Self {
+            sess: None,
+            // keys,
+            want_shell: false,
+            shell_started: false,
+        })
+    }
 }
 
-impl SpiBusFlush for MySpi {
-    type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>>
-    where
-        Self: 'a;
+impl ServBehaviour for DemoServer {
+    fn hostkeys(&mut self) -> BhResult<&[SignKey]> {
+        todo!()
+        // Ok(&self.keys)
+    }
 
-    fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
-        async move { Ok(()) }
+
+    fn have_auth_password(&self, user: TextString) -> bool {
+        true
     }
-}
 
-impl SpiBusRead<u32> for MySpi {
-    type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>>
-    where
-        Self: 'a;
-
-    fn read<'a>(&'a mut self, words: &'a mut [u32]) -> Self::ReadFuture<'a> {
-        async move {
-            self.dio.set_as_input();
-            for word in words {
-                let mut w = 0;
-                for _ in 0..32 {
-                    w = w << 1;
-
-                    // rising edge, sample data
-                    if self.dio.is_high() {
-                        w |= 0x01;
-                    }
-                    self.clk.set_high();
-
-                    // falling edge
-                    self.clk.set_low();
-                }
-                *word = w
-            }
+    fn have_auth_pubkey(&self, user: TextString) -> bool {
+        true
+    }
+
+    fn auth_password(&mut self, user: TextString, password: TextString) -> bool {
+        user.as_str().unwrap_or("") == "matt" && password.as_str().unwrap_or("") == "pw"
+    }
 
-            Ok(())
+    // fn auth_pubkey(&mut self, user: TextString, pubkey: &PubKey) -> bool {
+    //     if user.as_str().unwrap_or("") != "matt" {
+    //         return false
+    //     }
+
+    //     // key is tested1
+    //     pubkey.matches_openssh("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkNdReJERy1rPGqdfTN73TnayPR+lTNhdZvOgkAOs5x")
+    //     .unwrap_or_else(|e| {
+    //         warn!("Failed loading openssh key: {e}");
+    //         false
+    //     })
+    // }
+
+    fn open_session(&mut self, chan: u32) -> ChanOpened {
+        if self.sess.is_some() {
+            ChanOpened::Failure(ChanFail::SSH_OPEN_ADMINISTRATIVELY_PROHIBITED)
+        } else {
+            self.sess = Some(chan);
+            ChanOpened::Success
         }
     }
-}
 
-impl SpiBusWrite<u32> for MySpi {
-    type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>>
-    where
-        Self: 'a;
-
-    fn write<'a>(&'a mut self, words: &'a [u32]) -> Self::WriteFuture<'a> {
-        async move {
-            self.dio.set_as_output();
-            for word in words {
-                let mut word = *word;
-                for _ in 0..32 {
-                    // falling edge, setup data
-                    self.clk.set_low();
-                    if word & 0x8000_0000 == 0 {
-                        self.dio.set_low();
-                    } else {
-                        self.dio.set_high();
-                    }
-
-                    // rising edge
-                    self.clk.set_high();
-
-                    word = word << 1;
-                }
-            }
-            self.clk.set_low();
+    fn sess_shell(&mut self, chan: u32) -> bool {
+        let r = !self.want_shell && self.sess == Some(chan);
+        self.want_shell = true;
+        trace!("req want shell");
+        r
+    }
 
-            self.dio.set_as_input();
-            Ok(())
-        }
+    fn sess_pty(&mut self, chan: u32, _pty: &Pty) -> bool {
+        self.sess == Some(chan)
     }
 }
+
+
+
+async fn session(socket: &mut TcpSocket<'_>) -> sunset::Result<()> {
+        let mut app = DemoServer::new()?;
+
+        let mut ssh_rxbuf = [0; 1024];
+        let mut ssh_txbuf = [0; 1024];
+        let serv = server::SSHServer::new(&mut ssh_rxbuf, &mut ssh_txbuf, &mut app)?;
+        let serv = &serv;
+
+        let tx = async {
+            loop {
+                // TODO: make sunset read directly from socket, no intermediate buffer.
+                let mut buf = [0; 1024];
+                let l = serv.read(&mut buf).await?;
+                let buf = &buf[..l];
+                socket.write(buf).await.expect("write");
+            }
+            #[allow(unreachable_code)]
+            Ok::<_, sunset::Error>(())
+        };
+        // let rx = async {
+        //     loop {
+        //         // TODO: make sunset read directly from socket, no intermediate buffer.
+        //         let mut buf = [0; 1024];
+        //         let l = socket.read(&mut buf).await.expect("read");
+        //         let buf = &buf[..l];
+        //         serv.write(&buf).await?;
+        //     }
+        //     #[allow(unreachable_code)]
+        //     Ok::<_, sunset::Error>(())
+        // };
+        Ok(())
+}
+
+        // info!("Received connection from {:?}", socket.remote_endpoint());
+
+        // #[embassy_executor::task]
+        // async fn from_wir(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! {
+        //     stack.run().await
+        // }
+
+        // spawner.spawn(sunset_task(runner)).unwrap();
+
+        // run().unwrap();
+
+        // loop {
+        //     let n = match socket.read(&mut buf).await {
+        //         Ok(0) => {
+        //             warn!("read EOF");
+        //             break;
+        //         }
+        //         Ok(n) => n,
+        //         Err(e) => {
+        //             warn!("read error: {:?}", e);
+        //             break;
+        //         }
+        //     };
+
+        //     info!("rxd {:02x}", &buf[..n]);
+
+        //     match socket.write(&buf[..n]).await {
+        //         Ok(_sz) => {}
+        //         Err(e) => {
+        //             warn!("write error: {:?}", e);
+        //             break;
+        //         }
+        //     };
+        // }
+
diff --git a/src/server.rs b/src/server.rs
new file mode 100644
index 0000000000000000000000000000000000000000..557935106602cde36ad1cbf9268bc3099817f78b
--- /dev/null
+++ b/src/server.rs
@@ -0,0 +1,44 @@
+use sunset::*;
+
+use crate::*;
+
+use embassy_sunset::EmbassySunset;
+
+pub struct SSHServer<'a> {
+    sunset: EmbassySunset<'a>,
+}
+
+impl<'a> SSHServer<'a> {
+    pub fn new(inbuf: &'a mut [u8], outbuf: &'a mut [u8],
+        b: &mut (dyn ServBehaviour + Send),
+        ) -> Result<Self> {
+        let runner = Runner::new_server(inbuf, outbuf, b)?;
+        let sunset = EmbassySunset::new(runner);
+        Ok(Self { sunset })
+    }
+
+    pub async fn progress(
+        &mut self,
+        b: &mut (dyn ServBehaviour + Send),
+    ) -> Result<()>
+    {
+        let mut b = Behaviour::new_server(b);
+        self.sunset.progress(&mut b).await
+    }
+
+    // pub async fn channel(&mut self, ch: u32) -> Result<(ChanInOut<'a>, Option<ChanExtOut<'a>>)> {
+    //     let ty = self.sunset.with_runner(|r| r.channel_type(ch)).await?;
+    //     let inout = ChanInOut::new(ch, &self.sunset);
+    //     // TODO ext
+    //     let ext = None;
+    //     Ok((inout, ext))
+    // }
+
+    pub async fn read(&self, buf: &mut [u8]) -> Result<usize> {
+        self.sunset.read(buf).await
+    }
+
+    pub async fn write(&self, buf: &[u8]) -> Result<usize> {
+        self.sunset.write(buf).await
+    }
+}
diff --git a/src/wifi.rs b/src/wifi.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e34f24ea3d17ede3fa0210c14561a9397fde7cf0
--- /dev/null
+++ b/src/wifi.rs
@@ -0,0 +1,98 @@
+use embassy_rp::gpio::{Flex, Level, Output};
+use embassy_rp::peripherals::{PIN_23, PIN_24, PIN_25, PIN_29};
+use embedded_hal_async::spi::{ExclusiveDevice, SpiBusFlush, SpiBusRead, SpiBusWrite};
+use embedded_hal_1::spi::ErrorType;
+use core::convert::Infallible;
+use core::future::Future;
+
+#[embassy_executor::task]
+pub(crate) async fn wifi_task(
+    runner: cyw43::Runner<'static, Output<'static, PIN_23>, ExclusiveDevice<MySpi, Output<'static, PIN_25>>>,
+) -> ! {
+    runner.run().await
+}
+
+pub(crate) struct MySpi {
+    /// SPI clock
+    pub clk: Output<'static, PIN_29>,
+
+    /// 4 signals, all in one!!
+    /// - SPI MISO
+    /// - SPI MOSI
+    /// - IRQ
+    /// - strap to set to gSPI mode on boot.
+    pub dio: Flex<'static, PIN_24>,
+}
+
+impl ErrorType for MySpi {
+    type Error = Infallible;
+}
+
+impl SpiBusFlush for MySpi {
+    type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>>
+    where
+        Self: 'a;
+
+    fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
+        async move { Ok(()) }
+    }
+}
+
+impl SpiBusRead<u32> for MySpi {
+    type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a;
+
+    fn read<'a>(&'a mut self, words: &'a mut [u32]) -> Self::ReadFuture<'a> {
+        async move {
+            self.dio.set_as_input();
+            for word in words {
+                let mut w = 0;
+                for _ in 0..32 {
+                    w = w << 1;
+
+                    // rising edge, sample data
+                    if self.dio.is_high() {
+                        w |= 0x01;
+                    }
+                    self.clk.set_high();
+
+                    // falling edge
+                    self.clk.set_low();
+                }
+                *word = w
+            }
+
+            Ok(())
+        }
+    }
+}
+
+impl SpiBusWrite<u32> for MySpi {
+    type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a;
+
+    fn write<'a>(&'a mut self, words: &'a [u32]) -> Self::WriteFuture<'a> {
+        async move {
+            self.dio.set_as_output();
+            for word in words {
+                let mut word = *word;
+                for _ in 0..32 {
+                    // falling edge, setup data
+                    self.clk.set_low();
+                    if word & 0x8000_0000 == 0 {
+                        self.dio.set_low();
+                    } else {
+                        self.dio.set_high();
+                    }
+
+                    // rising edge
+                    self.clk.set_high();
+
+                    word = word << 1;
+                }
+            }
+            self.clk.set_low();
+
+            self.dio.set_as_input();
+            Ok(())
+        }
+    }
+}