-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
500 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
181
keystore/src/entities/platform/generic/mls/e2ei_intermediate_cert.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.