pub fn decrypt_verify<'a>(
        &self,
        out: &'a mut [u8],
        associated_data: &[u8],
        payload: &[u8],
    ) -> Result<&'a [u8], Error> {
        let olen = out.len();
        let alen = associated_data.len();
        let plen = payload.len();

        // Input sanity check
        if alen >= CCM_AAD_MAX_BYTES || plen >= CCM_PAYLOAD_MAX_BYTES {
            return Err(Error::UnsupportedSize);
        }
        if olen < plen - self.mlen {
            return Err(Error::InvalidOutSize);
        }

        // The sequence b for authentication is formatted as follows:
        // b = [FLAGS | nonce | length(MAC length)], where:
        //   FLAGS is 1 byte long
        //   nonce is 13 bytes long
        //   length(MAC length) is 2 bytes long
        // The byte FLAGS is composed by the following 8 bits:
        //   0-2 bits: used to represent the value of q-1
        //   3-5 bits: MAC length (encoded as: (mlen-2)/2)
        //   6: Adata (0 if alen == 0, and 1 otherwise)
        //   7: always 0
        let mut b = [0u8; AES_BLOCK_SIZE];
        let mut tag = [0u8; AES_BLOCK_SIZE];

        // Decryption ---------------------------------------------------------

        // Formatting the sequence b for decryption
        // q - 1 = 2 - 1 = 1
        b[0] = 1;
        b[1..14].copy_from_slice(&self.nonce[..13]);

        // Decrypting payload using ctr mode
        ccm_ctr_mode(
            &mut out[..plen - self.mlen],
            &payload[..plen - self.mlen],
            &mut b,
            &self.cipher,
        );

        // Restoring initial counter value (0)
        b[14] = 0;
        b[15] = 0;

        // Encrypting b and restoring the tag from input
        self.cipher
            .encrypt_block(GenericArray::from_mut_slice(&mut b));
        for i in 0..self.mlen {
            tag[i] = payload[plen - self.mlen + i] ^ b[i];
        }

        // Verifying the authentication tag -----------------------------------

        // Formatting the sequence b for authentication
        b[0] = if alen > 0 { 0x40 } else { 0 }
            | ((self.mlen as u8 - 2) / 2) << 3
            | 1;
        b[1..14].copy_from_slice(&self.nonce[..13]);
        b[14] = ((plen - self.mlen) >> 8) as u8;
        b[15] = (plen - self.mlen) as u8;

        // Computing the authentication tag using CBC-MAC
        self.cipher
            .encrypt_block(GenericArray::from_mut_slice(&mut b));
        if alen > 0 {
            ccm_cbc_mac(&mut b, associated_data, true, &self.cipher);
        }
        if plen > 0 {
            ccm_cbc_mac(&mut b, &out[..plen - self.mlen], false, &self.cipher);
        }

        // Comparing the received tag and the computed one
        if b[..self.mlen] != tag[..self.mlen] {
            // Erase the decrypted buffer
            out[..plen - self.mlen].iter_mut().for_each(|e| *e = 0);
            return Err(Error::VerificationFailed);
        }

        Ok(&mut out[..plen - self.mlen])
    }
/// CCM decryption and tag verification procedure.
///
/// `out` buffer must be at least (`payload.len()` - `c.mlen`) bytes long.
/// A slice to the decrypted output within the buffer will be returned.
CCM decryption and tag verification procedure.
CCM decryption and tag verification procedure .
pub fn decrypt_verify<'a>(
        &self,
        out: &'a mut [u8],
        associated_data: &[u8],
        payload: &[u8],
    ) -> Result<&'a [u8], Error> {
        let olen = out.len();
        let alen = associated_data.len();
        let plen = payload.len();
        // Input sanity check
        if alen >= CCM_AAD_MAX_BYTES || plen >= CCM_PAYLOAD_MAX_BYTES {
            return Err(Error::UnsupportedSize);
        }
        if olen < plen - self.mlen {
            return Err(Error::InvalidOutSize);
        }
        // The sequence b for authentication is formatted as follows:
        // b = [FLAGS | nonce | length(MAC length)], where:
        //   FLAGS is 1 byte long
        //   nonce is 13 bytes long
        //   length(MAC length) is 2 bytes long
        // The byte FLAGS is composed by the following 8 bits:
        //   0-2 bits: used to represent the value of q-1
        //   3-5 bits: MAC length (encoded as: (mlen-2)/2)
        //   6: Adata (0 if alen == 0, and 1 otherwise)
        //   7: always 0
        let mut b = [0u8; AES_BLOCK_SIZE];
        let mut tag = [0u8; AES_BLOCK_SIZE];
        // Decryption ---------------------------------------------------------
        // Formatting the sequence b for decryption
        // q - 1 = 2 - 1 = 1
        b[0] = 1;
        b[1..14].copy_from_slice(&self.nonce[..13]);
        // Decrypting payload using ctr mode
        ccm_ctr_mode(
            &mut out[..plen - self.mlen],
            &payload[..plen - self.mlen],
            &mut b,
            &self.cipher,
        );
        // Restoring initial counter value (0)
        b[14] = 0;
        b[15] = 0;
        // Encrypting b and restoring the tag from input
        self.cipher
            .encrypt_block(GenericArray::from_mut_slice(&mut b));
        for i in 0..self.mlen {
            tag[i] = payload[plen - self.mlen + i] ^ b[i];
        }
        // Verifying the authentication tag -----------------------------------
        // Formatting the sequence b for authentication
        b[0] = if alen > 0 { 0x40 } else { 0 }
            | ((self.mlen as u8 - 2) / 2) << 3
            | 1;
        b[1..14].copy_from_slice(&self.nonce[..13]);
        b[14] = ((plen - self.mlen) >> 8) as u8;
        b[15] = (plen - self.mlen) as u8;
        // Computing the authentication tag using CBC-MAC
        self.cipher
            .encrypt_block(GenericArray::from_mut_slice(&mut b));
        if alen > 0 {
            ccm_cbc_mac(&mut b, associated_data, true, &self.cipher);
        }
        if plen > 0 {
            ccm_cbc_mac(&mut b, &out[..plen - self.mlen], false, &self.cipher);
        }
        // Comparing the received tag and the computed one
        if b[..self.mlen] != tag[..self.mlen] {
            // Erase the decrypted buffer
            out[..plen - self.mlen].iter_mut().for_each(|e| *e = 0);
            return Err(Error::VerificationFailed);
        }
        Ok(&mut out[..plen - self.mlen])
    }
pub fn decrypt_verify < ' a > ( & self , out : & ' a mut [ u8 ] , associated_data : & [ u8 ] , payload : & [ u8 ] , ) -> Result < & ' a [ u8 ] , Error > { let olen = out . len ( ) ; let alen = associated_data . len ( ) ; let plen = payload . len ( ) ; // Input sanity check if alen >= CCM_AAD_MAX_BYTES || plen >= CCM_PAYLOAD_MAX_BYTES { return Err ( Error :: UnsupportedSize ) ; } if olen < plen - self . mlen { return Err ( Error :: InvalidOutSize ) ; } // The sequence b for authentication is formatted as follows: // b = [FLAGS | nonce | length(MAC length)], where: //   FLAGS is 1 byte long //   nonce is 13 bytes long //   length(MAC length) is 2 bytes long // The byte FLAGS is composed by the following 8 bits: //   0-2 bits: used to represent the value of q-1 //   3-5 bits: MAC length (encoded as: (mlen-2)/2) //   6: Adata (0 if alen == 0, and 1 otherwise) //   7: always 0 let mut b = [ 0u8 ; AES_BLOCK_SIZE ] ; let mut tag = [ 0u8 ; AES_BLOCK_SIZE ] ; // Decryption --------------------------------------------------------- // Formatting the sequence b for decryption // q - 1 = 2 - 1 = 1 b [ 0 ] = 1 ; b [ 1 .. 14 ] . copy_from_slice ( & self . nonce [ .. 13 ] ) ; // Decrypting payload using ctr mode ccm_ctr_mode ( & mut out [ .. plen - self . mlen ] , & payload [ .. plen - self . mlen ] , & mut b , & self . cipher , ) ; // Restoring initial counter value (0) b [ 14 ] = 0 ; b [ 15 ] = 0 ; // Encrypting b and restoring the tag from input self . cipher . encrypt_block ( GenericArray :: from_mut_slice ( & mut b ) ) ; for i in 0 .. self . mlen { tag [ i ] = payload [ plen - self . mlen + i ] ^ b [ i ] ; } // Verifying the authentication tag ----------------------------------- // Formatting the sequence b for authentication b [ 0 ] = if alen > 0 { 0x40 } else { 0 } | ( ( self . mlen as u8 - 2 ) / 2 ) << 3 | 1 ; b [ 1 .. 14 ] . copy_from_slice ( & self . nonce [ .. 13 ] ) ; b [ 14 ] = ( ( plen - self . mlen ) >> 8 ) as u8 ; b [ 15 ] = ( plen - self . mlen ) as u8 ; // Computing the authentication tag using CBC-MAC self . cipher . encrypt_block ( GenericArray :: from_mut_slice ( & mut b ) ) ; if alen > 0 { ccm_cbc_mac ( & mut b , associated_data , true , & self . cipher ) ; } if plen > 0 { ccm_cbc_mac ( & mut b , & out [ .. plen - self . mlen ] , false , & self . cipher ) ; } // Comparing the received tag and the computed one if b [ .. self . mlen ] != tag [ .. self . mlen ] { // Erase the decrypted buffer out [ .. plen - self . mlen ] . iter_mut ( ) . for_each ( | e | * e = 0 ) ; return Err ( Error :: VerificationFailed ) ; } Ok ( & mut out [ .. plen - self . mlen ] ) }
CCM decryption and tag verification procedure.
CCM decryption and tag verification procedure .
&self
out
&'a mut [u8]
associated_data
&[u8]
payload
&[u8]
&self
out
&'a mut [u8]
associated_data
&[u8]
payload
&[u8]