Skip to content

Commit 0499228

Browse files
introduce send_device_attestation() for device-attest-01
1 parent 8b2f640 commit 0499228

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/order.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use tokio::time::sleep;
1212
use crate::account::AccountInner;
1313
use crate::types::{
1414
Authorization, AuthorizationState, AuthorizationStatus, AuthorizedIdentifier, Challenge,
15-
ChallengeType, Empty, FinalizeRequest, OrderState, OrderStatus, Problem,
15+
ChallengeType, DeviceAttestation, Empty, FinalizeRequest, OrderState, OrderStatus, Problem,
1616
};
1717
use crate::{Error, Key, crypto, nonce_from_response, retry_after};
1818

@@ -453,6 +453,44 @@ impl ChallengeHandle<'_> {
453453
}
454454
}
455455

456+
/// Notify the server that the challenge is ready and send device attestation
457+
///
458+
/// This function is for the ACME challenge device-attest-01.
459+
/// See <https://datatracker.ietf.org/doc/draft-acme-device-attest/> for details.
460+
///
461+
/// Note: Do not use this function for http-01, tls-alpn-01 or dns-01 challenges.
462+
///
463+
/// `payload` is the device attestation object as defined in link. Provide the attestation
464+
/// object as a raw blob. Base64 encoding of the attestation object `payload.att_obj`
465+
/// is done by this function.
466+
pub async fn send_device_attestation(
467+
&mut self,
468+
payload: &DeviceAttestation,
469+
) -> Result<(), Error> {
470+
if self.challenge.r#type != ChallengeType::DeviceAttest01 {
471+
return Err(Error::Str("challenge type should be device-attest-01"));
472+
}
473+
474+
// The DeviceAttestation struct can be used for base64 encoding.
475+
let payload = DeviceAttestation {
476+
att_obj: BASE64_URL_SAFE_NO_PAD
477+
.encode(payload.att_obj.as_slice())
478+
.into_bytes(),
479+
};
480+
481+
let rsp = self
482+
.account
483+
.post(Some(&payload), self.nonce.take(), &self.challenge.url)
484+
.await?;
485+
486+
*self.nonce = nonce_from_response(&rsp);
487+
let response = Problem::check::<Challenge>(rsp).await?;
488+
match response.error {
489+
Some(details) => Err(Error::Api(details)),
490+
None => Ok(()),
491+
}
492+
}
493+
456494
/// Create a [`KeyAuthorization`] for this challenge
457495
///
458496
/// Combines a challenge's token with the thumbprint of the account's public key to compute

src/types.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ pub enum ChallengeType {
714714
Dns01,
715715
#[serde(rename = "tls-alpn-01")]
716716
TlsAlpn01,
717+
#[serde(rename = "device-attest-01")]
718+
DeviceAttest01,
717719
#[serde(untagged)]
718720
Unknown(String),
719721
}
@@ -943,6 +945,14 @@ pub(crate) enum SigningAlgorithm {
943945
#[derive(Debug, Serialize)]
944946
pub(crate) struct Empty {}
945947

948+
/// Attestation payload used for device-attest-01
949+
#[derive(Serialize)]
950+
#[serde(rename_all = "camelCase")]
951+
pub struct DeviceAttestation {
952+
/// attestation payload
953+
pub att_obj: Vec<u8>,
954+
}
955+
946956
#[cfg(test)]
947957
mod tests {
948958
#[cfg(feature = "x509-parser")]

0 commit comments

Comments
 (0)