00001
00010 #include "PKIFCryptoPPUtils.h"
00011 #include "PKIFCryptoPPKeyMaterial.h"
00012 #include "PKIFCryptoPPCredential.h"
00013
00014 #include "FileUtils.h"
00015 #include "PKIFBase64.h"
00016 #include "Buffer.h"
00017 #include "OID.h"
00018 #include "PKIFMemoryUtils.h"
00019
00020 #include "PKIFCredential.h"
00021 #include "PKIFKeyMaterial.h"
00022 #include "SubjectPublicKeyInfo.h"
00023 #include "Certificate.h"
00024
00025 #include "ASN1Helper.h"
00026 #include "PKIX1Explicit88.h"
00027 #include "ECC-CMS.h"
00028
00029 #include "PKIFAlgorithm.h"
00030
00031 #if defined(WIN32) || defined(_WIN32)
00032 #include <Winsock2.h>
00033 #endif
00034
00035 #if !defined(_WIN32)
00036 #include <netinet/in.h>
00037 #endif
00038
00039 #include "boost/filesystem/path.hpp"
00040 #include "boost/filesystem/operations.hpp"
00041 #include "boost/filesystem/fstream.hpp"
00042 #include "boost/scoped_ptr.hpp"
00043 #include <iostream>
00044 #include <sstream>
00045
00046 #include "boost/numeric/conversion/cast.hpp"
00047 #include "boost/numeric/conversion/bounds.hpp"
00048 #include "boost/limits.hpp"
00049
00050 #include "cryptlib.h"
00051 #include "queue.h"
00052 #include "asn.h"
00053 #include "sha.h"
00054
00055 #include <iostream>
00056 #include <strstream>
00057
00058
00059 using boost::numeric_cast;
00060 using boost::bad_numeric_cast;
00061
00062 using namespace std;
00063 namespace fs = boost::filesystem;
00064
00065 using namespace CryptoPP;
00066
00067 using namespace boost;
00068
00076 CPKIFBufferPtr GetTBSCertSequence(
00078 const CPKIFCertificate & cert)
00079 {
00080 CPKIFBufferPtr wholeCert = cert.Encoded();
00081 ByteQueue certReader, tbsCertWriter;
00082 certReader.Put(wholeCert->GetBuffer(),wholeCert->GetLength());
00083 BERSequenceDecoder x509Cert(certReader);
00084 BERSequenceDecoder tbsCert(x509Cert);
00085 DERSequenceEncoder tbsCertEnc(tbsCertWriter);
00086 tbsCert.CopyTo(tbsCertEnc);
00087 tbsCertEnc.MessageEnd();
00088 unsigned char * tbsCertBuf = 0;
00089
00090 unsigned long size = 0;
00091 try
00092 {
00093 size = numeric_cast<unsigned long>(tbsCertWriter.MaxRetrievable());
00094 }
00095 catch(bad_numeric_cast &)
00096 {
00097 throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "Cert size is an impossibly long number.");
00098 }
00099 unsigned long tbsCertSize = size;
00100 tbsCertBuf = new unsigned char[tbsCertSize];
00101 tbsCertWriter.Get(tbsCertBuf,tbsCertSize);
00102 CPKIFBufferPtr tbsOut(new CPKIFBuffer(true,tbsCertBuf,tbsCertSize));
00103 return tbsOut;
00104 }
00112 CPKIFCredentialPtr _MakeCredentialFromP8File(
00114 const std::string & file)
00115 {
00116
00117
00118
00119 CPKIFCredentialPtr rv((CPKIFCredential *)0);
00120 CPKIFBufferPtr filebuf = ReadFileIntoBuffer(file);
00121 unsigned char * derdata = 0;
00122 unsigned long derlen = 0;
00123 bool dataWasPEM = false;
00124
00125 if(filebuf->GetBuffer()[0] == '-') {
00126
00127 char * bufstr = new char[filebuf->GetLength()+1];
00128 memcpy(bufstr,filebuf->GetBuffer(),filebuf->GetLength());
00129 bufstr[filebuf->GetLength()] = 0;
00130 if(!PEMDecode_l(bufstr,filebuf->GetLength(),&derdata,&derlen)) {
00131 delete[] bufstr;
00132
00133 return rv;
00134 }
00135 dataWasPEM = true;
00136 delete[] bufstr;
00137 } else {
00138 derdata = const_cast<unsigned char *>(filebuf->GetBuffer());
00139 derlen = filebuf->GetLength();
00140 }
00141
00142
00143
00144 ByteQueue keyReader;
00145 keyReader.Put(derdata,derlen);
00146 BERSequenceDecoder privateKeyInfo(keyReader);
00147 word32 version;
00148 BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0);
00149 OID pkOID;
00150 BERSequenceDecoder algorithm(privateKeyInfo);
00151 pkOID.BERDecode(algorithm);
00152
00153 int size = 0;
00154 try
00155 {
00156 size = numeric_cast<int>(pkOID.m_values.size());
00157 }
00158 catch(bad_numeric_cast &)
00159 {
00160 throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "Size is an impossibly long number.");
00161 }
00162
00163 int ncomps = size;
00164 ostringstream os;
00165 for(int i = 0; i < ncomps; ++i)
00166 {
00167 os << pkOID.m_values[i];
00168 if(i != ncomps - 1) os << ".";
00169 }
00170 string oidStr = os.str();
00171 CPKIFOIDPtr keyOID(new CPKIFOID(oidStr));
00172 CPKIFAlgorithm * keyAlg = CPKIFAlgorithm::GetAlg(keyOID);
00173
00174 if(!keyAlg) {
00175 if(dataWasPEM) {
00176 PKIFZero(derdata,derlen);
00177 delete[] derdata;
00178 }
00179 return rv;
00180 }
00181
00182
00183 CPKIFCryptoPPCredentialPtr credOut(new CPKIFCryptoPPCredential());
00184 CPKIFBufferPtr keyBuf(new CPKIFBuffer(derdata,derlen));
00185 credOut->SetPrivateKey(keyBuf);
00186 credOut->SetAlgorithm(keyAlg);
00187 rv = dynamic_pointer_cast<CPKIFCredential,CPKIFCryptoPPCredential>(credOut);
00188 if(dataWasPEM) {
00189 PKIFZero(derdata,derlen);
00190 delete[] derdata;
00191 }
00192 return rv;
00193 }
00194
00206 CPKIFCredentialPtr MakeCredentialFromP8File(
00208 const std::string & file)
00209 {
00210 return _MakeCredentialFromP8File(file);
00211 }
00223 CPKIFCredentialPtr MakeCredentialFromP8File(const std::string & file, const std::string & certFile )
00224 {
00225 CPKIFCredentialPtr cred = _MakeCredentialFromP8File(file);
00226 if(cred != (CPKIFCredential*)NULL)
00227 {
00228 CPKIFBufferPtr filebuf = ReadFileIntoBuffer(certFile);
00229 unsigned char * derdata = 0;
00230 unsigned long derlen = 0;
00231 bool dataWasPEM = false;
00232
00233 if(filebuf->GetBuffer()[0] == '-') {
00234
00235 char * bufstr = new char[filebuf->GetLength()+1];
00236 memcpy(bufstr,filebuf->GetBuffer(),filebuf->GetLength());
00237 bufstr[filebuf->GetLength()] = 0;
00238 if(!PEMDecode_l(bufstr,filebuf->GetLength(),&derdata,&derlen)) {
00239 delete[] bufstr;
00240
00241 return cred;
00242 }
00243 dataWasPEM = true;
00244 delete[] bufstr;
00245 } else {
00246 derdata = const_cast<unsigned char *>(filebuf->GetBuffer());
00247 derlen = filebuf->GetLength();
00248 }
00249
00250 CPKIFCertificatePtr cert(new CPKIFCertificate);
00251 cert->Decode(derdata, derlen);
00252
00253 CPKIFCryptoPPCredentialPtr cppCred = dynamic_pointer_cast<CPKIFCryptoPPCredential, CPKIFCredential>(cred);
00254 cppCred->SetCertificate(cert);
00255 }
00256 return cred;
00257 }
00258
00267 CPKIFBufferPtr GetEncodedSPKIFromKM(const CPKIFKeyMaterial & km)
00268 {
00269 CPKIFCryptoPPKeyMaterialPtr cppKM(new CPKIFCryptoPPKeyMaterial(km));
00270 CPKIFBufferPtr rv = cppKM->GetRawSPKI();
00271 return rv;
00272 }
00273
00283 CPKIFBufferPtr DeriveKeyFromSecret(
00285 const CPKIFBufferPtr & secret,
00287 const CPKIFBufferPtr & sharedInfo,
00290 unsigned int keyLength)
00291 {
00292 CPKIFBufferPtr rv;
00293
00294 CACASNWRAPPER_CREATE(ECC_CMS_SharedInfo,ecsPDU);
00295
00296 unsigned long derivedKeyLen = keyLength;
00297
00298
00299 if(0 == derivedKeyLen) {
00300 ECC_CMS_SharedInfo * ecsi = ecsPDU.Decode(sharedInfo->GetBuffer(),sharedInfo->GetLength());
00301 if(!ecsi) throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "sharedInfo is invalid.");
00302 u_long nwKeySize32;
00303 if(ecsi->suppPubInfo.numocts > sizeof(u_long)) throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "sharedInfo is invalid.");
00304 memcpy(&nwKeySize32,ecsi->suppPubInfo.data,ecsi->suppPubInfo.numocts);
00305 u_long keySize32 = ntohl(nwKeySize32);
00306 derivedKeyLen = keySize32;
00307 }
00308
00309 CryptoPP::HashTransformation * sha = 0;
00310
00311
00312
00313
00314 if(derivedKeyLen <= 16) {
00315 sha = new CryptoPP::SHA256();
00316 } else {
00317 sha = new CryptoPP::SHA384();
00318 }
00319 boost::scoped_ptr<CryptoPP::HashTransformation> pSha(sha);
00320
00321 if(!pSha) throw std::runtime_error(string("Internal error: unable to instantiate hash object for key derivation"));
00322
00323
00324 unsigned char counter[4] = {0x00,0x00,0x00,0x01};
00325
00326 pSha->Update(secret->GetBuffer(),secret->GetLength());
00327 pSha->Update(counter,4);
00328 pSha->Update(sharedInfo->GetBuffer(),sharedInfo->GetLength());
00329 unsigned int digestLen = sha->DigestSize();
00330 unsigned char * temp = new unsigned char[digestLen];
00331 try {
00332 pSha->Final(temp);
00333 }catch(std::exception & e){
00334 delete[] temp;
00335 throw e;
00336 }
00337 rv = CPKIFBufferPtr(new CPKIFBuffer(true,temp,digestLen));
00338 return rv;
00339 }