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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use core::mem::transmute;
use core::ptr::{read_unaligned, write_unaligned};
use super::u64x2;

mod expand;

#[derive(Copy, Clone, Debug)]
pub struct Aes192 {
    encrypt_keys: [u64x2; 13],
    decrypt_keys: [u64x2; 13],
}

impl Aes192 {
    #[inline]
    pub fn new(key: &[u8; 24]) -> Self {
        let (encrypt_keys, decrypt_keys) = expand::expand(key);
        Aes192 { encrypt_keys: encrypt_keys, decrypt_keys: decrypt_keys }
    }

    #[inline]
    pub fn encrypt(&self, block: &mut [u8; 16]) {
        let keys = self.encrypt_keys;
        unsafe {
            let mut data: u64x2 = transmute(read_unaligned(block));

            asm!(include_str!("encrypt.asm")
                : "+{xmm0}"(data)
                :
                    "{xmm1}"(keys[0]), "{xmm2}"(keys[1]), "{xmm3}"(keys[2]),
                    "{xmm4}"(keys[3]), "{xmm5}"(keys[4]), "{xmm6}"(keys[5]),
                    "{xmm7}"(keys[6]), "{xmm8}"(keys[7]), "{xmm9}"(keys[8]),
                    "{xmm10}"(keys[9]), "{xmm11}"(keys[10]), "{xmm12}"(keys[11]),
                    "{xmm13}"(keys[12])
                :
                : "intel", "alignstack"
            );

            write_unaligned(block, transmute(data));
        }
    }

    #[inline]
    pub fn decrypt(&self, block: &mut [u8; 16]) {
        let keys = self.decrypt_keys;
        unsafe {
            let mut data: u64x2 = transmute(read_unaligned(block));

            asm!(include_str!("decrypt.asm")
                : "+{xmm0}"(data)
                :
                    "{xmm1}"(keys[12]), "{xmm2}"(keys[11]), "{xmm3}"(keys[10]),
                    "{xmm4}"(keys[9]), "{xmm5}"(keys[8]), "{xmm6}"(keys[7]),
                    "{xmm7}"(keys[6]), "{xmm8}"(keys[5]), "{xmm9}"(keys[4]),
                    "{xmm10}"(keys[3]), "{xmm11}"(keys[2]), "{xmm12}"(keys[1]),
                    "{xmm13}"(keys[0])
                :
                : "intel", "alignstack"
            );

            write_unaligned(block, transmute(data));
        }
    }

    #[inline]
    pub fn encrypt8(&self, blocks: &mut [u8; 8*16]) {
        let keys = self.encrypt_keys;
        unsafe {
            let mut data: [u64x2; 8] = transmute(read_unaligned(blocks));

            asm!(include_str!("encrypt8_1.asm")
                :
                    "+{xmm0}"(data[0]), "+{xmm1}"(data[1]), "+{xmm2}"(data[2]),
                    "+{xmm3}"(data[3]), "+{xmm4}"(data[4]), "+{xmm5}"(data[5]),
                    "+{xmm6}"(data[6]), "+{xmm7}"(data[7])
                :
                    "{xmm8}"(keys[0]), "{xmm9}"(keys[1]), "{xmm10}"(keys[2]),
                    "{xmm11}"(keys[3]), "{xmm12}"(keys[4]), "{xmm13}"(keys[5]),
                    "{xmm14}"(keys[6]), "{xmm15}"(keys[7])
                :
                : "intel", "alignstack"
            );

            asm!(include_str!("encrypt8_2.asm")
                :
                    "+{xmm0}"(data[0]), "+{xmm1}"(data[1]), "+{xmm2}"(data[2]),
                    "+{xmm3}"(data[3]), "+{xmm4}"(data[4]), "+{xmm5}"(data[5]),
                    "+{xmm6}"(data[6]), "+{xmm7}"(data[7])
                :
                    "{xmm11}"(keys[8]), "{xmm12}"(keys[9]), "{xmm13}"(keys[10]),
                    "{xmm14}"(keys[11]), "{xmm15}"(keys[12])
                :
                : "intel", "alignstack"
            );

            write_unaligned(blocks, transmute(data));
        }
    }

    #[inline]
    pub fn decrypt8(&self, blocks: &mut [u8; 8*16]) {
        let keys = self.decrypt_keys;
        unsafe {
            let mut data: [u64x2; 8] = transmute(read_unaligned(blocks));

            asm!(include_str!("decrypt8_1.asm")
                :
                    "+{xmm0}"(data[0]), "+{xmm1}"(data[1]), "+{xmm2}"(data[2]),
                    "+{xmm3}"(data[3]), "+{xmm4}"(data[4]), "+{xmm5}"(data[5]),
                    "+{xmm6}"(data[6]), "+{xmm7}"(data[7])
                :
                    "{xmm8}"(keys[12]), "{xmm9}"(keys[11]), "{xmm10}"(keys[10]),
                    "{xmm11}"(keys[9]), "{xmm12}"(keys[8]), "{xmm13}"(keys[7]),
                    "{xmm14}"(keys[6]), "{xmm15}"(keys[5])
                :
                : "intel", "alignstack"
            );

            asm!(include_str!("decrypt8_2.asm")
                :
                    "+{xmm0}"(data[0]), "+{xmm1}"(data[1]), "+{xmm2}"(data[2]),
                    "+{xmm3}"(data[3]), "+{xmm4}"(data[4]), "+{xmm5}"(data[5]),
                    "+{xmm6}"(data[6]), "+{xmm7}"(data[7])
                :
                    "{xmm11}"(keys[4]), "{xmm12}"(keys[3]), "{xmm13}"(keys[2]),
                    "{xmm14}"(keys[1]), "{xmm15}"(keys[0])
                :
                : "intel", "alignstack"
            );

            write_unaligned(blocks, transmute(data));
        }
    }
}

#[cfg(test)]
mod test_expand;