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 * DES 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/crypto.h>
17e1051a39Sopenharmony_ci#include "des_local.h"
18e1051a39Sopenharmony_ci#include "spr.h"
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_civoid DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc)
21e1051a39Sopenharmony_ci{
22e1051a39Sopenharmony_ci    register DES_LONG l, r, t, u;
23e1051a39Sopenharmony_ci    register DES_LONG *s;
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci    r = data[0];
26e1051a39Sopenharmony_ci    l = data[1];
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci    IP(r, l);
29e1051a39Sopenharmony_ci    /*
30e1051a39Sopenharmony_ci     * Things have been modified so that the initial rotate is done outside
31e1051a39Sopenharmony_ci     * the loop.  This required the DES_SPtrans values in sp.h to be rotated
32e1051a39Sopenharmony_ci     * 1 bit to the right. One perl script later and things have a 5% speed
33e1051a39Sopenharmony_ci     * up on a sparc2. Thanks to Richard Outerbridge for pointing this out.
34e1051a39Sopenharmony_ci     */
35e1051a39Sopenharmony_ci    /* clear the top bits on machines with 8byte longs */
36e1051a39Sopenharmony_ci    /* shift left by 2 */
37e1051a39Sopenharmony_ci    r = ROTATE(r, 29) & 0xffffffffL;
38e1051a39Sopenharmony_ci    l = ROTATE(l, 29) & 0xffffffffL;
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci    s = ks->ks->deslong;
41e1051a39Sopenharmony_ci    /*
42e1051a39Sopenharmony_ci     * I don't know if it is worth the effort of loop unrolling the inner
43e1051a39Sopenharmony_ci     * loop
44e1051a39Sopenharmony_ci     */
45e1051a39Sopenharmony_ci    if (enc) {
46e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 0);     /* 1 */
47e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 2);     /* 2 */
48e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 4);     /* 3 */
49e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 6);     /* 4 */
50e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 8);     /* 5 */
51e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 10);    /* 6 */
52e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 12);    /* 7 */
53e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 14);    /* 8 */
54e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 16);    /* 9 */
55e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 18);    /* 10 */
56e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 20);    /* 11 */
57e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 22);    /* 12 */
58e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 24);    /* 13 */
59e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 26);    /* 14 */
60e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 28);    /* 15 */
61e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 30);    /* 16 */
62e1051a39Sopenharmony_ci    } else {
63e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 30);    /* 16 */
64e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 28);    /* 15 */
65e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 26);    /* 14 */
66e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 24);    /* 13 */
67e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 22);    /* 12 */
68e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 20);    /* 11 */
69e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 18);    /* 10 */
70e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 16);    /* 9 */
71e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 14);    /* 8 */
72e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 12);    /* 7 */
73e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 10);    /* 6 */
74e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 8);     /* 5 */
75e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 6);     /* 4 */
76e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 4);     /* 3 */
77e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 2);     /* 2 */
78e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 0);     /* 1 */
79e1051a39Sopenharmony_ci    }
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci    /* rotate and clear the top bits on machines with 8byte longs */
82e1051a39Sopenharmony_ci    l = ROTATE(l, 3) & 0xffffffffL;
83e1051a39Sopenharmony_ci    r = ROTATE(r, 3) & 0xffffffffL;
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    FP(r, l);
86e1051a39Sopenharmony_ci    data[0] = l;
87e1051a39Sopenharmony_ci    data[1] = r;
88e1051a39Sopenharmony_ci    l = r = t = u = 0;
89e1051a39Sopenharmony_ci}
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_civoid DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc)
92e1051a39Sopenharmony_ci{
93e1051a39Sopenharmony_ci    register DES_LONG l, r, t, u;
94e1051a39Sopenharmony_ci    register DES_LONG *s;
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci    r = data[0];
97e1051a39Sopenharmony_ci    l = data[1];
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    /*
100e1051a39Sopenharmony_ci     * Things have been modified so that the initial rotate is done outside
101e1051a39Sopenharmony_ci     * the loop.  This required the DES_SPtrans values in sp.h to be rotated
102e1051a39Sopenharmony_ci     * 1 bit to the right. One perl script later and things have a 5% speed
103e1051a39Sopenharmony_ci     * up on a sparc2. Thanks to Richard Outerbridge for pointing this out.
104e1051a39Sopenharmony_ci     */
105e1051a39Sopenharmony_ci    /* clear the top bits on machines with 8byte longs */
106e1051a39Sopenharmony_ci    r = ROTATE(r, 29) & 0xffffffffL;
107e1051a39Sopenharmony_ci    l = ROTATE(l, 29) & 0xffffffffL;
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci    s = ks->ks->deslong;
110e1051a39Sopenharmony_ci    /*
111e1051a39Sopenharmony_ci     * I don't know if it is worth the effort of loop unrolling the inner
112e1051a39Sopenharmony_ci     * loop
113e1051a39Sopenharmony_ci     */
114e1051a39Sopenharmony_ci    if (enc) {
115e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 0);     /* 1 */
116e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 2);     /* 2 */
117e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 4);     /* 3 */
118e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 6);     /* 4 */
119e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 8);     /* 5 */
120e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 10);    /* 6 */
121e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 12);    /* 7 */
122e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 14);    /* 8 */
123e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 16);    /* 9 */
124e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 18);    /* 10 */
125e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 20);    /* 11 */
126e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 22);    /* 12 */
127e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 24);    /* 13 */
128e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 26);    /* 14 */
129e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 28);    /* 15 */
130e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 30);    /* 16 */
131e1051a39Sopenharmony_ci    } else {
132e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 30);    /* 16 */
133e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 28);    /* 15 */
134e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 26);    /* 14 */
135e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 24);    /* 13 */
136e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 22);    /* 12 */
137e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 20);    /* 11 */
138e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 18);    /* 10 */
139e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 16);    /* 9 */
140e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 14);    /* 8 */
141e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 12);    /* 7 */
142e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 10);    /* 6 */
143e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 8);     /* 5 */
144e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 6);     /* 4 */
145e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 4);     /* 3 */
146e1051a39Sopenharmony_ci        D_ENCRYPT(l, r, 2);     /* 2 */
147e1051a39Sopenharmony_ci        D_ENCRYPT(r, l, 0);     /* 1 */
148e1051a39Sopenharmony_ci    }
149e1051a39Sopenharmony_ci    /* rotate and clear the top bits on machines with 8byte longs */
150e1051a39Sopenharmony_ci    data[0] = ROTATE(l, 3) & 0xffffffffL;
151e1051a39Sopenharmony_ci    data[1] = ROTATE(r, 3) & 0xffffffffL;
152e1051a39Sopenharmony_ci    l = r = t = u = 0;
153e1051a39Sopenharmony_ci}
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_civoid DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
156e1051a39Sopenharmony_ci                  DES_key_schedule *ks2, DES_key_schedule *ks3)
157e1051a39Sopenharmony_ci{
158e1051a39Sopenharmony_ci    register DES_LONG l, r;
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    l = data[0];
161e1051a39Sopenharmony_ci    r = data[1];
162e1051a39Sopenharmony_ci    IP(l, r);
163e1051a39Sopenharmony_ci    data[0] = l;
164e1051a39Sopenharmony_ci    data[1] = r;
165e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks1, DES_ENCRYPT);
166e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks2, DES_DECRYPT);
167e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks3, DES_ENCRYPT);
168e1051a39Sopenharmony_ci    l = data[0];
169e1051a39Sopenharmony_ci    r = data[1];
170e1051a39Sopenharmony_ci    FP(r, l);
171e1051a39Sopenharmony_ci    data[0] = l;
172e1051a39Sopenharmony_ci    data[1] = r;
173e1051a39Sopenharmony_ci}
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_civoid DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
176e1051a39Sopenharmony_ci                  DES_key_schedule *ks2, DES_key_schedule *ks3)
177e1051a39Sopenharmony_ci{
178e1051a39Sopenharmony_ci    register DES_LONG l, r;
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ci    l = data[0];
181e1051a39Sopenharmony_ci    r = data[1];
182e1051a39Sopenharmony_ci    IP(l, r);
183e1051a39Sopenharmony_ci    data[0] = l;
184e1051a39Sopenharmony_ci    data[1] = r;
185e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks3, DES_DECRYPT);
186e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks2, DES_ENCRYPT);
187e1051a39Sopenharmony_ci    DES_encrypt2((DES_LONG *)data, ks1, DES_DECRYPT);
188e1051a39Sopenharmony_ci    l = data[0];
189e1051a39Sopenharmony_ci    r = data[1];
190e1051a39Sopenharmony_ci    FP(r, l);
191e1051a39Sopenharmony_ci    data[0] = l;
192e1051a39Sopenharmony_ci    data[1] = r;
193e1051a39Sopenharmony_ci}
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci#ifndef DES_DEFAULT_OPTIONS
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci# undef CBC_ENC_C__DONT_UPDATE_IV
198e1051a39Sopenharmony_ci# include "ncbc_enc.c"          /* DES_ncbc_encrypt */
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_civoid DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
201e1051a39Sopenharmony_ci                          long length, DES_key_schedule *ks1,
202e1051a39Sopenharmony_ci                          DES_key_schedule *ks2, DES_key_schedule *ks3,
203e1051a39Sopenharmony_ci                          DES_cblock *ivec, int enc)
204e1051a39Sopenharmony_ci{
205e1051a39Sopenharmony_ci    register DES_LONG tin0, tin1;
206e1051a39Sopenharmony_ci    register DES_LONG tout0, tout1, xor0, xor1;
207e1051a39Sopenharmony_ci    register const unsigned char *in;
208e1051a39Sopenharmony_ci    unsigned char *out;
209e1051a39Sopenharmony_ci    register long l = length;
210e1051a39Sopenharmony_ci    DES_LONG tin[2];
211e1051a39Sopenharmony_ci    unsigned char *iv;
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci    in = input;
214e1051a39Sopenharmony_ci    out = output;
215e1051a39Sopenharmony_ci    iv = &(*ivec)[0];
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_ci    if (enc) {
218e1051a39Sopenharmony_ci        c2l(iv, tout0);
219e1051a39Sopenharmony_ci        c2l(iv, tout1);
220e1051a39Sopenharmony_ci        for (l -= 8; l >= 0; l -= 8) {
221e1051a39Sopenharmony_ci            c2l(in, tin0);
222e1051a39Sopenharmony_ci            c2l(in, tin1);
223e1051a39Sopenharmony_ci            tin0 ^= tout0;
224e1051a39Sopenharmony_ci            tin1 ^= tout1;
225e1051a39Sopenharmony_ci
226e1051a39Sopenharmony_ci            tin[0] = tin0;
227e1051a39Sopenharmony_ci            tin[1] = tin1;
228e1051a39Sopenharmony_ci            DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3);
229e1051a39Sopenharmony_ci            tout0 = tin[0];
230e1051a39Sopenharmony_ci            tout1 = tin[1];
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_ci            l2c(tout0, out);
233e1051a39Sopenharmony_ci            l2c(tout1, out);
234e1051a39Sopenharmony_ci        }
235e1051a39Sopenharmony_ci        if (l != -8) {
236e1051a39Sopenharmony_ci            c2ln(in, tin0, tin1, l + 8);
237e1051a39Sopenharmony_ci            tin0 ^= tout0;
238e1051a39Sopenharmony_ci            tin1 ^= tout1;
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_ci            tin[0] = tin0;
241e1051a39Sopenharmony_ci            tin[1] = tin1;
242e1051a39Sopenharmony_ci            DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3);
243e1051a39Sopenharmony_ci            tout0 = tin[0];
244e1051a39Sopenharmony_ci            tout1 = tin[1];
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci            l2c(tout0, out);
247e1051a39Sopenharmony_ci            l2c(tout1, out);
248e1051a39Sopenharmony_ci        }
249e1051a39Sopenharmony_ci        iv = &(*ivec)[0];
250e1051a39Sopenharmony_ci        l2c(tout0, iv);
251e1051a39Sopenharmony_ci        l2c(tout1, iv);
252e1051a39Sopenharmony_ci    } else {
253e1051a39Sopenharmony_ci        register DES_LONG t0, t1;
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ci        c2l(iv, xor0);
256e1051a39Sopenharmony_ci        c2l(iv, xor1);
257e1051a39Sopenharmony_ci        for (l -= 8; l >= 0; l -= 8) {
258e1051a39Sopenharmony_ci            c2l(in, tin0);
259e1051a39Sopenharmony_ci            c2l(in, tin1);
260e1051a39Sopenharmony_ci
261e1051a39Sopenharmony_ci            t0 = tin0;
262e1051a39Sopenharmony_ci            t1 = tin1;
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_ci            tin[0] = tin0;
265e1051a39Sopenharmony_ci            tin[1] = tin1;
266e1051a39Sopenharmony_ci            DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3);
267e1051a39Sopenharmony_ci            tout0 = tin[0];
268e1051a39Sopenharmony_ci            tout1 = tin[1];
269e1051a39Sopenharmony_ci
270e1051a39Sopenharmony_ci            tout0 ^= xor0;
271e1051a39Sopenharmony_ci            tout1 ^= xor1;
272e1051a39Sopenharmony_ci            l2c(tout0, out);
273e1051a39Sopenharmony_ci            l2c(tout1, out);
274e1051a39Sopenharmony_ci            xor0 = t0;
275e1051a39Sopenharmony_ci            xor1 = t1;
276e1051a39Sopenharmony_ci        }
277e1051a39Sopenharmony_ci        if (l != -8) {
278e1051a39Sopenharmony_ci            c2l(in, tin0);
279e1051a39Sopenharmony_ci            c2l(in, tin1);
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ci            t0 = tin0;
282e1051a39Sopenharmony_ci            t1 = tin1;
283e1051a39Sopenharmony_ci
284e1051a39Sopenharmony_ci            tin[0] = tin0;
285e1051a39Sopenharmony_ci            tin[1] = tin1;
286e1051a39Sopenharmony_ci            DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3);
287e1051a39Sopenharmony_ci            tout0 = tin[0];
288e1051a39Sopenharmony_ci            tout1 = tin[1];
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci            tout0 ^= xor0;
291e1051a39Sopenharmony_ci            tout1 ^= xor1;
292e1051a39Sopenharmony_ci            l2cn(tout0, tout1, out, l + 8);
293e1051a39Sopenharmony_ci            xor0 = t0;
294e1051a39Sopenharmony_ci            xor1 = t1;
295e1051a39Sopenharmony_ci        }
296e1051a39Sopenharmony_ci
297e1051a39Sopenharmony_ci        iv = &(*ivec)[0];
298e1051a39Sopenharmony_ci        l2c(xor0, iv);
299e1051a39Sopenharmony_ci        l2c(xor1, iv);
300e1051a39Sopenharmony_ci    }
301e1051a39Sopenharmony_ci    tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
302e1051a39Sopenharmony_ci    tin[0] = tin[1] = 0;
303e1051a39Sopenharmony_ci}
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci#endif                          /* DES_DEFAULT_OPTIONS */
306