00001
00010 #include "PKIFXSECCrypto.h"
00011 #include "PKIFXSECCryptoSymmetricKey.h"
00012 #include "PKIFXSECCryptoKeyRaw.h"
00013
00014 #include "PKIFAlgorithm.h"
00015
00016 #include <xsec/utils/XSECPlatformUtils.hpp>
00018 struct PKIFXSECCryptoSymmetricKeyImpl
00019 {
00020 IPKIFCryptoRawOperations * m_raw;
00021 IPKIFRawCryptContext * m_ctx;
00022 XSECCryptoSymmetricKey::SymmetricKeyType m_kt;
00023 bool m_bIVSent;
00024 };
00026
00033 XSECCryptoSymmetricKey::SymmetricKeyType getXSECKeyType(PKIFCRYPTO::SYMKEY_ALG alg)
00034 {
00035 switch(alg) {
00036 case PKIFCRYPTO::TDES:
00037 return XSECCryptoSymmetricKey::KEY_3DES_192;
00038 break;
00039 case PKIFCRYPTO::AES128:
00040 return XSECCryptoSymmetricKey::KEY_AES_128;
00041 break;
00042 case PKIFCRYPTO::AES192:
00043 return XSECCryptoSymmetricKey::KEY_AES_192;
00044 break;
00045 case PKIFCRYPTO::AES256:
00046 return XSECCryptoSymmetricKey::KEY_AES_256;
00047 break;
00048 }
00049
00050 return XSECCryptoSymmetricKey::KEY_NONE;
00051 }
00059 PKIFCRYPTO::SYMKEY_ALG getPKIFKeyType(XSECCryptoSymmetricKey::SymmetricKeyType alg)
00060 {
00061 switch(alg) {
00062 case XSECCryptoSymmetricKey::KEY_3DES_192:
00063 return PKIFCRYPTO::TDES;
00064 break;
00065 case XSECCryptoSymmetricKey::KEY_AES_128:
00066 return PKIFCRYPTO::AES128;
00067 break;
00068 case XSECCryptoSymmetricKey::KEY_AES_192:
00069 return PKIFCRYPTO::AES192;
00070 break;
00071 case XSECCryptoSymmetricKey::KEY_AES_256:
00072 return PKIFCRYPTO::AES256;
00073 break;
00074 }
00075
00076 return PKIFCRYPTO::AES128;
00077 }
00078
00084 PKIFCRYPTO::SYMKEY_MODE getPKIFMode(XSECCryptoSymmetricKey::SymmetricKeyMode mode)
00085 {
00086 switch(mode) {
00087 case XSECCryptoSymmetricKey::MODE_CBC:
00088 return PKIFCRYPTO::CBC;
00089 break;
00090 case XSECCryptoSymmetricKey::MODE_ECB:
00091 return PKIFCRYPTO::ECB;
00092 break;
00093 }
00094
00095 return PKIFCRYPTO::ECB;
00096 }
00097
00105 PKIFXSECCryptoSymmetricKey::PKIFXSECCryptoSymmetricKey()
00106 :m_rawKey(new PKIFXSECCryptoKeyRaw()),m_impl(new PKIFXSECCryptoSymmetricKeyImpl)
00107 {
00108 m_impl->m_raw = 0;
00109 m_impl->m_ctx = 0;
00110 m_impl->m_bIVSent = false;
00111 }
00112
00120 PKIFXSECCryptoSymmetricKey::PKIFXSECCryptoSymmetricKey(
00122 IPKIFCryptoRawOperations * raw)
00123 :m_rawKey(new PKIFXSECCryptoKeyRaw()), m_impl(new PKIFXSECCryptoSymmetricKeyImpl)
00124 {
00125 m_impl->m_raw = raw;
00126 m_impl->m_ctx = 0;
00127 m_impl->m_bIVSent = false;
00128 }
00129
00137 PKIFXSECCryptoSymmetricKey::~PKIFXSECCryptoSymmetricKey()
00138 {
00139 if(m_rawKey) {
00140 delete m_rawKey;
00141 m_rawKey = 0;
00142 }
00143 if(m_impl) {
00144
00145 delete m_impl;
00146 m_impl = 0;
00147 }
00148 }
00149
00158 XSECCryptoKey * PKIFXSECCryptoSymmetricKey::clone() const
00159 {
00160 CPKIFKeyMaterialPtr kp = m_rawKey->getPKIFKeyMaterial();
00161 PKIFXSECCryptoSymmetricKey * rv = new PKIFXSECCryptoSymmetricKey(m_impl->m_raw);
00162 rv->setPKIFKeyMaterial(kp);
00163
00164 return rv;
00165 }
00166
00174 void PKIFXSECCryptoSymmetricKey::setKey(
00176 const unsigned char * inBuf,
00178 unsigned int inLength)
00179 {
00180 m_rawKey->setKey(inBuf,inLength);
00181 m_rawKey->getPKIFKeyMaterial()->SetSymmetricKeyAlgorithm(getPKIFKeyType(m_impl->m_kt));
00182 }
00183
00190 unsigned int PKIFXSECCryptoSymmetricKey::getKey(
00192 safeBuffer &outBuf)
00193 {
00194 return m_rawKey->getKey(outBuf);
00195 }
00196
00204 CPKIFKeyMaterialPtr PKIFXSECCryptoSymmetricKey::getPKIFKeyMaterial()
00205 {
00206 return m_rawKey->getPKIFKeyMaterial();
00207 }
00208
00216 void PKIFXSECCryptoSymmetricKey::setPKIFKeyMaterial(
00218 CPKIFKeyMaterialPtr & km)
00219 {
00220 m_rawKey->setPKIFKeyMaterial(km);
00221 }
00222
00230 const XMLCh * PKIFXSECCryptoSymmetricKey::getProviderName() const
00231 {
00232 return m_rawKey->getProviderName();
00233 }
00234
00242 XSECCryptoSymmetricKey::SymmetricKeyType PKIFXSECCryptoSymmetricKey::getSymmetricKeyType() const
00243 {
00244 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return XSECCryptoSymmetricKey::KEY_NONE;
00245 return getXSECKeyType(m_rawKey->getPKIFKeyMaterial()->GetSymmetricKeyAlgorithm());
00246 }
00247
00255 void PKIFXSECCryptoSymmetricKey::setSymmetricType(XSECCryptoSymmetricKey::SymmetricKeyType type)
00256 {
00257 m_impl->m_kt = type;
00258 }
00259
00267 bool PKIFXSECCryptoSymmetricKey::decryptInit(
00269 bool doPad,
00271 SymmetricKeyMode mode,
00274 const unsigned char * iv)
00275 {
00276 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return false;
00277 if(XSECCryptoSymmetricKey::MODE_NONE == mode) return false;
00278 if(!m_impl->m_raw) return false;
00279 PKIFCRYPTO::SYMKEY_MODE pkifMode = getPKIFMode(mode);
00280 CPKIFKeyMaterialPtr km = m_rawKey->getPKIFKeyMaterial();
00281 km->SetMode(pkifMode);
00282 if(iv) {
00283 CPKIFAlgorithm * alg = CPKIFAlgorithm::GetAlg(km->GetSymmetricKeyAlgorithm(),pkifMode);
00284 if(!alg) return false;
00285 km->SetIV(iv,alg->BlockSize());
00286 }
00287 if(m_impl->m_ctx) {
00288 delete m_impl->m_ctx;
00289 m_impl->m_ctx = 0;
00290 }
00291
00292
00293
00294 return true;
00295 }
00296
00304 unsigned int PKIFXSECCryptoSymmetricKey::decrypt(
00306 const unsigned char * inBuf,
00308 unsigned char * plainBuf,
00310 unsigned int inLength,
00312 unsigned int maxOutLength)
00313 {
00314 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return 0;
00315
00316
00317 CPKIFKeyMaterialPtr km = m_rawKey->getPKIFKeyMaterial();
00318 unsigned int processedLength = 0;
00319 unsigned char * ctCurr = const_cast<unsigned char *>(inBuf);
00320
00321
00322 CPKIFAlgorithm * alg = CPKIFAlgorithm::GetAlg(km->GetSymmetricKeyAlgorithm(),km->GetMode());
00323 if(!alg) return 0;
00324 if(inLength < alg->BlockSize()) return 0;
00325 if(alg->NeedsIV() && !km->GetIV()) {
00326 km->SetIV(inBuf,alg->BlockSize());
00327 processedLength += alg->BlockSize();
00328 ctCurr += alg->BlockSize();
00329 }
00330 int outLen = maxOutLength;
00331 if(!m_impl->m_ctx) m_impl->m_ctx = m_impl->m_raw->CryptInit(*km);
00332 if(!m_impl->m_ctx) return 0;
00333 m_impl->m_raw->Decrypt(m_impl->m_ctx,ctCurr,inLength - processedLength,plainBuf,&outLen,false);
00334 return outLen;
00335 }
00343 unsigned int PKIFXSECCryptoSymmetricKey::decryptFinish(
00345 unsigned char * plainBuf,
00347 unsigned int maxOutLength)
00348 {
00349 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return false;
00350 if(!m_impl->m_ctx) return false;
00351 int outLen = maxOutLength;
00352 m_impl->m_raw->Decrypt(m_impl->m_ctx,0,0,plainBuf,&outLen,true);
00353 return outLen;
00354 }
00355
00363 bool PKIFXSECCryptoSymmetricKey::encryptInit(
00365 bool doPad,
00367 SymmetricKeyMode mode,
00369 const unsigned char * iv)
00370 {
00371 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return false;
00372 if(XSECCryptoSymmetricKey::MODE_NONE == mode) return false;
00373 if(!m_impl->m_raw) return false;
00374 PKIFCRYPTO::SYMKEY_MODE pkifMode = getPKIFMode(mode);
00375 CPKIFKeyMaterialPtr km = m_rawKey->getPKIFKeyMaterial();
00376 km->SetMode(pkifMode);
00377 CPKIFAlgorithm * alg = CPKIFAlgorithm::GetAlg(km->GetSymmetricKeyAlgorithm(),pkifMode);
00378 if(!alg) return false;
00379 if(iv) {
00380 km->SetIV(iv,alg->BlockSize());
00381
00382 } else if(!iv && alg->NeedsIV()) {
00383 PKIFXSECCrypto * cp = dynamic_cast<PKIFXSECCrypto *>(XSECPlatformUtils::g_cryptoProvider);
00384 if(!cp) return false;
00385 int ivLen = alg->BlockSize();
00386 unsigned char * ivBuf = new unsigned char[ivLen];
00387 cp->getRandom(ivBuf,ivLen);
00388 km->SetIV(ivBuf,ivLen);
00389 delete[] ivBuf;
00390 }
00391 if(m_impl->m_ctx) {
00392 delete m_impl->m_ctx;
00393 m_impl->m_ctx = 0;
00394 }
00395 m_impl->m_ctx = m_impl->m_raw->CryptInit(*km);
00396 return (m_impl->m_ctx != 0);
00397 }
00398
00406 unsigned int PKIFXSECCryptoSymmetricKey::encrypt(
00408 const unsigned char * inBuf,
00410 unsigned char * cipherBuf,
00412 unsigned int inLength,
00414 unsigned int maxOutLength)
00415 {
00416 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return 0;
00417 if(!m_impl->m_ctx) return 0;
00418 CPKIFKeyMaterialPtr km = m_rawKey->getPKIFKeyMaterial();
00419 unsigned int processedLength = 0;
00420
00421
00422
00423 CPKIFAlgorithm * alg = CPKIFAlgorithm::GetAlg(km->GetSymmetricKeyAlgorithm(),km->GetMode());
00424 if(!alg) return 0;
00425 if(inLength < alg->BlockSize()) return 0;
00426 if(alg->NeedsIV() && !m_impl->m_bIVSent) {
00427 memcpy(cipherBuf,km->GetIV(),alg->BlockSize());
00428 processedLength += alg->BlockSize();
00429 m_impl->m_bIVSent = true;
00430 }
00431
00432 int outLen = maxOutLength - processedLength;
00433 unsigned char * ptBuf = const_cast<unsigned char *>(inBuf);
00434 m_impl->m_raw->Encrypt(m_impl->m_ctx,ptBuf,inLength,cipherBuf+processedLength,&outLen,false);
00435 processedLength += outLen;
00436 return processedLength;
00437 }
00438
00446 unsigned int PKIFXSECCryptoSymmetricKey::encryptFinish(
00448 unsigned char * plainBuf,
00450 unsigned int maxOutLength)
00451 {
00452 if(!m_rawKey || !m_rawKey->getPKIFKeyMaterial()) return false;
00453 if(!m_impl->m_ctx) return false;
00454 int outLen = maxOutLength;
00455 m_impl->m_raw->Encrypt(m_impl->m_ctx,0,0,plainBuf,&outLen,true);
00456 return outLen;
00457 }
00458