WvStreams
wvtripledes.cc
1 /*
2  * Worldvisions Tunnel Vision Software:
3  * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
4  *
5  * TripleDES cryptography abstractions.
6  */
7 #include "wvtripledes.h"
8 #include <assert.h>
9 #include <openssl/rand.h>
10 
11 /***** WvTripleDESEncoder ****/
12 
13 WvTripleDESEncoder::WvTripleDESEncoder(Mode _mode, const void *_key1,
14  const void *_key2, const void *_key3) :
15  mode(_mode)
16 {
17  setkey(_key1, _key2, _key3);
18 }
19 
20 
21 // WvTripleDESEncoder::~WvTripleDESEncoder()
22 // {
23 // delete[] key;
24 // delete deskey1;
25 // delete deskey2;
26 // delete deskey3;
27 // }
28 
29 
31 {
32  memset(ivec, 0, sizeof(ivec));
33  ivecoff = 0;
34  return true;
35 }
36 
37 
38 void WvTripleDESEncoder::setkey(const void *_key1, const void *_key2,
39  const void *_key3)
40 {
41  memcpy(key, _key1, DES_KEY_SZ);
42  DES_set_key(&key, &deskey1);
43 
44  memcpy(key, _key2, DES_KEY_SZ);
45  DES_set_key(&key, &deskey2);
46 
47  memcpy(key, _key3, DES_KEY_SZ);
48  DES_set_key(&key, &deskey3);
49 
50  memset(ivec, 0, sizeof(ivec));
51  ivecoff = 0;
52 }
53 
54 
55 void WvTripleDESEncoder::setiv(const void *_iv)
56 {
57  memcpy(ivec, _iv, sizeof(ivec));
58  ivecoff = 0;
59 }
60 
61 bool WvTripleDESEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
62 {
63  size_t len = in.used();
64  bool success = true;
65  switch (mode) {
66  case ECBEncrypt:
67  case ECBDecrypt:
68  case CBCEncrypt: // The caller should ensure the padding is correct or
69  case CBCDecrypt: // we do it for them, in probably the wrong way.
70  {
71  size_t remainder = len & 7; // conviently this is the same as len % 8
72  len -= remainder;
73  if (remainder != 0 && flush)
74  {
75  if (mode == ECBEncrypt || mode == CBCEncrypt)
76  {
77  // if flushing on encryption, add some randomized padding
78  size_t padlen = 8 - remainder;
79  unsigned char *pad = in.alloc(padlen);
80  RAND_pseudo_bytes(pad, padlen);
81  len += 8;
82  }
83  else // nothing we can do here, flushing does not make sense!
84  success = false;
85  }
86  }
87 
88  default:
89  break;
90  }
91 
92  if (len == 0)
93  return success;
94 
95  const unsigned char *data = in.get(len);
96  unsigned char *crypt = out.alloc(len);
97 
98  switch (mode)
99  {
100  case ECBEncrypt:
101  case ECBDecrypt:
102  // ECB works 64bits at a time
103  while (len >= 8)
104  {
105 #if OPENSSL_VERSION_NUMBER >= 0x0090705fL \
106  && OPENSSL_VERSION_NUMBER < 0x0090800fL
107  DES_ecb3_encrypt(data, crypt,
108  &deskey1, &deskey2, &deskey3,
109  mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
110 #else
111  DES_ecb3_encrypt(reinterpret_cast<const_DES_cblock*>(&data),
112  reinterpret_cast<DES_cblock*>(&crypt),
113  &deskey1, &deskey2, &deskey3,
114  mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
115 #endif
116  len -= 8;
117  data += 8;
118  crypt += 8;
119  }
120  break;
121 
122  case CFBEncrypt:
123  case CFBDecrypt:
124  // CFB simulates a stream
125  DES_ede3_cfb64_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
126  &ivec, &ivecoff,
127  mode == CFBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
128  break;
129  case CBCEncrypt:
130  DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
131  &ivec, DES_ENCRYPT);
132  break;
133  case CBCDecrypt:
134  DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
135  &ivec, DES_DECRYPT);
136  break;
137  }
138  return success;
139 }
140 
141 
142 /***** WvTripleDESStream *****/
143 
144 WvTripleDESStream::WvTripleDESStream(WvStream *_cloned, const void *_key1,
145  const void *_key2, const void *_key3,
146  WvTripleDESEncoder::Mode readmode,
147  WvTripleDESEncoder::Mode writemode) :
148  WvEncoderStream(_cloned)
149 {
150  readchain.append(new WvTripleDESEncoder(readmode,
151  _key1, _key2, _key3), true);
152  writechain.append(new WvTripleDESEncoder(writemode,
153  _key1, _key2, _key3), true);
154 }
WvBufBaseCommonImpl::get
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
WvEncoderStream
WvEncoderStream chains a series of encoders on the input and output ports of the underlying stream to...
Definition: wvencoderstream.h:37
WvTripleDESEncoder::CFBEncrypt
@ CFBEncrypt
Definition: wvtripledes.h:28
WvBufBaseCommonImpl::alloc
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
Definition: wvbufbase.h:379
WvTripleDESEncoder::_encode
virtual bool _encode(WvBuf &in, WvBuf &out, bool flush)
Template method implementation of encode().
Definition: wvtripledes.cc:61
WvTripleDESEncoder::_reset
virtual bool _reset()
Template method implementation of reset().
Definition: wvtripledes.cc:30
WvBufBase< unsigned char >
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:22
WvStream
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
Definition: wvstream.h:24
WvTripleDESEncoder
An encoder implementing the TripleDES encryption method.
Definition: wvtripledes.h:22
WvEncoder::flush
bool flush(WvBuf &inbuf, WvBuf &outbuf, bool finish=false)
Flushes the encoder and optionally finishes it.
Definition: wvencoder.h:163
WvTripleDESEncoder::ECBEncrypt
@ ECBEncrypt
Definition: wvtripledes.h:26
WvBufBaseCommonImpl::used
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
WvTripleDESEncoder::CFBDecrypt
@ CFBDecrypt
Definition: wvtripledes.h:29
WvTripleDESEncoder::CBCEncrypt
@ CBCEncrypt
Definition: wvtripledes.h:30
WvTripleDESEncoder::Mode
Mode
Definition: wvtripledes.h:25
WvTripleDESEncoder::ECBDecrypt
@ ECBDecrypt
Definition: wvtripledes.h:27
WvTripleDESEncoder::CBCDecrypt
@ CBCDecrypt
Definition: wvtripledes.h:31