1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
use crate::constants::tags::StructureTag;
use crate::tss2_esys::{TPM2B_DIGEST, TPMT_TK_HASHCHECK, TPMT_TK_VERIFIED};
use crate::utils::Hierarchy;
use crate::{Error, Result, WrapperErrorKind};
use log::error;
use std::convert::{TryFrom, TryInto};

/// Macro used for implementing try_from
/// TssTicketType -> TicketType
/// TicketType -> TssTicketType
const TPM2B_DIGEST_BUFFER_SIZE: usize = 64;
macro_rules! impl_ticket_try_froms {
    ($ticket_type:ident, $tss_ticket_type:ident) => {
        impl TryFrom<$ticket_type> for $tss_ticket_type {
            type Error = Error;
            fn try_from(ticket: $ticket_type) -> Result<Self> {
                let digest = ticket.digest;
                if digest.len() > TPM2B_DIGEST_BUFFER_SIZE {
                    return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
                }
                let mut buffer = [0; TPM2B_DIGEST_BUFFER_SIZE];
                buffer[..digest.len()].clone_from_slice(&digest[..digest.len()]);
                Ok($tss_ticket_type {
                    tag: <$ticket_type>::TAG.into(),
                    hierarchy: ticket.hierarchy.rh(),
                    digest: TPM2B_DIGEST {
                        size: digest.len().try_into().unwrap(), // should not fail based on the checks done above
                        buffer,
                    },
                })
            }
        }

        impl TryFrom<$tss_ticket_type> for $ticket_type {
            type Error = Error;

            fn try_from(tss_ticket: $tss_ticket_type) -> Result<Self> {
                match StructureTag::try_from(tss_ticket.tag) {
                    Ok(val) => {
                        if val != <$ticket_type>::TAG {
                            return Err(Error::local_error(WrapperErrorKind::InconsistentParams));
                        }
                    }
                    Err(why) => {
                        error!("Failed to parsed tag: {}", why);
                        return Err(Error::local_error(WrapperErrorKind::InvalidParam));
                    }
                };

                let len = tss_ticket.digest.size.into();
                if len > TPM2B_DIGEST_BUFFER_SIZE {
                    error!(
                        "Error: Invalid digest size.(Digest size: {0} > Digest buffer size: {1})",
                        len, TPM2B_DIGEST_BUFFER_SIZE,
                    );
                    return Err(Error::local_error(WrapperErrorKind::InvalidParam));
                }
                let mut digest = tss_ticket.digest.buffer.to_vec();
                digest.truncate(len);

                let hierarchy = tss_ticket.hierarchy.try_into()?;

                Ok($ticket_type { hierarchy, digest })
            }
        }
    };
}

pub trait Ticket {
    const TAG: StructureTag;
    fn hierarchy(&self) -> Hierarchy;
    fn digest(&self) -> &[u8];
}

#[derive(Debug, Clone)]
pub struct HashcheckTicket {
    hierarchy: Hierarchy,
    digest: Vec<u8>,
}

impl Ticket for HashcheckTicket {
    /// The tag of the verified ticket.
    const TAG: StructureTag = StructureTag::Hashcheck;
    /// Get the hierarchy associated with the verification ticket.
    fn hierarchy(&self) -> Hierarchy {
        self.hierarchy
    }

    /// Get the digest associated with the verification ticket.
    fn digest(&self) -> &[u8] {
        &self.digest
    }
}

impl_ticket_try_froms!(HashcheckTicket, TPMT_TK_HASHCHECK);

/// Rust native wrapper for `TPMT_TK_VERIFIED` objects.
#[derive(Debug)]
pub struct VerifiedTicket {
    hierarchy: Hierarchy,
    digest: Vec<u8>,
}

impl Ticket for VerifiedTicket {
    // type TssTicketType = TPMT_TK_VERIFIED;
    /// The tag of the verified ticket.
    const TAG: StructureTag = StructureTag::Verified;
    /// Get the hierarchy associated with the verification ticket.
    fn hierarchy(&self) -> Hierarchy {
        self.hierarchy
    }
    /// Get the digest associated with the verification ticket.
    fn digest(&self) -> &[u8] {
        &self.digest
    }
}

impl_ticket_try_froms!(VerifiedTicket, TPMT_TK_VERIFIED);