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  * WinCAPICryptoProvider := Base class to handle Windows Crypto API
24  *
25  * Author(s): Berin Lautenbach
26  *
27  * $Id: WinCAPICryptoProvider.hpp 1817863 2017-12-11 22:47:43Z scantor $
28  *
29  */
30 
31 #ifndef WINCAPICRYPTOPROVIDER_INCLUDE
32 #define WINCAPICRYPTOPROVIDER_INCLUDE
33 
34 #include <xsec/framework/XSECDefs.hpp>
35 #include <xsec/enc/XSECCryptoProvider.hpp>
36 
37 #if defined (XSEC_HAVE_WINCAPI)
38 
39 #if defined (_WIN32_WINNT)
40 #    undef _WIN32_WINNT
41 #endif
42 #define _WIN32_WINNT 0x0400
43 #include <wincrypt.h>
44 
45 
46 // For older versions of wincrypt.h
47 
48 #if !defined (PROV_RSA_AES)
49 #    define PROV_RSA_AES      24
50 #    define ALG_SID_AES_128   14
51 #    define ALG_SID_AES_192   15
52 #    define ALG_SID_AES_256   16
53 #    define ALG_SID_AES       17
54 #    define CALG_AES_128      (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_128)
55 #    define CALG_AES_192      (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_192)
56 #    define CALG_AES_256      (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_256)
57 #endif
58 
59 #define WINCAPI_BLOBHEADERLEN   0x08
60 #define WINCAPI_DSSPUBKEYLEN    0x08
61 #define WINCAPI_DSSSEEDLEN      0x18
62 #define WINCAPI_RSAPUBKEYLEN    0x0C
63 
64 /**
65  * @defgroup wincapicrypto Windows Crypto API Interface
66  * @ingroup crypto
67  * The WinCAPI crypto provides an experimental inerface to
68  * the Windows Cryptographic API.
69  *
70  * All initialisation of the Windows providers needs to be done
71  * by the calling application.  The interface will call the provided
72  * DSS (PROV_DSS) provider and RSA (PROV_RSA_FULL) provider to perform
73  * cryptographic functions.
74  *
75  * The tools use the default providers, but the calling application
76  * can use any providers that implement PROV_DSS and PROV_FULL_RSA.
77  *
78  * Note that, unlike the OpenSSL classes, the various implementation
79  * classes all require their owner provider class to be passed into
80  * the constructor.  This allows them to access the RSA and DSS CAPI
81  * providers being used for the implementation.
82  *
83  * @todo Need to allow the various classes to over-ride the PROV
84  * objects to allow specific private key instances rather than one
85  * instance across the library instance.
86  */
87  /*\@{*/
88 
89 class XSEC_EXPORT WinCAPICryptoProvider : public XSECCryptoProvider {
90 
91 
92 public :
93 
94     /** @name Constructors and Destructors */
95     //@{
96     /**
97      * \brief Create a Windows CAPI interface layer
98      *
99      * Windows CSPs work under a provider model.  The user should specify
100      * which CSP to use.
101      *
102      * @param provDSSName Name of DSS provider - must be of type PROV_DSS.
103      * Will use the default Windows DSS provider if nothing passed in.
104      * @param provRSAName RSA provider - must be of type PROV_RSA_FULL.
105      * Will use the default RSA_FULL provider if nothing passed in
106          * @param dwFlags If you are running XSEC as service you should specify
107          * CRYPT_MACHINE_KEYSET here
108      */
109 
110     WinCAPICryptoProvider(LPCSTR provDSSName = NULL, LPCSTR provRSAName = NULL, DWORD dwFlags = 0);
111 
112     virtual ~WinCAPICryptoProvider();
113 
114     //@}
115 
116     /** @name Hashing (Digest) Functions */
117     //@{
118 
119     /**
120      * \brief Get the provider's maximum digest length.
121      *
122      * Call used by the library to max out the buffer sizes it uses.
123      *
124      * @returns maximum size to allow for
125      */
126     virtual unsigned int getMaxHashSize() const;
127 
128     /**
129      * \brief Return a hashing implementation.
130      *
131      * Call used by the library to obtain a hashing implementation from the
132      * provider.
133      *
134      * @returns a pointer to a hashing object.
135      */
136     virtual XSECCryptoHash* hash(XSECCryptoHash::HashType type) const;
137 
138     /**
139      * \brief Return an HMAC implementation.
140      *
141      * Call used by the library to obtain an HMAC implementation from the
142      * provider.  The caller will need to set the key in the hash
143      * object with an XSECCryptoKeyHMAC using XSECCryptoHash::setKey().
144      *
145      * @returns a pointer to the hashing object.
146      */
147     virtual XSECCryptoHash* HMAC(XSECCryptoHash::HashType type) const;
148 
149     /**
150      * \brief Return a HMAC key
151      *
152      * Sometimes the library needs to create an HMAC key (notably within
153      * the XKMS utilities.
154      *
155      * This function allows the library to obtain a key that can then have
156      * a value set within it.
157      */
158 
159     virtual XSECCryptoKeyHMAC* keyHMAC(void) const;
160 
161     //@}
162 
163     /** @name Encoding functions */
164     //@{
165 
166     /**
167      * \brief Return a Base64 encoder/decoder implementation.
168      *
169      * Call used by the library to obtain a Base64
170      * encoder/decoder.
171      *
172      * @note Windows providers do not implement Base64, so the internal
173      * implementation (XSCrypt) is used instead.
174      *
175      *
176      * @returns Pointer to the new Base64 encoder.
177      * @see XSCryptCryptoBase64
178      */
179 
180     virtual XSECCryptoBase64* base64() const;
181 
182     //@}
183 
184     /** @name Keys and Certificates */
185     //@{
186 
187     /**
188      * \brief Return a DSA key implementation object.
189      *
190      * Call used by the library to obtain a DSA key object.
191      *
192      * @returns Pointer to the new DSA key
193      * @see WinCAPICryptoKeyDSA
194      */
195 
196     virtual XSECCryptoKeyDSA* keyDSA() const;
197 
198     /**
199      * \brief Return an RSA key implementation object.
200      *
201      * Call used by the library to obtain an WinCAPI RSA key object.
202      *
203      * @returns Pointer to the new RSA key
204      * @see WinCAPICryptoKeyRSA
205      */
206 
207     virtual XSECCryptoKeyRSA* keyRSA() const;
208 
209     /**
210      * \brief Return an EC key implementation object.
211      *
212      * Call used by the library to obtain an WinCAPI EC key object.
213      *
214      * @returns Pointer to the new EC key
215      */
216 
217     virtual XSECCryptoKeyEC* keyEC() const;
218 
219     /**
220      * \brief Return a key implementation object based on DER-encoded input.
221      *
222      * Call used by the library to obtain a key object from a DER-encoded key.
223      *
224      * @param buf       DER-encoded data
225      * @param buflen    length of data
226      * @param base64    true iff data is base64-encoded
227      * @returns Pointer to the new key
228      */
229 
230     virtual XSECCryptoKey* keyDER(const char* buf, unsigned long buflen, bool base64) const;
231 
232     /**
233      * \brief Return an X509 implementation object.
234      *
235      * Call used by the library to obtain an object that can work
236      * with X509 certificates.
237      *
238      * @returns Pointer to the new X509 object
239      * @see WinCAPICryptoX509
240      */
241 
242     virtual XSECCryptoX509* X509() const;
243 
244     //@}
245 
246     /** @name Windows CAPI Specific methods */
247     //@{
248 
249     /**
250      * \brief Returns the Crypto Provider being used for DSS
251      */
252 
getProviderDSS(void)253     HCRYPTPROV getProviderDSS(void) {return m_provDSS;}
254 
255     /**
256      * \brief Returns the Provider being used for RSA functions
257      */
258 
getProviderRSA(void)259     HCRYPTPROV getProviderRSA(void) {return m_provRSA;}
260 
261     /**
262      * \brief Return the internal key store provider
263      */
264 
getApacheKeyStore(void)265     HCRYPTPROV getApacheKeyStore(void) {return m_provApacheKeyStore;}
266 
267     /**
268      * \brief Translate B64 I2OS integer to a WinCAPI int.
269      *
270      * Decodes a Base64 (ds:CryptoBinary) integer and reverses the order to
271      * allow loading into a Windows CAPI function.  (CAPI uses Little Endian
272      * storage of integers).
273      *
274      * @param b64 Base 64 string
275      * @param b64Len Length of base64 string
276      * @param retLen Parameter to hold length of return integer
277      */
278 
279     static BYTE* b642WinBN(const char* b64, unsigned int b64Len, unsigned int& retLen);
280 
281     /**
282      * \brief Translate a WinCAPI int to a B64 I2OS integer .
283      *
284      * Encodes a Windows integer in I2OSP base64 encoded format.
285      *
286      * @param n Buffer holding the Windows Integer
287      * @param nLen Length of data in buffer
288      * @param retLen Parameter to hold length of return integer
289      * @returns A pointer to a buffer holding the encoded data
290      * (transfers ownership)
291      */
292 
293     static unsigned char* WinBN2b64(BYTE* n, DWORD nLen, unsigned int &retLen);
294 
295     /**
296      * \brief Determine whether a given algorithm is supported
297      *
298      * A call that can be used to determine whether a given
299      * symmetric algorithm is supported
300      */
301 
302     virtual bool algorithmSupported(XSECCryptoSymmetricKey::SymmetricKeyType alg) const;
303 
304     /**
305      * \brief Determine whether a given algorithm is supported
306      *
307      * A call that can be used to determine whether a given
308      * digest algorithm is supported
309      */
310 
311     virtual bool algorithmSupported(XSECCryptoHash::HashType alg) const;
312 
313     /**
314      * \brief Return a Symmetric Key implementation object.
315      *
316      * Call used by the library to obtain a bulk encryption
317      * object.
318      *
319      * @returns Pointer to the new SymmetricKey object
320      * @see XSECCryptoSymmetricKey
321      */
322 
323     virtual XSECCryptoSymmetricKey* keySymmetric(XSECCryptoSymmetricKey::SymmetricKeyType alg) const;
324 
325     /**
326      * \brief Obtain some random octets
327      *
328      * For generation of IVs and the like, the library needs to be able
329      * to obtain "random" octets.  The library uses this call to the
330      * crypto provider to obtain what it needs.
331      *
332      * @param buffer The buffer to place the random data in
333      * @param numOctets Number of bytes required
334      * @returns Number of bytes obtained.
335      */
336 
337     virtual unsigned int getRandom(unsigned char * buffer, unsigned int numOctets) const;
338 
339 
340     //@}
341 
342     /** @name Information Functions */
343     //@{
344 
345     /**
346      * \brief Returns a string that identifies the Crypto Provider
347      */
348 
349     virtual const XMLCh* getProviderName() const;
350 
351     //@}
352 
353 
354 private:
355     HCRYPTPROV        m_provDSS;
356     HCRYPTPROV        m_provRSA;
357     HCRYPTPROV        m_provApacheKeyStore;
358     LPCSTR            m_provDSSName;
359     LPCSTR            m_provRSAName;
360     bool              m_haveAES;
361     DWORD             m_provRSAType;
362 
363 };
364 
365 /*\@}*/
366 
367 #endif /* XSEC_HAVE_WINCAPI */
368 #endif /* WINCAPICRYPTOPROVIDER_INCLUDE */
369 
370