@@ -303,9 +303,9 @@ static const ulong32 ORIG_S[4][256] = {
303303
304304static void s_blowfish_encipher (ulong32 * L , ulong32 * R , const symmetric_key * skey )
305305{
306- int r ;
306+ int rounds ;
307307
308- ulong32 _L , _R ;
308+ ulong32 l , r ;
309309#ifndef __GNUC__
310310 const ulong32 * S1 , * S2 , * S3 , * S4 ;
311311
@@ -315,23 +315,34 @@ static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *ske
315315 S4 = skey -> blowfish .S [3 ];
316316#endif
317317
318- _L = * L ;
319- _R = * R ;
318+ l = * L ;
319+ r = * R ;
320320
321321 /* do 16 rounds */
322- for (r = 0 ; r < 16 ; ) {
323- _L ^= skey -> blowfish .K [r ++ ]; _R ^= F (_L );
324- _R ^= skey -> blowfish .K [r ++ ]; _L ^= F (_R );
325- _L ^= skey -> blowfish .K [r ++ ]; _R ^= F (_L );
326- _R ^= skey -> blowfish .K [r ++ ]; _L ^= F (_R );
322+ for (rounds = 0 ; rounds < 16 ; ) {
323+ l ^= skey -> blowfish .K [rounds ++ ]; r ^= F (l );
324+ r ^= skey -> blowfish .K [rounds ++ ]; l ^= F (r );
325+ l ^= skey -> blowfish .K [rounds ++ ]; r ^= F (l );
326+ r ^= skey -> blowfish .K [rounds ++ ]; l ^= F (r );
327327 }
328328
329329 /* last keying */
330- _R ^= skey -> blowfish .K [17 ];
331- _L ^= skey -> blowfish .K [16 ];
330+ l ^= skey -> blowfish .K [16 ];
331+ r ^= skey -> blowfish .K [17 ];
332+
333+ * L = r ;
334+ * R = l ;
335+ }
332336
333- * L = _L ;
334- * R = _R ;
337+ void blowfish_enc (ulong32 * data , unsigned long blocks , const symmetric_key * skey )
338+ {
339+ unsigned long i ;
340+ ulong32 * d = data ;
341+
342+ for (i = 0 ; i < blocks ; ++ i ) {
343+ s_blowfish_encipher (d , d + 1 , skey );
344+ d += 2 ;
345+ }
335346}
336347
337348static ulong32 s_blowfish_stream2word (const unsigned char * d , int dlen , int * cur )
@@ -352,70 +363,60 @@ static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur
352363}
353364
354365 /**
355- Initialize the Blowfish block cipher
366+ Expand the Blowfish internal state
356367 @param key The symmetric key you wish to pass
357368 @param keylen The key length in bytes
369+ @param data The additional data you wish to pass (can be NULL)
370+ @param datalen The additional data length in bytes
358371 @param num_rounds The number of rounds desired (0 for default)
359372 @param skey The key in as scheduled by this function.
360373 @return CRYPT_OK if successful
361374 */
362- int blowfish_setup (const unsigned char * key , int keylen , int num_rounds ,
363- symmetric_key * skey )
375+ int blowfish_expand (const unsigned char * key , int keylen ,
376+ const unsigned char * data , int datalen ,
377+ symmetric_key * skey )
364378{
365- ulong32 x , z , A , B [2 ];
366- int y ;
379+ ulong32 x , y , A , B [2 ];
380+ int i ;
367381
368382 LTC_ARGCHK (key != NULL );
369383 LTC_ARGCHK (skey != NULL );
370384
371- /* check key length */
372- if (keylen < 8 || keylen > 56 ) {
373- return CRYPT_INVALID_KEYSIZE ;
374- }
375-
376- /* check rounds */
377- if (num_rounds != 0 && num_rounds != 16 ) {
378- return CRYPT_INVALID_ROUNDS ;
379- }
380-
381385 /* load in key bytes (Supplied by David Hopwood) */
382- y = 0 ;
383- for (x = y = 0 ; x < 18 ; x ++ ) {
384- A = s_blowfish_stream2word (key , keylen , & y );
385- skey -> blowfish .K [x ] = ORIG_P [x ] ^ A ;
386- }
387-
388- /* copy sboxes */
389- for (x = 0 ; x < 4 ; x ++ ) {
390- for (y = 0 ; y < 256 ; y ++ ) {
391- skey -> blowfish .S [x ][y ] = ORIG_S [x ][y ];
392- }
386+ i = 0 ;
387+ for (x = 0 ; x < 18 ; x ++ ) {
388+ A = s_blowfish_stream2word (key , keylen , & i );
389+ skey -> blowfish .K [x ] ^= A ;
393390 }
394391
395- /* encrypt K array */
396- for (x = 0 ; x < 2 ; x ++ ) {
397- B [x ] = 0 ;
398- }
399392
393+ i = 0 ;
394+ B [0 ] = 0 ;
395+ B [1 ] = 0 ;
400396 for (x = 0 ; x < 18 ; x += 2 ) {
401-
397+ if (data != NULL ) {
398+ B [0 ] ^= s_blowfish_stream2word (data , datalen , & i );
399+ B [1 ] ^= s_blowfish_stream2word (data , datalen , & i );
400+ }
402401 /* encrypt it */
403402 s_blowfish_encipher (& B [0 ], & B [1 ], skey );
404403 /* copy it */
405- skey -> blowfish .K [x ] = B [1 ];
406- skey -> blowfish .K [x + 1 ] = B [1 ] = B [0 ];
407- B [0 ] = skey -> blowfish .K [x ];
404+ skey -> blowfish .K [x ] = B [0 ];
405+ skey -> blowfish .K [x + 1 ] = B [1 ];
408406 }
409407
410408 /* encrypt S array */
411409 for (x = 0 ; x < 4 ; x ++ ) {
412410 for (y = 0 ; y < 256 ; y += 2 ) {
411+ if (data != NULL ) {
412+ B [0 ] ^= s_blowfish_stream2word (data , datalen , & i );
413+ B [1 ] ^= s_blowfish_stream2word (data , datalen , & i );
414+ }
413415 /* encrypt it */
414416 s_blowfish_encipher (& B [0 ], & B [1 ], skey );
415417 /* copy it */
416- skey -> blowfish .S [x ][y ] = B [1 ];
417- skey -> blowfish .S [x ][y + 1 ] = B [1 ] = B [0 ];
418- B [0 ] = skey -> blowfish .S [x ][y ];
418+ skey -> blowfish .S [x ][y ] = B [0 ];
419+ skey -> blowfish .S [x ][y + 1 ] = B [1 ];
419420 }
420421 }
421422
@@ -426,6 +427,49 @@ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
426427 return CRYPT_OK ;
427428}
428429
430+ /**
431+ Initialize the Blowfish block cipher
432+ @param key The symmetric key you wish to pass
433+ @param keylen The key length in bytes
434+ @param num_rounds The number of rounds desired (0 for default)
435+ @param skey The key in as scheduled by this function.
436+ @return CRYPT_OK if successful
437+ */
438+ int blowfish_setup (const unsigned char * key , int keylen , int num_rounds ,
439+ symmetric_key * skey )
440+ {
441+ /* check key length */
442+ if (keylen < 8 || keylen > 56 ) {
443+ return CRYPT_INVALID_KEYSIZE ;
444+ }
445+ /* check rounds */
446+ if (num_rounds != 0 && num_rounds != 16 ) {
447+ return CRYPT_INVALID_ROUNDS ;
448+ }
449+
450+ return blowfish_setup_with_data (key , keylen , NULL , 0 , skey );
451+ }
452+
453+ /**
454+ Alternative initialize of the Blowfish block cipher
455+ @param key The symmetric key you wish to pass
456+ @param keylen The key length in bytes
457+ @param data The additional data you wish to pass (can be NULL)
458+ @param datalen The additional data length in bytes
459+ @param num_rounds The number of rounds desired (0 for default)
460+ @param skey The key in as scheduled by this function.
461+ @return CRYPT_OK if successful
462+ */
463+
464+ int blowfish_setup_with_data (const unsigned char * key , int keylen ,
465+ const unsigned char * data , int datalen ,
466+ symmetric_key * skey )
467+ {
468+ XMEMCPY (skey -> blowfish .K , ORIG_P , sizeof (ORIG_P ));
469+ XMEMCPY (skey -> blowfish .S , ORIG_S , sizeof (ORIG_S ));
470+ return blowfish_expand (key , keylen , data , datalen , skey );
471+ }
472+
429473/**
430474 Encrypts a block of text with Blowfish
431475 @param pt The input plaintext (8 bytes)
@@ -452,8 +496,8 @@ int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symme
452496 s_blowfish_encipher (& L , & R , skey );
453497
454498 /* store */
455- STORE32H (R , & ct [0 ]);
456- STORE32H (L , & ct [4 ]);
499+ STORE32H (L , & ct [0 ]);
500+ STORE32H (R , & ct [4 ]);
457501
458502 return CRYPT_OK ;
459503}
@@ -584,6 +628,8 @@ int blowfish_test(void)
584628 for (y = 0 ; y < 1000 ; y ++ ) blowfish_ecb_decrypt (tmp [0 ], tmp [0 ], & key );
585629 for (y = 0 ; y < 8 ; y ++ ) if (tmp [0 ][y ] != 0 ) return CRYPT_FAIL_TESTVECTOR ;
586630 }
631+
632+
587633 return CRYPT_OK ;
588634 #endif
589635}
0 commit comments