add more specific error handeling to certs
All checks were successful
Build and Test / account (push) Successful in 6m7s
All checks were successful
Build and Test / account (push) Successful in 6m7s
This commit is contained in:
parent
893bcecc9e
commit
6b96e1db51
1 changed files with 52 additions and 16 deletions
|
|
@ -15,6 +15,7 @@ use bytemuck::bytes_of;
|
||||||
use chrono::{NaiveDate, NaiveDateTime, Utc};
|
use chrono::{NaiveDate, NaiveDateTime, Utc};
|
||||||
use openssl::bn::BigNum;
|
use openssl::bn::BigNum;
|
||||||
use openssl::ecdsa::EcdsaSig;
|
use openssl::ecdsa::EcdsaSig;
|
||||||
|
use openssl::error::ErrorStack;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::request::{FromRequest, Outcome};
|
use rocket::request::{FromRequest, Outcome};
|
||||||
|
|
@ -262,7 +263,7 @@ pub async fn link_certificate_to_pid(
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO certificate_pids (cert_hash, pid)
|
"INSERT INTO certificate_pids (cert_hash, pid)
|
||||||
VALUES ($1, $2)
|
VALUES ($1, $2)
|
||||||
ON CONFLICT DO NOTHING"
|
ON CONFLICT DO NOTHING",
|
||||||
)
|
)
|
||||||
.bind(&hash[..])
|
.bind(&hash[..])
|
||||||
.bind(pid)
|
.bind(pid)
|
||||||
|
|
@ -330,14 +331,17 @@ impl<'r> FromRequest<'r> for DeviceCert {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cert = match Certificate::new(cert_header) {
|
let cert = match Certificate::new(cert_header) {
|
||||||
Some(c) => c,
|
Ok(c) => c,
|
||||||
None => return Outcome::Error((Status::BadGateway, INVALID_TOKEN_ERRORS)),
|
Err(e) => {
|
||||||
|
println!("error occurred whilest getting cert data: {}", e);
|
||||||
|
return Outcome::Error((Status::BadGateway, INVALID_TOKEN_ERRORS));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let hash = cert.hash();
|
let hash = cert.hash();
|
||||||
|
|
||||||
let existing = sqlx::query_as::<_, CertificateRecord>(
|
let existing = sqlx::query_as::<_, CertificateRecord>(
|
||||||
"SELECT hash, banned FROM certificates WHERE hash = $1"
|
"SELECT hash, banned FROM certificates WHERE hash = $1",
|
||||||
)
|
)
|
||||||
.bind(&hash[..])
|
.bind(&hash[..])
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
|
|
@ -359,7 +363,7 @@ impl<'r> FromRequest<'r> for DeviceCert {
|
||||||
} else {
|
} else {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO certificates (hash, banned)
|
"INSERT INTO certificates (hash, banned)
|
||||||
VALUES ($1, false)"
|
VALUES ($1, false)",
|
||||||
)
|
)
|
||||||
.bind(&hash[..])
|
.bind(&hash[..])
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
|
|
@ -396,19 +400,36 @@ MFIwEAYHKoZIzj0CAQYFK4EEABsDPgAEAP1WBBgs8XUJIQDDCK5IOZEbb5+h1TqV
|
||||||
rwgzSUcrAAFxMWm1kf/TDL9z2nZkuo0N+VtNEQREZDXA7aQv
|
rwgzSUcrAAFxMWm1kf/TDL9z2nZkuo0N+VtNEQREZDXA7aQv
|
||||||
-----END PUBLIC KEY-----"#;
|
-----END PUBLIC KEY-----"#;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
enum CertError {
|
||||||
|
#[error("unable to decode base64: {0}")]
|
||||||
|
Base64(#[from] base64::DecodeError),
|
||||||
|
#[error("unable to decode outer cert: {0}")]
|
||||||
|
OuterBinError(binrw::Error),
|
||||||
|
#[error("unable to decode inner cert: {0}")]
|
||||||
|
BinError(binrw::Error),
|
||||||
|
#[error("unable to create openssl ecdsa sig: {0}")]
|
||||||
|
EcdsaSig(ErrorStack),
|
||||||
|
#[error("error whilest validating signature: {0}")]
|
||||||
|
CryptoVerifError(ErrorStack),
|
||||||
|
#[error("certificate is not valid")]
|
||||||
|
ValidationError,
|
||||||
|
}
|
||||||
|
|
||||||
impl Certificate {
|
impl Certificate {
|
||||||
fn new(data: &str) -> Option<Self> {
|
fn new(data: &str) -> Result<Self, CertError> {
|
||||||
let data = BASE64_STANDARD.decode(data).unwrap();
|
let data = BASE64_STANDARD.decode(data)?;
|
||||||
|
|
||||||
let cert = OuterCertificate::read(&mut Cursor::new(&data)).ok()?;
|
let cert =
|
||||||
|
OuterCertificate::read(&mut Cursor::new(&data)).map_err(CertError::OuterBinError)?;
|
||||||
|
|
||||||
println!("key");
|
let key = openssl::ec::EcKey::public_key_from_pem(PUB_PEM).expect("invalid pem file");
|
||||||
|
|
||||||
let key = openssl::ec::EcKey::public_key_from_pem(PUB_PEM).ok()?;
|
let sig_components = read_p1363(&cert.signature)
|
||||||
|
.expect("unable to read signature despite fixed size signature");
|
||||||
|
|
||||||
let sig_components = read_p1363(&cert.signature)?;
|
let sig = EcdsaSig::from_private_components(sig_components.0, sig_components.1)
|
||||||
|
.map_err(CertError::EcdsaSig)?;
|
||||||
let sig = EcdsaSig::from_private_components(sig_components.0, sig_components.1).unwrap();
|
|
||||||
|
|
||||||
let mut hasher = openssl::sha::Sha256::new();
|
let mut hasher = openssl::sha::Sha256::new();
|
||||||
|
|
||||||
|
|
@ -416,11 +437,14 @@ impl Certificate {
|
||||||
|
|
||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
|
|
||||||
if !sig.verify(&hash[..], &key).ok()? {
|
if !sig
|
||||||
return None;
|
.verify(&hash[..], &key)
|
||||||
|
.map_err(CertError::CryptoVerifError)?
|
||||||
|
{
|
||||||
|
return Err(CertError::ValidationError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Certificate::read(&mut Cursor::new(cert.data)).ok()
|
Certificate::read(&mut Cursor::new(cert.data)).map_err(CertError::BinError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(&self) -> [u8; 32] {
|
pub fn hash(&self) -> [u8; 32] {
|
||||||
|
|
@ -446,3 +470,15 @@ fn read_p1363(data: &[u8]) -> Option<(BigNum, BigNum)> {
|
||||||
BigNum::from_slice(&data[half_len..]).ok()?,
|
BigNum::from_slice(&data[half_len..]).ok()?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::account::account::Certificate;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
const CERT: &str = "AAEABQAsTGvAP1XNwh6JO+z47AkwVvqPYHRDO9X11BdhYwCIEipUJne32JSWMAYsFe1LqWT+0AkSnaDCkMWK1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSb290LUNBMDAwMDAwMDMtTVMwMDAwMDAxMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk5HNDQ0Y2FiZmMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1/THZAcTyFksveCuIl5fOM7Fb6ebi6mUqcVJlQQDqvsgMAW12aEaECJWV+Y6wXOL+E7yP5WJ/9VAd4jlgrvZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||||
|
|
||||||
|
Certificate::new(CERT).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue