zlicenser-server 0.1.2

Server library for the zlicenser hardware-bound software licensing framework.
Documentation
use std::sync::Arc;

use axum::{
    Json,
    extract::{Path, State},
    http::StatusCode,
    response::{IntoResponse, Response},
};
use serde::Serialize;
use uuid::Uuid;

use crate::issuance::handlers::{ConsentInput, HandlerContext, LicenseReceipt, LicenseRequest};
use crate::storage::Storage;

pub async fn request_handler<S: Storage + Clone + Send + Sync + 'static>(
    State(ctx): State<Arc<HandlerContext<S>>>,
    Json(req): Json<LicenseRequest>,
) -> Response {
    match crate::issuance::handlers::handle_license_request(&ctx, req).await {
        Ok(offer) => (StatusCode::OK, Json(offer)).into_response(),
        Err(e) => e.into_response(),
    }
}

#[derive(serde::Deserialize)]
pub struct ReceiptBody {
    pub offer_nonce: Vec<u8>,
    pub customer_signature: Vec<u8>,
    pub consent: ConsentInput,
}

pub async fn receipt_handler<S: Storage + Clone + Send + Sync + 'static>(
    State(ctx): State<Arc<HandlerContext<S>>>,
    Path(session_id): Path<Uuid>,
    Json(body): Json<ReceiptBody>,
) -> Response {
    let customer_signature: [u8; 64] = match body.customer_signature.try_into() {
        Ok(sig) => sig,
        Err(_) => return crate::Error::InvalidReceiptSignature.into_response(),
    };
    let receipt = LicenseReceipt {
        offer_nonce: body.offer_nonce,
        customer_signature,
        consent: body.consent,
    };
    match crate::issuance::handlers::handle_license_receipt(&ctx, session_id, receipt).await {
        Ok(grant) => {
            #[derive(Serialize)]
            struct GrantResponse {
                license_id: String,
                binding_cert_bytes: Vec<u8>,
                tsa_token: Vec<u8>,
                wrapped_ephemeral_pubkey: Option<Vec<u8>>,
                wrapped_ciphertext: Option<Vec<u8>>,
            }
            (
                StatusCode::OK,
                Json(GrantResponse {
                    license_id: grant.license_id.to_string(),
                    binding_cert_bytes: grant.binding_cert.to_bytes(),
                    tsa_token: grant.tsa_token,
                    wrapped_ephemeral_pubkey: grant
                        .wrapped_secret
                        .as_ref()
                        .map(|w| w.ephemeral_pubkey.to_vec()),
                    wrapped_ciphertext: grant.wrapped_secret.map(|w| w.ciphertext),
                }),
            )
                .into_response()
        }
        Err(e) => e.into_response(),
    }
}