1 /****************************************************************************
2 *																			*
3 *					  cryptlib CAST-128 Encryption Routines					*
4 *						Copyright Peter Gutmann 1997-2005					*
5 *																			*
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9   #include "crypt.h"
10   #include "context.h"
11   #include "cast.h"
12 #else
13   #include "crypt.h"
14   #include "context/context.h"
15   #include "crypt/cast.h"
16 #endif /* Compiler-specific includes */
17 
18 #ifdef USE_CAST
19 
20 /* Defines to map from EAY to native naming */
21 
22 #define CAST_BLOCKSIZE			CAST_BLOCK
23 
24 /* The size of the keyscheduled CAST key */
25 
26 #define CAST_EXPANDED_KEYSIZE	sizeof( CAST_KEY )
27 
28 /****************************************************************************
29 *																			*
30 *								CAST Self-test Routines						*
31 *																			*
32 ****************************************************************************/
33 
34 #ifndef CONFIG_NO_SELFTEST
35 
36 /* CAST test vectors from CAST specification */
37 
38 static const struct CAST_TEST {
39 	BYTE key[ CAST_KEY_LENGTH + 8 ];
40 	BYTE plaintext[ CAST_BLOCKSIZE + 8 ];
41 	BYTE ciphertext[ CAST_BLOCKSIZE + 8 ];
42 	} FAR_BSS testCAST[] = {
43 	{ { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
44 		0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A },
45 	  { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
46 	  { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 } }
47 	};
48 
49 /* Test the CAST code against the CAST test vectors */
50 
selfTest(void)51 static int selfTest( void )
52 	{
53 	const CAPABILITY_INFO *capabilityInfo = getCASTCapability();
54 	BYTE keyData[ CAST_EXPANDED_KEYSIZE + 8 ];
55 	int i, status;
56 
57 	memset( keyData, 0, CAST_EXPANDED_KEYSIZE );	/* Keep static analysers happy */
58 	for( i = 0; i < sizeof( testCAST ) / sizeof( struct CAST_TEST ); i++ )
59 		{
60 		status = testCipher( capabilityInfo, keyData, testCAST[ i ].key,
61 							 CAST_KEY_LENGTH, testCAST[ i ].plaintext,
62 							 testCAST[ i ].ciphertext );
63 		if( cryptStatusError( status ) )
64 			return( status );
65 		}
66 
67 	return( CRYPT_OK );
68 	}
69 #else
70 	#define selfTest	NULL
71 #endif /* !CONFIG_NO_SELFTEST */
72 
73 /****************************************************************************
74 *																			*
75 *								Control Routines							*
76 *																			*
77 ****************************************************************************/
78 
79 /* Return context subtype-specific information */
80 
81 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
getInfo(IN_ENUM (CAPABILITY_INFO)const CAPABILITY_INFO_TYPE type,INOUT_OPT CONTEXT_INFO * contextInfoPtr,OUT void * data,IN_INT_Z const int length)82 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
83 					INOUT_OPT CONTEXT_INFO *contextInfoPtr,
84 					OUT void *data,
85 					IN_INT_Z const int length )
86 	{
87 	assert( contextInfoPtr == NULL || \
88 			isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
89 	assert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \
90 			( length > 0 && isWritePtr( data, length ) ) );
91 
92 	REQUIRES( type > CAPABILITY_INFO_NONE && type < CAPABILITY_INFO_LAST );
93 
94 	if( type == CAPABILITY_INFO_STATESIZE )
95 		{
96 		int *valuePtr = ( int * ) data;
97 
98 		*valuePtr = CAST_EXPANDED_KEYSIZE;
99 
100 		return( CRYPT_OK );
101 		}
102 
103 	return( getDefaultInfo( type, contextInfoPtr, data, length ) );
104 	}
105 
106 /****************************************************************************
107 *																			*
108 *							CAST En/Decryption Routines						*
109 *																			*
110 ****************************************************************************/
111 
112 /* Encrypt/decrypt data in ECB mode */
113 
encryptECB(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)114 static int encryptECB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
115 					   int noBytes )
116 	{
117 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
118 	int blockCount = noBytes / CAST_BLOCKSIZE;
119 
120 	while( blockCount-- > 0 )
121 		{
122 		/* Encrypt a block of data */
123 		CAST_ecb_encrypt( buffer, buffer, convInfo->key, CAST_ENCRYPT );
124 
125 		/* Move on to next block of data */
126 		buffer += CAST_BLOCKSIZE;
127 		}
128 
129 	return( CRYPT_OK );
130 	}
131 
decryptECB(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)132 static int decryptECB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
133 					   int noBytes )
134 	{
135 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
136 	int blockCount = noBytes / CAST_BLOCKSIZE;
137 
138 	while( blockCount-- > 0 )
139 		{
140 		/* Decrypt a block of data */
141 		CAST_ecb_encrypt( buffer, buffer, convInfo->key, CAST_DECRYPT );
142 
143 		/* Move on to next block of data */
144 		buffer += CAST_BLOCKSIZE;
145 		}
146 
147 	return( CRYPT_OK );
148 	}
149 
150 /* Encrypt/decrypt data in CBC mode */
151 
encryptCBC(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)152 static int encryptCBC( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
153 					   int noBytes )
154 	{
155 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
156 
157 	CAST_cbc_encrypt( buffer, buffer, noBytes, convInfo->key,
158 					  convInfo->currentIV, CAST_ENCRYPT );
159 
160 	return( CRYPT_OK );
161 	}
162 
decryptCBC(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)163 static int decryptCBC( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
164 					   int noBytes )
165 	{
166 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
167 
168 	CAST_cbc_encrypt( buffer, buffer, noBytes, convInfo->key,
169 					  convInfo->currentIV, CAST_DECRYPT );
170 
171 	return( CRYPT_OK );
172 	}
173 
174 /* Encrypt/decrypt data in CFB mode */
175 
encryptCFB(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)176 static int encryptCFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
177 					   int noBytes )
178 	{
179 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
180 	int i, ivCount = convInfo->ivCount;
181 
182 	/* If there's any encrypted material left in the IV, use it now */
183 	if( ivCount > 0 )
184 		{
185 		int bytesToUse;
186 
187 		/* Find out how much material left in the encrypted IV we can use */
188 		bytesToUse = CAST_BLOCKSIZE - ivCount;
189 		if( noBytes < bytesToUse )
190 			bytesToUse = noBytes;
191 
192 		/* Encrypt the data */
193 		for( i = 0; i < bytesToUse; i++ )
194 			buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
195 		memcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );
196 
197 		/* Adjust the byte count and buffer position */
198 		noBytes -= bytesToUse;
199 		buffer += bytesToUse;
200 		ivCount += bytesToUse;
201 		}
202 
203 	while( noBytes > 0 )
204 		{
205 		ivCount = ( noBytes > CAST_BLOCKSIZE ) ? CAST_BLOCKSIZE : noBytes;
206 
207 		/* Encrypt the IV */
208 		CAST_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,
209 						  convInfo->key, CAST_ENCRYPT );
210 
211 		/* XOR the buffer contents with the encrypted IV */
212 		for( i = 0; i < ivCount; i++ )
213 			buffer[ i ] ^= convInfo->currentIV[ i ];
214 
215 		/* Shift the ciphertext into the IV */
216 		memcpy( convInfo->currentIV, buffer, ivCount );
217 
218 		/* Move on to next block of data */
219 		noBytes -= ivCount;
220 		buffer += ivCount;
221 		}
222 
223 	/* Remember how much of the IV is still available for use */
224 	convInfo->ivCount = ( ivCount % CAST_BLOCKSIZE );
225 
226 	return( CRYPT_OK );
227 	}
228 
229 /* Decrypt data in CFB mode.  Note that the transformation can be made
230    faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp
231    all in one loop */
232 
decryptCFB(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)233 static int decryptCFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
234 					   int noBytes )
235 	{
236 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
237 	BYTE temp[ CAST_BLOCKSIZE + 8 ];
238 	int i, ivCount = convInfo->ivCount;
239 
240 	/* If there's any encrypted material left in the IV, use it now */
241 	if( ivCount > 0 )
242 		{
243 		int bytesToUse;
244 
245 		/* Find out how much material left in the encrypted IV we can use */
246 		bytesToUse = CAST_BLOCKSIZE - ivCount;
247 		if( noBytes < bytesToUse )
248 			bytesToUse = noBytes;
249 
250 		/* Decrypt the data */
251 		memcpy( temp, buffer, bytesToUse );
252 		for( i = 0; i < bytesToUse; i++ )
253 			buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
254 		memcpy( convInfo->currentIV + ivCount, temp, bytesToUse );
255 
256 		/* Adjust the byte count and buffer position */
257 		noBytes -= bytesToUse;
258 		buffer += bytesToUse;
259 		ivCount += bytesToUse;
260 		}
261 
262 	while( noBytes > 0 )
263 		{
264 		ivCount = ( noBytes > CAST_BLOCKSIZE ) ? CAST_BLOCKSIZE : noBytes;
265 
266 		/* Encrypt the IV */
267 		CAST_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,
268 						  convInfo->key, CAST_ENCRYPT );
269 
270 		/* Save the ciphertext */
271 		memcpy( temp, buffer, ivCount );
272 
273 		/* XOR the buffer contents with the encrypted IV */
274 		for( i = 0; i < ivCount; i++ )
275 			buffer[ i ] ^= convInfo->currentIV[ i ];
276 
277 		/* Shift the ciphertext into the IV */
278 		memcpy( convInfo->currentIV, temp, ivCount );
279 
280 		/* Move on to next block of data */
281 		noBytes -= ivCount;
282 		buffer += ivCount;
283 		}
284 
285 	/* Remember how much of the IV is still available for use */
286 	convInfo->ivCount = ( ivCount % CAST_BLOCKSIZE );
287 
288 	/* Clear the temporary buffer */
289 	zeroise( temp, CAST_BLOCKSIZE );
290 
291 	return( CRYPT_OK );
292 	}
293 
294 /****************************************************************************
295 *																			*
296 *							CAST Key Management Routines					*
297 *																			*
298 ****************************************************************************/
299 
300 /* Key schedule an CAST key */
301 
initKey(CONTEXT_INFO * contextInfoPtr,const void * key,const int keyLength)302 static int initKey( CONTEXT_INFO *contextInfoPtr, const void *key,
303 					const int keyLength )
304 	{
305 	CONV_INFO *convInfo = contextInfoPtr->ctxConv;
306 
307 	/* Copy the key to internal storage */
308 	if( convInfo->userKey != key )
309 		memcpy( convInfo->userKey, key, keyLength );
310 	convInfo->userKeyLength = keyLength;
311 
312 	CAST_set_key( convInfo->key, CAST_KEY_LENGTH, ( BYTE * ) key );
313 	return( CRYPT_OK );
314 	}
315 
316 /****************************************************************************
317 *																			*
318 *						Capability Access Routines							*
319 *																			*
320 ****************************************************************************/
321 
322 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
323 	CRYPT_ALGO_CAST, bitsToBytes( 64 ), "CAST-128", 8,
324 	MIN_KEYSIZE, bitsToBytes( 128 ), bitsToBytes( 128 ),
325 	selfTest, getInfo, NULL, initGenericParams, initKey, NULL,
326 	encryptECB, decryptECB, encryptCBC, decryptCBC,
327 	encryptCFB, decryptCFB
328 	};
329 
getCASTCapability(void)330 const CAPABILITY_INFO *getCASTCapability( void )
331 	{
332 	return( &capabilityInfo );
333 	}
334 
335 #endif /* USE_CAST */
336