| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * XSECCryptoSymmetricKey := Bulk encryption algorithms should all be |
| * implemented via this interface |
| * |
| * $Id$ |
| * |
| */ |
| |
| #include <xsec/enc/XSECCryptoException.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> |
| #include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp> |
| #include <xsec/framework/XSECDefs.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/utils/XSECPlatformUtils.hpp> |
| |
| |
| XERCES_CPP_NAMESPACE_USE |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| |
| #include "../../utils/XSECDOMUtils.hpp" |
| |
| #include <xercesc/util/Janitor.hpp> |
| |
| // -------------------------------------------------------------------------------- |
| // Constructors and Destructors |
| // -------------------------------------------------------------------------------- |
| |
| WinCAPICryptoSymmetricKey::WinCAPICryptoSymmetricKey( |
| HCRYPTPROV prov, |
| XSECCryptoSymmetricKey::SymmetricKeyType type) : |
| m_keyType(type), |
| m_keyMode(MODE_NONE), |
| m_initialised(false), |
| m_doPad(true), |
| m_p(prov), |
| m_k(0) { |
| |
| |
| } |
| |
| WinCAPICryptoSymmetricKey::~WinCAPICryptoSymmetricKey() { |
| |
| if (m_k != 0) |
| CryptDestroyKey(m_k); |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Basic Key interface methods |
| // -------------------------------------------------------------------------------- |
| |
| XSECCryptoKey * WinCAPICryptoSymmetricKey::clone() const { |
| |
| WinCAPICryptoSymmetricKey * ret; |
| |
| XSECnew(ret, WinCAPICryptoSymmetricKey(m_p, m_keyType)); |
| ret->m_keyLen = m_keyLen; |
| ret->m_keyBuf = m_keyBuf; |
| |
| if (m_k != 0) { |
| |
| #if (_WIN32_WINNT > 0x0400) |
| |
| // Only supported in Win2K and above |
| |
| if (CryptDuplicateKey(m_k, |
| 0, |
| 0, |
| &(ret->m_k)) == 0 ) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey Error attempting to clone key parameters"); |
| |
| } |
| #else |
| |
| ret->setKey(m_keyBuf.rawBuffer(), m_keyLen); |
| |
| #endif |
| } |
| else |
| ret->m_k = 0; |
| |
| return ret; |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Store the key value |
| // -------------------------------------------------------------------------------- |
| |
| void WinCAPICryptoSymmetricKey::setKey(const unsigned char * key, unsigned int keyLen) { |
| |
| m_keyBuf.sbMemcpyIn(key, keyLen); |
| m_keyLen = keyLen; |
| |
| if (m_k != 0) |
| CryptDestroyKey(m_k); |
| |
| m_p = 0; |
| m_k = createWindowsKey(key, keyLen, m_keyType, &m_p); |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Decrypt |
| // -------------------------------------------------------------------------------- |
| |
| int WinCAPICryptoSymmetricKey::decryptCtxInit(const unsigned char * iv) { |
| |
| // Returns amount of IV data used (in bytes) |
| // Sets m_initialised iff the key is OK and the IV is OK. |
| |
| if (m_initialised) |
| return 0; |
| |
| if (m_k == 0) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Cannot initialise without key"); |
| } |
| else if (m_keyMode == MODE_NONE) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Cannot initialise without mode"); |
| } |
| |
| DWORD cryptMode; |
| if (m_keyMode == MODE_CBC) { |
| |
| if (iv == NULL) { |
| |
| return 0; // Cannot initialise without an IV |
| |
| } |
| |
| cryptMode = CRYPT_MODE_CBC; |
| |
| if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting cipher mode"); |
| |
| } |
| |
| if (!CryptSetKeyParam(m_k, KP_IV, (unsigned char *) iv, 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting IV"); |
| |
| } |
| |
| } |
| else if (m_keyMode == MODE_ECB) { |
| cryptMode = CRYPT_MODE_ECB; |
| |
| if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting cipher mode"); |
| |
| } |
| } |
| else { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unknown cipher mode"); |
| } |
| |
| // Set up the context according to the required cipher type |
| switch (m_keyType) { |
| |
| case (XSECCryptoSymmetricKey::KEY_3DES_192) : |
| |
| // A 3DES CBC key |
| |
| m_blockSize = 8; |
| m_bytesInLastBlock = 0; |
| m_initialised = true; |
| |
| break; |
| |
| case (XSECCryptoSymmetricKey::KEY_AES_128) : |
| case (XSECCryptoSymmetricKey::KEY_AES_192) : |
| case (XSECCryptoSymmetricKey::KEY_AES_256) : |
| |
| // An AES key |
| |
| m_blockSize = 16; |
| m_bytesInLastBlock = 0; |
| m_initialised = true; |
| |
| break; |
| |
| default : |
| |
| // Cannot do this without an IV |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unknown key type"); |
| |
| } |
| |
| // Setup ivSize |
| switch (m_keyMode) { |
| case MODE_CBC: |
| m_ivSize = m_blockSize; |
| break; |
| |
| case MODE_GCM: |
| m_ivSize = 12; |
| break; |
| |
| default: |
| m_ivSize = 0; |
| } |
| |
| return m_ivSize; |
| } |
| |
| |
| bool WinCAPICryptoSymmetricKey::decryptInit(bool doPad, |
| SymmetricKeyMode mode, |
| const unsigned char* iv, |
| const unsigned char* tag, |
| unsigned int taglen) { |
| |
| m_initialised = false; |
| m_doPad = doPad; |
| m_keyMode = mode; |
| decryptCtxInit(iv); |
| return true; |
| |
| } |
| |
| unsigned int WinCAPICryptoSymmetricKey::decrypt(const unsigned char * inBuf, |
| unsigned char * plainBuf, |
| unsigned int inLength, |
| unsigned int maxOutLength) { |
| |
| |
| |
| // NOTE: This won't actually stop WinCAPI blowing the buffer, so the onus is |
| // on the caller. |
| |
| unsigned int offset = 0; |
| if (!m_initialised) { |
| offset = decryptCtxInit(inBuf); |
| if (offset > inLength) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Not enough data passed in to get IV"); |
| } |
| } |
| |
| /* As per bug #38365 - we need to ensure there are enough characters to decrypt. |
| Otherwise we get some nasty errors due to rounding calculations when inputs |
| are too small */ |
| |
| else if (m_bytesInLastBlock + inLength < m_blockSize) { |
| // Not enough input data |
| memcpy(&m_lastBlock[m_bytesInLastBlock], inBuf, inLength); |
| m_bytesInLastBlock += inLength; |
| return 0; |
| } |
| |
| DWORD outl = inLength - offset; |
| |
| // Copy in last block |
| if (m_bytesInLastBlock > 0) |
| memcpy(plainBuf, m_lastBlock, m_bytesInLastBlock); |
| |
| // Copy out the tail, as we _MUST_ know when we come to the end for decryptFinal |
| unsigned int rounding = (outl % m_blockSize) + m_blockSize; |
| memcpy(&plainBuf[m_bytesInLastBlock], &inBuf[offset], outl - rounding); |
| |
| // Copy the tail to m_lastBlock |
| memcpy(m_lastBlock, &inBuf[offset + outl - rounding], rounding); |
| outl = outl - rounding + m_bytesInLastBlock; |
| m_bytesInLastBlock = rounding; |
| |
| if (!CryptDecrypt(m_k, |
| 0, |
| FALSE, |
| 0, |
| plainBuf, |
| &outl)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error during WinCAPI decrypt"); |
| |
| } |
| |
| return outl; |
| |
| } |
| |
| unsigned int WinCAPICryptoSymmetricKey::decryptFinish(unsigned char * plainBuf, |
| unsigned int maxOutLength) { |
| |
| DWORD outl = m_bytesInLastBlock; |
| |
| memcpy(plainBuf, m_lastBlock, outl); |
| |
| if (!CryptDecrypt(m_k, |
| 0, |
| FALSE, |
| 0, |
| plainBuf, |
| &outl)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error during WinCAPI decrypt finalisation"); |
| |
| } |
| |
| if (m_doPad) { |
| |
| // Need to do this ourselves, as WinCAPI appears broken |
| if (plainBuf[outl - 1] > m_blockSize) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Bad padding"); |
| } |
| |
| outl -= plainBuf[outl - 1]; |
| |
| } |
| |
| // This is just to reset the key, and does nothing else useful. |
| DWORD tmpout = maxOutLength - outl; |
| CryptDecrypt(m_k, 0, TRUE, 0, &plainBuf[outl], &tmpout); |
| |
| return outl; |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Encrypt |
| // -------------------------------------------------------------------------------- |
| |
| void WinCAPICryptoSymmetricKey::encryptCtxInit(const unsigned char * iv) { |
| |
| |
| |
| if (m_initialised == true) |
| return; |
| |
| if (m_keyLen == 0) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Cannot initialise without key"); |
| } |
| else if (m_keyMode == MODE_NONE) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Cannot initialise without mode"); |
| } |
| |
| m_initialised = true; |
| |
| // Set up the context according to the required cipher type |
| |
| const unsigned char * usedIV = NULL; |
| unsigned char genIV[256]; |
| DWORD cryptMode; |
| |
| // Tell the library that the IV still has to be sent |
| |
| if (m_keyMode == MODE_CBC) { |
| |
| if (iv == NULL) { |
| |
| BOOL res = CryptGenRandom(m_p, 256, genIV); |
| if (res == FALSE) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error generating random IV"); |
| } |
| |
| usedIV = genIV; |
| //return 0; // Cannot initialise without an IV |
| |
| } |
| else |
| usedIV = iv; |
| |
| cryptMode = CRYPT_MODE_CBC; |
| |
| if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting cipher mode"); |
| |
| } |
| |
| // Set the IV parameter |
| if (!CryptSetKeyParam(m_k, KP_IV, (unsigned char *) usedIV, 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting IV"); |
| |
| } |
| |
| } |
| else if (m_keyMode == MODE_ECB) { |
| |
| cryptMode = CRYPT_MODE_ECB; |
| |
| if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting cipher mode"); |
| |
| } |
| } |
| else { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "OpenSSL:SymmetricKey - Unsupported cipher mode"); |
| } |
| |
| switch (m_keyType) { |
| |
| case (XSECCryptoSymmetricKey::KEY_3DES_192) : |
| |
| // A 3DES key |
| |
| m_blockSize = 8; |
| if (m_keyMode == MODE_CBC) |
| m_ivSize = 8; |
| else |
| m_ivSize = 0; |
| m_bytesInLastBlock = 0; |
| |
| break; |
| |
| case (XSECCryptoSymmetricKey::KEY_AES_128) : |
| case (XSECCryptoSymmetricKey::KEY_AES_192) : |
| case (XSECCryptoSymmetricKey::KEY_AES_256) : |
| |
| // An AES key |
| |
| m_blockSize = 16; |
| if (m_keyMode == MODE_CBC) |
| m_ivSize = 16; |
| else if (m_keyMode == MODE_GCM) |
| m_ivSize = 12; |
| else |
| m_ivSize = 0; |
| m_bytesInLastBlock = 0; |
| |
| break; |
| |
| default : |
| |
| // Cannot do this without an IV |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unknown key type"); |
| |
| } |
| |
| if (usedIV != NULL && m_ivSize > 0) |
| memcpy(m_lastBlock, usedIV, m_ivSize); |
| |
| |
| } |
| bool WinCAPICryptoSymmetricKey::encryptInit(bool doPad, |
| SymmetricKeyMode mode, |
| const unsigned char * iv) { |
| |
| m_doPad = doPad; |
| m_keyMode = mode; |
| m_initialised = false; |
| encryptCtxInit(iv); |
| return true; |
| |
| } |
| |
| unsigned int WinCAPICryptoSymmetricKey::encrypt(const unsigned char * inBuf, |
| unsigned char * cipherBuf, |
| unsigned int inLength, |
| unsigned int maxOutLength) { |
| |
| if (m_initialised == false) { |
| |
| encryptInit(); |
| |
| } |
| |
| // NOTE: This won't actually stop WinCAPI blowing the buffer, so the onus is |
| // on the caller. |
| |
| unsigned int offset = 0; |
| unsigned char * bufPtr; |
| unsigned char * encPtr; // Ptr to start of block to encrypt |
| |
| DWORD outl = 0; |
| |
| if (m_ivSize > 0) { |
| |
| DWORD len = m_ivSize; |
| if (!CryptGetKeyParam(m_k, KP_IV, (unsigned char *) m_lastBlock, &len, 0)) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error setting IV"); |
| |
| } |
| memcpy(cipherBuf, m_lastBlock, m_ivSize); |
| offset = m_ivSize; |
| outl += m_ivSize; |
| m_ivSize = 0; |
| |
| } |
| |
| /* As per bug #38365 - we need to ensure there are enough characters to encrypt. |
| Otherwise we get some nasty errors due to rounding calculations when inputs |
| are too small */ |
| |
| if (inLength < m_blockSize) { |
| // Not enough input data |
| memcpy(&m_lastBlock[m_bytesInLastBlock], inBuf, inLength); |
| m_bytesInLastBlock += inLength; |
| |
| // Just in case we have returned an IV |
| return outl; |
| } |
| |
| bufPtr = &cipherBuf[offset]; |
| encPtr = bufPtr; |
| |
| if (m_bytesInLastBlock > 0) { |
| memcpy(bufPtr, m_lastBlock, m_bytesInLastBlock); |
| bufPtr = &bufPtr[m_bytesInLastBlock]; |
| outl += m_bytesInLastBlock; |
| } |
| |
| unsigned int rounding = (m_bytesInLastBlock + inLength) % m_blockSize; |
| rounding += m_blockSize; |
| |
| outl += inLength - rounding; |
| if (outl > maxOutLength) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Not enough space in output buffer for encrypt"); |
| } |
| |
| outl -= offset; |
| |
| // Now copy back one block + rounding |
| memcpy(m_lastBlock, &inBuf[inLength - rounding], rounding); |
| m_bytesInLastBlock = rounding; |
| |
| // Finally, copy in last of buffer to encrypt |
| memcpy(bufPtr, inBuf, inLength - rounding); |
| |
| // Do the enrypt |
| if (!CryptEncrypt(m_k, 0, FALSE, 0, encPtr, &outl, maxOutLength)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error during WinCAPI encrypt"); |
| } |
| |
| return outl + offset; |
| |
| } |
| |
| unsigned int WinCAPICryptoSymmetricKey::encryptFinish(unsigned char * cipherBuf, |
| unsigned int maxOutLength, |
| unsigned int taglen) { |
| |
| DWORD outl = m_bytesInLastBlock + m_blockSize; |
| |
| if (outl > maxOutLength) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Not enough space in output buffer for encrypt - NOTE WinCAPI requires an extra block to complete encryption"); |
| } |
| |
| outl = 0; |
| |
| if (m_bytesInLastBlock != 0) { |
| |
| memcpy(cipherBuf, m_lastBlock, m_bytesInLastBlock); |
| outl = m_bytesInLastBlock; |
| |
| } |
| |
| if (!CryptEncrypt(m_k, 0, TRUE, 0, cipherBuf, &outl, maxOutLength)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Error during WinCAPI encrypt"); |
| } |
| |
| if (!m_doPad) { |
| |
| // It is the responsibility of the caller to ensure they have |
| // passed in block size num bytes |
| |
| if (outl >= m_blockSize) |
| outl -= m_blockSize; |
| |
| } |
| |
| return outl; |
| |
| } |
| |
| |
| // -------------------------------------------------------------------------------- |
| // Create a windows key |
| // -------------------------------------------------------------------------------- |
| |
| HCRYPTKEY WinCAPICryptoSymmetricKey::createWindowsKey( |
| const unsigned char * key, |
| unsigned int keyLen, |
| XSECCryptoSymmetricKey::SymmetricKeyType type, |
| HCRYPTPROV * prov) { |
| |
| // First get the correct Provider handle to load the key into |
| |
| HCRYPTPROV p; |
| |
| if (prov == NULL || *prov == 0) { |
| if (!strEquals(XSECPlatformUtils::g_cryptoProvider->getProviderName(), DSIGConstants::s_unicodeStrPROVWinCAPI)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Main provider is not Windows provider"); |
| } |
| |
| WinCAPICryptoProvider * cp = |
| (WinCAPICryptoProvider*) XSECPlatformUtils::g_cryptoProvider; |
| |
| p = cp->getApacheKeyStore(); |
| |
| if (p == 0) { |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unable to retrieve internal key store"); |
| |
| } |
| |
| if (prov != NULL) |
| *prov = p; |
| } |
| |
| else if (prov != NULL) |
| p = *prov; |
| |
| // Get the key wrapping key |
| HCRYPTKEY k; |
| if (!CryptGetUserKey(p, AT_KEYEXCHANGE, &k)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unable to retrieve internal key pair"); |
| } |
| |
| // Find out how long the output will be |
| DWORD outl = 0; |
| if (!CryptEncrypt(k, 0, TRUE, 0, 0, &outl, keyLen)) { |
| DWORD error = GetLastError(); |
| if (error == NTE_BAD_KEY) { |
| // We throw either way, but this is *likely* to be an unsupported OS issue |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey::createWindowsKey - Error encrypting a key - is this >= Windows 2000?"); |
| } |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unable to determine space required to encrypt key"); |
| } |
| |
| // Create the necessary buffer |
| unsigned char * encryptBuf; |
| unsigned int encryptBufSize = outl; |
| XSECnew(encryptBuf, unsigned char[outl]); |
| ArrayJanitor<unsigned char> j_encryptBuf(encryptBuf); |
| |
| memcpy(encryptBuf, key, keyLen); |
| outl = keyLen; |
| |
| // Do the encrypt |
| |
| if (!CryptEncrypt(k, 0, TRUE, 0, encryptBuf, &outl, encryptBufSize)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unable to encrypt key"); |
| } |
| |
| // Now we have the encrypted buffer, create a SIMPLEBLOB structure |
| |
| unsigned char * simpleBlob; |
| XSECnew(simpleBlob, unsigned char [sizeof (BLOBHEADER) + sizeof (DWORD) + outl]); |
| ArrayJanitor<unsigned char> j_simpleBlob(simpleBlob); |
| |
| BLOBHEADER * blobHeader = (BLOBHEADER *) simpleBlob; |
| blobHeader->bType = SIMPLEBLOB; |
| blobHeader->bVersion = CUR_BLOB_VERSION; |
| blobHeader->reserved = 0; |
| |
| unsigned int expectedLength; |
| |
| switch (type) { |
| |
| case (XSECCryptoSymmetricKey::KEY_3DES_192) : |
| blobHeader->aiKeyAlg = CALG_3DES; |
| expectedLength = 24; |
| break; |
| case (XSECCryptoSymmetricKey::KEY_AES_128) : |
| blobHeader->aiKeyAlg = CALG_AES_128; |
| expectedLength = 16; |
| break; |
| case (XSECCryptoSymmetricKey::KEY_AES_192) : |
| blobHeader->aiKeyAlg = CALG_AES_192; |
| expectedLength = 24; |
| break; |
| case (XSECCryptoSymmetricKey::KEY_AES_256) : |
| blobHeader->aiKeyAlg = CALG_AES_256; |
| expectedLength = 32; |
| break; |
| default : |
| |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey::createWindowsKey - Unknown Symmetric key type"); |
| |
| } |
| |
| // Check key length - otherwise the user could get some very cryptic error messages |
| if (keyLen != expectedLength) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey::createWindowsKey - Key length incorrect for algorithm"); |
| } |
| |
| DWORD * algId = (DWORD *) (simpleBlob + sizeof(BLOBHEADER)); |
| *algId = CALG_RSA_KEYX; |
| |
| // Copy in the encrypted data |
| memcpy(&simpleBlob[sizeof(BLOBHEADER) + sizeof(DWORD)], encryptBuf, outl); |
| |
| // Now do the import |
| |
| HCRYPTKEY k2; |
| |
| if (!CryptImportKey(p, simpleBlob, sizeof(BLOBHEADER) + sizeof(DWORD) + outl, k, CRYPT_EXPORTABLE, &k2)) { |
| throw XSECCryptoException(XSECCryptoException::SymmetricError, |
| "WinCAPI:SymmetricKey - Unable to import key"); |
| } |
| |
| return k2; |
| |
| } |
| |
| |
| #endif /* XSEC_HAVE_WINCAPI */ |