File: wvtripledes.cc

package info (click to toggle)
wvstreams 4.6.1-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 6,820 kB
  • ctags: 7,837
  • sloc: cpp: 64,203; ansic: 4,154; sh: 4,094; makefile: 549; perl: 402
file content (154 lines) | stat: -rw-r--r-- 3,737 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * Worldvisions Tunnel Vision Software:
 *   Copyright (C) 1997-2003 Net Integration Technologies, Inc.
 * 
 * TripleDES cryptography abstractions.
 */
#include "wvtripledes.h"
#include <assert.h>
#include <openssl/rand.h>

/***** WvTripleDESEncoder ****/

WvTripleDESEncoder::WvTripleDESEncoder(Mode _mode, const void *_key1, 
				       const void *_key2, const void *_key3) :
    mode(_mode)
{
    setkey(_key1, _key2, _key3);
}


// WvTripleDESEncoder::~WvTripleDESEncoder()
// {
//     delete[] key;
//     delete deskey1;
//     delete deskey2;
//     delete deskey3;
// }


bool WvTripleDESEncoder::_reset()
{
    memset(ivec, 0, sizeof(ivec));
    ivecoff = 0;
    return true;
}


void WvTripleDESEncoder::setkey(const void *_key1, const void *_key2, 
				const void *_key3)
{
    memcpy(key, _key1, DES_KEY_SZ);
    DES_set_key(&key, &deskey1);

    memcpy(key, _key2, DES_KEY_SZ);
    DES_set_key(&key, &deskey2);

    memcpy(key, _key3, DES_KEY_SZ);
    DES_set_key(&key, &deskey3);

    memset(ivec, 0, sizeof(ivec));
    ivecoff = 0;
}


void WvTripleDESEncoder::setiv(const void *_iv)
{
    memcpy(ivec, _iv, sizeof(ivec));
    ivecoff = 0;
}

bool WvTripleDESEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
{
    size_t len = in.used();
    bool success = true;
    switch (mode) {
    case ECBEncrypt:
    case ECBDecrypt:
    case CBCEncrypt: // The caller should ensure the padding is correct or
    case CBCDecrypt: // we do it for them, in probably the wrong way.
    {
	size_t remainder = len & 7; // conviently this is the same as len % 8
	len -= remainder;
	if (remainder != 0 && flush)
	{
	    if (mode == ECBEncrypt || mode == CBCEncrypt)
	    {
		// if flushing on encryption, add some randomized padding
		size_t padlen = 8 - remainder;
		unsigned char *pad = in.alloc(padlen);
		RAND_pseudo_bytes(pad, padlen);
		len += 8;
	    }
	    else // nothing we can do here, flushing does not make sense!
		success = false;
	}
    }

    default:
	break;
    }

    if (len == 0) 
	return success;
    
    const unsigned char *data = in.get(len);
    unsigned char *crypt = out.alloc(len);
    
    switch (mode)
    {
    case ECBEncrypt:
    case ECBDecrypt:
	// ECB works 64bits at a time
	while (len >= 8)
	{
#if OPENSSL_VERSION_NUMBER >= 0x0090705fL \
    && OPENSSL_VERSION_NUMBER < 0x0090800fL
	    DES_ecb3_encrypt(data, crypt,
			     &deskey1, &deskey2, &deskey3,
			     mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
#else
	    DES_ecb3_encrypt(reinterpret_cast<const_DES_cblock*>(&data),
			     reinterpret_cast<DES_cblock*>(&crypt),
			     &deskey1, &deskey2, &deskey3,
			     mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
#endif
	    len -= 8;
	    data += 8;
	    crypt += 8;
	}
	break;

    case CFBEncrypt:
    case CFBDecrypt:
	// CFB simulates a stream
	DES_ede3_cfb64_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
			       &ivec, &ivecoff,
			       mode == CFBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
        break;
    case CBCEncrypt:
	DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
			     &ivec, DES_ENCRYPT);
	break;
    case CBCDecrypt:
	DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
			     &ivec, DES_DECRYPT);
	break;
    }
    return success;
}


/***** WvTripleDESStream *****/

WvTripleDESStream::WvTripleDESStream(WvStream *_cloned, const void *_key1,
				     const void *_key2, const void *_key3, 
				     WvTripleDESEncoder::Mode readmode, 
				     WvTripleDESEncoder::Mode writemode) :
    WvEncoderStream(_cloned)
{
    readchain.append(new WvTripleDESEncoder(readmode,
					    _key1, _key2, _key3), true);
    writechain.append(new WvTripleDESEncoder(writemode,
					     _key1, _key2, _key3), true);
}