void blowfish_initialize( blowfish_t* blowfish, const void* key, const unsigned int length ) { unsigned int capped_length = ( length <= MAXKEY ) ? length : MAXKEY; const unsigned char* ckey = key; uint32_t data, ldata, hdata; unsigned int isub, ikey, iword, ibox, ientry; memcpy( blowfish->parray, _blowfish_parray_init, 4 * SUBKEYS ); memcpy( blowfish->sboxes, _blowfish_sboxes_init, 4 * SBOXES * SBOXENTRIES ); for( isub = 0, ikey = 0; isub < SUBKEYS; ++isub ) { data = 0; for( iword = 0; iword < 4; ++iword, ++ikey ) data = ( data << 8 ) | ckey[ ikey % capped_length ]; blowfish->parray[isub] ^= data; } ldata = 0; hdata = 0; for( isub = 0; isub < SUBKEYS; isub += 2 ) { _blowfish_encrypt_words( blowfish, &ldata, &hdata ); /*lint --e{661,679} */ blowfish->parray[isub] = ldata; blowfish->parray[isub+1] = hdata; } for( ibox = 0; ibox < SBOXES; ++ibox ) { for( ientry = 0; ientry < SBOXENTRIES; ientry += 2 ) { _blowfish_encrypt_words( blowfish, &ldata, &hdata ); /*lint --e{661,679} */ blowfish->sboxes[ibox][ientry] = ldata; blowfish->sboxes[ibox][ientry+1] = hdata; } } //Reset memory for paranoids /*lint --e{438} */ data = 0; ldata = 0; hdata = 0; }
DECLARE_TEST(blowfish, initialize) { blowfish_t* blowfish; unsigned int i, j; uint32_t left, right; blowfish = blowfish_allocate(); for (i = 0; i < NUM_VARIABLEKEYTESTS; ++i) { blowfish_initialize(blowfish, _test_key_variable[i], 8); left = _test_plaintext_left[i]; right = _test_plaintext_right[i]; _blowfish_encrypt_words(blowfish, &left, &right); EXPECT_EQ(memcmp(&left, &_test_ciphertext_left[i], 4), 0); EXPECT_EQ(memcmp(&right, &_test_ciphertext_right[i], 4), 0); _blowfish_decrypt_words(blowfish, &left, &right); EXPECT_EQ(memcmp(&left, &_test_plaintext_left[i], 4), 0); EXPECT_EQ(memcmp(&right, &_test_plaintext_right[i], 4), 0); } for (j = 1, i = NUM_VARIABLEKEYTESTS; i < (NUM_VARIABLEKEYTESTS + NUM_SETKEYTESTS); ++i) { blowfish_initialize(blowfish, _test_key_set, j++); left = _test_plaintext_left[i]; right = _test_plaintext_right[i]; _blowfish_encrypt_words(blowfish, &left, &right); EXPECT_EQ(memcmp(&left, &_test_ciphertext_left[i], 4), 0); EXPECT_EQ(memcmp(&right, &_test_ciphertext_right[i], 4), 0); _blowfish_decrypt_words(blowfish, &left, &right); EXPECT_EQ(memcmp(&left, &_test_plaintext_left[i], 4), 0); EXPECT_EQ(memcmp(&right, &_test_plaintext_right[i], 4), 0); } blowfish_deallocate(blowfish); return 0; }
void blowfish_decrypt( const blowfish_t* blowfish, void* data, unsigned int length, const blowfish_mode_t mode, const uint64_t vec ) { uint32_t* RESTRICT cur; uint32_t* RESTRICT end; uint32_t chain[2]; uint32_t prev_chain[2]; uint32_t swap_chain[2]; if( length % 8 ) length -= ( length % 8 ); if( !data || !length ) return; /*lint --e{826} */ cur = data; end = pointer_offset( data, length ); chain[0] = (uint32_t)( ( vec >> 32ULL ) & 0xFFFFFFFFU ); chain[1] = (uint32_t)( vec & 0xFFFFFFFFU ); switch( mode ) { case BLOWFISH_ECB: { for( ; cur < end; cur += 2 ) _blowfish_decrypt_words( blowfish, cur, cur + 1 ); break; } case BLOWFISH_CBC: { for( ; cur < end; cur += 2 ) { prev_chain[0] = cur[0]; prev_chain[1] = cur[1]; _blowfish_decrypt_words( blowfish, cur, cur + 1 ); cur[0] ^= chain[0]; cur[1] ^= chain[1]; swap_chain[0] = chain[0]; swap_chain[1] = chain[1]; chain[0] = prev_chain[0]; chain[1] = prev_chain[1]; prev_chain[0] = swap_chain[0]; prev_chain[1] = swap_chain[1]; } break; } case BLOWFISH_CFB: { for( ; cur < end; cur += 2 ) { prev_chain[0] = cur[0]; prev_chain[1] = cur[1]; _blowfish_encrypt_words( blowfish, chain, chain + 1 ); cur[0] ^= chain[0]; cur[1] ^= chain[1]; swap_chain[0] = chain[0]; swap_chain[1] = chain[1]; chain[0] = prev_chain[0]; chain[1] = prev_chain[1]; prev_chain[0] = swap_chain[0]; prev_chain[1] = swap_chain[1]; } break; } case BLOWFISH_OFB: { for( ; cur < end; cur += 2 ) { _blowfish_encrypt_words( blowfish, chain, chain + 1 ); cur[0] ^= chain[0]; cur[1] ^= chain[1]; } break; } default: break; } //Reset memory for paranoids /*lint --e{438} */ chain[0] = 0; chain[1] = 0; prev_chain[0] = 0; prev_chain[1] = 0; swap_chain[0] = 0; swap_chain[1] = 0; }