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: OpenSSLCryptoSymmetricKey.hpp 1808174 2017-09-12 21:50:30Z scantor $
29  *
30  */
31 
32 
33 
34 #ifndef OPENSSLCRYPTOSYMMETRICKEY_INCLUDE
35 #define OPENSSLCRYPTOSYMMETRICKEY_INCLUDE
36 
37 #include <xsec/framework/XSECDefs.hpp>
38 #include <xsec/enc/XSECCryptoSymmetricKey.hpp>
39 
40 #if defined (XSEC_HAVE_OPENSSL)
41 
42 // OpenSSL Includes
43 
44 #include <openssl/evp.h>
45 
46 #define MAX_BLOCK_SIZE      32
47 
48 /**
49  * \ingroup opensslcrypto
50  */
51 
52 /**
53  * \brief Base interface definition for symmetric key material.
54  *
55  * This is the implementation for a wrapper of OpenSSL symmetric
56  * crypto functions.
57  */
58 
59 class XSEC_EXPORT OpenSSLCryptoSymmetricKey : public XSECCryptoSymmetricKey {
60 
61 public :
62 
63     /** @name Constructors and Destructors */
64     //@{
65 
66     /**
67      * \brief Constructor
68      *
69      * Can only construct a Symmetric key if we know what type it is
70      **/
71 
72     OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::SymmetricKeyType type);
73 
74     /**
75      * \brief Destructor
76      *
77      * Implementations must ensure that the held key is properly destroyed
78      * (overwritten) when key objects are deleted.
79      */
80 
81     virtual ~OpenSSLCryptoSymmetricKey();
82 
83     //@}
84 
85     /** @name Basic CryptoKey Interface methods */
86     //@{
87 
88     /**
89      * \brief Returns a string that identifies the crypto owner of this library.
90      */
91 
92     virtual const XMLCh * getProviderName() const;
93 
94     /**
95      * \brief Clone the key
96      *
97      * All keys need to be able to copy themselves and return
98      * a pointer to the copy.  This allows the library to
99      * duplicate keys.
100      */
101 
102     virtual XSECCryptoKey * clone() const;
103 
104     //@}
105 
106     /** @name Symmetric key interface methods */
107     //@{
108 
109     /**
110      * \brief What type of symmetric key is this?
111      *
112      * There are a number of different types of symmetric key.
113      * This method allows callers to determine the type of this
114      * particular key
115      */
116 
117     SymmetricKeyType getSymmetricKeyType(void) const;
118 
119     /**
120      * \brief Set the key from the provided bytes
121      *
122      * Symmetric keys can all be loaded from a buffer containing a series
123      * of bytes.
124      *
125      * @param key The buffer containing the key bytes
126      * @param keyLen The number of key bytes in the buffer
127      *
128      */
129 
130     void setKey(const unsigned char * key, unsigned int keyLen);
131 
132     /**
133      * \brief Initialise an decryption process
134      *
135      * Setup the key to get ready for a decryption session.
136      * Callers can pass in an IV.  If one is not provided,
137      * but the algorithm requires one (e.g. 3DES_CBC), then
138      * implementations should assume that the start of the
139      * cipher text stream will in fact be the IV.
140      *
141      * @param doPad By default, we perform padding for last block
142      * @param mode mode selection (Currently ECB or CBC mode only)
143      * @param iv Initialisation Vector to be used.  NULL if one is
144      * not required, or if IV will be set from data stream
145      * @param tag Authentication tag to be used for AEAD ciphers
146      * @param taglen length of Authentication Tag
147      * @returns true if the initialisation succeeded.
148      */
149 
150     virtual bool decryptInit(bool doPad = true,
151                              SymmetricKeyMode mode = MODE_CBC,
152                              const unsigned char * iv = NULL,
153                              const unsigned char* tag = NULL,
154                              unsigned int taglen = 0);
155 
156     /**
157      * \brief Continue an decrypt operation using this key.
158      *
159      * Decryption must have been set up using an encryptInit
160      * call.  Takes the inBuf and continues a decryption operation,
161      * writing the output to outBuf.
162      *
163      * This function does not have to guarantee that all input
164      * will be decrypted.  In cases where the input is not a length
165      * of the block size, the implementation will need to hold back
166      * cipher-text to be handles during the next operation.
167      *
168      * @note While maxOutLength is defined, the OpenSSL libraries will
169      * not read the value, so the onus is on the caller to ensure the
170      * buffer is long enough to hold the output!
171      *
172      * @param inBuf Octets to be decrypted
173      * @param plainBuf Buffer to place output in
174      * @param inLength Number of bytes to decrypt
175      * @param maxOutLength Maximum number of bytes to place in output
176      * buffer
177      * @returns Bytes placed in output Buffer
178      */
179 
180     virtual unsigned int decrypt(const unsigned char * inBuf,
181                                  unsigned char * plainBuf,
182                                  unsigned int inLength,
183                                  unsigned int maxOutLength);
184 
185     /**
186      * \brief Finish a decryption operation
187      *
188      * Complete a decryption process.  No cipher text is passed in,
189      * as this should simply be removing any remaining text from
190      * the plain storage buffer.
191      *
192      * May throw an exception if there is some stored cipher text
193      * that is not the length of the block size for block algorithms.
194      *
195      * @note While maxOutLength is defined, the OpenSSL libraries will
196      * not read the value, so the onus is on the caller to ensure the
197      * buffer is long enough to hold the output!
198      *
199      * @param plainBuf Buffer to place any remaining plain text in
200      * @param maxOutLength Maximum number of bytes to pace in output
201      * @returns Bytes placed in output buffer
202      */
203 
204     virtual unsigned int decryptFinish(unsigned char * plainBuf,
205                                        unsigned int maxOutLength);
206 
207     /**
208      * \brief Initialise an encryption process
209      *
210      * Setup the key to get ready for a decryption session.
211      * Callers can pass in an IV.  If one is not provided,
212      * but the algorithm requires one (e.g. 3DES_CBC), then
213      * implementations are required to generate one.
214      *
215      * @param doPad By default, we perform padding for last block
216      * @param mode What mode to handle blocks (Currently CBC or ECB)
217      * @param iv Initialisation Vector to be used.  NULL if one is
218      * not required, or if IV is to be generated
219      * @returns true if the initialisation succeeded.
220      */
221 
222     virtual bool encryptInit(bool doPad = true,
223                              SymmetricKeyMode mode = MODE_CBC,
224                              const unsigned char * iv = NULL);
225 
226     /**
227      * \brief Continue an encryption operation using this key.
228      *
229      * Encryption must have been set up using an encryptInit
230      * call.  Takes the inBuf and continues a encryption operation,
231      * writing the output to outBuf.
232      *
233      * This function does not have to guarantee that all input
234      * will be encrypted.  In cases where the input is not a length
235      * of the block size, the implementation will need to hold back
236      * plain-text to be handled during the next operation.
237      *
238      * @param inBuf Octets to be encrypted
239      * @param cipherBuf Buffer to place output in
240      * @param inLength Number of bytes to encrypt
241      * @param maxOutLength Maximum number of bytes to place in output
242      * buffer
243      * @returns Bytes placed in output Buffer
244      */
245 
246     virtual unsigned int encrypt(const unsigned char * inBuf,
247                                  unsigned char * cipherBuf,
248                                  unsigned int inLength,
249                                  unsigned int maxOutLength);
250 
251     /**
252      * \brief Finish a encryption operation
253      *
254      * Complete a encryption process.  No plain text is passed in,
255      * as this should simply be removing any remaining text from
256      * the plain storage buffer and creating a final padded block.
257      *
258      * Padding is performed by taking the remaining block, and
259      * setting the last byte to equal the number of bytes of
260      * padding.  If the plain was an exact multiple of the block size,
261      * then an extra block of padding will be used.  For example, if
262      * the block size is 8 bytes, and there were three remaining plain
263      * text bytes (0x01, 0x02 and 0x03), the final block will be :
264      *
265      * 0x010203????????05
266      *
267      * @param plainBuf Buffer to place final block of cipher text in
268      * @param maxOutLength Maximum number of bytes to pace in output
269      * @param taglen length of Authentication Tag
270      * @returns Bytes placed in output buffer
271      */
272 
273     virtual unsigned int encryptFinish(unsigned char * plainBuf,
274                                        unsigned int maxOutLength,
275                                        unsigned int taglen = 0);
276 
277     //@}
278 
279     /** @name OpenSSL Library Specific functions */
280     //@{
281 
282     /**
283      * \brief Get OpenSSL cipher context structure
284      */
285 
getOpenSSLEVP_CIPHER_CTX(void)286     EVP_CIPHER_CTX * getOpenSSLEVP_CIPHER_CTX(void) {return mp_ctx;}
287 
288     /**
289      * \brief Get OpenSSL cipher context structure
290      */
291 
getOpenSSLEVP_CIPHER_CTX(void) const292     const EVP_CIPHER_CTX * getOpenSSLEVP_CIPHER_CTX(void) const {return mp_ctx;}
293 
294     //@}
295 
296 private:
297 
298     // Unimplemented constructors
299 
300     OpenSSLCryptoSymmetricKey();
301     OpenSSLCryptoSymmetricKey(const OpenSSLCryptoSymmetricKey &);
302     OpenSSLCryptoSymmetricKey & operator= (const OpenSSLCryptoSymmetricKey &);
303 
304     // Private functions
305     int decryptCtxInit(const unsigned char* iv, const unsigned char* tag, unsigned int taglen);
306 
307     // Private variables
308     SymmetricKeyType                m_keyType;
309     SymmetricKeyMode                m_keyMode;
310     EVP_CIPHER_CTX                  *mp_ctx;        // OpenSSL Cipher Context structure
311 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
312     EVP_CIPHER_CTX                  m_ctx_space;    // OpenSSL Cipher Context structure - store
313 #endif
314     safeBuffer                      m_keyBuf;       // Holder of the key
315     safeBuffer                      m_tagBuf;       // Holder of authentication tag
316     unsigned int                    m_keyLen;
317     bool                            m_initialised;  // Is the context ready to work?
318     unsigned char                   m_lastBlock[MAX_BLOCK_SIZE];
319     int                             m_blockSize;
320     int                             m_ivSize;
321     int                             m_bytesInLastBlock;
322     bool                            m_ivSent;       // Has the IV been put in the stream
323     bool                            m_doPad;        // Do we pad last block?
324 };
325 
326 #endif /* XSEC_HAVE_OPENSSL */
327 #endif /* OPENSSLCRYPTOSYMMETRICKEY_INCLUDE */
328