Initial commit
[keepassx] / src / crypto / twoclass.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2007 Tarek Saidi <tarek.saidi@arcor.de>            * 
3  *   Copyright (c) 2003,2004 Dominik Reichl <dominik.reichl@t-online.de>   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; version 2 of the License.               *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18  ***************************************************************************/
19
20
21 #include <QString>
22 #include "twoclass.h"
23
24 static bool g_bInitialized = false;
25
26 CTwofish::CTwofish()
27 {
28 }
29
30 CTwofish::~CTwofish()
31 {
32 }
33
34 bool CTwofish::init(quint8 *pKey, unsigned long uKeyLen, quint8 *initVector)
35 {
36         //ASSERT(pKey != NULL);
37         if(pKey == NULL) return false;
38         //ASSERT(uKeyLen != 0);
39         if(uKeyLen == 0) return false;
40
41         if(g_bInitialized == false)
42         {
43                 Twofish_initialise();
44                 g_bInitialized = true;
45         }
46
47         Twofish_prepare_key((Twofish_Byte *)pKey, uKeyLen, &m_key);
48
49         if(initVector != NULL) memcpy(m_pInitVector, initVector, 16);
50         else memset(m_pInitVector, 0, 16);
51
52         return true;
53 }
54
55 int CTwofish::padEncrypt(quint8 *pInput, int nInputOctets, quint8 *pOutBuffer)
56 {
57         int i, numBlocks, padLen;
58         quint8 block[16], *iv;
59
60         //ASSERT((pInput != NULL) && (nInputOctets != NULL) && (pOutBuffer != NULL));
61         if((pInput == NULL) || (nInputOctets <= 0) || (pOutBuffer == NULL)) return 0;
62
63         numBlocks = nInputOctets / 16;
64
65         iv = m_pInitVector;
66         for(i = numBlocks; i > 0; i--)
67         {
68                 ((quint32*)block)[0] = ((quint32*)pInput)[0] ^ ((quint32*)iv)[0];
69                 ((quint32*)block)[1] = ((quint32*)pInput)[1] ^ ((quint32*)iv)[1];
70                 ((quint32*)block)[2] = ((quint32*)pInput)[2] ^ ((quint32*)iv)[2];
71                 ((quint32*)block)[3] = ((quint32*)pInput)[3] ^ ((quint32*)iv)[3];
72
73                 Twofish_encrypt(&m_key, (Twofish_Byte *)block, (Twofish_Byte *)pOutBuffer);
74
75                 iv = pOutBuffer;
76                 pInput += 16;
77                 pOutBuffer += 16;
78         }
79
80         padLen = 16 - (nInputOctets - (16 * numBlocks));
81
82         for (i = 0; i < 16 - padLen; i++)
83         {
84                 block[i] = (quint8)(pInput[i] ^ iv[i]);
85         }
86
87         for (i = 16 - padLen; i < 16; i++)
88         {
89                 block[i] = (quint8)((quint8)padLen ^ iv[i]);
90         }
91
92         Twofish_encrypt(&m_key, (Twofish_Byte *)block, (Twofish_Byte *)pOutBuffer);
93
94         return 16 * (numBlocks + 1);
95 }
96
97 int CTwofish::padDecrypt(quint8 *pInput, int nInputOctets, quint8 *pOutBuffer)
98 {
99         int i, numBlocks, padLen;
100         quint8 block[16];
101         quint32 iv[4];
102
103         //ASSERT((pInput != NULL) && (nInputOctets != NULL) && (pOutBuffer != NULL));
104         if((pInput == NULL) || (nInputOctets <= 0) || (pOutBuffer == NULL)) return 0;
105
106         if((nInputOctets % 16) != 0) { /*ASSERT(FALSE);*/ return -1; }
107
108         numBlocks = nInputOctets / 16;
109
110         memcpy(iv, m_pInitVector, 16);
111
112         for(i = numBlocks - 1; i > 0; i--)
113         {
114                 Twofish_decrypt(&m_key, (Twofish_Byte *)pInput, (Twofish_Byte *)block);
115                 ((quint32*)block)[0] ^= iv[0];
116                 ((quint32*)block)[1] ^= iv[1];
117                 ((quint32*)block)[2] ^= iv[2];
118                 ((quint32*)block)[3] ^= iv[3];
119                 memcpy(iv, pInput, 16);
120                 memcpy(pOutBuffer, block, 16);
121                 pInput += 16;
122                 pOutBuffer += 16;
123         }
124
125         Twofish_decrypt(&m_key, (Twofish_Byte *)pInput, (Twofish_Byte *)block);
126         ((quint32*)block)[0] ^= iv[0];
127         ((quint32*)block)[1] ^= iv[1];
128         ((quint32*)block)[2] ^= iv[2];
129         ((quint32*)block)[3] ^= iv[3];
130         padLen = block[15];
131         if(padLen <= 0 || padLen > 16) return -1;
132         for(i = 16 - padLen; i < 16; i++)
133         {
134                 if(block[i] != padLen) return -1;
135         }
136         memcpy(pOutBuffer, block, 16 - padLen);
137
138         return 16*numBlocks - padLen;
139 }