1 /*
2  * Copyright (c) 2000, 2002, 2005 X-Way Rights BV
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  */
19 
20 /*!\file blockmode.c
21  * \brief Blockcipher operation modes.
22  * \author Bob Deblier <bob.deblier@telenet.be>
23  * \ingroup BC_m
24  */
25 
26 #define BEECRYPT_DLL_EXPORT
27 
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 
32 #include "beecrypt/blockmode.h"
33 
blockEncryptECB(const blockCipher * bc,blockCipherParam * bp,uint32_t * dst,const uint32_t * src,unsigned int nblocks)34 int blockEncryptECB(const blockCipher* bc, blockCipherParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
35 {
36 	register const unsigned int blockwords = bc->blocksize >> 2;
37 
38 	while (nblocks > 0)
39 	{
40 		bc->raw.encrypt(bp, dst, src);
41 
42 		dst += blockwords;
43 		src += blockwords;
44 
45 		nblocks--;
46 	}
47 
48 	return 0;
49 }
50 
blockDecryptECB(const blockCipher * bc,blockCipherParam * bp,uint32_t * dst,const uint32_t * src,unsigned int nblocks)51 int blockDecryptECB(const blockCipher* bc, blockCipherParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
52 {
53 	register const unsigned int blockwords = bc->blocksize >> 2;
54 
55 	while (nblocks > 0)
56 	{
57 		bc->raw.decrypt(bp, dst, src);
58 
59 		dst += blockwords;
60 		src += blockwords;
61 
62 		nblocks--;
63 	}
64 
65 	return 0;
66 }
67 
blockEncryptCBC(const blockCipher * bc,blockCipherParam * bp,uint32_t * dst,const uint32_t * src,unsigned int nblocks)68 int blockEncryptCBC(const blockCipher* bc, blockCipherParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
69 {
70 	register const unsigned int blockwords = bc->blocksize >> 2;
71 	register uint32_t* fdback = bc->getfb(bp);
72 
73 	if (nblocks > 0)
74 	{
75 		register unsigned int i;
76 
77 		for (i = 0; i < blockwords; i++)
78 			dst[i] = src[i] ^ fdback[i];
79 
80 		bc->raw.encrypt(bp, dst, dst);
81 
82 		nblocks--;
83 
84 		while (nblocks > 0)
85 		{
86 			for (i = 0; i < blockwords; i++)
87 				dst[i+blockwords] = src[i+blockwords] ^ dst[i];
88 
89 			dst += blockwords;
90 
91 			bc->raw.encrypt(bp, dst, dst);
92 
93 			src += blockwords;
94 
95 			nblocks--;
96 		}
97 
98 		for (i = 0; i < blockwords; i++)
99 			fdback[i] = dst[i];
100 	}
101 
102 	return 0;
103 }
104 
blockDecryptCBC(const blockCipher * bc,blockCipherParam * bp,uint32_t * dst,const uint32_t * src,unsigned int nblocks)105 int blockDecryptCBC(const blockCipher* bc, blockCipherParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
106 {
107 	register const unsigned int blockwords = bc->blocksize >> 2;
108 	register uint32_t* fdback = bc->getfb(bp);
109 	register uint32_t* buf = (uint32_t*) malloc(blockwords * sizeof(uint32_t));
110 
111 	if (buf)
112 	{
113 		while (nblocks > 0)
114 		{
115 			register uint32_t tmp;
116 			register unsigned int i;
117 
118 			bc->raw.decrypt(bp, buf, src);
119 
120 			for (i = 0; i < blockwords; i++)
121 			{
122 				tmp = src[i];
123 				dst[i] = buf[i] ^ fdback[i];
124 				fdback[i] = tmp;
125 			}
126 
127 			dst += blockwords;
128 			src += blockwords;
129 
130 			nblocks--;
131 		}
132 		free(buf);
133 		return 0;
134 	}
135 
136 	return -1;
137 }
138 
blockEncryptCTR(const blockCipher * bc,blockCipherParam * bp,uint32_t * dst,const uint32_t * src,unsigned int nblocks)139 int blockEncryptCTR(const blockCipher* bc, blockCipherParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
140 {
141 	/* host-endian counter is kept in fdback;
142 	 * swap to big-endian buffer;
143 	 * encrypt buffer;
144 	 * src ^ ciphertext -> dst
145 	 * increment fdback (as mpi) by one inlined;
146 	 */
147 
148 	register const unsigned int blockwords = bc->blocksize >> 2;
149 	register uint32_t* fdback = bc->getfb(bp);
150 	register uint32_t* buf = (uint32_t*) malloc(blockwords * sizeof(uint32_t));
151 
152 	if (buf)
153 	{
154 		while (nblocks > 0)
155 		{
156 			unsigned int i, j;
157 
158 			#if WORDS_BIGENDIAN
159 			bc->raw.encrypt(bp, buf, fdback);
160 			#else
161 			for (i = 0, j = blockwords-1; i < blockwords; i++, j--)
162 				buf[i] = swapu32(fdback[j]);
163 			bc->raw.encrypt(bp, buf, buf);
164 			#endif
165 
166 			for (i = 0; i < blockwords; i++)
167 				dst[i] = src[i] ^ buf[i];
168 
169 			dst += blockwords;
170 			src += blockwords;
171 
172 			nblocks--;
173 
174 			/* increment counter */
175 			mpaddw((blockwords >> 1), (mpw*) fdback, 1);
176 		}
177 		free(buf);
178 		return 0;
179 	}
180 
181 	return -1;
182 }
183