Skip to main content

zlicenser_protocol/message/
grant.rs

1// Field order is the wire format. Do not reorder without a protocol version bump.
2
3use serde::{Deserialize, Serialize};
4
5use super::request::Identity;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct LicenseGrant {
9    pub payload: LicenseGrantPayload,
10    #[serde(with = "crate::wire::bytes::sig_bytes")]
11    pub vendor_signature: [u8; 64],
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub struct LicenseGrantPayload {
16    pub protocol_version: u16,
17    pub grant_id: [u8; 16],
18    pub request_id: [u8; 16],
19    pub product_id: String,
20    pub product_version: String,
21    pub identity: Identity,
22    pub fingerprint_commitment: [u8; 32],
23    pub terms: LicenseTerms,
24    pub vendor_public_key: [u8; 32],
25    pub issued_at: u64,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub tsa_token: Option<Vec<u8>>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub struct LicenseTerms {
32    pub connectivity: ConnectivityMode,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub grace_period_seconds: Option<u64>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub expires_at: Option<u64>,
37    pub max_seats: u32,
38    /// Empty means no fingerprint restriction. Non-empty restricts to these specific hashes.
39    pub allowed_fingerprints: Vec<[u8; 32]>,
40    pub transfer_policy: TransferPolicy,
41    pub tsa_tier: TsaTier,
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "kebab-case")]
46pub enum ConnectivityMode {
47    AirGapped,
48    Online,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52#[serde(rename_all = "kebab-case")]
53pub enum TransferPolicy {
54    VendorApproved,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58#[serde(rename_all = "kebab-case")]
59pub enum TsaTier {
60    /// free, tamper-evidence only
61    Free,
62    /// subscription-based, commercially recognised, not eIDAS qualified
63    Standard,
64    /// eIDAS qualified, statutory legal weight
65    Qualified,
66}