1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * XSECCryptoSymmetricKey := Bulk encryption algorithms should all be
24  *							implemented via this interface
25  *
26  * Author(s): Berin Lautenbach
27  *
28  * $Id: WinCAPICryptoSymmetricKey.hpp 1808174 2017-09-12 21:50:30Z scantor $
29  *
30  */
31 
32 
33 
34 #ifndef WINCAPICRYPTOSYMMETRICKEY_INCLUDE
35 #define WINCAPICRYPTOSYMMETRICKEY_INCLUDE
36 
37 #include <xsec/framework/XSECDefs.hpp>
38 #include <xsec/enc/XSECCryptoSymmetricKey.hpp>
39 
40 #if defined (XSEC_HAVE_WINCAPI)
41 
42 #if !defined(_WIN32_WINNT)
43 #	define _WIN32_WINNT 0x0400
44 #endif
45 
46 #include <wincrypt.h>
47 
48 #define WINCAPI_MAX_BLOCK_SIZE		32
49 
50 /**
51  * \ingroup wincapicrypto
52  */
53 
54 /**
55  * \brief Base interface definition for symmetric key material.
56  *
57  * This is the implementation for a wrapper of Windows CryptoAPI symmetric
58  * crypto functions.
59  */
60 
61 class XSEC_EXPORT WinCAPICryptoSymmetricKey : public XSECCryptoSymmetricKey {
62 
63 public :
64 
65 	/** @name Constructors and Destructors */
66 	//@{
67 
68 	/**
69 	 * \brief Constructor
70 	 *
71 	 * Can only construct a Symmetric key if we know what type it is
72 	 *
73 	 * @param prov The appropriate provider that supports the required algorithm.
74 	 * Can be 0 if the app is going to pass in an octet via setKey, as the library
75 	 * will use its own internal key store and handle to CSP.
76 	 * @param type The type of key (i.e. algorithm) to create
77 	 **/
78 
79 	WinCAPICryptoSymmetricKey(HCRYPTPROV prov, XSECCryptoSymmetricKey::SymmetricKeyType type);
80 
81 	/**
82 	 * \brief Destructor
83 	 *
84 	 * Implementations must ensure that the held key is properly destroyed
85 	 * (overwritten) when key objects are deleted.
86 	 */
87 
88 	virtual ~WinCAPICryptoSymmetricKey();
89 
90 	//@}
91 
92 	/** @name Basic CryptoKey Interface methods */
93 	//@{
94 
95 	/**
96 	 * \brief Returns a string that identifies the crypto owner of this library.
97 	 */
98 
getProviderName() const99     virtual const XMLCh * getProviderName() const {return DSIGConstants::s_unicodeStrPROVWinCAPI;}
100 
101 	/**
102 	 * \brief Clone the key
103 	 *
104 	 * All keys need to be able to copy themselves and return
105 	 * a pointer to the copy.  This allows the library to
106 	 * duplicate keys.
107 	 */
108 
109 	virtual XSECCryptoKey * clone() const;
110 
111 	//@}
112 
113 	/** @name Symmetric key interface methods */
114 	//@{
115 
116 	/**
117 	 * \brief What type of symmetric key is this?
118 	 *
119 	 * There are a number of different types of symmetric key.
120 	 * This method allows callers to determine the type of this
121 	 * particular key
122 	 */
123 
getSymmetricKeyType(void) const124     SymmetricKeyType getSymmetricKeyType(void) const {return m_keyType;}
125 
126 	/**
127 	 * \brief Set the key from the provided bytes
128 	 *
129 	 * Symmetric keys can all be loaded from a buffer containing a series
130 	 * of bytes.
131 	 *
132 	 * @param key The buffer containing the key bytes
133 	 * @param keyLen The number of key bytes in the buffer
134 	 *
135 	 */
136 
137 	void setKey(const unsigned char * key, unsigned int keyLen);
138 
139 	/**
140 	 * \brief Initialise an decryption process
141 	 *
142 	 * Setup the key to get ready for a decryption session.
143 	 * Callers can pass in an IV.  If one is not provided,
144 	 * but the algorithm requires one (e.g. 3DES_CBC), then
145 	 * implementations should assume that the start of the
146 	 * cipher text stream will in fact be the IV.
147 	 *
148 	 * @param doPad By default, we perform padding for last block
149 	 * @param mode mode selection (Currently ECB or CBC mode only)
150 	 * @param iv Initialisation Vector to be used.  NULL if one is
151 	 * not required, or if IV will be set from data stream
152      * @param tag Authentication tag to be used for AEAD ciphers
153      * @param taglen length of Authentication Tag
154 	 * @returns true if the initialisation succeeded.
155 	 */
156 
157 	virtual bool decryptInit(bool doPad = true,
158 							 SymmetricKeyMode mode = MODE_CBC,
159 							 const unsigned char * iv = NULL,
160                              const unsigned char* tag = NULL,
161                              unsigned int taglen = 0);
162 
163 	/**
164 	 * \brief Continue an decrypt operation using this key.
165 	 *
166 	 * Decryption must have been set up using an encryptInit
167 	 * call.  Takes the inBuf and continues a decryption operation,
168 	 * writing the output to outBuf.
169 	 *
170 	 * This function does not have to guarantee that all input
171 	 * will be decrypted.  In cases where the input is not a length
172 	 * of the block size, the implementation will need to hold back
173 	 * cipher-text to be handles during the next operation.
174 	 *
175 	 * @note While maxOutLength is defined, the WinCAPI library will
176 	 * not read the value, so the onus is on the caller to ensure the
177 	 * buffer is long enough to hold the output!
178 	 *
179 	 * @param inBuf Octets to be decrypted
180 	 * @param plainBuf Buffer to place output in
181 	 * @param inLength Number of bytes to decrypt
182 	 * @param maxOutLength Maximum number of bytes to place in output
183 	 * buffer
184 	 * @returns Bytes placed in output Buffer
185 	 */
186 
187 	virtual unsigned int decrypt(const unsigned char * inBuf,
188 								 unsigned char * plainBuf,
189 								 unsigned int inLength,
190 								 unsigned int maxOutLength);
191 
192 	/**
193 	 * \brief Finish a decryption operation
194 	 *
195 	 * Complete a decryption process.  No cipher text is passed in,
196 	 * as this should simply be removing any remaining text from
197 	 * the plain storage buffer.
198 	 *
199 	 * May throw an exception if there is some stored cipher text
200 	 * that is not the length of the block size for block algorithms.
201 	 *
202 	 * @note While maxOutLength is defined, the WinCAPI library will
203 	 * not read the value, so the onus is on the caller to ensure the
204 	 * buffer is long enough to hold the output!
205 	 *
206 	 * @param plainBuf Buffer to place any remaining plain text in
207 	 * @param maxOutLength Maximum number of bytes to pace in output
208 	 * @returns Bytes placed in output buffer
209 	 */
210 
211 	virtual unsigned int decryptFinish(unsigned char * plainBuf,
212 									   unsigned int maxOutLength);
213 
214 	/**
215 	 * \brief Initialise an encryption process
216 	 *
217 	 * Setup the key to get ready for a decryption session.
218 	 * Callers can pass in an IV.  If one is not provided,
219 	 * but the algorithm requires one (e.g. 3DES_CBC), then
220 	 * implementations are required to generate one.
221 	 *
222 	 * @param doPad By default, we perform padding for last block
223 	 * @param mode What mode to handle blocks (Currently CBC or ECB)
224 	 * @param iv Initialisation Vector to be used.  NULL if one is
225 	 * not required, or if IV is to be generated
226 	 * @returns true if the initialisation succeeded.
227 	 */
228 
229 	virtual bool encryptInit(bool doPad = true,
230 							 SymmetricKeyMode mode = MODE_CBC,
231 							 const unsigned char * iv = NULL);
232 
233 	/**
234 	 * \brief Continue an encryption operation using this key.
235 	 *
236 	 * Encryption must have been set up using an encryptInit
237 	 * call.  Takes the inBuf and continues a encryption operation,
238 	 * writing the output to outBuf.
239 	 *
240 	 * This function does not have to guarantee that all input
241 	 * will be encrypted.  In cases where the input is not a length
242 	 * of the block size, the implementation will need to hold back
243 	 * plain-text to be handled during the next operation.
244 	 *
245 	 * @param inBuf Octets to be encrypted
246 	 * @param cipherBuf Buffer to place output in
247 	 * @param inLength Number of bytes to encrypt
248 	 * @param maxOutLength Maximum number of bytes to place in output
249 	 * buffer
250 	 * @returns Bytes placed in output Buffer
251 	 */
252 
253 	virtual unsigned int encrypt(const unsigned char * inBuf,
254 								 unsigned char * cipherBuf,
255 								 unsigned int inLength,
256 								 unsigned int maxOutLength);
257 
258 	/**
259 	 * \brief Finish a encryption operation
260 	 *
261 	 * Complete a encryption process.  No plain text is passed in,
262 	 * as this should simply be removing any remaining text from
263 	 * the plain storage buffer and creating a final padded block.
264 	 *
265 	 * Padding is performed by taking the remaining block, and
266 	 * setting the last byte to equal the number of bytes of
267 	 * padding.  If the plain was an exact multiple of the block size,
268 	 * then an extra block of padding will be used.  For example, if
269 	 * the block size is 8 bytes, and there were three remaining plain
270 	 * text bytes (0x01, 0x02 and 0x03), the final block will be :
271 	 *
272 	 * 0x010203????????05
273 	 *
274 	 * @param plainBuf Buffer to place final block of cipher text in
275 	 * @param maxOutLength Maximum number of bytes to pace in output
276      * @param taglen length of Authentication Tag
277 	 * @returns Bytes placed in output buffer
278 	 */
279 
280 	virtual unsigned int encryptFinish(unsigned char * plainBuf,
281 									   unsigned int maxOutLength,
282                                        unsigned int taglen = 0);
283 
284 	//@}
285 
286 	/** @name Windows utility functions */
287 	//@{
288 
289 	/**
290 	 * \brief Create a symmetric key from a octet string
291 	 *
292 	 * Uses the ApacheKeyStore to wrap an octet string in a public key
293 	 * and then load it into the Apache Key Container within the defined
294 	 * CSP
295 	 *
296 	 * @param key The buffer of bytes to load from
297 	 * @param keyLen The number of bytes to load
298 	 * @param type The key type to create from the bytes
299 	 * @param prov If NULL, ignored.  If non-null, but *prov == 0, the
300 	 * function will use an internal handle to a CSP and return the value
301 	 * in *prov.  If *prov != 0, use contents of *prov as the provider to
302 	 * load the key into.  NOTE - The provider <em>must</em> have a
303 	 * AT_KEYEXCHANGE key pair available.
304 	 * @returns a pointer to the key or 0 on failure
305 	 */
306 
307 	static HCRYPTKEY createWindowsKey(const unsigned char * key,
308 									  unsigned int keyLen,
309 									  XSECCryptoSymmetricKey::SymmetricKeyType type,
310 									  HCRYPTPROV * prov);
311 
312 
313 
314 private:
315 
316 	// Unimplemented constructors
317 
318 	WinCAPICryptoSymmetricKey();
319 	WinCAPICryptoSymmetricKey(const WinCAPICryptoSymmetricKey &);
320 	WinCAPICryptoSymmetricKey & operator= (const WinCAPICryptoSymmetricKey &);
321 
322 	int decryptCtxInit(const unsigned char * iv);
323 	void encryptCtxInit(const unsigned char * iv);
324 
325 	// Private variables
326 	SymmetricKeyType				m_keyType;
327 	SymmetricKeyMode				m_keyMode;		// ECB or CBC
328 	safeBuffer					m_keyBuf;		// Holder of the key
329 	unsigned int					m_keyLen;
330 	bool							m_initialised;
331 	bool							m_doPad;
332 
333 	unsigned char				m_lastBlock[WINCAPI_MAX_BLOCK_SIZE];
334 	unsigned int					m_bytesInLastBlock;
335 	unsigned int					m_blockSize;
336 	unsigned int					m_ivSize;
337 
338 	HCRYPTPROV					m_p;
339 	HCRYPTKEY					m_k;
340 
341 };
342 
343 #endif /* XSEC_HAVE_WINCAPI */
344 #endif /* WINCAPICRYPTOSYMMETRICKEY_INCLUDE */
345