Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
OtaK committed Dec 13, 2023
1 parent 84bd838 commit 8c23555
Show file tree
Hide file tree
Showing 11 changed files with 500 additions and 7 deletions.
2 changes: 1 addition & 1 deletion keystore/src/entities/mls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ pub struct E2eiAcmeCA {
derive(serde::Serialize, serde::Deserialize)
)]
pub struct E2eiIntermediateCert {
// TODO: add a key to identify the CA cert; Using a combination of SKI & AKI extensions concatenated like so is suitable: `SKI[+AKI]`
// key to identify the CA cert; Using a combination of SKI & AKI extensions concatenated like so is suitable: `SKI[+AKI]`
pub ski_aki_pair: String,
pub content: Vec<u8>,
}
Expand Down
2 changes: 1 addition & 1 deletion keystore/src/entities/platform/generic/mls/e2ei_acme_ca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl EntityBase for E2eiAcmeCA {
type AutoGeneratedFields = ();

fn to_missing_key_err_kind() -> MissingKeyErrorKind {
MissingKeyErrorKind::RefreshToken
MissingKeyErrorKind::E2eiAcmeCA
}

async fn find_all(_conn: &mut Self::ConnectionType, _params: EntityFindParams) -> CryptoKeystoreResult<Vec<Self>> {
Expand Down
160 changes: 160 additions & 0 deletions keystore/src/entities/platform/generic/mls/e2ei_crl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Wire
// Copyright (C) 2022 Wire Swiss GmbH

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.

use crate::{
connection::{DatabaseConnection, KeystoreDatabaseConnection},
entities::{E2eiCrl, Entity, EntityBase, EntityFindParams, StringEntityId},
CryptoKeystoreError, MissingKeyErrorKind,
};

impl Entity for E2eiCrl {
fn id_raw(&self) -> &[u8] {
self.distribution_point.as_bytes()
}
}

#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
impl EntityBase for E2eiCrl {
type ConnectionType = KeystoreDatabaseConnection;
type AutoGeneratedFields = ();

fn to_missing_key_err_kind() -> MissingKeyErrorKind {
MissingKeyErrorKind::E2eiCrl
}

async fn find_all(
conn: &mut Self::ConnectionType,
params: EntityFindParams,
) -> crate::CryptoKeystoreResult<Vec<Self>> {
let transaction = conn.transaction()?;
let query: String = format!("SELECT rowid, distribution_point FROM e2ei_crls {}", params.to_sql());

let mut stmt = transaction.prepare_cached(&query)?;
let mut rows = stmt.query_map([], |r| Ok((r.get(0)?, r.get(1)?)))?;
let entities = rows.try_fold(Vec::new(), |mut acc, row_res| {
use std::io::Read as _;
let (rowid, id) = row_res?;

let mut blob = transaction.blob_open(rusqlite::DatabaseName::Main, "e2ei_crls", "content", rowid, false)?;

let mut content = vec![];
blob.read_to_end(&mut content)?;
blob.close()?;

acc.push(Self {
distribution_point,
content,
});

crate::CryptoKeystoreResult::Ok(acc)
})?;

Ok(entities)
}

async fn save(&self, conn: &mut Self::ConnectionType) -> crate::CryptoKeystoreResult<()> {
use rusqlite::OptionalExtension as _;
use rusqlite::ToSql as _;

Self::ConnectionType::check_buffer_size(self.content.len())?;

let transaction = conn.transaction()?;
let existing_rowid = transaction
.query_row(
"SELECT rowid FROM e2ei_crls WHERE distribution_point = ?",
[self.distribution_point.as_str()],
|r| r.get::<_, i64>(0),
)
.optional()?;

let row_id = if existing_rowid.is_some() {
return Err(CryptoKeystoreError::AlreadyExists);
} else {
let zb = rusqlite::blob::ZeroBlob(self.content.len() as i32);
let params: [rusqlite::types::ToSqlOutput; 2] = [self.distribution_point.to_sql()?, zb.to_sql()?];
transaction.execute(
"INSERT INTO e2ei_crls (distribution_point, content) VALUES (?, ?)",
params,
)?;
transaction.last_insert_rowid()
};

let mut blob = transaction.blob_open(rusqlite::DatabaseName::Main, "e2ei_crls", "content", row_id, false)?;

use std::io::Write as _;
blob.write_all(&self.content)?;
blob.close()?;

transaction.commit()?;

Ok(())
}

async fn find_one(
conn: &mut Self::ConnectionType,
id: &StringEntityId,
) -> crate::CryptoKeystoreResult<Option<Self>> {
let transaction = conn.transaction()?;
use rusqlite::OptionalExtension as _;
let distribution_point: String = id.try_into()?;
let mut row_id = transaction
.query_row(
"SELECT rowid FROM e2ei_crls WHERE distribution_point = ?",
[distribution_point.as_str()],
|r| r.get::<_, i64>(0),
)
.optional()?;

if let Some(rowid) = row_id.take() {
let mut blob = transaction.blob_open(rusqlite::DatabaseName::Main, "e2ei_crls", "content", rowid, true)?;
use std::io::Read as _;
let mut buf = Vec::with_capacity(blob.len());
blob.read_to_end(&mut buf)?;
blob.close()?;

transaction.commit()?;

Ok(Some(Self {
distribution_point,
content: buf,
}))
} else {
Ok(None)
}
}

async fn count(conn: &mut Self::ConnectionType) -> crate::CryptoKeystoreResult<usize> {
Ok(conn.query_row("SELECT COUNT(*) FROM e2ei_crls", [], |r| r.get(0))?)
}

async fn delete(conn: &mut Self::ConnectionType, ids: &[StringEntityId]) -> crate::CryptoKeystoreResult<()> {
let transaction = conn.transaction()?;
let len = ids.len();
let mut updated = 0;
for id in ids {
updated += transaction.execute("DELETE FROM e2ei_crls WHERE distribution_point = ?", [id.try_as_str()?])?;
}

if updated == len {
transaction.commit()?;
Ok(())
} else {
transaction.rollback()?;
Err(Self::to_missing_key_err_kind().into())
}
}
}
181 changes: 181 additions & 0 deletions keystore/src/entities/platform/generic/mls/e2ei_intermediate_cert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Wire
// Copyright (C) 2022 Wire Swiss GmbH

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.

use crate::{
connection::{DatabaseConnection, KeystoreDatabaseConnection},
entities::{E2eiIntermediateCert, Entity, EntityBase, EntityFindParams, StringEntityId},
CryptoKeystoreError, MissingKeyErrorKind,
};

impl Entity for E2eiIntermediateCert {
fn id_raw(&self) -> &[u8] {
self.ski_aki_pair.as_bytes()
}
}

#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
impl EntityBase for E2eiIntermediateCert {
type ConnectionType = KeystoreDatabaseConnection;
type AutoGeneratedFields = ();

fn to_missing_key_err_kind() -> MissingKeyErrorKind {
MissingKeyErrorKind::E2eiIntermediateCert
}

async fn find_all(
conn: &mut Self::ConnectionType,
params: EntityFindParams,
) -> crate::CryptoKeystoreResult<Vec<Self>> {
let transaction = conn.transaction()?;
let query: String = format!(
"SELECT rowid, ski_aki_pair FROM e2ei_intermediate_certs {}",
params.to_sql()
);

let mut stmt = transaction.prepare_cached(&query)?;
let mut rows = stmt.query_map([], |r| Ok((r.get(0)?, r.get(1)?)))?;
let entities = rows.try_fold(Vec::new(), |mut acc, row_res| {
use std::io::Read as _;
let (rowid, id) = row_res?;

let mut blob = transaction.blob_open(
rusqlite::DatabaseName::Main,
"e2ei_intermediate_certs",
"content",
rowid,
false,
)?;

let mut content = vec![];
blob.read_to_end(&mut content)?;
blob.close()?;

acc.push(Self { ski_aki_pair, content });

crate::CryptoKeystoreResult::Ok(acc)
})?;

Ok(entities)
}

async fn save(&self, conn: &mut Self::ConnectionType) -> crate::CryptoKeystoreResult<()> {
use rusqlite::OptionalExtension as _;
use rusqlite::ToSql as _;

Self::ConnectionType::check_buffer_size(self.content.len())?;

let transaction = conn.transaction()?;
let existing_rowid = transaction
.query_row(
"SELECT rowid FROM e2ei_intermediate_certs WHERE ski_aki_pair = ?",
[self.ski_aki_pair.as_str()],
|r| r.get::<_, i64>(0),
)
.optional()?;

let row_id = if existing_rowid.is_some() {
return Err(CryptoKeystoreError::AlreadyExists);
} else {
let zb = rusqlite::blob::ZeroBlob(self.content.len() as i32);
let params: [rusqlite::types::ToSqlOutput; 2] = [self.ski_aki_pair.to_sql()?, zb.to_sql()?];
transaction.execute(
"INSERT INTO e2ei_intermediate_certs (ski_aki_pair, content) VALUES (?, ?)",
params,
)?;
transaction.last_insert_rowid()
};

let mut blob = transaction.blob_open(
rusqlite::DatabaseName::Main,
"e2ei_intermediate_certs",
"content",
row_id,
false,
)?;

use std::io::Write as _;
blob.write_all(&self.content)?;
blob.close()?;

transaction.commit()?;

Ok(())
}

async fn find_one(
conn: &mut Self::ConnectionType,
id: &StringEntityId,
) -> crate::CryptoKeystoreResult<Option<Self>> {
let transaction = conn.transaction()?;
use rusqlite::OptionalExtension as _;
let ski_aki_pair: String = id.try_into()?;
let mut row_id = transaction
.query_row(
"SELECT rowid FROM e2ei_intermediate_certs WHERE ski_aki_pair = ?",
[ski_aki_pair.as_str()],
|r| r.get::<_, i64>(0),
)
.optional()?;

if let Some(rowid) = row_id.take() {
let mut blob = transaction.blob_open(
rusqlite::DatabaseName::Main,
"e2ei_intermediate_certs",
"content",
rowid,
true,
)?;
use std::io::Read as _;
let mut buf = Vec::with_capacity(blob.len());
blob.read_to_end(&mut buf)?;
blob.close()?;

transaction.commit()?;

Ok(Some(Self {
ski_aki_pair,
content: buf,
}))
} else {
Ok(None)
}
}

async fn count(conn: &mut Self::ConnectionType) -> crate::CryptoKeystoreResult<usize> {
Ok(conn.query_row("SELECT COUNT(*) FROM e2ei_intermediate_certs", [], |r| r.get(0))?)
}

async fn delete(conn: &mut Self::ConnectionType, ids: &[StringEntityId]) -> crate::CryptoKeystoreResult<()> {
let transaction = conn.transaction()?;
let len = ids.len();
let mut updated = 0;
for id in ids {
updated += transaction.execute(
"DELETE FROM e2ei_intermediate_certs WHERE ski_aki_pair = ?",
[id.try_as_str()?],
)?;
}

if updated == len {
transaction.commit()?;
Ok(())
} else {
transaction.rollback()?;
Err(Self::to_missing_key_err_kind().into())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl EntityBase for E2eiRefreshToken {
type AutoGeneratedFields = ();

fn to_missing_key_err_kind() -> MissingKeyErrorKind {
MissingKeyErrorKind::RefreshToken
MissingKeyErrorKind::E2eiRefreshToken
}

async fn find_all(_conn: &mut Self::ConnectionType, _params: EntityFindParams) -> CryptoKeystoreResult<Vec<Self>> {
Expand Down
2 changes: 1 addition & 1 deletion keystore/src/entities/platform/wasm/mls/e2ei_acme_ca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl EntityBase for E2eiAcmeCA {
type AutoGeneratedFields = ();

fn to_missing_key_err_kind() -> MissingKeyErrorKind {
MissingKeyErrorKind::RefreshToken
MissingKeyErrorKind::E2eiAcmeCA
}

async fn find_all(_conn: &mut Self::ConnectionType, _params: EntityFindParams) -> CryptoKeystoreResult<Vec<Self>> {
Expand Down
Loading

0 comments on commit 8c23555

Please sign in to comment.