1 /*
2  * Copyright (c) 2010 SURFnet bv
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*****************************************************************************
28  SymmetricAlgorithm.cpp
29 
30  Base class for symmetric algorithm classes
31  *****************************************************************************/
32 
33 #include "SymmetricAlgorithm.h"
34 #include <algorithm>
35 #include <string.h>
36 
SymmetricAlgorithm()37 SymmetricAlgorithm::SymmetricAlgorithm()
38 {
39 	currentKey = NULL;
40 	currentCipherMode = SymMode::Unknown;
41 	currentPaddingMode = true;
42 	currentCounterBits = 0;
43 	currentTagBytes = 0;
44 	currentOperation = NONE;
45 	currentBufferSize = 0;
46 }
47 
encryptInit(const SymmetricKey * key,const SymMode::Type mode,const ByteString &,bool padding,size_t counterBits,const ByteString &,size_t tagBytes)48 bool SymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */)
49 {
50 	if ((key == NULL) || (currentOperation != NONE))
51 	{
52 		return false;
53 	}
54 
55 	currentKey = key;
56 	currentCipherMode = mode;
57 	currentPaddingMode = padding;
58 	currentCounterBits = counterBits;
59 	currentTagBytes = tagBytes;
60 	currentOperation = ENCRYPT;
61 	currentBufferSize = 0;
62 
63 	return true;
64 }
65 
encryptUpdate(const ByteString & data,ByteString &)66 bool SymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& /*encryptedData*/)
67 {
68 	if (currentOperation != ENCRYPT)
69 	{
70 		return false;
71 	}
72 
73 	currentBufferSize += data.size();
74 
75 	return true;
76 }
77 
encryptFinal(ByteString &)78 bool SymmetricAlgorithm::encryptFinal(ByteString& /*encryptedData*/)
79 {
80 	if (currentOperation != ENCRYPT)
81 	{
82 		return false;
83 	}
84 
85 	currentKey = NULL;
86 	currentCipherMode = SymMode::Unknown;
87 	currentPaddingMode = true;
88 	currentCounterBits = 0;
89 	currentTagBytes = 0;
90 	currentOperation = NONE;
91 	currentBufferSize = 0;
92 
93 	return true;
94 }
95 
decryptInit(const SymmetricKey * key,const SymMode::Type mode,const ByteString &,bool padding,size_t counterBits,const ByteString &,size_t tagBytes)96 bool SymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */)
97 {
98 	if ((key == NULL) || (currentOperation != NONE))
99 	{
100 		return false;
101 	}
102 
103 	currentKey = key;
104 	currentCipherMode = mode;
105 	currentPaddingMode = padding;
106 	currentCounterBits = counterBits;
107 	currentTagBytes = tagBytes;
108 	currentOperation = DECRYPT;
109 	currentBufferSize = 0;
110 	currentAEADBuffer.wipe();
111 
112 	return true;
113 }
114 
115 
decryptUpdate(const ByteString & encryptedData,ByteString &)116 bool SymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& /*data*/)
117 {
118 	if (currentOperation != DECRYPT)
119 	{
120 		return false;
121 	}
122 
123 	currentBufferSize += encryptedData.size();
124 	currentAEADBuffer += encryptedData;
125 
126 	return true;
127 }
128 
decryptFinal(ByteString &)129 bool SymmetricAlgorithm::decryptFinal(ByteString& /*data*/)
130 {
131 	if (currentOperation != DECRYPT)
132 	{
133 		return false;
134 	}
135 
136 	currentKey = NULL;
137 	currentCipherMode = SymMode::Unknown;
138 	currentPaddingMode = true;
139 	currentCounterBits = 0;
140 	currentTagBytes = 0;
141 	currentOperation = NONE;
142 	currentBufferSize = 0;
143 	currentAEADBuffer.wipe();
144 
145 	return true;
146 }
147 
148 // Key factory
recycleKey(SymmetricKey * toRecycle)149 void SymmetricAlgorithm::recycleKey(SymmetricKey* toRecycle)
150 {
151 	delete toRecycle;
152 }
153 
generateKey(SymmetricKey & key,RNG * rng)154 bool SymmetricAlgorithm::generateKey(SymmetricKey& key, RNG* rng /* = NULL */)
155 {
156 	if (rng == NULL)
157 	{
158 		return false;
159 	}
160 
161 	if (key.getBitLen() == 0)
162 	{
163 		return false;
164 	}
165 
166 	ByteString keyBits;
167 
168 	if (!rng->generateRandom(keyBits, key.getBitLen()/8))
169 	{
170 		return false;
171 	}
172 
173 	return key.setKeyBits(keyBits);
174 }
175 
reconstructKey(SymmetricKey & key,const ByteString & serialisedData)176 bool SymmetricAlgorithm::reconstructKey(SymmetricKey& key, const ByteString& serialisedData)
177 {
178 	return key.setKeyBits(serialisedData);
179 }
180 
getCipherMode()181 SymMode::Type SymmetricAlgorithm::getCipherMode()
182 {
183 	return currentCipherMode;
184 }
185 
getPaddingMode()186 bool SymmetricAlgorithm::getPaddingMode()
187 {
188 	return currentPaddingMode;
189 }
190 
getBufferSize()191 unsigned long SymmetricAlgorithm::getBufferSize()
192 {
193 	return currentBufferSize;
194 }
195 
getTagBytes()196 size_t SymmetricAlgorithm::getTagBytes()
197 {
198 	return currentTagBytes;
199 }
200 
isStreamCipher()201 bool SymmetricAlgorithm::isStreamCipher()
202 {
203 	switch (currentCipherMode)
204 	{
205 		case SymMode::CFB:
206 		case SymMode::CTR:
207 		case SymMode::GCM:
208 		case SymMode::OFB:
209 			return true;
210 		default:
211 			break;
212 	}
213 
214 	return false;
215 }
216 
isBlockCipher()217 bool SymmetricAlgorithm::isBlockCipher()
218 {
219 	switch (currentCipherMode)
220 	{
221 		case SymMode::CBC:
222 		case SymMode::ECB:
223 			return true;
224 		default:
225 			break;
226 	}
227 
228 	return false;
229 }
230