Skip to content

Commit

Permalink
Merge pull request #3 from trailofbits/ww/ownership
Browse files Browse the repository at this point in the history
rust: fix typo, OwnedMessageImprint is owned by PyBytes
  • Loading branch information
DarkaMaul authored Oct 2, 2024
2 parents a90d2b9 + 739b400 commit 6ad600e
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 170 deletions.
14 changes: 6 additions & 8 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version-file: pyproject.toml
cache: "pip"
cache-dependency-path: pyproject.toml

- name: Setup rust
uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8
with:
components: rustfmt
toolchain: 1.81.0

- name: install uv
run: >
curl --no-progress-meter --location --fail
--proto '=https' --tlsv1.2
"https://astral.sh/uv/install.sh"
| sh
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.18"
enable-cache: true
cache-dependency-glob: pyproject.toml

- name: lint
run: make lint INSTALL_EXTRA=lint
21 changes: 11 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ jobs:
strategy:
matrix:
python:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v3
with:
python-version: ${{ matrix.python }}
cache: "pip"
cache-dependency-path: pyproject.toml
version: "0.4.18"
enable-cache: true
cache-dependency-glob: pyproject.toml

- name: install uv
run: >
curl --no-progress-meter --location --fail
--proto '=https' --tlsv1.2
"https://astral.sh/uv/install.sh"
| sh
- name: Install Python ${{ matrix.python }}
run: uv python install ${{ matrix.python }}

- name: Setup rust
uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ test tests: $(VENV)/pyvenv.cfg
pytest --cov=$(PY_IMPORT) $(T) $(TEST_ARGS) && \
python -m coverage report -m $(COV_ARGS)
cargo test --manifest-path rust/Cargo.toml
cargo test --manifest-path rust/tsp-asn1/Cargo.toml
19 changes: 4 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,13 @@ classifiers = [
dynamic = ["version"]
readme = "README.md"
license = { file = "LICENSE" }
authors = [
{ name = "Trail of Bits", email = "opensource@trailofbits.com" },
]
dependencies = [
"maturin>=1.7,<2.0",
"cryptography"
]
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
dependencies = ["maturin>=1.7,<2.0", "cryptography"]

[project.optional-dependencies]
doc = []
test = ["pytest", "pytest-cov", "pretend", "coverage[toml]"]
lint = [
"ruff ~= 0.6.7"
]
lint = ["ruff ~= 0.6.7"]
dev = ["sigstore-tsp[test,lint,doc]"]

[project.urls]
Expand All @@ -48,8 +41,4 @@ line-length = 100
include = ["src/**/*.py"]

[tool.ruff.lint]
select = ["ALL"]
# D203 and D213 are incompatible with D211 and D212 respectively.
# COM812 and ISC001 can cause conflicts when using ruff as a formatter.
# See https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules.
ignore = ["D203", "D213", "COM812", "ISC001"]
select = ["E", "F", "I", "W", "UP", "TCH"]
3 changes: 2 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ name = "sigstore-tsp"
version = "0.1.0"
edition = "2021"
authors = [
"Alexis Challande <alexis.challande@trailofbits.com>"
"Trail of Bits <opensource@trailofbits.com>"
]
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
Expand Down
110 changes: 51 additions & 59 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
pub mod oid;
pub mod util;

use std::sync::Arc;

use asn1::SimpleAsn1Readable;
use pyo3::{exceptions::PyValueError, prelude::*};
use rand::Rng;
use sha2::Digest;
use tsp_asn1::cms::SignedData as RawSignedData;
use tsp_asn1::tsp::{
MessageImprint as RawMessageImprint, RawTimeStampReq, RawTimeStampResp, TSTInfo as RawTSTInfo,
TimeStampToken,
};

self_cell::self_cell!(
struct OwnedTimeStamReq {
struct OwnedTimeStampReq {
owner: pyo3::Py<pyo3::types::PyBytes>,
#[covariant]
dependent: RawTimeStampReq,
Expand All @@ -21,7 +21,7 @@ self_cell::self_cell!(

#[pyo3::pyclass]
pub struct TimeStampReq {
raw: Arc<OwnedTimeStamReq>,
raw: OwnedTimeStampReq,
}

#[pyo3::pymethods]
Expand Down Expand Up @@ -56,13 +56,12 @@ impl TimeStampReq {
}

#[getter]
fn message_imprint(&self) -> PyResult<PyMessageImprint> {
// fn message_imprint<'p>(&self, py: pyo3::Python<'p>) -> PyResult<PyMessageImprint> {
fn message_imprint(&self, py: pyo3::Python<'_>) -> PyResult<PyMessageImprint> {
Ok(PyMessageImprint {
contents: OwnedMessageImprint::try_new(Arc::clone(&self.raw), |v| {
Ok::<_, ()>(v.borrow_dependent().message_imprint.clone())
contents: OwnedMessageImprint::try_new(self.raw.borrow_owner().clone_ref(py), |v| {
RawMessageImprint::parse_data(v.as_bytes(py))
})
.unwrap(),
.map_err(|_| PyValueError::new_err("invalid message imprint"))?,
})
}

Expand All @@ -80,8 +79,7 @@ impl TimeStampReq {

self_cell::self_cell!(
struct OwnedMessageImprint {
owner: Arc<OwnedTimeStamReq>,
// owner: pyo3::Py<pyo3::types::PyBytes>,
owner: pyo3::Py<pyo3::types::PyBytes>,
#[covariant]
dependent: RawMessageImprint,
}
Expand Down Expand Up @@ -114,7 +112,7 @@ impl PyMessageImprint {
}

self_cell::self_cell!(
struct OwnedTimeStamResp {
struct OwnedTimeStampResp {
owner: pyo3::Py<pyo3::types::PyBytes>,
#[covariant]
dependent: RawTimeStampResp,
Expand All @@ -123,7 +121,7 @@ self_cell::self_cell!(

#[pyo3::pyclass]
pub struct TimeStampResp {
raw: Arc<OwnedTimeStamResp>,
raw: OwnedTimeStampResp,
}

#[pyo3::pymethods]
Expand Down Expand Up @@ -158,18 +156,22 @@ impl TimeStampResp {

// TST INFO
#[getter]
fn tst_info(&self) -> PyResult<PyTSTInfo> {
fn tst_info(&self, py: pyo3::Python<'_>) -> PyResult<PyTSTInfo> {
let py_tstinfo = PyTSTInfo {
raw: OwnedTSTInfo::try_new(Arc::clone(&self.raw), |v| {
let timestamp_token = v.borrow_dependent().time_stamp_token.as_ref();
match timestamp_token {
Some(content) => match &content.content {
tsp_asn1::tsp::Content::SignedData(signed_data) => {
let tst_info = signed_data.as_inner().content_info.tst_info().unwrap();
Ok::<_, PyErr>(tst_info)
}
},
None => Err(pyo3::exceptions::PyValueError::new_err("")),
raw: OwnedTSTInfo::try_new(self.raw.borrow_owner().clone_ref(py), |v| {
let resp = RawTimeStampResp::parse_data(v.as_bytes(py))
.map_err(|_| PyValueError::new_err("invalid TimeStampResp"))?;

match resp.time_stamp_token {
Some(TimeStampToken {
_content_type,
content: tsp_asn1::tsp::Content::SignedData(signed_data),
}) => signed_data
.as_inner()
.content_info
.tst_info()
.map_err(|_| PyValueError::new_err("invalid TSTInfo")),
None => Err(PyValueError::new_err("missing TimeStampToken")),
}
})
.unwrap(),
Expand All @@ -178,27 +180,18 @@ impl TimeStampResp {
}

// Signed Data
fn signed_data(&self) -> PyResult<SignedData> {
fn signed_data(&self, py: pyo3::Python<'_>) -> PyResult<SignedData> {
let py_signed_data = SignedData {
raw: OwnedSignedData::try_new(Arc::clone(&self.raw), |v| {
let timestamp_token = v.borrow_dependent().time_stamp_token.as_ref();
match timestamp_token {
Some(content) => match &content.content {
tsp_asn1::tsp::Content::SignedData(signed_data) => {
let s = signed_data.as_inner();
Ok::<_, PyErr>(RawSignedData {
version: s.version,
digest_algorithms: s.digest_algorithms.clone(),
content_info: s.content_info.clone(),
certificates: s.certificates.clone(),
crls: None,
signer_infos: s.signer_infos.clone(),
})
}
},
None => Err(pyo3::exceptions::PyValueError::new_err(
"Missing Timestamp Content",
)),
raw: OwnedSignedData::try_new(self.raw.borrow_owner().clone_ref(py), |v| {
let resp = RawTimeStampResp::parse_data(v.as_bytes(py))
.map_err(|_| PyValueError::new_err("invalid TimeStampResp"))?;

match resp.time_stamp_token {
Some(TimeStampToken {
_content_type,
content: tsp_asn1::tsp::Content::SignedData(signed_data),
}) => Ok(*signed_data.into_inner()),
None => Err(PyValueError::new_err("missing TimeStampToken")),
}
})
.unwrap(),
Expand All @@ -209,7 +202,7 @@ impl TimeStampResp {

self_cell::self_cell!(
pub struct OwnedSignedData {
owner: Arc<OwnedTimeStamResp>,
owner: pyo3::Py<pyo3::types::PyBytes>,
#[covariant]
dependent: RawSignedData,
}
Expand Down Expand Up @@ -273,7 +266,7 @@ impl SignedData {

self_cell::self_cell!(
pub struct OwnedTSTInfo {
owner: Arc<OwnedTimeStamResp>,
owner: pyo3::Py<pyo3::types::PyBytes>,
#[covariant]
dependent: RawTSTInfo,
}
Expand Down Expand Up @@ -336,16 +329,15 @@ impl PyTSTInfo {
}
}

// TODO(DM) Message Imprint
// #[getter]
// fn message_imprint(&self) -> PyResult<PyMessageImprint> {
// Ok(PyMessageImprint {
// contents: OwnedMessageImprint::try_new(Arc::clone(&self.raw), |v| {
// Ok::<_, ()>(v.borrow_dependent().message_imprint.clone())
// })
// .unwrap(),
// })
// }
#[getter]
fn message_imprint(&self, py: pyo3::Python<'_>) -> PyResult<PyMessageImprint> {
Ok(PyMessageImprint {
contents: OwnedMessageImprint::try_new(self.raw.borrow_owner().clone_ref(py), |v| {
RawMessageImprint::parse_data(v.as_bytes(py))
})
.map_err(|_| PyValueError::new_err("invalid message imprint"))?,
})
}

#[getter]
fn serial_number<'p>(&self, py: pyo3::Python<'p>) -> PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
Expand Down Expand Up @@ -418,7 +410,7 @@ pub(crate) fn parse_timestamp_response(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> PyResult<TimeStampResp> {
let raw = OwnedTimeStamResp::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))
let raw = OwnedTimeStampResp::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))
.map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("ASN.1 parse error: {:?}", e))
})?;
Expand All @@ -432,7 +424,7 @@ pub(crate) fn parse_timestamp_request(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> PyResult<TimeStampReq> {
let raw = OwnedTimeStamReq::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))
let raw = OwnedTimeStampReq::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))
.map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("ASN.1 parse error: {:?}", e))
})?;
Expand Down Expand Up @@ -476,7 +468,7 @@ pub(crate) fn create_timestamp_request(
.map_err(|e| PyValueError::new_err(format!("Serialization error: {:?}", e)));
let py_bytes = pyo3::types::PyBytes::new_bound(py, &request_bytes.unwrap()).unbind();

let raw = OwnedTimeStamReq::try_new(py_bytes, |data| asn1::parse_single(data.as_bytes(py)))
let raw = OwnedTimeStampReq::try_new(py_bytes, |data| asn1::parse_single(data.as_bytes(py)))
.map_err(|e| {
pyo3::exceptions::PyValueError::new_err(format!("ASN.1 parse error: {:?}", e))
})?;
Expand Down
2 changes: 1 addition & 1 deletion rust/tsp-asn1/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/tsp-asn1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tsp-asn1"
version = "0.0.1"
edition = "2021"
authors = [
"Alexis Challande <alexis.challande@trailofbits.com>"
"Trail of Bits <opensource@trailofbits.com>"
]
publish = false

Expand Down
Loading

0 comments on commit 6ad600e

Please sign in to comment.