1*9bac3682Sbeck /* $OpenBSD: e_des.c,v 1.24 2024/04/09 13:52:41 beck Exp $ */
2c109e398Sbeck /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3c109e398Sbeck * All rights reserved.
4c109e398Sbeck *
5c109e398Sbeck * This package is an SSL implementation written
6c109e398Sbeck * by Eric Young (eay@cryptsoft.com).
7c109e398Sbeck * The implementation was written so as to conform with Netscapes SSL.
8c109e398Sbeck *
9c109e398Sbeck * This library is free for commercial and non-commercial use as long as
10c109e398Sbeck * the following conditions are aheared to. The following conditions
11c109e398Sbeck * apply to all code found in this distribution, be it the RC4, RSA,
12c109e398Sbeck * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13c109e398Sbeck * included with this distribution is covered by the same copyright terms
14c109e398Sbeck * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15c109e398Sbeck *
16c109e398Sbeck * Copyright remains Eric Young's, and as such any Copyright notices in
17c109e398Sbeck * the code are not to be removed.
18c109e398Sbeck * If this package is used in a product, Eric Young should be given attribution
19c109e398Sbeck * as the author of the parts of the library used.
20c109e398Sbeck * This can be in the form of a textual message at program startup or
21c109e398Sbeck * in documentation (online or textual) provided with the package.
22c109e398Sbeck *
23c109e398Sbeck * Redistribution and use in source and binary forms, with or without
24c109e398Sbeck * modification, are permitted provided that the following conditions
25c109e398Sbeck * are met:
26c109e398Sbeck * 1. Redistributions of source code must retain the copyright
27c109e398Sbeck * notice, this list of conditions and the following disclaimer.
28c109e398Sbeck * 2. Redistributions in binary form must reproduce the above copyright
29c109e398Sbeck * notice, this list of conditions and the following disclaimer in the
30c109e398Sbeck * documentation and/or other materials provided with the distribution.
31c109e398Sbeck * 3. All advertising materials mentioning features or use of this software
32c109e398Sbeck * must display the following acknowledgement:
33c109e398Sbeck * "This product includes cryptographic software written by
34c109e398Sbeck * Eric Young (eay@cryptsoft.com)"
35c109e398Sbeck * The word 'cryptographic' can be left out if the rouines from the library
36c109e398Sbeck * being used are not cryptographic related :-).
37c109e398Sbeck * 4. If you include any Windows specific code (or a derivative thereof) from
38c109e398Sbeck * the apps directory (application code) you must include an acknowledgement:
39c109e398Sbeck * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40c109e398Sbeck *
41c109e398Sbeck * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42c109e398Sbeck * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43c109e398Sbeck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44c109e398Sbeck * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45c109e398Sbeck * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46c109e398Sbeck * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47c109e398Sbeck * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c109e398Sbeck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49c109e398Sbeck * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50c109e398Sbeck * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51c109e398Sbeck * SUCH DAMAGE.
52c109e398Sbeck *
53c109e398Sbeck * The licence and distribution terms for any publically available version or
54c109e398Sbeck * derivative of this code cannot be changed. i.e. this code cannot simply be
55c109e398Sbeck * copied and put under another distribution licence
56c109e398Sbeck * [including the GNU Public Licence.]
57c109e398Sbeck */
58c109e398Sbeck
59b76ab7f9Sjsing #include <limits.h>
60c109e398Sbeck #include <stdio.h>
618cf4d6a6Sjsing
628cf4d6a6Sjsing #include <openssl/opensslconf.h>
638cf4d6a6Sjsing
6440d8aef3Sdjm #ifndef OPENSSL_NO_DES
65b6ab114eSjsing
66c109e398Sbeck #include <openssl/evp.h>
67da347917Sbeck #include <openssl/des.h>
68b6ab114eSjsing #include <openssl/objects.h>
69c109e398Sbeck
70c9675a23Stb #include "evp_local.h"
71b6ab114eSjsing
725b4a16c0Sjsing static int
des_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)735b4a16c0Sjsing des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
745b4a16c0Sjsing const unsigned char *iv, int enc)
755b4a16c0Sjsing {
765b4a16c0Sjsing DES_cblock *deskey = (DES_cblock *)key;
775b4a16c0Sjsing
785b4a16c0Sjsing DES_set_key_unchecked(deskey, ctx->cipher_data);
795b4a16c0Sjsing return 1;
805b4a16c0Sjsing }
815b4a16c0Sjsing
825b4a16c0Sjsing static int
des_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)835b4a16c0Sjsing des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
845b4a16c0Sjsing {
855b4a16c0Sjsing switch (type) {
865b4a16c0Sjsing case EVP_CTRL_RAND_KEY:
875b4a16c0Sjsing if (DES_random_key((DES_cblock *)ptr) == 0)
885b4a16c0Sjsing return 0;
895b4a16c0Sjsing return 1;
905b4a16c0Sjsing
915b4a16c0Sjsing default:
925b4a16c0Sjsing return -1;
935b4a16c0Sjsing }
945b4a16c0Sjsing }
95c109e398Sbeck
96ba3920edSjsing static int
des_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)97ba3920edSjsing des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
980a5d6edeSdjm const unsigned char *in, size_t inl)
99c109e398Sbeck {
100dd2f4c2eSjsing size_t i, bl;
101dd2f4c2eSjsing
102dd2f4c2eSjsing bl = ctx->cipher->block_size;
103dd2f4c2eSjsing
104dd2f4c2eSjsing if (inl < bl)
105dd2f4c2eSjsing return 1;
106dd2f4c2eSjsing
107dd2f4c2eSjsing inl -= bl;
108dd2f4c2eSjsing
109dd2f4c2eSjsing for (i = 0; i <= inl; i += bl)
110ba3920edSjsing DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i),
111ba3920edSjsing ctx->cipher_data, ctx->encrypt);
112b76ab7f9Sjsing
113c109e398Sbeck return 1;
114c109e398Sbeck }
115c109e398Sbeck
116ba3920edSjsing static int
des_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)117ba3920edSjsing des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1180a5d6edeSdjm const unsigned char *in, size_t inl)
119c109e398Sbeck {
120fa590012Sjsing size_t chunk = LONG_MAX & ~0xff;
121b76ab7f9Sjsing
122fa590012Sjsing while (inl >= chunk) {
123fa590012Sjsing DES_ofb64_encrypt(in, out, (long)chunk, ctx->cipher_data,
1240a5d6edeSdjm (DES_cblock *)ctx->iv, &ctx->num);
125fa590012Sjsing inl -= chunk;
126fa590012Sjsing in += chunk;
127fa590012Sjsing out += chunk;
1280a5d6edeSdjm }
1290a5d6edeSdjm if (inl)
1300a5d6edeSdjm DES_ofb64_encrypt(in, out, (long)inl, ctx->cipher_data,
1310a5d6edeSdjm (DES_cblock *)ctx->iv, &ctx->num);
132c109e398Sbeck return 1;
133c109e398Sbeck }
134c109e398Sbeck
135ba3920edSjsing static int
des_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)136ba3920edSjsing des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1370a5d6edeSdjm const unsigned char *in, size_t inl)
138c109e398Sbeck {
139fa590012Sjsing size_t chunk = LONG_MAX & ~0xff;
140b76ab7f9Sjsing
141fa590012Sjsing while (inl >= chunk) {
142fa590012Sjsing DES_ncbc_encrypt(in, out, (long)chunk, ctx->cipher_data,
1430a5d6edeSdjm (DES_cblock *)ctx->iv, ctx->encrypt);
144fa590012Sjsing inl -= chunk;
145fa590012Sjsing in += chunk;
146fa590012Sjsing out += chunk;
1470a5d6edeSdjm }
1480a5d6edeSdjm if (inl)
149da347917Sbeck DES_ncbc_encrypt(in, out, (long)inl, ctx->cipher_data,
150da347917Sbeck (DES_cblock *)ctx->iv, ctx->encrypt);
151c109e398Sbeck return 1;
152c109e398Sbeck }
153c109e398Sbeck
154ba3920edSjsing static int
des_cfb64_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)155ba3920edSjsing des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1560a5d6edeSdjm const unsigned char *in, size_t inl)
157c109e398Sbeck {
158fa590012Sjsing size_t chunk = LONG_MAX & ~0xff;
159b76ab7f9Sjsing
160fa590012Sjsing while (inl >= chunk) {
161fa590012Sjsing DES_cfb64_encrypt(in, out, (long)chunk, ctx->cipher_data,
1620a5d6edeSdjm (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
163fa590012Sjsing inl -= chunk;
164fa590012Sjsing in += chunk;
165fa590012Sjsing out += chunk;
1660a5d6edeSdjm }
1670a5d6edeSdjm if (inl)
168da347917Sbeck DES_cfb64_encrypt(in, out, (long)inl, ctx->cipher_data,
169da347917Sbeck (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
170c109e398Sbeck return 1;
171c109e398Sbeck }
172c109e398Sbeck
17340d8aef3Sdjm /* Although we have a CFB-r implementation for DES, it doesn't pack the right
17440d8aef3Sdjm way, so wrap it here */
175ba3920edSjsing static int
des_cfb1_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)176ba3920edSjsing des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1770a5d6edeSdjm const unsigned char *in, size_t inl)
17840d8aef3Sdjm {
17940d8aef3Sdjm unsigned char c[1], d[1];
180fa590012Sjsing size_t chunk = LONG_MAX / 8;
181fa590012Sjsing size_t n;
182b76ab7f9Sjsing
183ba3920edSjsing if (inl < chunk)
184ba3920edSjsing chunk = inl;
1850a5d6edeSdjm
186ba3920edSjsing while (inl && inl >= chunk) {
187ba3920edSjsing for (n = 0; n < chunk*8; ++n) {
18840d8aef3Sdjm c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
189ba3920edSjsing DES_cfb_encrypt(c, d, 1, 1, ctx->cipher_data,
190ba3920edSjsing (DES_cblock *)ctx->iv, ctx->encrypt);
191ba3920edSjsing out[n / 8] = (out[n / 8] &
192ba3920edSjsing ~(0x80 >> (unsigned int)(n % 8))) |
1930a5d6edeSdjm ((d[0] & 0x80) >> (unsigned int)(n % 8));
19440d8aef3Sdjm }
1950a5d6edeSdjm inl -= chunk;
1960a5d6edeSdjm in += chunk;
1970a5d6edeSdjm out += chunk;
198ba3920edSjsing if (inl < chunk)
199ba3920edSjsing chunk = inl;
2000a5d6edeSdjm }
2010a5d6edeSdjm
20240d8aef3Sdjm return 1;
20340d8aef3Sdjm }
20440d8aef3Sdjm
205ba3920edSjsing static int
des_cfb8_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)206ba3920edSjsing des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2070a5d6edeSdjm const unsigned char *in, size_t inl)
20840d8aef3Sdjm {
209fa590012Sjsing size_t chunk = LONG_MAX & ~0xff;
210b76ab7f9Sjsing
211fa590012Sjsing while (inl >= chunk) {
212fa590012Sjsing DES_cfb_encrypt(in, out, 8, (long)chunk,
213ba3920edSjsing ctx->cipher_data, (DES_cblock *)ctx->iv, ctx->encrypt);
214fa590012Sjsing inl -= chunk;
215fa590012Sjsing in += chunk;
216fa590012Sjsing out += chunk;
2170a5d6edeSdjm }
2180a5d6edeSdjm if (inl)
2190a5d6edeSdjm DES_cfb_encrypt(in, out, 8, (long)inl, ctx->cipher_data,
2200a5d6edeSdjm (DES_cblock *)ctx->iv, ctx->encrypt);
22140d8aef3Sdjm return 1;
22240d8aef3Sdjm }
22340d8aef3Sdjm
224dd2f4c2eSjsing static const EVP_CIPHER des_cbc = {
225dd2f4c2eSjsing .nid = NID_des_cbc,
226dd2f4c2eSjsing .block_size = 8,
227dd2f4c2eSjsing .key_len = 8,
228dd2f4c2eSjsing .iv_len = 8,
229dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CBC_MODE,
230dd2f4c2eSjsing .init = des_init_key,
231dd2f4c2eSjsing .do_cipher = des_cbc_cipher,
232dd2f4c2eSjsing .cleanup = NULL,
233dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
234dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
235dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
236dd2f4c2eSjsing .ctrl = des_ctrl,
237dd2f4c2eSjsing };
238c109e398Sbeck
239dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_cbc(void)240dd2f4c2eSjsing EVP_des_cbc(void)
241dd2f4c2eSjsing {
242dd2f4c2eSjsing return &des_cbc;
243dd2f4c2eSjsing }
244*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_cbc);
24540d8aef3Sdjm
246dd2f4c2eSjsing static const EVP_CIPHER des_cfb64 = {
247dd2f4c2eSjsing .nid = NID_des_cfb64,
248dd2f4c2eSjsing .block_size = 1,
249dd2f4c2eSjsing .key_len = 8,
250dd2f4c2eSjsing .iv_len = 8,
251dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
252dd2f4c2eSjsing .init = des_init_key,
253dd2f4c2eSjsing .do_cipher = des_cfb64_cipher,
254dd2f4c2eSjsing .cleanup = NULL,
255dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
256dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
257dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
258dd2f4c2eSjsing .ctrl = des_ctrl,
259dd2f4c2eSjsing };
260dd2f4c2eSjsing
261dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_cfb64(void)262dd2f4c2eSjsing EVP_des_cfb64(void)
263dd2f4c2eSjsing {
264dd2f4c2eSjsing return &des_cfb64;
265dd2f4c2eSjsing }
266*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_cfb64);
267dd2f4c2eSjsing
268dd2f4c2eSjsing static const EVP_CIPHER des_ofb = {
269dd2f4c2eSjsing .nid = NID_des_ofb64,
270dd2f4c2eSjsing .block_size = 1,
271dd2f4c2eSjsing .key_len = 8,
272dd2f4c2eSjsing .iv_len = 8,
273dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_OFB_MODE,
274dd2f4c2eSjsing .init = des_init_key,
275dd2f4c2eSjsing .do_cipher = des_ofb_cipher,
276dd2f4c2eSjsing .cleanup = NULL,
277dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
278dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
279dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
280dd2f4c2eSjsing .ctrl = des_ctrl,
281dd2f4c2eSjsing };
282dd2f4c2eSjsing
283dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_ofb(void)284dd2f4c2eSjsing EVP_des_ofb(void)
285dd2f4c2eSjsing {
286dd2f4c2eSjsing return &des_ofb;
287dd2f4c2eSjsing }
288*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_ofb);
289dd2f4c2eSjsing
290dd2f4c2eSjsing static const EVP_CIPHER des_ecb = {
291dd2f4c2eSjsing .nid = NID_des_ecb,
292dd2f4c2eSjsing .block_size = 8,
293dd2f4c2eSjsing .key_len = 8,
294dd2f4c2eSjsing .iv_len = 0,
295dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_ECB_MODE,
296dd2f4c2eSjsing .init = des_init_key,
297dd2f4c2eSjsing .do_cipher = des_ecb_cipher,
298dd2f4c2eSjsing .cleanup = NULL,
299dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
300dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
301dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
302dd2f4c2eSjsing .ctrl = des_ctrl,
303dd2f4c2eSjsing };
304dd2f4c2eSjsing
305dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_ecb(void)306dd2f4c2eSjsing EVP_des_ecb(void)
307dd2f4c2eSjsing {
308dd2f4c2eSjsing return &des_ecb;
309dd2f4c2eSjsing }
310*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_ecb);
311dd2f4c2eSjsing
312dd2f4c2eSjsing static const EVP_CIPHER des_cfb1 = {
313dd2f4c2eSjsing .nid = NID_des_cfb1,
314dd2f4c2eSjsing .block_size = 1,
315dd2f4c2eSjsing .key_len = 8,
316dd2f4c2eSjsing .iv_len = 8,
317dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
318dd2f4c2eSjsing .init = des_init_key,
319dd2f4c2eSjsing .do_cipher = des_cfb1_cipher,
320dd2f4c2eSjsing .cleanup = NULL,
321dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
322dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
323dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
324dd2f4c2eSjsing .ctrl = des_ctrl,
325dd2f4c2eSjsing };
326dd2f4c2eSjsing
327dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_cfb1(void)328dd2f4c2eSjsing EVP_des_cfb1(void)
329dd2f4c2eSjsing {
330dd2f4c2eSjsing return &des_cfb1;
331dd2f4c2eSjsing }
332*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_cfb1);
333dd2f4c2eSjsing
334dd2f4c2eSjsing static const EVP_CIPHER des_cfb8 = {
335dd2f4c2eSjsing .nid = NID_des_cfb8,
336dd2f4c2eSjsing .block_size = 1,
337dd2f4c2eSjsing .key_len = 8,
338dd2f4c2eSjsing .iv_len = 8,
339dd2f4c2eSjsing .flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
340dd2f4c2eSjsing .init = des_init_key,
341dd2f4c2eSjsing .do_cipher = des_cfb8_cipher,
342dd2f4c2eSjsing .cleanup = NULL,
343dd2f4c2eSjsing .ctx_size = sizeof(DES_key_schedule),
344dd2f4c2eSjsing .set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
345dd2f4c2eSjsing .get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
346dd2f4c2eSjsing .ctrl = des_ctrl,
347dd2f4c2eSjsing };
348dd2f4c2eSjsing
349dd2f4c2eSjsing const EVP_CIPHER *
EVP_des_cfb8(void)350dd2f4c2eSjsing EVP_des_cfb8(void)
351dd2f4c2eSjsing {
352dd2f4c2eSjsing return &des_cfb8;
353dd2f4c2eSjsing }
354*9bac3682Sbeck LCRYPTO_ALIAS(EVP_des_cfb8);
355c109e398Sbeck #endif
356