1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * BF low level APIs are deprecated for public use, but still ok for internal
12e1051a39Sopenharmony_ci * use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <openssl/blowfish.h>
17e1051a39Sopenharmony_ci#include "bf_local.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci/*
20e1051a39Sopenharmony_ci * Blowfish as implemented from 'Blowfish: Springer-Verlag paper' (From
21e1051a39Sopenharmony_ci * LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, CAMBRIDGE
22e1051a39Sopenharmony_ci * SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
23e1051a39Sopenharmony_ci */
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20)
26e1051a39Sopenharmony_ci# error If you set BF_ROUNDS to some value other than 16 or 20, you will have \
27e1051a39Sopenharmony_cito modify the code.
28e1051a39Sopenharmony_ci#endif
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_civoid BF_encrypt(BF_LONG *data, const BF_KEY *key)
31e1051a39Sopenharmony_ci{
32e1051a39Sopenharmony_ci    register BF_LONG l, r;
33e1051a39Sopenharmony_ci    register const BF_LONG *p, *s;
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci    p = key->P;
36e1051a39Sopenharmony_ci    s = &(key->S[0]);
37e1051a39Sopenharmony_ci    l = data[0];
38e1051a39Sopenharmony_ci    r = data[1];
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci    l ^= p[0];
41e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[1]);
42e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[2]);
43e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[3]);
44e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[4]);
45e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[5]);
46e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[6]);
47e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[7]);
48e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[8]);
49e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[9]);
50e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[10]);
51e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[11]);
52e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[12]);
53e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[13]);
54e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[14]);
55e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[15]);
56e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[16]);
57e1051a39Sopenharmony_ci# if BF_ROUNDS == 20
58e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[17]);
59e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[18]);
60e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[19]);
61e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[20]);
62e1051a39Sopenharmony_ci# endif
63e1051a39Sopenharmony_ci    r ^= p[BF_ROUNDS + 1];
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_ci    data[1] = l & 0xffffffffU;
66e1051a39Sopenharmony_ci    data[0] = r & 0xffffffffU;
67e1051a39Sopenharmony_ci}
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_civoid BF_decrypt(BF_LONG *data, const BF_KEY *key)
70e1051a39Sopenharmony_ci{
71e1051a39Sopenharmony_ci    register BF_LONG l, r;
72e1051a39Sopenharmony_ci    register const BF_LONG *p, *s;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ci    p = key->P;
75e1051a39Sopenharmony_ci    s = &(key->S[0]);
76e1051a39Sopenharmony_ci    l = data[0];
77e1051a39Sopenharmony_ci    r = data[1];
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    l ^= p[BF_ROUNDS + 1];
80e1051a39Sopenharmony_ci#  if BF_ROUNDS == 20
81e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[20]);
82e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[19]);
83e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[18]);
84e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[17]);
85e1051a39Sopenharmony_ci#  endif
86e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[16]);
87e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[15]);
88e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[14]);
89e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[13]);
90e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[12]);
91e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[11]);
92e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[10]);
93e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[9]);
94e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[8]);
95e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[7]);
96e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[6]);
97e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[5]);
98e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[4]);
99e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[3]);
100e1051a39Sopenharmony_ci    BF_ENC(r, l, s, p[2]);
101e1051a39Sopenharmony_ci    BF_ENC(l, r, s, p[1]);
102e1051a39Sopenharmony_ci    r ^= p[0];
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    data[1] = l & 0xffffffffU;
105e1051a39Sopenharmony_ci    data[0] = r & 0xffffffffU;
106e1051a39Sopenharmony_ci}
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_civoid BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
109e1051a39Sopenharmony_ci                    const BF_KEY *schedule, unsigned char *ivec, int encrypt)
110e1051a39Sopenharmony_ci{
111e1051a39Sopenharmony_ci    register BF_LONG tin0, tin1;
112e1051a39Sopenharmony_ci    register BF_LONG tout0, tout1, xor0, xor1;
113e1051a39Sopenharmony_ci    register long l = length;
114e1051a39Sopenharmony_ci    BF_LONG tin[2];
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    if (encrypt) {
117e1051a39Sopenharmony_ci        n2l(ivec, tout0);
118e1051a39Sopenharmony_ci        n2l(ivec, tout1);
119e1051a39Sopenharmony_ci        ivec -= 8;
120e1051a39Sopenharmony_ci        for (l -= 8; l >= 0; l -= 8) {
121e1051a39Sopenharmony_ci            n2l(in, tin0);
122e1051a39Sopenharmony_ci            n2l(in, tin1);
123e1051a39Sopenharmony_ci            tin0 ^= tout0;
124e1051a39Sopenharmony_ci            tin1 ^= tout1;
125e1051a39Sopenharmony_ci            tin[0] = tin0;
126e1051a39Sopenharmony_ci            tin[1] = tin1;
127e1051a39Sopenharmony_ci            BF_encrypt(tin, schedule);
128e1051a39Sopenharmony_ci            tout0 = tin[0];
129e1051a39Sopenharmony_ci            tout1 = tin[1];
130e1051a39Sopenharmony_ci            l2n(tout0, out);
131e1051a39Sopenharmony_ci            l2n(tout1, out);
132e1051a39Sopenharmony_ci        }
133e1051a39Sopenharmony_ci        if (l != -8) {
134e1051a39Sopenharmony_ci            n2ln(in, tin0, tin1, l + 8);
135e1051a39Sopenharmony_ci            tin0 ^= tout0;
136e1051a39Sopenharmony_ci            tin1 ^= tout1;
137e1051a39Sopenharmony_ci            tin[0] = tin0;
138e1051a39Sopenharmony_ci            tin[1] = tin1;
139e1051a39Sopenharmony_ci            BF_encrypt(tin, schedule);
140e1051a39Sopenharmony_ci            tout0 = tin[0];
141e1051a39Sopenharmony_ci            tout1 = tin[1];
142e1051a39Sopenharmony_ci            l2n(tout0, out);
143e1051a39Sopenharmony_ci            l2n(tout1, out);
144e1051a39Sopenharmony_ci        }
145e1051a39Sopenharmony_ci        l2n(tout0, ivec);
146e1051a39Sopenharmony_ci        l2n(tout1, ivec);
147e1051a39Sopenharmony_ci    } else {
148e1051a39Sopenharmony_ci        n2l(ivec, xor0);
149e1051a39Sopenharmony_ci        n2l(ivec, xor1);
150e1051a39Sopenharmony_ci        ivec -= 8;
151e1051a39Sopenharmony_ci        for (l -= 8; l >= 0; l -= 8) {
152e1051a39Sopenharmony_ci            n2l(in, tin0);
153e1051a39Sopenharmony_ci            n2l(in, tin1);
154e1051a39Sopenharmony_ci            tin[0] = tin0;
155e1051a39Sopenharmony_ci            tin[1] = tin1;
156e1051a39Sopenharmony_ci            BF_decrypt(tin, schedule);
157e1051a39Sopenharmony_ci            tout0 = tin[0] ^ xor0;
158e1051a39Sopenharmony_ci            tout1 = tin[1] ^ xor1;
159e1051a39Sopenharmony_ci            l2n(tout0, out);
160e1051a39Sopenharmony_ci            l2n(tout1, out);
161e1051a39Sopenharmony_ci            xor0 = tin0;
162e1051a39Sopenharmony_ci            xor1 = tin1;
163e1051a39Sopenharmony_ci        }
164e1051a39Sopenharmony_ci        if (l != -8) {
165e1051a39Sopenharmony_ci            n2l(in, tin0);
166e1051a39Sopenharmony_ci            n2l(in, tin1);
167e1051a39Sopenharmony_ci            tin[0] = tin0;
168e1051a39Sopenharmony_ci            tin[1] = tin1;
169e1051a39Sopenharmony_ci            BF_decrypt(tin, schedule);
170e1051a39Sopenharmony_ci            tout0 = tin[0] ^ xor0;
171e1051a39Sopenharmony_ci            tout1 = tin[1] ^ xor1;
172e1051a39Sopenharmony_ci            l2nn(tout0, tout1, out, l + 8);
173e1051a39Sopenharmony_ci            xor0 = tin0;
174e1051a39Sopenharmony_ci            xor1 = tin1;
175e1051a39Sopenharmony_ci        }
176e1051a39Sopenharmony_ci        l2n(xor0, ivec);
177e1051a39Sopenharmony_ci        l2n(xor1, ivec);
178e1051a39Sopenharmony_ci    }
179e1051a39Sopenharmony_ci    tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
180e1051a39Sopenharmony_ci    tin[0] = tin[1] = 0;
181e1051a39Sopenharmony_ci}
182