Skip to content

Commit

Permalink
Merge pull request #208 from geonnave/add-python-wrapper
Browse files Browse the repository at this point in the history
Add `lakers-python`
  • Loading branch information
geonnave authored Feb 8, 2024
2 parents 41eab35 + ecddac0 commit 11ff1ef
Show file tree
Hide file tree
Showing 24 changed files with 757 additions and 41 deletions.
40 changes: 37 additions & 3 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
strategy:
fail-fast: false
matrix:
crypto_backend: [lakers-crypto/hacspec, lakers-crypto/psa, lakers-crypto/rustcrypto]
crypto_backend: [lakers-crypto/psa, lakers-crypto/rustcrypto]
ead: [ead-none, ead-authz]

steps:
Expand All @@ -61,7 +61,7 @@ jobs:
strategy:
fail-fast: false
matrix:
crypto_backend: [lakers-crypto/hacspec, lakers-crypto/psa, lakers-crypto/psa-baremetal, lakers-crypto/cryptocell310, lakers-crypto/rustcrypto]
crypto_backend: [lakers-crypto/psa, lakers-crypto/psa-baremetal, lakers-crypto/cryptocell310, lakers-crypto/rustcrypto]
ead: [ead-none, ead-authz]

steps:
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
cd lakers
# generate the fstar files
cargo-hax -C -p lakers --no-default-features --features='lakers-crypto/hacspec, ead-none' --release \; into -i '-lakers::generate_connection_identifier_cbor -lakers::generate_connection_identifier' fstar
cargo-hax -C -p lakers --no-default-features --features='lakers-crypto/rustcrypto, ead-none' --release \; into -i '-lakers::generate_connection_identifier_cbor -lakers::generate_connection_identifier' fstar
cargo-hax -C -p lakers-shared \; into -i '-lakers_shared::ffi::**' fstar
# even if fstar generation was ok, fail if something is not implemented
Expand Down Expand Up @@ -132,6 +132,35 @@ jobs:
path: ./target/lakers-c-*.zip


build-lakers-python:
needs: check-style
runs-on: ubuntu-latest

strategy:
fail-fast: false

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Build Python package
run: |
cd lakers-python
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -U pip maturin pytest
pip freeze
maturin develop && pytest
maturin build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: lakers-python
path: ./target/wheels/*.whl


run-example-on-qemu:
needs: unit-tests
runs-on: ubuntu-latest
Expand Down Expand Up @@ -218,6 +247,11 @@ jobs:
with:
name: lakers-c
path: ./release-artifacts
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: lakers-python
path: ./release-artifacts
- name: Release
uses: ncipollo/release-action@v1
with:
Expand Down
15 changes: 10 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
# build
target/*
bin
.pytest_cache
__pycache__
.venv*

# hax
*.fst

# in Rust, libraries should avoid checking the lock file in version control
# read more: https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries
Cargo.lock

cscope*

# editors
*.swp
*.swo
cscope*
.DS_Store
.vscode
*.fst

bin
19 changes: 10 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ members = [
"ead/lakers-ead-authz",
"crypto",
"crypto/lakers-crypto-cc2538",
"crypto/lakers-crypto-hacspec",
# "crypto/lakers-crypto-hacspec",
"crypto/lakers-crypto-psa",
"crypto/lakers-crypto-rustcrypto",
"crypto/lakers-crypto-cryptocell310-sys",
"examples/coap",
"examples/lakers-no_std",
"examples/lakers-cc2538",
"lakers-c",
"lakers-python",
]

# reduced "default-members", should include only packages that can be built and
Expand All @@ -22,7 +23,7 @@ default-members = [
"lib",
"ead",
"crypto",
"crypto/lakers-crypto-hacspec",
"crypto/lakers-crypto-rustcrypto",
"examples/coap",
]

Expand All @@ -48,17 +49,17 @@ lakers-crypto = { path = "crypto/" }

lakers-crypto-cc2538 = { path = "crypto/lakers-crypto-cc2538/" }
lakers-crypto-cryptocell310 = { path = "crypto/lakers-crypto-cryptocell310-sys/" }
lakers-crypto-hacspec = { path = "crypto/lakers-crypto-hacspec/" }
# lakers-crypto-hacspec = { path = "crypto/lakers-crypto-hacspec/" }
lakers-crypto-psa = { path = "crypto/lakers-crypto-psa/" }
lakers-crypto-rustcrypto = { package = "lakers-crypto-rustcrypto", path = "crypto/lakers-crypto-rustcrypto/", version = "^0.4.1" }

lakers = { package = "lakers", path = "lib/", version = "^0.4.1", default-features = false }

[patch.crates-io]
hacspec-lib = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
hacspec-p256 = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
hacspec-hkdf = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
hacspec-sha256 = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
hacspec-aes = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
hacspec-aes-ccm = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-lib = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-p256 = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-hkdf = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-sha256 = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-aes = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
# hacspec-aes-ccm = { git = "https://github.com/malishav/hacspec", branch = "aesccm" }
psa-crypto = { git = "https://github.com/malishav/rust-psa-crypto", branch = "baremetal" }
4 changes: 2 additions & 2 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ readme.workspace = true
lakers-shared = { package = "lakers-shared", path = "../shared", default-features = false }

# hacspec
lakers-crypto-hacspec = { workspace = true, optional = true }
# lakers-crypto-hacspec = { workspace = true, optional = true }

# cc2538 hardware accelerated
lakers-crypto-cc2538 = { workspace = true, optional = true }
Expand All @@ -29,7 +29,7 @@ rand_core = { version = "0.6.4", optional = true, default-features = false }

[features]
default = [ ]
hacspec = [ "lakers-crypto-hacspec" ]
# hacspec = [ "lakers-crypto-hacspec" ]
cc2538 = [ "lakers-crypto-cc2538" ]
psa = [ "lakers-crypto-psa" ]
psa-baremetal = [ "psa", "lakers-crypto-psa/baremetal" ]
Expand Down
2 changes: 1 addition & 1 deletion ead/lakers-ead-authz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod shared;
#[cfg(test)]
mod test_vectors;

pub use authenticator::ZeroTouchAuthenticator;
pub use authenticator::{ZeroTouchAuthenticator, ZeroTouchAuthenticatorWaitVoucherResp};
pub use device::{ZeroTouchDevice, ZeroTouchDeviceDone, ZeroTouchDeviceWaitEAD2};
pub use server::ZeroTouchServer;

Expand Down
2 changes: 1 addition & 1 deletion examples/coap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"

[dependencies]
lakers = { package = "lakers", path = "../../lib", features = ["ead-authz"] }
lakers-crypto = { path = "../../crypto/", features = [ "hacspec" ] }
lakers-crypto = { path = "../../crypto/", features = [ "rustcrypto" ] }
hexlit = "0.5.3"
coap = { version = "0.13" }
coap-lite = { version = "0.11.3" }
Expand Down
6 changes: 3 additions & 3 deletions lakers-c/src/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub unsafe extern "C" fn initiator_prepare_message_1(
Some(ead_1)
};

let result = match i_prepare_message_1(state, &mut default_crypto(), c_i, &ead_1) {
let result = match i_prepare_message_1(&state, &mut default_crypto(), c_i, &ead_1) {
Ok((state, msg_1)) => {
*message_1 = msg_1;
*initiator_c_out = EdhocInitiatorWaitM2C { state };
Expand Down Expand Up @@ -122,7 +122,7 @@ pub unsafe extern "C" fn initiator_parse_message_2(
// raw pointers do not have ownership information, requiring manual handling of the data
let state = core::ptr::read(&(*initiator_c).state);

let result = match i_parse_message_2(state, &mut default_crypto(), &(*message_2)) {
let result = match i_parse_message_2(&state, &mut default_crypto(), &(*message_2)) {
Ok((state, c_r, id_cred_r, ead_2)) => {
ProcessingM2C::copy_into_c(state, &mut (*initiator_c_out).state);
*c_r_out = c_r;
Expand Down Expand Up @@ -164,7 +164,7 @@ pub unsafe extern "C" fn initiator_verify_message_2(

let state = core::ptr::read(&(*initiator_c).state).to_rust();

match i_verify_message_2(state, &mut default_crypto(), valid_cred_r, &(*i)) {
match i_verify_message_2(&state, &mut default_crypto(), valid_cred_r, &(*i)) {
Ok(state) => {
*initiator_c_out = EdhocInitiatorProcessedM2C { state, cred_i };
0
Expand Down
18 changes: 18 additions & 0 deletions lakers-python/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "lakers-python" # this will be the name of the package on pypi
edition = "2021"
version ="0.1.2"
repository.workspace = true
license.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
pyo3 = { version = "0.20.2", features = ["extension-module"] }
lakers = { package = "lakers", path = "../lib", default-features = false, features = ["ead-authz"] }
lakers-shared = { path = "../shared", features = ["python-bindings"] }
lakers-crypto = { path = "../crypto", default-features = false, features = ["rustcrypto"] }

[lib]
name = "lakers" # this will be the name of the python package (as in `import lakers`), and it must match the module name in lib.rs
crate-type = ["cdylib"]
40 changes: 40 additions & 0 deletions lakers-python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Lakers Python
Python wrapper for the [`lakers` crate](https://github.com/openwsn-berkeley/lakers).

# Installation and usage

```console
pip install lakers-python
```

```python
import lakers

# generate a keypair
lakers.p256_generate_key_pair()

# instantiate a initiator and prepare EDHOC's message 1
initiator = lakers.EdhocInitiator()
message_1 = initiator.prepare_message_1(c_i=None, ead_1=None)

# for more examples, see the tests in the repository
```

# Development

To build and test:
```bash
maturin develop
pytest
```

## Requirements

The maturin executable must be available. The recommended way is to install and use it in a virtual environment:

```
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip maturin pytest
pip freeze
```
3 changes: 3 additions & 0 deletions lakers-python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"
40 changes: 40 additions & 0 deletions lakers-python/src/ead_authz/authenticator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use lakers::*;
use pyo3::prelude::*;

#[pyclass(name = "AuthzAutenticator")]
pub struct PyAuthzAutenticator {
authenticator: ZeroTouchAuthenticator,
authenticator_wait: ZeroTouchAuthenticatorWaitVoucherResp,
}

#[pymethods]
impl PyAuthzAutenticator {
#[new]
fn new() -> Self {
Self {
authenticator: ZeroTouchAuthenticator::default(),
authenticator_wait: ZeroTouchAuthenticatorWaitVoucherResp::default(),
}
}

pub fn process_ead_1(
&mut self,
ead_1: EADItem,
message_1: Vec<u8>,
) -> PyResult<(Vec<u8>, Vec<u8>)> {
let message_1 = EdhocMessageBuffer::new_from_slice(message_1.as_slice()).unwrap(); // FIXME: avoid unwrap
let (state, loc_w, voucher_request) =
self.authenticator.process_ead_1(&ead_1, &message_1)?;
self.authenticator_wait = state;
Ok((
Vec::from(loc_w.as_slice()),
Vec::from(voucher_request.as_slice()),
))
}

pub fn prepare_ead_2(&self, voucher_response: Vec<u8>) -> PyResult<EADItem> {
let voucher_response =
EdhocMessageBuffer::new_from_slice(voucher_response.as_slice()).unwrap(); // FIXME: avoid unwrap
Ok(self.authenticator_wait.prepare_ead_2(&voucher_response)?)
}
}
4 changes: 4 additions & 0 deletions lakers-python/src/ead_authz/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod authenticator;
pub use authenticator::*;
mod server;
pub use server::*;
37 changes: 37 additions & 0 deletions lakers-python/src/ead_authz/server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use lakers::*;
use lakers_crypto::default_crypto;
use pyo3::prelude::*;

#[pyclass(name = "AuthzEnrollmentServer")]
pub struct PyAuthzEnrollmentServer {
server: ZeroTouchServer,
}

#[pymethods]
impl PyAuthzEnrollmentServer {
#[new]
pub fn new(w: Vec<u8>, cred_v: Vec<u8>, acl: Option<Vec<u8>>) -> Self {
let mut w_arr = BytesP256ElemLen::default();
w_arr.copy_from_slice(&w.as_slice());
let acl = if let Some(acl) = acl {
Some(EdhocMessageBuffer::new_from_slice(acl.as_slice()).unwrap())
} else {
None
};

Self {
server: ZeroTouchServer::new(w_arr, cred_v.as_slice(), acl),
}
}

fn handle_voucher_request(&self, vreq: Vec<u8>) -> PyResult<Vec<u8>> {
let vreq = EdhocMessageBuffer::new_from_slice(vreq.as_slice()).unwrap();
match self
.server
.handle_voucher_request(&mut default_crypto(), &vreq)
{
Ok(voucher_response) => Ok(Vec::from(voucher_response.as_slice())),
Err(error) => Err(error.into()),
}
}
}
Loading

0 comments on commit 11ff1ef

Please sign in to comment.