1// blowfish.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "blowfish.h"
5#include "misc.h"
6
7NAMESPACE_BEGIN(CryptoPP)
8
9void Blowfish::Base::UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &)
10{
11	AssertValidKeyLength(keylength);
12
13	unsigned i, j=0, k;
14	word32 data, dspace[2] = {0, 0};
15
16	memcpy(pbox, p_init, sizeof(p_init));
17	memcpy(sbox, s_init, sizeof(s_init));
18
19	// Xor key string into encryption key vector
20	for (i=0 ; i<ROUNDS+2 ; ++i)
21	{
22		data = 0 ;
23		for (k=0 ; k<4 ; ++k )
24			data = (data << 8) | key_string[j++ % keylength];
25		pbox[i] ^= data;
26	}
27
28	crypt_block(dspace, pbox);
29
30	for (i=0; i<ROUNDS; i+=2)
31		crypt_block(pbox+i, pbox+i+2);
32
33	crypt_block(pbox+ROUNDS, sbox);
34
35	for (i=0; i<4*256-2; i+=2)
36		crypt_block(sbox+i, sbox+i+2);
37
38	if (!IsForwardTransformation())
39		for (i=0; i<(ROUNDS+2)/2; i++)
40			std::swap(pbox[i], pbox[ROUNDS+1-i]);
41}
42
43// this version is only used to make pbox and sbox
44void Blowfish::Base::crypt_block(const word32 in[2], word32 out[2]) const
45{
46	word32 left = in[0];
47	word32 right = in[1];
48
49	const word32 *const s=sbox;
50	const word32 *p=pbox;
51
52	left ^= p[0];
53
54	for (unsigned i=0; i<ROUNDS/2; i++)
55	{
56		right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
57			  ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
58			  ^ p[2*i+1];
59
60		left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
61			 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
62			 ^ p[2*i+2];
63	}
64
65	right ^= p[ROUNDS+1];
66
67	out[0] = right;
68	out[1] = left;
69}
70
71void Blowfish::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
72{
73	typedef BlockGetAndPut<word32, BigEndian> Block;
74
75	word32 left, right;
76	Block::Get(inBlock)(left)(right);
77
78	const word32 *const s=sbox;
79	const word32 *p=pbox;
80
81	left ^= p[0];
82
83	for (unsigned i=0; i<ROUNDS/2; i++)
84	{
85		right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
86			  ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
87			  ^ p[2*i+1];
88
89		left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
90			 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
91			 ^ p[2*i+2];
92	}
93
94	right ^= p[ROUNDS+1];
95
96	Block::Put(xorBlock, outBlock)(right)(left);
97}
98
99NAMESPACE_END
100