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
//! Data Authentication Algorithm (DAA) implemetnation as defined in the FIPS 113.
//!
//! **WARNING!** The algorithm is not considered secure by today's standards.
//! DO NOT USE it if you don't have to be compatible with legacy software!
//!
//! # Examples
//!
//! ```
//! use daa::{Daa, Mac};
//!
//! // test from FIPS 113
//! let key = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
//! let mut mac = Daa::new_varkey(&key).unwrap();
//! mac.input(b"7654321 Now is the time for ");
//! let correct = [0xF1, 0xD3, 0x0F, 0x68, 0x49, 0x31, 0x2C, 0xA4];
//! mac.verify(&correct).unwrap();
//! ```
#![no_std]
#![doc(html_logo_url =
    "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
extern crate des;
pub extern crate crypto_mac;

pub use crypto_mac::Mac;
use crypto_mac::MacResult;
use crypto_mac::generic_array::GenericArray;
use crypto_mac::generic_array::typenum::Unsigned;
use des::Des;
use des::block_cipher_trait::BlockCipher;

use core::fmt;

type Block = GenericArray<u8, <Des as BlockCipher>::BlockSize>;

/// DAA instance
#[derive(Clone)]
pub struct Daa {
    cipher: Des,
    buffer: Block,
    pos: usize,
}

impl Mac for Daa {
    type OutputSize = <Des as BlockCipher>::BlockSize;
    type KeySize = <Des as BlockCipher>::KeySize;

    fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
        let cipher = Des::new(key);
        Self { cipher, buffer: Default::default(), pos: 0 }
    }

    #[inline]
    fn input(&mut self, mut data: &[u8]) {
        let n = <Des as BlockCipher>::BlockSize::to_usize();

        let rem = n - self.pos;
        if data.len() >= rem {
            let (l, r) = data.split_at(rem);
            data = r;
            for (a, b) in self.buffer[self.pos..].iter_mut().zip(l) {
                *a ^= *b;
            }
            self.pos = n;
        } else {
            for (a, b) in self.buffer[self.pos..].iter_mut().zip(data) {
                *a ^= *b;
            }
            self.pos += data.len();
            return;
        }

        while data.len() >= n {
            self.cipher.encrypt_block(&mut self.buffer);

            let (l, r) = data.split_at(n);
            data = r;

            for i in 0..n {
                self.buffer[i] ^= l[i];
            }
        }

        if data.len() != 0 {
            self.cipher.encrypt_block(&mut self.buffer);
            for (a, b) in self.buffer.iter_mut().zip(data) {
                *a ^= *b;
            }
            self.pos = data.len();
        }
    }

    #[inline]
    fn result(mut self) -> MacResult<Self::OutputSize> {
        if self.pos != 0 {
            self.cipher.encrypt_block(&mut self.buffer);
        }
        MacResult::new(self.buffer)
    }

    #[inline]
    fn reset(&mut self) {
        if self.pos != 0 {
            self.pos = 0;
            self.buffer = Default::default();
        }
    }
}

impl fmt::Debug for Daa {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Daa")
    }
}