00001
00009 #include "PKIFCryptoPP.h"
00010 #include "PKIFCryptoPPCredential.h"
00011 #include "PKIFCryptoPPKeyMaterial.h"
00012 #include "PKIFCryptoPPExternalDigest.h"
00013 #include "PKIFCryptoPPKAContext.h"
00014
00015 #include "ToolkitUtils.h"
00016 #include "PKIFCryptoErrors.h"
00017 #include "PKIFCryptoPPErrors.h"
00018 #include "PKIFCryptoException.h"
00019 #include "KeyUsage.h"
00020 #include "PKIFAlgorithm.h"
00021 #include "Buffer.h"
00022 #include "SubjectPublicKeyInfo.h"
00023 #include "Certificate.h"
00024
00025 #include "ASN1Helper.h"
00026 #include "ECC-CMS.h"
00027
00028 #include "cryptlib.h"
00029 #include "pubkey.h"
00030 #include "sha.h"
00031 #include "queue.h"
00032 #include "osrng.h"
00033 #include "rsa.h"
00034 #include "dsa.h"
00035 #include "eccrypto.h"
00036 #include "asn.h"
00037 #include "dsa.h"
00038 #include "modes.h"
00039 #include "aes.h"
00040 #include "hmac.h"
00041 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
00042 #include "md5.h"
00043
00044 #include <oids.h>
00045
00046
00047 #include <boost/scoped_ptr.hpp>
00048
00049 using namespace CryptoPP;
00050 using namespace std;
00051 using namespace boost;
00052
00053 #include <sstream>
00054
00055 #include "boost/numeric/conversion/cast.hpp"
00056
00057 #if defined(WIN32) || defined(_WIN32)
00058 #include <Winsock2.h>
00059 #endif
00060
00061 #if !defined(_WIN32)
00062 #include <netinet/in.h>
00063 #endif
00064
00065 using boost::numeric_cast;
00066 using boost::bad_numeric_cast;
00067
00068 using namespace std;
00069 using namespace CryptoPP;
00070
00072 struct CPKIFCryptoPPImpl
00073 {
00074 };
00076
00085 CPKIFCryptoPP::CPKIFCryptoPP()
00086 :m_impl(new CPKIFCryptoPPImpl)
00087 {
00088 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00089 }
00097 CPKIFCryptoPP::~CPKIFCryptoPP()
00098 {
00099 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00100 if(!m_impl) {
00101 delete m_impl;
00102 m_impl = 0;
00103 }
00104 }
00105
00115 void CPKIFCryptoPP::Initialize()
00116 {
00117 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00118 }
00119
00130 void CPKIFCryptoPP::GetKeyList(
00132 CPKIFCredentialList& v,
00134 CPKIFKeyUsagePtr& ku)
00135 {
00136 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_NOT_IMPLEMENTED, "The crypto++ colleague does not store keys.");
00137 }
00138
00149 void CPKIFCryptoPP::GetKeyList(
00151 CPKIFCredentialList& v,
00153 std::bitset<9>* ku)
00154 {
00155 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_NOT_IMPLEMENTED, "The crypto++ colleague does not store keys.");
00156 }
00157
00167 bool CPKIFCryptoPP::OwnsKey(
00169 const CPKIFCredential& keyID) const
00170 {
00171 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00172
00173 const CPKIFCryptoPPCredential * cryptoppkey = dynamic_cast<const CPKIFCryptoPPCredential *>(&keyID);
00174 return (0 != cryptoppkey);
00175 }
00184 CPKIFCredentialPtr CPKIFCryptoPP::MakeKeyID(
00187 const std::string& asciiHexKeyID)
00188 {
00189 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00190 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_NOT_IMPLEMENTED, "The crypto++ colleague does not store keys.");
00191 }
00212 void CPKIFCryptoPP::Sign(
00214 const CPKIFCredential& key,
00216 unsigned char* pHashData,
00218 int nHashDataLen,
00220 unsigned char* pSignature,
00223 int* nSignatureLen,
00225 PKIFCRYPTO::HASH_ALG ha
00226 )
00227
00228 {
00229 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00230 CPKIFCryptoPPCredential * cryptoppkey = const_cast<CPKIFCryptoPPCredential *>(dynamic_cast<const CPKIFCryptoPPCredential *>(&key));
00231 if(!cryptoppkey) {
00232 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-crypto++ credential",
00233 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00234 }
00235 CPKIFAlgorithm * keyAlg = cryptoppkey->GetAlgorithm();
00236 if(!keyAlg) {
00237 RAISE_CRYPTO_EXCEPTION("Crypto++ credential has not been properly populated",thisComponent,COMMON_INVALID_INPUT,this);
00238 }
00239 bool isDSA = false;
00240 PK_Signer * signer = 0;
00241 ByteQueue keyReader;
00242 keyReader.Put(cryptoppkey->m_keyBuf->GetBuffer(),cryptoppkey->m_keyBuf->GetLength());
00243 switch(keyAlg->AsymkeyAlg()) {
00244 case PKIFCRYPTO::RSA:
00245 switch(ha) {
00246 case PKIFCRYPTO::MD5:
00247 signer = new RSASS<PKCS1v15,CryptoPP::Weak::MD5>::Signer(keyReader);
00248 break;
00249 case PKIFCRYPTO::SHA1:
00250 signer = new RSASS<PKCS1v15,CryptoPP::SHA1>::Signer(keyReader);
00251 break;
00252 case PKIFCRYPTO::SHA256:
00253 signer = new RSASS<PKCS1v15,CryptoPP::SHA256>::Signer(keyReader);
00254 break;
00255 case PKIFCRYPTO::SHA384:
00256 signer = new RSASS<PKCS1v15,CryptoPP::SHA384>::Signer(keyReader);
00257 break;
00258 case PKIFCRYPTO::SHA512:
00259 signer = new RSASS<PKCS1v15,CryptoPP::SHA512>::Signer(keyReader);
00260 break;
00261 default:
00262 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00263 break;
00264 }
00265 break;
00266 case PKIFCRYPTO::ECC:
00267 isDSA = true;
00268 switch(ha) {
00269 case PKIFCRYPTO::SHA1:
00270 signer = new ECDSA<ECP,CryptoPP::SHA1>::Signer(keyReader);
00271 break;
00272 case PKIFCRYPTO::SHA256:
00273 signer = new ECDSA<ECP,CryptoPP::SHA256>::Signer(keyReader);
00274 break;
00275 case PKIFCRYPTO::SHA384:
00276 signer = new ECDSA<ECP,CryptoPP::SHA384>::Signer(keyReader);
00277 break;
00278 case PKIFCRYPTO::SHA512:
00279 signer = new ECDSA<ECP,CryptoPP::SHA512>::Signer(keyReader);
00280 break;
00281 default:
00282 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00283 break;
00284 }
00285 break;
00286 case PKIFCRYPTO::DSS:
00287 isDSA = true;
00288 switch(ha) {
00289 case PKIFCRYPTO::SHA1:
00290 signer = new DSA::Signer(keyReader);
00291 break;
00292 default:
00293 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00294 break;
00295 }
00296 break;
00297 default:
00298 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00299 break;
00300 }
00301 int expectedLen = static_cast<int>(signer->SignatureLength());
00302 if(*nSignatureLen < expectedLen) {
00303 delete signer;
00304 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_INVALID_INPUT, "Signature buffer too short");
00305 }
00306
00307 PKIFCryptoPPExternalDigestAccumulator * ed = NewEDAccumulator(pHashData,nHashDataLen);
00308 static RandomPool rng;
00309
00310
00311
00312 if(!isDSA) {
00313 signer->Sign(rng,ed,pSignature);
00314 *nSignatureLen = expectedLen;
00315 } else {
00316 unsigned char * rawSig = new unsigned char[expectedLen];
00317
00318
00319
00320
00321
00322 PK_MessageAccumulatorBase * acc = dynamic_cast<PK_MessageAccumulatorBase *>(signer->NewSignatureAccumulator(rng));
00323 ed->m_presignature = acc->m_presignature;
00324 ed->m_k = acc->m_k;
00325
00326 signer->Sign(rng,ed,pSignature);
00327 *nSignatureLen = expectedLen;
00328
00329
00330 }
00331 }
00332
00345 void CPKIFCryptoPP::Decrypt(
00348 const CPKIFCredential& key,
00350 unsigned char* pData,
00352 int nDataLen,
00354 unsigned char* pResult,
00357 int* pnResultLen)
00358 {
00359 LOG_STRING_DEBUG(__FUNCTION__,TOOLKIT_CRYPTO_CRYPTOPP,0,this);
00360 const CPKIFCryptoPPCredential * cryptoppkey = dynamic_cast<const CPKIFCryptoPPCredential *>(&key);
00361 if(!cryptoppkey) {
00362 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-Crypto++ credential",
00363 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00364 }
00365
00366 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_NOT_IMPLEMENTED, "The crypto++ colleague does not store keys.");
00367 }
00368
00380 void CPKIFCryptoPP::Encrypt(
00383 const CPKIFCredential& key,
00385 unsigned char* pData,
00387 int nDataLen,
00389 unsigned char* pResult,
00392 int* pnResultLen)
00393 {
00394 RAISE_CRYPTO_EXCEPTION("Encryption is unimplemented for stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00395 }
00409 bool CPKIFCryptoPP::Verify(
00412 const CPKIFCredential& key,
00415 unsigned char* pHashData,
00417 int nHashDataLen,
00419 unsigned char* pSignature,
00421 int nSignatureLen,
00423 PKIFCRYPTO::HASH_ALG ha
00424 )
00425 {
00426 RAISE_CRYPTO_EXCEPTION("Verification is unimplemented for stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00427 return false;
00428 }
00442 IPKIFCryptContext* CPKIFCryptoPP::CryptInit(
00445 CPKIFCredentialPtr& key,
00447 bool pad)
00448 {
00449 RAISE_CRYPTO_EXCEPTION("Context-based operations are unimplemented for Crypto++ stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00450 return 0;
00451 }
00464 void CPKIFCryptoPP::Decrypt(
00467 IPKIFCryptContext* cryptContext,
00469 unsigned char* pData,
00471 int nDataLen,
00473 unsigned char* pResult,
00476 int* pnResultLen,
00479 bool final)
00480 {
00481 RAISE_CRYPTO_EXCEPTION("Context-based decryption is unimplemented for stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00482 }
00495 void CPKIFCryptoPP::Encrypt(IPKIFCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)
00496 {
00497 RAISE_CRYPTO_EXCEPTION("Encryption is unimplemented for stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00498 }
00499
00506 void GetPrivateExponent(CryptoPP::SecByteBlock & exp, CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> & key)
00507 {
00508 exp.New(key.GetPrivateExponent().ByteCount());
00509 key.GetPrivateExponent().Encode(exp,exp.m_size);
00510 }
00511
00519 void GetEncodedPublicKey(CryptoPP::SecByteBlock & enc, CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> & key)
00520 {
00521 CryptoPP::ByteQueue bq;
00522 key.DEREncodePublicKey(bq);
00523
00524 size_t len;
00525 try {
00526 len = boost::numeric_cast<size_t,CryptoPP::lword>(bq.MaxRetrievable());
00527 }catch(boost::numeric::bad_numeric_cast &){
00528 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPP, COMMON_INVALID_INPUT, "Failed to decode public key");
00529 }
00530 enc.New(len);
00531 bq.Get(enc,len);
00532 }
00533
00547 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00550 CPKIFCredentialPtr& myPrivateKey,
00552 const CPKIFCertificatePtr& theirCert,
00554 const CPKIFAlgorithm * alg)
00555 {
00556
00557
00558 CPKIFCryptoPPKeyMaterialPtr km(new CPKIFCryptoPPKeyMaterial(*theirCert));
00559 CPKIFBufferPtr rawKey = km->GetRawSPKI();
00560 return SecretAgree(myPrivateKey, rawKey, alg);
00561 }
00562
00580
00581
00582
00583 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00586 CPKIFCredentialPtr& myPrivateKey,
00590 const CPKIFBufferPtr& theirPublicKey,
00592 const CPKIFAlgorithm * alg)
00593 {
00594 CPKIFOIDPtr kaOID = alg->OID();
00595 CryptoPP::SecByteBlock theirPubInteger;
00596 CPKIFCryptoPPCredentialPtr myCppCred;
00597
00598
00599 CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> theirPub;
00600 CryptoPP::ByteQueue pubq;
00601 pubq.Put(theirPublicKey->GetBuffer(),theirPublicKey->GetLength());
00602 try {
00603 theirPub.BERDecode(pubq);
00604 } catch(CryptoPP::BERDecodeErr &) {
00605 RAISE_CRYPTO_EXCEPTION("Unable to decode public key for ECDH",thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00606 }
00607
00608
00609 GetEncodedPublicKey(theirPubInteger,theirPub);
00610
00611
00612 if(!myPrivateKey) {
00613
00614 CryptoPP::AutoSeededRandomPool rng;
00615 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> ephemeralPriv;
00616 ephemeralPriv.Initialize(rng,theirPub.GetGroupParameters());
00617
00618
00619
00620
00621 CryptoPP::ByteQueue ephemq;
00622 ephemeralPriv.DEREncode(ephemq);
00623 CPKIFCryptoPPCredential * ephemeralCred = new CPKIFCryptoPPCredential();
00624 CPKIFBufferPtr keyBuf(new CPKIFBuffer());
00625 unsigned char * keyBufRaw = keyBuf->AllocateBuffer(static_cast<int>(ephemq.MaxRetrievable()));
00626 ephemq.Get(keyBufRaw,keyBuf->GetLength());
00627 ephemeralCred->SetPrivateKey(keyBuf);
00628 myCppCred = CPKIFCryptoPPCredentialPtr(ephemeralCred);
00629 myCppCred->SetAlgorithm(CPKIFAlgorithm::GetAlg(PKIFCRYPTO::ECC));
00630
00631 myPrivateKey = dynamic_pointer_cast<CPKIFCredential, CPKIFCryptoPPCredential>(myCppCred);
00632
00633 }
00634
00635
00636 if(!myCppCred) {
00637 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-Crypto++ credential",
00638 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00639 }
00640
00641
00642 CryptoPP::ByteQueue privq;
00643 privq.Put(myCppCred->m_keyBuf->GetBuffer(),myCppCred->m_keyBuf->GetLength());
00644 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> myPriv;
00645 myPriv.BERDecode(privq);
00646
00647 bool kaResult = false;
00648 CryptoPP::ECDH<CryptoPP::ECP>::Domain * ecdh = 0;
00649
00650 if(*kaOID == *g_ecdh_std_sha256kdf || *kaOID == *g_ecdh_std_sha384kdf) {
00651
00652 ecdh = new CryptoPP::ECDH<CryptoPP::ECP>::Domain(myPriv.GetGroupParameters());
00653
00654 } else {
00655 RAISE_CRYPTO_EXCEPTION("Unsupported key agreement scheme",thisComponent,PKIF_CRYPTOPP_UNSUPPORTED_ALG,this);
00656 }
00657
00658
00659
00660 if(!ecdh) {
00661 RAISE_CRYPTO_EXCEPTION("Unable to initialize ECDH key agreement", thisComponent, COMMON_UNKNOWN_ERROR, this);
00662 }
00663 CPKIFCryptoPPKAContextPtr kaCtx(new CPKIFCryptoPPKAContext());
00664 kaCtx->SetOwner(this);
00665 kaCtx->SetAlgorithm(alg);
00666 CPKIFBufferPtr sharedSecret(new CPKIFBuffer());
00667 unsigned char* ss = sharedSecret->AllocateBuffer(ecdh->AgreedValueLength());
00668 CryptoPP::SecByteBlock myExp;
00669 GetPrivateExponent(myExp,myPriv);
00670
00671
00672 kaResult = ecdh->Agree(ss, myExp, theirPubInteger);
00673
00674 if(!kaResult) {
00675
00676
00677
00678
00679 RAISE_CRYPTO_EXCEPTION("Unable to complete key agreement operation", thisComponent, PKIF_CRYPTOPP_INVALID_KEY_AGREEMENT, this);
00680 }
00681
00682 kaCtx->SetSecret(sharedSecret);
00683 return dynamic_pointer_cast<IPKIFKeyAgreeContext,CPKIFCryptoPPKAContext>(kaCtx);
00684 }
00685
00686
00701
00702
00703 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00705 const CPKIFCredentialPtr& myPrivateKey,
00707 CPKIFCredentialPtr & ephemeralKeyPair,
00709 const CPKIFCertificatePtr& theirCert,
00711 const CPKIFAlgorithm * alg)
00712 {
00713 CPKIFCryptoPPKeyMaterialPtr km(new CPKIFCryptoPPKeyMaterial(*theirCert));
00714 CPKIFBufferPtr rawKey = km->GetRawSPKI();
00715 return SecretAgree(myPrivateKey, ephemeralKeyPair, rawKey, alg);
00716 }
00717
00735
00736
00737 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00739 const CPKIFCredentialPtr& myPrivateKey,
00741 CPKIFCredentialPtr & ephemeralKeyPair,
00743 const CPKIFBufferPtr& theirPublicKey,
00745 const CPKIFAlgorithm * alg)
00746 {
00747 CPKIFOIDPtr kaOID = alg->OID();
00748 if(*kaOID != *g_ecmqv_sha1kdf) {
00749 RAISE_CRYPTO_EXCEPTION("Crypto++ SecretAgree() called with an unsupported algorithm",
00750 thisComponent,CRYPTO_ALG_NOT_SUPPORTED,this);
00751 }
00752
00753 CPKIFCryptoPPCredentialPtr myCppCred = dynamic_pointer_cast<CPKIFCryptoPPCredential, CPKIFCredential>(myPrivateKey);
00754 if(!myCppCred) {
00755 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-Crypto++ credential",
00756 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00757 }
00758
00759
00760
00761 CryptoPP::ByteQueue privq;
00762 privq.Put(myCppCred->m_keyBuf->GetBuffer(),myCppCred->m_keyBuf->GetLength());
00763 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> myPriv;
00764 myPriv.BERDecode(privq);
00765
00766
00767 CPKIFCryptoPPCredentialPtr ephemCppCred;
00768 if(!ephemeralKeyPair) {
00769 CryptoPP::AutoSeededRandomPool rng;
00770 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> ephemeralPriv;
00771
00772 ephemeralPriv.Initialize(rng,myPriv.GetGroupParameters());
00773 CryptoPP::ByteQueue ephemq;
00774 ephemeralPriv.DEREncode(ephemq);
00775 CPKIFCryptoPPCredential * ephemeralCred = new CPKIFCryptoPPCredential();
00776 ephemeralCred->SetAlgorithm(myCppCred->GetAlgorithm());
00777 CPKIFBufferPtr keyBuf(new CPKIFBuffer());
00778
00779 unsigned char * keyBufRaw = keyBuf->AllocateBuffer((int)ephemq.MaxRetrievable());
00780 ephemq.Get(keyBufRaw,keyBuf->GetLength());
00781 ephemeralCred->SetPrivateKey(keyBuf);
00782 ephemCppCred = CPKIFCryptoPPCredentialPtr(ephemeralCred);
00783
00784 ephemeralKeyPair = dynamic_pointer_cast<CPKIFCredential, CPKIFCryptoPPCredential>(ephemCppCred);
00785 } else {
00786 ephemCppCred = dynamic_pointer_cast<CPKIFCryptoPPCredential, CPKIFCredential>(ephemeralKeyPair);
00787 }
00788 if(!ephemCppCred) {
00789 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-Crypto++ credential",
00790 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00791 }
00792
00793
00794 CryptoPP::ByteQueue ephemq;
00795 ephemq.Put(ephemCppCred->m_keyBuf->GetBuffer(),ephemCppCred->m_keyBuf->GetLength());
00796 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> ephemPriv;
00797 try {
00798 ephemPriv.BERDecode(ephemq);
00799 } catch(CryptoPP::BERDecodeErr &){
00800 RAISE_CRYPTO_EXCEPTION("Unable to decode ephemeral keypair for MQV",thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00801 }
00802
00803 CryptoPP::SecByteBlock myprivbb;
00804 GetPrivateExponent(myprivbb,myPriv);
00805
00806
00807 CryptoPP::SecByteBlock theirPubInteger;
00808 CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> theirPubTmp;
00809 CryptoPP::ByteQueue pubq;
00810
00811 try {
00812 pubq.Put(theirPublicKey->GetBuffer(),theirPublicKey->GetLength());
00813 theirPubTmp.BERDecode(pubq);
00814 GetEncodedPublicKey(theirPubInteger,theirPubTmp);
00815 } catch(CryptoPP::Exception &) {
00816 theirPubInteger.New(theirPublicKey->GetLength());
00817 memcpy(theirPubInteger,theirPublicKey->GetBuffer(),theirPublicKey->GetLength());
00818 }
00819
00820
00821
00822 CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> ephemPub;
00823 ephemPriv.MakePublicKey(ephemPub);
00824
00825 CryptoPP::SecByteBlock eprivbb;
00826 CryptoPP::SecByteBlock epubbb;
00827 CryptoPP::SecByteBlock econcat;
00828
00829
00830
00831 GetPrivateExponent(eprivbb,ephemPriv);
00832 GetEncodedPublicKey(epubbb,ephemPub);
00833 econcat.New(eprivbb.m_size+epubbb.m_size);
00834 memcpy(econcat,eprivbb,eprivbb.m_size);
00835 memcpy(econcat+eprivbb.m_size,epubbb,epubbb.m_size);
00836
00837 CryptoPP::ECMQV<CryptoPP::ECP>::Domain ecmqv(myPriv.GetGroupParameters());
00838 CPKIFCryptoPPKAContextPtr ctx(new CPKIFCryptoPPKAContext());
00839 ctx->SetOwner(this);
00840 ctx->SetAlgorithm(alg);
00841 CPKIFBufferPtr sharedSecret(new CPKIFBuffer());
00842 unsigned char* ss = sharedSecret->AllocateBuffer(ecmqv.AgreedValueLength());
00843 bool kaResult = ecmqv.Agree(ss,myprivbb,econcat,theirPubInteger,theirPubInteger);
00844
00845 if(!kaResult) {
00846
00847
00848
00849
00850 RAISE_CRYPTO_EXCEPTION("Unable to complete key agreement operation", thisComponent, PKIF_CRYPTOPP_INVALID_KEY_AGREEMENT, this);
00851 }
00852 ctx->SetSecret(sharedSecret);
00853 return dynamic_pointer_cast<IPKIFKeyAgreeContext,CPKIFCryptoPPKAContext>(ctx);
00854
00855 }
00856
00857
00858
00874 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00876 const CPKIFCredentialPtr& myPrivateKey,
00879 const CPKIFBufferPtr& ephemeralPublicKey,
00881 const CPKIFCertificatePtr& theirCert,
00883 const CPKIFAlgorithm * alg)
00884 {
00885 CPKIFCryptoPPKeyMaterialPtr km(new CPKIFCryptoPPKeyMaterial(*theirCert));
00886 CPKIFBufferPtr rawKey = km->GetRawSPKI();
00887 return SecretAgree(myPrivateKey, ephemeralPublicKey, rawKey, alg);
00888 }
00889
00908 IPKIFKeyAgreeContextPtr CPKIFCryptoPP::SecretAgree(
00910 const CPKIFCredentialPtr& myPrivateKey,
00913 const CPKIFBufferPtr& ephemeralPublicKey,
00915 const CPKIFBufferPtr& theirPublicKey,
00917 const CPKIFAlgorithm * alg)
00918 {
00919 CPKIFOIDPtr kaOID = alg->OID();
00920 if(*kaOID != *g_ecmqv_sha1kdf) {
00921 RAISE_CRYPTO_EXCEPTION("Crypto++ KeyAgreement() called with an unsupported algorithm",
00922 thisComponent,CRYPTO_ALG_NOT_SUPPORTED,this);
00923 }
00924 CPKIFCryptoPPCredentialPtr myCppCred = dynamic_pointer_cast<CPKIFCryptoPPCredential, CPKIFCredential>(myPrivateKey);
00925 if(!myCppCred) {
00926 RAISE_CRYPTO_EXCEPTION("Crypto++ Crypto colleague was given a non-Crypto++ credential",
00927 thisComponent,CRYPTO_UNRECOGNIZED_CREDENTIAL,this);
00928 }
00929 CryptoPP::ByteQueue privq;
00930 privq.Put(myCppCred->m_keyBuf->GetBuffer(),myCppCred->m_keyBuf->GetLength());
00931 CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> myPriv;
00932 myPriv.BERDecode(privq);
00933 CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> myPub;
00934 myPriv.MakePublicKey(myPub);
00935
00936 CryptoPP::SecByteBlock epbb(ephemeralPublicKey->GetLength());
00937 memcpy(epbb, ephemeralPublicKey->GetBuffer(), ephemeralPublicKey->GetLength());
00938
00939
00940
00941
00942 CryptoPP::SecByteBlock myprivbb;
00943 GetPrivateExponent(myprivbb,myPriv);
00944
00945 CryptoPP::SecByteBlock mypubbb;
00946 GetEncodedPublicKey(mypubbb,myPub);
00947
00948
00949 CryptoPP::SecByteBlock theirPubInteger;
00950 CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> theirPubTmp;
00951 CryptoPP::ByteQueue pubq;
00952
00953 try {
00954 pubq.Put(theirPublicKey->GetBuffer(),theirPublicKey->GetLength());
00955 theirPubTmp.BERDecode(pubq);
00956 GetEncodedPublicKey(theirPubInteger,theirPubTmp);
00957 } catch(CryptoPP::Exception &) {
00958 theirPubInteger.New(theirPublicKey->GetLength());
00959 memcpy(theirPubInteger,theirPublicKey->GetBuffer(),theirPublicKey->GetLength());
00960 }
00961
00962 CryptoPP::SecByteBlock myconcat;
00963
00964
00965
00966 myconcat.New(myprivbb.m_size+mypubbb.m_size);
00967 memcpy(myconcat,myprivbb,myprivbb.m_size);
00968 memcpy(myconcat+myprivbb.m_size,mypubbb,mypubbb.m_size);
00969
00970 CryptoPP::ECMQV<CryptoPP::ECP>::Domain ecmqv(myPriv.GetGroupParameters());
00971 CPKIFCryptoPPKAContextPtr ctx(new CPKIFCryptoPPKAContext());
00972 ctx->SetOwner(this);
00973 ctx->SetAlgorithm(alg);
00974 CPKIFBufferPtr sharedSecret(new CPKIFBuffer());
00975 unsigned char* ss = sharedSecret->AllocateBuffer(ecmqv.AgreedValueLength());
00976 bool kaResult = ecmqv.Agree(ss,myprivbb,myconcat,theirPubInteger,epbb);
00977
00978 if(!kaResult) {
00979
00980
00981
00982
00983 RAISE_CRYPTO_EXCEPTION("Unable to complete key agreement operation", thisComponent, PKIF_CRYPTOPP_INVALID_KEY_AGREEMENT, this);
00984 }
00985 ctx->SetSecret(sharedSecret);
00986 return dynamic_pointer_cast<IPKIFKeyAgreeContext,CPKIFCryptoPPKAContext>(ctx);
00987 }
00988
00989
01000 CPKIFKeyMaterialPtr CPKIFCryptoPP::DeriveKey(
01002 const IPKIFKeyAgreeContextPtr & context,
01004 unsigned long keyLen
01005 )
01006 {
01007 const CPKIFAlgorithm * kaAlg = context->GetAlgorithm();
01008 CPKIFOIDPtr kaOID = kaAlg->OID();
01009 if( *kaOID != *g_ecdh_std_sha256kdf &&
01010 *kaOID != *g_ecdh_std_sha384kdf )
01011 {
01012 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with an invalid algorithm",
01013 thisComponent,COMMON_INVALID_INPUT,this);
01014 }
01015 CPKIFCryptoPPKAContextPtr cppCtx = dynamic_pointer_cast<CPKIFCryptoPPKAContext,IPKIFKeyAgreeContext>(context);
01016 if(!cppCtx) {
01017 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with an invalid context",
01018 thisComponent,COMMON_INVALID_INPUT,this);
01019 }
01020
01021 unsigned long digestSize = 0;
01022 try {
01023 digestSize = boost::numeric_cast<unsigned long,int>(kaAlg->DigestSize());
01024 }catch(...){
01025 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with an invalid algorithm parameter",
01026 thisComponent,COMMON_INVALID_INPUT,this);
01027 }
01028
01029
01030 CPKIFBufferList appendedBuffers = context->GetAppendedSharedInfo();
01031 if(appendedBuffers.size() != 1) {
01032 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with invalid shared info input",
01033 thisComponent,COMMON_INVALID_INPUT,this);
01034 }
01035 CPKIFBufferList prependedBuffers = context->GetPrependedSharedInfo();
01036 if(prependedBuffers.size() != 0) {
01037 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with invalid shared info input",
01038 thisComponent,COMMON_INVALID_INPUT,this);
01039 }
01040 CPKIFBufferPtr sharedInfo = appendedBuffers[0];
01041
01042
01043 CACASNWRAPPER_CREATE(ECC_CMS_SharedInfo,ecsPDU);
01044
01045
01046
01047
01048 if(0 == keyLen) {
01049 ECC_CMS_SharedInfo * ecsi = ecsPDU.Decode(sharedInfo->GetBuffer(),sharedInfo->GetLength());
01050 if(!ecsi) throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "keyLen is invalid and not in sharedInfo.");
01051 u_long nwKeySize32;
01052 if(ecsi->suppPubInfo.numocts > sizeof(u_long)) throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "sharedInfo is invalid.");
01053 memcpy(&nwKeySize32,ecsi->suppPubInfo.data,ecsi->suppPubInfo.numocts);
01054 u_long keySize32 = ntohl(nwKeySize32);
01055 keyLen = keySize32;
01056 }
01057
01058 if(keyLen > digestSize || keyLen <= 0) {
01059 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with invalid parameters",
01060 thisComponent,COMMON_INVALID_INPUT,this);
01061 }
01062
01063 CryptoPP::HashTransformation * sha = 0;
01064
01065 switch(kaAlg->HashAlg())
01066 {
01067 case PKIFCRYPTO::SHA256:
01068 sha = new CryptoPP::SHA256;
01069 break;
01070 case PKIFCRYPTO::SHA384:
01071 sha = new CryptoPP::SHA384;
01072 break;
01073 default:
01074
01075 break;
01076 }
01077
01078 boost::scoped_ptr<CryptoPP::HashTransformation> pSha(sha);
01079 if(!pSha) {
01080 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPP::DeriveKey() called with incompatible digest",
01081 thisComponent,COMMON_INVALID_INPUT,this);
01082 }
01083
01084
01085 unsigned char counter[4] = {0x00,0x00,0x00,0x01};
01086 CPKIFBufferPtr secret = cppCtx->GetSecret();
01087 pSha->Update(secret->GetBuffer(),secret->GetLength());
01088 pSha->Update(counter,4);
01089 pSha->Update(sharedInfo->GetBuffer(),sharedInfo->GetLength());
01090 unsigned int digestLen = sha->DigestSize();
01091
01092 CryptoPP::SecByteBlock tmpKey;
01093 tmpKey.New(digestLen);
01094 pSha->Final(tmpKey);
01095 CPKIFCryptoPPKeyMaterialPtr cppKM(new CPKIFCryptoPPKeyMaterial());
01096 cppKM->SetKeyAlg(kaAlg);
01097
01098 cppKM->SetSymmetricKey(tmpKey,keyLen);
01099 return dynamic_pointer_cast<CPKIFKeyMaterial,CPKIFCryptoPPKeyMaterial>(cppKM);
01100 }