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