168651Skris/* crypto/evp/e_des.c */
268651Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
368651Skris * All rights reserved.
468651Skris *
568651Skris * This package is an SSL implementation written
668651Skris * by Eric Young (eay@cryptsoft.com).
768651Skris * The implementation was written so as to conform with Netscapes SSL.
868651Skris *
968651Skris * This library is free for commercial and non-commercial use as long as
1068651Skris * the following conditions are aheared to.  The following conditions
1168651Skris * apply to all code found in this distribution, be it the RC4, RSA,
1268651Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1368651Skris * included with this distribution is covered by the same copyright terms
1468651Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1568651Skris *
1668651Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1768651Skris * the code are not to be removed.
1868651Skris * If this package is used in a product, Eric Young should be given attribution
1968651Skris * as the author of the parts of the library used.
2068651Skris * This can be in the form of a textual message at program startup or
2168651Skris * in documentation (online or textual) provided with the package.
2268651Skris *
2368651Skris * Redistribution and use in source and binary forms, with or without
2468651Skris * modification, are permitted provided that the following conditions
2568651Skris * are met:
2668651Skris * 1. Redistributions of source code must retain the copyright
2768651Skris *    notice, this list of conditions and the following disclaimer.
2868651Skris * 2. Redistributions in binary form must reproduce the above copyright
2968651Skris *    notice, this list of conditions and the following disclaimer in the
3068651Skris *    documentation and/or other materials provided with the distribution.
3168651Skris * 3. All advertising materials mentioning features or use of this software
3268651Skris *    must display the following acknowledgement:
3368651Skris *    "This product includes cryptographic software written by
3468651Skris *     Eric Young (eay@cryptsoft.com)"
3568651Skris *    The word 'cryptographic' can be left out if the rouines from the library
3668651Skris *    being used are not cryptographic related :-).
3768651Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3868651Skris *    the apps directory (application code) you must include an acknowledgement:
3968651Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4068651Skris *
4168651Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4268651Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4368651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4468651Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4568651Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4668651Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4768651Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4868651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4968651Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5068651Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5168651Skris * SUCH DAMAGE.
5268651Skris *
5368651Skris * The licence and distribution terms for any publically available version or
5468651Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5568651Skris * copied and put under another distribution licence
5668651Skris * [including the GNU Public Licence.]
5768651Skris */
5868651Skris
5968651Skris#include <stdio.h>
6068651Skris#include "cryptlib.h"
61142425Snectar#ifndef OPENSSL_NO_DES
6268651Skris#include <openssl/evp.h>
6368651Skris#include <openssl/objects.h>
6468651Skris#include "evp_locl.h"
65109998Smarkm#include <openssl/des.h>
66160814Ssimon#include <openssl/rand.h>
6768651Skris
6868651Skrisstatic int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
6968651Skris			const unsigned char *iv, int enc);
70160814Ssimonstatic int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
7168651Skris
7268651Skris/* Because of various casts and different names can't use IMPLEMENT_BLOCK_CIPHER */
7368651Skris
7468651Skrisstatic int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
75238405Sjkim			  const unsigned char *in, size_t inl)
7668651Skris{
7768651Skris	BLOCK_CIPHER_ecb_loop()
78109998Smarkm		DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i), ctx->cipher_data, ctx->encrypt);
7968651Skris	return 1;
8068651Skris}
8168651Skris
8268651Skrisstatic int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
83238405Sjkim			  const unsigned char *in, size_t inl)
8468651Skris{
85238405Sjkim	while(inl>=EVP_MAXCHUNK)
86238405Sjkim		{
87238405Sjkim		DES_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, ctx->cipher_data,
88238405Sjkim				(DES_cblock *)ctx->iv, &ctx->num);
89238405Sjkim		inl-=EVP_MAXCHUNK;
90238405Sjkim		in +=EVP_MAXCHUNK;
91238405Sjkim		out+=EVP_MAXCHUNK;
92238405Sjkim		}
93238405Sjkim	if (inl)
94238405Sjkim		DES_ofb64_encrypt(in, out, (long)inl, ctx->cipher_data,
95238405Sjkim				(DES_cblock *)ctx->iv, &ctx->num);
9668651Skris	return 1;
9768651Skris}
9868651Skris
9968651Skrisstatic int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
100238405Sjkim			  const unsigned char *in, size_t inl)
10168651Skris{
102238405Sjkim	while(inl>=EVP_MAXCHUNK)
103238405Sjkim		{
104238405Sjkim		DES_ncbc_encrypt(in, out, (long)EVP_MAXCHUNK, ctx->cipher_data,
105238405Sjkim				(DES_cblock *)ctx->iv, ctx->encrypt);
106238405Sjkim		inl-=EVP_MAXCHUNK;
107238405Sjkim		in +=EVP_MAXCHUNK;
108238405Sjkim		out+=EVP_MAXCHUNK;
109238405Sjkim		}
110238405Sjkim	if (inl)
111238405Sjkim		DES_ncbc_encrypt(in, out, (long)inl, ctx->cipher_data,
112238405Sjkim				(DES_cblock *)ctx->iv, ctx->encrypt);
11368651Skris	return 1;
11468651Skris}
11568651Skris
116142425Snectarstatic int des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
117238405Sjkim			    const unsigned char *in, size_t inl)
11868651Skris{
119238405Sjkim	while(inl>=EVP_MAXCHUNK)
120238405Sjkim		{
121238405Sjkim		DES_cfb64_encrypt(in,out, (long)EVP_MAXCHUNK, ctx->cipher_data,
122238405Sjkim				(DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
123238405Sjkim		inl-=EVP_MAXCHUNK;
124238405Sjkim		in +=EVP_MAXCHUNK;
125238405Sjkim		out+=EVP_MAXCHUNK;
126238405Sjkim		}
127238405Sjkim	if (inl)
128238405Sjkim		DES_cfb64_encrypt(in, out, (long)inl, ctx->cipher_data,
129109998Smarkm			  (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
13068651Skris	return 1;
13168651Skris}
13268651Skris
133142425Snectar/* Although we have a CFB-r implementation for DES, it doesn't pack the right
134142425Snectar   way, so wrap it here */
135142425Snectarstatic int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
136238405Sjkim			   const unsigned char *in, size_t inl)
137142425Snectar    {
138238405Sjkim    size_t n,chunk=EVP_MAXCHUNK/8;
139142425Snectar    unsigned char c[1],d[1];
140142425Snectar
141238405Sjkim    if (inl<chunk) chunk=inl;
142238405Sjkim
143238405Sjkim    while (inl && inl>=chunk)
144142425Snectar	{
145238405Sjkim	for(n=0 ; n < chunk*8; ++n)
146238405Sjkim	    {
147238405Sjkim	    c[0]=(in[n/8]&(1 << (7-n%8))) ? 0x80 : 0;
148238405Sjkim	    DES_cfb_encrypt(c,d,1,1,ctx->cipher_data,(DES_cblock *)ctx->iv,
149142425Snectar			ctx->encrypt);
150238405Sjkim	    out[n/8]=(out[n/8]&~(0x80 >> (unsigned int)(n%8))) |
151238405Sjkim		     ((d[0]&0x80) >> (unsigned int)(n%8));
152238405Sjkim	    }
153238405Sjkim	inl-=chunk;
154238405Sjkim	in +=chunk;
155238405Sjkim	out+=chunk;
156238405Sjkim	if (inl<chunk) chunk=inl;
157142425Snectar	}
158238405Sjkim
159142425Snectar    return 1;
160142425Snectar    }
161142425Snectar
162142425Snectarstatic int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
163238405Sjkim			   const unsigned char *in, size_t inl)
164142425Snectar    {
165238405Sjkim    while (inl>=EVP_MAXCHUNK)
166238405Sjkim	{
167238405Sjkim	DES_cfb_encrypt(in,out,8,(long)EVP_MAXCHUNK,ctx->cipher_data,
168238405Sjkim			(DES_cblock *)ctx->iv,ctx->encrypt);
169238405Sjkim	inl-=EVP_MAXCHUNK;
170238405Sjkim	in +=EVP_MAXCHUNK;
171238405Sjkim	out+=EVP_MAXCHUNK;
172238405Sjkim	}
173238405Sjkim    if (inl)
174238405Sjkim	DES_cfb_encrypt(in,out,8,(long)inl,ctx->cipher_data,
175238405Sjkim			(DES_cblock *)ctx->iv,ctx->encrypt);
176142425Snectar    return 1;
177142425Snectar    }
178142425Snectar
179109998SmarkmBLOCK_CIPHER_defs(des, DES_key_schedule, NID_des, 8, 8, 8, 64,
180238405Sjkim			EVP_CIPH_RAND_KEY, des_init_key, NULL,
18168651Skris			EVP_CIPHER_set_asn1_iv,
18268651Skris			EVP_CIPHER_get_asn1_iv,
183160814Ssimon			des_ctrl)
18468651Skris
185160814SsimonBLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,1,
186238405Sjkim		     EVP_CIPH_RAND_KEY, des_init_key,NULL,
187142425Snectar		     EVP_CIPHER_set_asn1_iv,
188160814Ssimon		     EVP_CIPHER_get_asn1_iv,des_ctrl)
18968651Skris
190160814SsimonBLOCK_CIPHER_def_cfb(des,DES_key_schedule,NID_des,8,8,8,
191238405Sjkim		     EVP_CIPH_RAND_KEY,des_init_key,NULL,
192142425Snectar		     EVP_CIPHER_set_asn1_iv,
193160814Ssimon		     EVP_CIPHER_get_asn1_iv,des_ctrl)
194142425Snectar
19568651Skrisstatic int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
19668651Skris			const unsigned char *iv, int enc)
19768651Skris	{
198109998Smarkm	DES_cblock *deskey = (DES_cblock *)key;
199160814Ssimon#ifdef EVP_CHECK_DES_KEY
200160814Ssimon	if(DES_set_key_checked(deskey,ctx->cipher_data) != 0)
201160814Ssimon		return 0;
202160814Ssimon#else
203109998Smarkm	DES_set_key_unchecked(deskey,ctx->cipher_data);
204160814Ssimon#endif
20568651Skris	return 1;
20668651Skris	}
20768651Skris
208160814Ssimonstatic int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
209160814Ssimon	{
210160814Ssimon
211160814Ssimon	switch(type)
212160814Ssimon		{
213160814Ssimon	case EVP_CTRL_RAND_KEY:
214160814Ssimon		if (RAND_bytes(ptr, 8) <= 0)
215160814Ssimon			return 0;
216160814Ssimon		DES_set_odd_parity((DES_cblock *)ptr);
217160814Ssimon		return 1;
218160814Ssimon
219160814Ssimon	default:
220160814Ssimon		return -1;
221160814Ssimon		}
222160814Ssimon	}
223160814Ssimon
22468651Skris#endif
225