/* * * Copyright (c) 2010 * ntldr PGP key ID - 0xC48251EB4F8E4E6E * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef _M_ARM64 #include #include #define __stosb memset #define __movsb memmove #else #include #endif #include "serpent_small.h" #define LTf(_b) { \ _b[0] = _rotl(_b[0], 13); \ _b[2] = _rotl(_b[2], 3); \ _b[1] ^= _b[0] ^ _b[2]; \ _b[3] ^= _b[2] ^ (_b[0] << 3); \ _b[1] = _rotl(_b[1], 1); \ _b[3] = _rotl(_b[3], 7); \ _b[0] ^= _b[1] ^ _b[3]; \ _b[2] ^= _b[3] ^ (_b[1] << 7); \ _b[0] = _rotl(_b[0], 5); \ _b[2] = _rotl(_b[2], 22); \ } #define ITf(_b) { \ _b[2] = _rotr(_b[2], 22); \ _b[0] = _rotr(_b[0], 5); \ _b[2] ^= _b[3] ^ (_b[1] << 7); \ _b[0] ^= _b[1] ^ _b[3]; \ _b[3] = _rotr(_b[3], 7); \ _b[1] = _rotr(_b[1], 1); \ _b[3] ^= _b[2] ^ (_b[0] << 3); \ _b[1] ^= _b[0] ^ _b[2]; \ _b[2] = _rotr(_b[2], 3); \ _b[0] = _rotr(_b[0], 13); \ } #define PHI 0x9E3779B9 typedef void (*sbox_p)(unsigned long b[4]); static void sE1(unsigned long b[4]) { unsigned long t = b[1]; b[3] ^= b[0]; b[1] &= b[3]; t ^= b[2]; b[1] ^= b[0]; b[0] |= b[3]; b[0] ^= t; t ^= b[3]; b[3] ^= b[2]; b[2] |= b[1]; b[2] ^= t; t = ~t; t |= b[1]; b[1] ^= b[3]; b[1] ^= t; b[3] |= b[0]; b[1] ^= b[3]; t ^= b[3]; b[3] = b[0]; b[0] = b[1]; b[1] = t; } static void sE2(unsigned long b[4]) { unsigned long t; b[0] = ~b[0]; b[2] = ~b[2]; t = b[0]; b[0] &= b[1]; b[2] ^= b[0]; b[0] |= b[3]; b[3] ^= b[2]; b[1] ^= b[0]; b[0] ^= t; t |= b[1]; b[1] ^= b[3]; b[2] |= b[0]; b[2] &= t; b[0] ^= b[1]; b[1] &= b[2]; b[1] ^= b[0]; b[0] &= b[2]; t ^= b[0]; b[0] = b[2]; b[2] = b[3]; b[3] = b[1]; b[1] = t; } static void sE3(unsigned long b[4]) { unsigned long t = b[0]; b[0] &= b[2]; b[0] ^= b[3]; b[2] ^= b[1]; b[2] ^= b[0]; b[3] |= t; b[3] ^= b[1]; t ^= b[2]; b[1] = b[3]; b[3] |= t; b[3] ^= b[0]; b[0] &= b[1]; t ^= b[0]; b[1] ^= b[3]; b[1] ^= t; b[0] = b[2]; b[2] = b[1]; b[1] = b[3]; b[3] = ~t; } static void sE4(unsigned long b[4]) { unsigned long t = b[0]; b[0] |= b[3]; b[3] ^= b[1]; b[1] &= t; t ^= b[2]; b[2] ^= b[3]; b[3] &= b[0]; t |= b[1]; b[3] ^= t; b[0] ^= b[1]; t &= b[0]; b[1] ^= b[3]; t ^= b[2]; b[1] |= b[0]; b[1] ^= b[2]; b[0] ^= b[3]; b[2] = b[1]; b[1] |= b[3]; b[0] ^= b[1]; b[1] = b[2]; b[2] = b[3]; b[3] = t; } static void sE5(unsigned long b[4]) { unsigned long t; b[1] ^= b[3]; b[3] = ~b[3]; b[2] ^= b[3]; b[3] ^= b[0]; t = b[1]; b[1] &= b[3]; b[1] ^= b[2]; t ^= b[3]; b[0] ^= t; b[2] &= t; b[2] ^= b[0]; b[0] &= b[1]; b[3] ^= b[0]; t |= b[1]; t ^= b[0]; b[0] |= b[3]; b[0] ^= b[2]; b[2] &= b[3]; b[0] = ~b[0]; t ^= b[2]; b[2] = b[0]; b[0] = b[1]; b[1] = t; } static void sE6(unsigned long b[4]) { unsigned long t; b[0] ^= b[1]; b[1] ^= b[3]; b[3] = ~b[3]; t = b[1]; b[1] &= b[0]; b[2] ^= b[3]; b[1] ^= b[2]; b[2] |= t; t ^= b[3]; b[3] &= b[1]; b[3] ^= b[0]; t ^= b[1]; t ^= b[2]; b[2] ^= b[0]; b[0] &= b[3]; b[2] = ~b[2]; b[0] ^= t; t |= b[3]; t ^= b[2]; b[2] = b[0]; b[0] = b[1]; b[1] = b[3]; b[3] = t; } static void sE7(unsigned long b[4]) { unsigned long t = b[3]; b[2] = ~b[2]; b[3] &= b[0]; b[0] ^= t; b[3] ^= b[2]; b[2] |= t; b[1] ^= b[3]; b[2] ^= b[0]; b[0] |= b[1]; b[2] ^= b[1]; t ^= b[0]; b[0] |= b[3]; b[0] ^= b[2]; t ^= b[3]; t ^= b[0]; b[3] = ~b[3]; b[2] &= t; b[3] ^= b[2]; b[2] = t; } static void sE8(unsigned long b[4]) { unsigned long t = b[1]; b[1] |= b[2]; b[1] ^= b[3]; t ^= b[2]; b[2] ^= b[1]; b[3] |= t; b[3] &= b[0]; t ^= b[2]; b[3] ^= b[1]; b[1] |= t; b[1] ^= b[0]; b[0] |= t; b[0] ^= b[2]; b[1] ^= t; b[2] ^= b[1]; b[1] &= b[0]; b[1] ^= t; b[2] = ~b[2]; b[2] |= b[0]; t ^= b[2]; b[2] = b[1]; b[1] = b[3]; b[3] = b[0]; b[0] = t; } static void sD1(unsigned long b[4]) { unsigned long t = b[1]; b[2] = ~b[2]; b[1] |= b[0]; t = ~t; b[1] ^= b[2]; b[2] |= t; b[1] ^= b[3]; b[0] ^= t; b[2] ^= b[0]; b[0] &= b[3]; t ^= b[0]; b[0] |= b[1]; b[0] ^= b[2]; b[3] ^= t; b[2] ^= b[1]; b[3] ^= b[0]; b[3] ^= b[1]; b[2] &= b[3]; t ^= b[2]; b[2] = b[1]; b[1] = t; } static void sD2(unsigned long b[4]) { unsigned long t = b[1]; b[1] ^= b[3]; b[3] &= b[1]; t ^= b[2]; b[3] ^= b[0]; b[0] |= b[1]; b[2] ^= b[3]; b[0] ^= t; b[0] |= b[2]; b[1] ^= b[3]; b[0] ^= b[1]; b[1] |= b[3]; b[1] ^= b[0]; t = ~t; t ^= b[1]; b[1] |= b[0]; b[1] ^= b[0]; b[1] |= t; b[3] ^= b[1]; b[1] = b[0]; b[0] = t; t = b[2]; b[2] = b[3]; b[3] = t; } static void sD3(unsigned long b[4]) { unsigned long t; b[2] ^= b[3]; b[3] ^= b[0]; t = b[3]; b[3] &= b[2]; b[3] ^= b[1]; b[1] |= b[2]; b[1] ^= t; t &= b[3]; b[2] ^= b[3]; t &= b[0]; t ^= b[2]; b[2] &= b[1]; b[2] |= b[0]; b[3] = ~b[3]; b[2] ^= b[3]; b[0] ^= b[3]; b[0] &= b[1]; b[3] ^= t; b[3] ^= b[0]; b[0] = b[1]; b[1] = t; } static void sD4(unsigned long b[4]) { unsigned long t = b[2]; b[2] ^= b[1]; b[0] ^= b[2]; t &= b[2]; t ^= b[0]; b[0] &= b[1]; b[1] ^= b[3]; b[3] |= t; b[2] ^= b[3]; b[0] ^= b[3]; b[1] ^= t; b[3] &= b[2]; b[3] ^= b[1]; b[1] ^= b[0]; b[1] |= b[2]; b[0] ^= b[3]; b[1] ^= t; b[0] ^= b[1]; t = b[0]; b[0] = b[2]; b[2] = b[3]; b[3] = t; } static void sD5(unsigned long b[4]) { unsigned long t = b[2]; b[2] &= b[3]; b[2] ^= b[1]; b[1] |= b[3]; b[1] &= b[0]; t ^= b[2]; t ^= b[1]; b[1] &= b[2]; b[0] = ~b[0]; b[3] ^= t; b[1] ^= b[3]; b[3] &= b[0]; b[3] ^= b[2]; b[0] ^= b[1]; b[2] &= b[0]; b[3] ^= b[0]; b[2] ^= t; b[2] |= b[3]; b[3] ^= b[0]; b[2] ^= b[1]; b[1] = b[3]; b[3] = t; } static void sD6(unsigned long b[4]) { unsigned long t = b[3]; b[1] = ~b[1]; b[2] ^= b[1]; b[3] |= b[0]; b[3] ^= b[2]; b[2] |= b[1]; b[2] &= b[0]; t ^= b[3]; b[2] ^= t; t |= b[0]; t ^= b[1]; b[1] &= b[2]; b[1] ^= b[3]; t ^= b[2]; b[3] &= t; t ^= b[1]; b[3] ^= t; t = ~t; b[3] ^= b[0]; b[0] = b[1]; b[1] = t; t = b[3]; b[3] = b[2]; b[2] = t; } static void sD7(unsigned long b[4]) { unsigned long t = b[2]; b[0] ^= b[2]; b[2] &= b[0]; t ^= b[3]; b[2] = ~b[2]; b[3] ^= b[1]; b[2] ^= b[3]; t |= b[0]; b[0] ^= b[2]; b[3] ^= t; t ^= b[1]; b[1] &= b[3]; b[1] ^= b[0]; b[0] ^= b[3]; b[0] |= b[2]; b[3] ^= b[1]; t ^= b[0]; b[0] = b[1]; b[1] = b[2]; b[2] = t; } static void sD8(unsigned long b[4]) { unsigned long t = b[2]; b[2] ^= b[0]; b[0] &= b[3]; t |= b[3]; b[2] = ~b[2]; b[3] ^= b[1]; b[1] |= b[0]; b[0] ^= b[2]; b[2] &= t; b[3] &= t; b[1] ^= b[2]; b[2] ^= b[0]; b[0] |= b[2]; t ^= b[1]; b[0] ^= b[3]; b[3] ^= t; t |= b[0]; b[3] ^= b[2]; t ^= b[2]; b[2] = b[1]; b[1] = b[0]; b[0] = b[3]; b[3] = t; } static void __declspec(noinline) KXf(unsigned long *keys, unsigned long round, unsigned long b[4]) { b[0] ^= keys[4*round ]; b[1] ^= keys[4*round+1]; b[2] ^= keys[4*round+2]; b[3] ^= keys[4*round+3]; } static sbox_p se_tab[] = { sE1, sE2, sE3, sE4, sE5, sE6, sE7, sE8 }; static sbox_p sd_tab[] = { sD1, sD2, sD3, sD4, sD5, sD6, sD7, sD8 }; void serpent256_set_key(const unsigned char *key, serpent256_key *skey) { unsigned long W[140], i; __movsb((unsigned char*)&W, key, SERPENT_KEY_SIZE); for(i = 8; i != 140; ++i) { W[i] = _rotl(W[i-8] ^ W[i-5] ^ W[i-3] ^ W[i-1] ^ PHI ^ (i-8), 11); } for (i = 8; i <= 136; i += 4) { se_tab[7 - (((i / 4) + 2) % 8)](&W[i]); } __movsb((unsigned char*)&skey->expkey, (unsigned char*)(W+8), (SERPENT_EXPKEY_WORDS * sizeof(unsigned long))); } void serpent256_encrypt(const unsigned char *in, unsigned char *out, serpent256_key *key) { unsigned long b[4]; int i; __movsb((unsigned char*)&b, in, SERPENT_BLOCK_SIZE); for (i = 0; i < 32; i++) { KXf(key->expkey, i, b); se_tab[i % 8](b); if (i == 31) KXf(key->expkey, 32, b); else LTf(b); } __movsb(out, (const unsigned char*)&b, SERPENT_BLOCK_SIZE); } void serpent256_decrypt(const unsigned char *in, unsigned char *out, serpent256_key *key) { unsigned long b[4]; int i; __movsb((unsigned char*)&b, in, SERPENT_BLOCK_SIZE); for (i = 31; i >= 0; i--) { if (i == 31) KXf(key->expkey, 32, b); else ITf(b); sd_tab[i % 8](b); KXf(key->expkey, i, b); } __movsb(out, (const unsigned char*)&b, SERPENT_BLOCK_SIZE); }