PKIFNSSRaw.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFNSSRaw.h"
00010 #include "PKIFNSSRawCryptContext.h"
00011 #include "PKIFNSSHashContext.h"
00012 
00013 #include "PKIFCryptoException.h"
00014 #include "PKIFKeyMaterial.h"
00015 #include "PKIFCryptoPPKeyMaterial.h"
00016 #include "PKIFAlgorithm.h"
00017 
00018 #include "ToolkitUtils.h"
00019 #include "PKIFNSSErrors.h"
00020 #include "PKIFNSSDatabase.h"
00021 #include "PKIFCryptoErrors.h"
00022 #include "Certificate.h"
00023 #include "Buffer.h"
00024 
00025 #include <sstream>
00026 
00027 #include "PKIFNSSConfig.h"
00028 #include "PKIFNSSUtils.h"
00029 #include "nspr.h"
00030 
00031 using namespace std;
00032 
00033 static CK_MECHANISM_TYPE CipherMechForKey(const CPKIFKeyMaterial &key, bool pad = false);
00034 template<bool _CryptDirection>
00035 static void _ASymCrypt(const CPKIFKeyMaterial& key, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool pad = true);
00036 
00037 
00039 struct CPKIFNSSRawImpl
00040 {
00041     string m_dbdir;
00042 };
00044 
00046 
00053 CK_MECHANISM_TYPE CipherMechForKey(
00055     const CPKIFKeyMaterial &key, 
00057     bool pad)
00058 {
00059     switch(key.GetSymmetricKeyAlgorithm())
00060     {
00061     case PKIFCRYPTO::TDES:
00062         switch(key.GetMode())
00063         {
00064         case PKIFCRYPTO::ECB:
00065             return CKM_DES3_ECB;
00066             break;
00067         case PKIFCRYPTO::CBC:
00068             return pad ? CKM_DES3_CBC_PAD : CKM_DES3_CBC;
00069             break;
00070         default:
00071             break;
00072         }
00073         break;
00074     case PKIFCRYPTO::DES:
00075         switch(key.GetMode())
00076         {
00077         case PKIFCRYPTO::ECB:
00078             return CKM_DES_ECB;
00079             break;
00080         case PKIFCRYPTO::CBC:
00081             return pad ? CKM_DES_CBC_PAD : CKM_DES_CBC;
00082             break;
00083         default:
00084             break;
00085         }
00086         break;
00087     case PKIFCRYPTO::AES:
00088     case PKIFCRYPTO::AES128:
00089     case PKIFCRYPTO::AES192:
00090     case PKIFCRYPTO::AES256:
00091         switch(key.GetMode())
00092         {
00093         case PKIFCRYPTO::ECB:
00094             return CKM_AES_ECB;
00095             break;
00096         case PKIFCRYPTO::CBC:
00097             return pad ? CKM_AES_CBC_PAD : CKM_AES_CBC;
00098             break;
00099         default:
00100             break;
00101         }
00102         break;
00103     default:
00104         break;
00105     }
00106     RAISE_CRYPTO_EXCEPTION("Unsupported algorithm and mode combination", TOOLKIT_CRYPTO_NSSRAW, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00107     // avoid warnings on certain compilers
00108     return CKM_VENDOR_DEFINED;
00109 }
00110 
00111 
00122 static SECOidTag NSSPKAlg(PKIFCRYPTO::ASYMKEY_ALG alg)
00123 {
00124     switch(alg)
00125     {
00126         case PKIFCRYPTO::RSA:
00127             return SEC_OID_PKCS1_RSA_ENCRYPTION;
00128             break;
00129         case PKIFCRYPTO::DSS:
00130             return SEC_OID_ANSIX9_DSA_SIGNATURE;
00131             break;
00132         case PKIFCRYPTO::ECC:
00133             return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
00134             break;
00135     }
00136     return SEC_OID_UNKNOWN;
00137 }
00138 
00149 static SECOidTag NSSSigAlg(PKIFCRYPTO::ASYMKEY_ALG alg, PKIFCRYPTO::HASH_ALG ha)
00150 {
00151     switch(alg)
00152     {
00153         case PKIFCRYPTO::RSA:
00154             return SEC_OID_PKCS1_RSA_ENCRYPTION;
00155             break;
00156         case PKIFCRYPTO::DSS: // we only support "normal" DSA with NSS
00157             return SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00158             break;
00159         case PKIFCRYPTO::ECC:   // remember, only use with VFY_VerifyDigest right now.
00160                     // Revisit this when ECC support is introduced for this colleague.
00161             return SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST;
00162             break;
00163     }
00164     return SEC_OID_UNKNOWN;
00165 }
00166 
00167 
00179 CPKIFNSSRaw::CPKIFNSSRaw(
00181     const std::string & dbdir)
00182     :m_impl(new CPKIFNSSRawImpl)
00183 {
00184     LOG_STRING_DEBUG("CPKIFNSSRaw::CPKIFNSSRaw(void)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00185     m_impl->m_dbdir = dbdir;
00186 }
00194 CPKIFNSSRaw::~CPKIFNSSRaw(void)
00195 {
00196     LOG_STRING_DEBUG("CPKIFNSSRaw::~CPKIFNSSRaw(void)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00197     if(!m_impl) {
00198         delete m_impl;
00199         m_impl = 0;
00200     }
00201 }
00209 void CPKIFNSSRaw::Initialize()
00210 {
00211     LOG_STRING_DEBUG("CPKIFNSSRaw::Initialize()", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00212     if(m_impl->m_dbdir == "")
00213         CPKIFNSSDatabase * db = CPKIFNSSDatabase::GetInstance();
00214     else
00215         CPKIFNSSDatabase * db = CPKIFNSSDatabase::GetInstance(m_impl->m_dbdir);
00216 }
00228 bool CPKIFNSSRaw::SupportsAlgorithm(
00230     const CPKIFKeyMaterial& key)
00231 {
00232     LOG_STRING_DEBUG("CPKIFNSSRaw::SupportsAlgorithm(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00233     if(key.ContainsSymmetricKeyMaterial())
00234     {   
00235         try
00236         {
00237             if (CKM_VENDOR_DEFINED != CipherMechForKey(key)) return true;
00238         }
00239         catch(CPKIFCryptoException& e)
00240         {
00241             if(CRYPTO_ALG_NOT_SUPPORTED == e.GetErrorCode())
00242             {
00243                 //EXCEPTION DELETION
00244                 //The GetSymAlgorithm function throws upon failure but
00245                 //this function should return false.
00246                 //delete e;
00247                 return false;
00248             }
00249             else
00250                 throw e; //should never happen
00251         }
00252     }
00253     else if(key.ContainsCertificate())
00254     {
00255         SECItem encCert;
00256         // this is safe since the encoded cert never gets modified on import
00257         encCert.data = const_cast< unsigned char *>(key.GetCertificate());
00258         encCert.len = key.GetCertificateLength();
00259         encCert.type = siBuffer;
00260         SECItem * encCerts[1];
00261         encCerts[0] = &encCert;
00262         
00263         // an array of CERTCertificate pointers that will hold the one decoded object
00264         // XXX Responsibility for freeing this is undocumented in NSS.
00265         // XXX TODO: Make sure we free it if needed
00266         CERTCertificate ** cert = NULL;
00267 
00268         // Import certs into a temporary NSS database
00269         SECStatus rv = CERT_ImportCerts(CERT_GetDefaultCertDB(),certUsageUserCertImport,
00270             1,encCerts,&cert,PR_FALSE,PR_FALSE,NULL);
00271 
00272         if(rv != SECSuccess || !cert || !cert[0])
00273         {
00274             if(cert) PR_Free(cert);
00275             std::ostringstream os;
00276             os << "CERT_ImportCerts failed: "; // XXX TODO: Find NSS Equivalent << GetLastError();
00277             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_CERT_IMPORT_FAILED, this)
00278         }
00279 
00280         SECAlgorithmID alg = cert[0]->subjectPublicKeyInfo.algorithm;
00281         SECOidTag oid = SECOID_GetAlgorithmTag(&alg);
00282         CERT_DestroyCertificate(cert[0]);
00283         PR_Free(cert);
00284         switch(oid) {
00285             // XXX TODO REVIEW: Double check OID constants here
00286                 case SEC_OID_PKCS1_RSA_ENCRYPTION:
00287                 case SEC_OID_ANSIX9_DSA_SIGNATURE:
00288                 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
00289                     return true;
00290                     break;
00291                 default:
00292                     return false;
00293                     break;
00294         }
00295 
00296     }
00297     else
00298     {
00299         RAISE_CRYPTO_EXCEPTION("key parameter contents not recognized.", thisComponent, COMMON_INVALID_INPUT, this);
00300     }
00301     return false;
00302 }
00313 void CPKIFNSSRaw::Sign(
00315     const CPKIFKeyMaterial& key,
00317     unsigned char* pHashData, 
00319     int nHashDataLen, 
00321     unsigned char* pSignature, 
00324     int* nSignatureLen,
00326     PKIFCRYPTO::HASH_ALG hashAlg
00327     )
00328 {
00329     LOG_STRING_DEBUG("CPKIFNSSRaw::Sign(const CPKIFKeyMaterial& key,...)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00330     // Don't do raw signature generation since we don't have a way of slinging raw private keys around
00331     RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented for raw key material.", thisComponent, COMMON_NOT_IMPLEMENTED, this);
00332 }
00333 
00341 void CPKIFNSSRaw::Decrypt(  
00343     const CPKIFKeyMaterial& key,
00345     unsigned char* pData, 
00347     int nDataLen, 
00349     unsigned char* pResult, 
00352     int* pnResultLen, 
00356     bool pad)
00357 {
00358     if(key.ContainsSymmetricKeyMaterial()) {
00359         CPKIFNSSRawCryptContext * ctx = static_cast<CPKIFNSSRawCryptContext *>(this->CryptInit(key,pad));
00360         try {
00361             Decrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00362         } catch(...) {
00363             delete ctx;
00364             throw;
00365         }
00366         delete ctx;
00367     } else {
00368         _ASymCrypt<false>(key, pData, nDataLen, pResult, pnResultLen, pad);
00369     }
00370 }
00378 void CPKIFNSSRaw::Encrypt(
00380     const CPKIFKeyMaterial& key,
00382     unsigned char* pData, 
00384     int nDataLen, 
00386     unsigned char* pResult, 
00389     int* pnResultLen, 
00393     bool pad)
00394 {
00395     if(key.ContainsSymmetricKeyMaterial()) {
00396         CPKIFNSSRawCryptContext * ctx = static_cast<CPKIFNSSRawCryptContext *>(this->CryptInit(key,pad));
00397         try {
00398             Encrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00399         } catch(...) {
00400             delete ctx;
00401             throw;
00402         }
00403         delete ctx;
00404     } else {
00405         _ASymCrypt<true>(key, pData, nDataLen, pResult, pnResultLen, pad);
00406     }
00407 }
00408 
00426 IPKIFRawCryptContext* CPKIFNSSRaw::HMACInit(const CPKIFKeyMaterial &key, PKIFCRYPTO::HASH_ALG ha)
00427 {
00428     LOG_STRING_DEBUG("CPKIFNSSRaw::HMACInit(const CPKIFKeyMaterial& key, HASH_ALG ha)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00429     // the iterative crypt functions are a bad idea with RSA or DSA keys...
00430     if(!key.ContainsSymmetricKeyMaterial())
00431     {
00432         throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, "HMACInit() only makes sense for symmetric keys.");
00433     }
00434     
00435     // check the hash alg before allocating anything
00436     CK_MECHANISM_TYPE hash_mech = CKM_VENDOR_DEFINED;
00437     switch(ha)
00438     {
00439     case PKIFCRYPTO::SHA1:
00440         hash_mech = CKM_SHA_1_HMAC;
00441         break;
00442 #ifndef FIPS_MODE
00443     case PKIFCRYPTO::MD5:
00444         hash_mech = CKM_MD5_HMAC;
00445         break;
00446 #endif
00447     case PKIFCRYPTO::SHA256:
00448         hash_mech = CKM_SHA256_HMAC;
00449         break;
00450     case PKIFCRYPTO::SHA384:
00451         hash_mech = CKM_SHA384_HMAC;
00452         break;
00453     case PKIFCRYPTO::SHA512:
00454         hash_mech = CKM_SHA512_HMAC;
00455         break;
00456     default:
00457         std::ostringstream os;
00458         os << "Unsupported hash algorithm encountered: " << ha;
00459         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00460     }
00461 
00462     // throw bad_alloc... nothing to cleanup
00463     CPKIFNSSRawCryptContext * ctx = new CPKIFNSSRawCryptContext();
00464 
00465     //ctx->m_mech = CipherMechForKey(key,false);
00466     ctx->m_mech = hash_mech;
00467 
00468     ctx->m_slot = PK11_GetBestSlot(ctx->m_mech,NULL);
00469     if(0 == ctx->m_slot)
00470     {
00471         delete ctx;
00472         // XXX TODO: Find and push NSS err message as well
00473         RAISE_CRYPTO_EXCEPTION("No NSS slot supports this algorithm",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_UNSUPPORTED_ALG,NULL);
00474     }
00475 
00476     SECItem keyItem;
00477     keyItem.data = const_cast<unsigned char *>(key.GetSymmetricKey());
00478     keyItem.len = key.GetSymmetricKeyLength();
00479     keyItem.type = siBuffer;
00480 
00481     // CKA_SIGN is needed for HMAC
00482     ctx->m_sk = PK11_ImportSymKey(ctx->m_slot,ctx->m_mech,PK11_OriginUnwrap,CKA_SIGN, &keyItem, NULL);
00483 
00484     if( 0 == ctx->m_sk )
00485     {
00486         delete ctx;
00487         RAISE_CRYPTO_EXCEPTION("Unable to import raw symmetric key",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_RAW_IMPORT_FAILED,NULL);
00488     }
00489 
00490     // no parameters are supplied for HMAC
00491     ctx->m_param = 0;
00492     SECItem noParams;
00493     noParams.data = 0;
00494     noParams.len = 0;
00495     noParams.type = siBuffer;
00496     ctx->m_bNeedsPad = false;
00497 
00498     ctx->m_ctx = PK11_CreateContextBySymKey(hash_mech,CKA_SIGN,ctx->m_sk,&noParams);
00499     if(!ctx->m_ctx)
00500     {
00501         delete ctx;
00502         RAISE_CRYPTO_EXCEPTION("Unable to use raw symmetric key to create HMAC context",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_RAW_IMPORT_FAILED,0);
00503     }
00504     SECStatus rv = PK11_DigestBegin(ctx->m_ctx);
00505     if(SECSuccess != rv) {
00506         delete ctx;
00507         RAISE_CRYPTO_EXCEPTION("Unable to use raw symmetric key to create HMAC context",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_RAW_IMPORT_FAILED,0);
00508     }
00509 
00510 
00511     return ctx;
00512 }
00513 
00526 void CPKIFNSSRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)
00527 {
00528     LOG_STRING_DEBUG("CPKIFNSSRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00529     //sanity check the inputs: 
00530     //  hash must not be NULL, must be of a type this class supports and must not be empty
00531     //  pData MAY be NULL (if not it is assumed to be at least nDataLen bytes)
00532     //  nDataLen must not be less than zero
00533     if(NULL == ctx || 0 > nDataLen)
00534         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HMACUpdate.");
00535 
00536     //cast the context to the type this class handles.  if the cast fails
00537     //then the context is not the correct type.
00538     CPKIFNSSRawCryptContext* hmacCtx = dynamic_cast<CPKIFNSSRawCryptContext*>(ctx);
00539     if(NULL == hmacCtx)
00540         throw CPKIFCryptoException(thisComponent, PKIFNSS_INCORRECT_HASH_CONTEXT, "Incorrect context passed to HMACUpdate.");
00541 
00542     if(NULL == hmacCtx->m_ctx)
00543         throw CPKIFCryptoException(thisComponent, PKIFNSS_EMPTY_HASH_CONTEXT, "Empty context passed to HMACUpdate.");
00544     SECStatus rv = PK11_DigestOp(hmacCtx->m_ctx,pData,nDataLen);
00545     if(SECSuccess != rv)
00546     {
00547         std::ostringstream os;
00548         os << "PK11_DigestOp failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00549         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_DIGEST_OP_FAILED, NULL);
00550     }
00551 }
00552 
00565 void CPKIFNSSRaw::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)
00566 {
00567     LOG_STRING_DEBUG("CPKIFNSSRaw::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00568 
00569     //sanity check the inputs: 
00570     //  ctx must not be NULL, must be of a type this class supports and must not be empty
00571     //  result must not be NULL (it is assumed to be at least *pnResultLen bytes)
00572     //  pnResultLen must not be NULL and *pnResultLen must not be less than or equal to zero
00573     if(NULL == ctx || NULL == pResult || NULL == pnResultLen || 0 >= *pnResultLen)
00574         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HMACFinal.");
00575 
00576     CPKIFNSSRawCryptContext* hmacCtx = dynamic_cast<CPKIFNSSRawCryptContext*>(ctx);
00577     if(NULL == hmacCtx)
00578         throw CPKIFCryptoException(thisComponent, PKIFNSS_INCORRECT_HASH_CONTEXT, "Incorrect context passed to HMACFinal().");
00579 
00580     if(NULL == hmacCtx->m_ctx)
00581         throw CPKIFCryptoException(thisComponent, PKIFNSS_EMPTY_HASH_CONTEXT, "Empty context passed to HMACFinal().");
00582 
00583     //terminate the hash and retrieve the hash value
00584     unsigned int outLen = 0;
00585     SECStatus rv = PK11_DigestFinal(hmacCtx->m_ctx,pResult,&outLen,*pnResultLen);
00586     if(SECSuccess != rv) 
00587     {
00588         std::ostringstream os;
00589         os << "PK11_DigestFinal failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00590         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_DIGEST_OP_FAILED, NULL);
00591     }
00592     // XXX TODO: bounds check before casting
00593     *pnResultLen = (int)outLen;
00594 
00595 }
00596 
00597 
00608 static bool _Verify(
00610     const CPKIFKeyMaterial& key,
00613     unsigned char* pHashData, 
00615     int nHashDataLen, 
00617     unsigned char* pSignature, 
00619     int nSignatureLen,
00621     PKIFCRYPTO::HASH_ALG hashAlg)
00622 {
00623 #undef CLEANUP
00624 #define CLEANUP \
00625 { \
00626     if (pk) \
00627     {   SECKEY_DestroyPublicKey(pk); pk = 0;    }   \
00628 } 
00629 
00630     LOG_STRING_DEBUG("_Verify(const CPKIFKeyMaterial& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_NSSRAW, 0, NULL);
00631     if(!key.ContainsCertificate()) {
00632         RAISE_CRYPTO_EXCEPTION("CPKIFNSSRaw _Verify called without a certificate.", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, NULL);
00633     }
00634     
00635     // an array of CERTCertificate pointers that will hold the one decoded object
00636     CERTCertificate ** cert = 0;
00637     // NSS public key object that will be extracted from the cert
00638     SECKEYPublicKey * pk = 0;
00639 
00640         
00641     CPKIFCryptoPPKeyMaterialPtr cppkm(new CPKIFCryptoPPKeyMaterial(key));
00642     CPKIFBufferPtr derKeyBuf = cppkm->GetRawSPKI();
00643     if(!derKeyBuf) {
00644         CLEANUP;
00645         RAISE_CRYPTO_EXCEPTION("Unable to get SubjectPublicKeyInfo from key material.",
00646             TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL);
00647     }
00648     SECItem derKey;
00649     memset(&derKey,0x00,sizeof(SECItem));
00650     derKey.type = siBuffer;
00651     derKey.data = const_cast< unsigned char *>(derKeyBuf->GetBuffer());
00652     derKey.len = derKeyBuf->GetLength();    
00653 
00654     CERTSubjectPublicKeyInfo * nssSPKI = SECKEY_DecodeDERSubjectPublicKeyInfo(&derKey);
00655     if(!nssSPKI) {
00656         CLEANUP;
00657         RAISE_CRYPTO_EXCEPTION("Unable to get SubjectPublicKeyInfo from key material.",
00658             TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL);
00659     }
00660     pk = SECKEY_ExtractPublicKey(nssSPKI);
00661     SECKEY_DestroySubjectPublicKeyInfo(nssSPKI);
00662 
00663     // these should work for RSA and DSA signatures equally well
00664     if(!pk) {
00665         CLEANUP;
00666         RAISE_CRYPTO_EXCEPTION("CERT_ExtractPublicKey failed", TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL);
00667     }
00668 
00669     // verification shouldn't modify these
00670     SECItem hash, sig;
00671     hash.data = pHashData;
00672     hash.len = nHashDataLen;
00673     hash.type = siBuffer;
00674     sig.data = pSignature;
00675     sig.len = nSignatureLen;
00676     sig.type = siBuffer;
00677     // The PK11_Verify interface required us to decode the DSA signature.
00678     // VFY_VerifyDigest does not. Leaving this here as a sample in case
00679     // the next interface change requires it again.
00680     // GIB 10/2008
00681 #if 0   
00682     SECItem * decodedSig = 0;
00683 
00684     if(PKIFCRYPTO::DSS == cppkm->GetKeyAlg()->AsymkeyAlg())
00685     {
00686         decodedSig = DSAU_DecodeDerSig(&sig);
00687         if(decodedSig) {
00688             sig.len = decodedSig->len;
00689             sig.type = decodedSig->type;
00690             sig.data = decodedSig->data;
00691         } else {
00692             CLEANUP;
00693             // XXX *** TODO THROW
00694             return false;
00695         }
00696     }
00697 #endif
00698 
00699     // We used to call PK11_Verify(), as suggested in NSS TN#5. That no longer works unless you
00700     // encode the hash and OID first, and from here we'd need to guess at a couple different encodings.
00701     // Unfortunately, VFY_VerifyDigest will be deprecated in NSS 3.12 to go away some time after that.
00702     // There's no alternative to the deprecated function in the FIPS-validated versions, so we need to
00703     // stick with it for as long as we plan to support the 3.11.4 series of NSS.
00704     // GIB 10/2008
00705     // SECStatus rv = PK11_Verify(pk,&sig,&hash,NULL);
00706     SECOidTag sigAlg = NSSSigAlg(cppkm->GetKeyAlg()->AsymkeyAlg(),hashAlg);
00707     SECStatus rv = VFY_VerifyDigest(&hash,pk,&sig,sigAlg,0);
00708 
00709     // if(decodedSig) SECITEM_FreeItem(decodedSig, PR_TRUE);
00710 
00711     bool sigOK = (rv == SECSuccess);
00712 
00713     CLEANUP;
00714     return sigOK;
00715 }
00724 bool CPKIFNSSRaw::VerifyCertificate(
00727     const CPKIFCertificate& issCert, 
00730     const CPKIFCertificate& subCert)
00731 {
00732 #undef CLEANUP
00733 #define CLEANUP \
00734 { \
00735     if (cert && cert[1] )  \
00736     {   CERT_DestroyCertificate(cert[1]); cert[1] = 0; }  \
00737     if (cert && cert[0])  \
00738     {   CERT_DestroyCertificate(cert[0]); cert[0] = 0; }  \
00739     if (cert) \
00740     {   PR_Free(cert); cert = 0; }  \
00741 } 
00742     LOG_STRING_DEBUG("CPKIFNSSRaw::VerifyCertificate(const CPKIFCertificate& issCert, const CPKIFCertificate& subCert)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00743     CPKIFBufferPtr issDer = issCert.Encoded();
00744     CPKIFBufferPtr subDer = subCert.Encoded();
00745     SECItem issDerSi;
00746     issDerSi.data = const_cast<unsigned char *>(issDer->GetBuffer());
00747     issDerSi.len = issDer->GetLength();
00748     issDerSi.type = siBuffer;
00749     SECItem subDerSi;
00750     subDerSi.data = const_cast<unsigned char *>(subDer->GetBuffer());
00751     subDerSi.len = subDer->GetLength();
00752     subDerSi.type = siBuffer;
00753     SECItem * encCerts[2] = {&issDerSi,&subDerSi};
00754     CERTCertificate ** cert = 0;
00755     // Import certs into a temporary NSS database
00756     SECStatus rv = CERT_ImportCerts(CERT_GetDefaultCertDB(),certUsageUserCertImport,
00757         2,encCerts,&cert,PR_FALSE,PR_FALSE,NULL);
00758 
00759     if(rv != SECSuccess || !cert || !cert[0] || !cert[1])
00760     {
00761         CLEANUP;
00762         std::ostringstream os;
00763         os << "CERT_ImportCerts failed: "; // XXX TODO: Find NSS Equivalent << GetLastError();
00764         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL)
00765     }
00766 
00767     CERTCertificate * sub = cert[1];
00768     CERTCertificate * iss = cert[0];
00769 
00770 
00771     // only verify the crypto... don't worry about other matters here
00772     rv = CERT_VerifySignedDataWithPublicKeyInfo(&sub->signatureWrap,&iss->subjectPublicKeyInfo,NULL);
00773     CLEANUP;
00774     return rv == SECSuccess;
00775 
00776 }
00777 
00778 //support RSA w/ SHA1 (DSS and MD5)
00788 bool CPKIFNSSRaw::Verify(
00790     const CPKIFKeyMaterial& key,
00792     unsigned char* pHashData, 
00794     int nHashDataLen, 
00796     unsigned char* pSignature, 
00798     int nSignatureLen,
00800     PKIFCRYPTO::HASH_ALG hashAlg
00801     )
00802 {
00803     //no state 
00804     return _Verify(key, pHashData, nHashDataLen, pSignature, nSignatureLen, hashAlg);
00805 }
00816 void CPKIFNSSRaw::GenRandom(
00818     unsigned char* buf,
00820     int len)
00821 {
00822     //This function will use the context in m_hProv if present, otherwise a temp context is created.
00823     //CryptGenRandom is called to retrieve the specified number of bytes.  The buf param is assumed
00824     //to be at least len bytes in size.
00825 
00826     LOG_STRING_DEBUG("CPKIFNSSRaw::GenRandom(unsigned char* buf, int len)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00827 
00828     if(NULL == buf || 0 == len)
00829         return; //no need to raise an exception.  the caller asks for nothing and received nothing.
00830 
00831     SECStatus rv = PK11_GenerateRandom(buf,len);
00832     if(SECSuccess != rv) {
00833         RAISE_CRYPTO_EXCEPTION("PK11_GenerateRandom() failed", thisComponent, PKIFNSS_RNG_FAILED, this);
00834     }
00835 }
00849 IPKIFHashContext* CPKIFNSSRaw::HashInit(
00852     PKIFCRYPTO::HASH_ALG alg)
00853 {
00854     LOG_STRING_DEBUG("CPKIFNSSRaw::HashInit(HASH_ALG alg)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00855     //std::cerr << "CPKIFNSSRaw::HashInit" << std::endl;
00856     //support SHA1 (MD5)
00857     SECOidTag hashAlg;
00858     switch(alg)
00859     {
00860     case PKIFCRYPTO::SHA1:
00861         hashAlg = SEC_OID_SHA1;
00862         break;
00863 #ifndef FIPS_MODE
00864     case PKIFCRYPTO::MD5:
00865         hashAlg = SEC_OID_MD5;
00866         break;
00867 #endif
00868     case PKIFCRYPTO::SHA256:
00869         hashAlg = SEC_OID_SHA256;
00870         break;
00871     case PKIFCRYPTO::SHA384:
00872         hashAlg = SEC_OID_SHA384;
00873         break;
00874     case PKIFCRYPTO::SHA512:
00875         hashAlg = SEC_OID_SHA512;
00876         break;
00877     default:
00878         std::ostringstream os;
00879         os << "Unsupported hash algorithm encountered: " << alg;
00880         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00881     }
00882 
00883     //create a hash context object and populate it with context and hash objects
00884     //throw bad_alloc; nothing to clean up in this function
00885     CPKIFNSSHashContext* hashCtx = new CPKIFNSSHashContext();
00886     hashCtx->m_hashContext = PK11_CreateDigestContext(hashAlg);
00887     if(!hashCtx->m_hashContext)
00888     {
00889         delete hashCtx;
00890 
00891         std::ostringstream os;
00892         os << "PK11_CreateDigestContext failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00893         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_CREATE_DIGEST_CONTEXT_FAILED, NULL);
00894     }
00895     SECStatus rv = PK11_DigestBegin(hashCtx->m_hashContext);
00896     if(SECSuccess != rv)
00897     {
00898         delete hashCtx;
00899 
00900         std::ostringstream os;
00901         os << "PK11_DigestBegin failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00902         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_DIGEST_BEGIN_FAILED, NULL);
00903     }
00904 
00905     return hashCtx;
00906 }
00919 void CPKIFNSSRaw::HashUpdate(
00921     IPKIFHashContext* hash, 
00923     unsigned char* pData, 
00925     int nDataLen)
00926 {
00927     LOG_STRING_DEBUG("CPKIFNSSRaw::HashUpdate(IPKIFHashContext* hash, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00928     //sanity check the inputs: 
00929     //  hash must not be NULL, must be of a type this class supports and must not be empty
00930     //  pData MAY be NULL (if not it is assumed to be at least nDataLen bytes)
00931     //  nDataLen must not be less than zero
00932     if(NULL == hash || 0 > nDataLen)
00933         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashUpdate.");
00934 
00935     //cast the hash context to the type this class handles.  if the cast fails
00936     //then the context is not the correct type.
00937     CPKIFNSSHashContext* hashCtx = dynamic_cast<CPKIFNSSHashContext*>(hash);
00938     if(NULL == hashCtx)
00939         throw CPKIFCryptoException(thisComponent, PKIFNSS_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashUpdate.");
00940 
00941     if(NULL == hashCtx->m_hashContext)
00942         throw CPKIFCryptoException(thisComponent, PKIFNSS_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
00943     SECStatus rv = PK11_DigestOp(hashCtx->m_hashContext,pData,nDataLen);
00944     if(SECSuccess != rv)
00945     {
00946         std::ostringstream os;
00947         os << "PK11_DigestOp failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00948         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_DIGEST_OP_FAILED, NULL);
00949     }
00950 }
00964 void CPKIFNSSRaw::HashFinal(
00966     IPKIFHashContext* hash,
00968     unsigned char* pResult, 
00971     int* pnResultLen)
00972 {
00973     LOG_STRING_DEBUG("CPKIFNSSRaw::HashFinal(IPKIFHashContext* hash, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00974 
00975     //sanity check the inputs: 
00976     //  hash must not be NULL, must be of a type this class supports and must not be empty
00977     //  result must not be NULL (it is assumed to be at least *pnResultLen bytes)
00978     //  pnResultLen must not be NULL and *pnResultLen must not be less than or equal to zero
00979     if(NULL == hash || NULL == pResult || NULL == pnResultLen || 0 >= *pnResultLen)
00980         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashFinal.");
00981 
00982     CPKIFNSSHashContext* hashCtx = dynamic_cast<CPKIFNSSHashContext*>(hash);
00983     if(NULL == hashCtx)
00984         throw CPKIFCryptoException(thisComponent, PKIFNSS_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashFinal.");
00985 
00986     if(NULL == hashCtx->m_hashContext)
00987         throw CPKIFCryptoException(thisComponent, PKIFNSS_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
00988 
00989     //terminate the hash and retrieve the hash value
00990     unsigned int outLen = 0;
00991     SECStatus rv = PK11_DigestFinal(hashCtx->m_hashContext,pResult,&outLen,*pnResultLen);
00992     if(SECSuccess != rv) 
00993     {
00994         std::ostringstream os;
00995         os << "PK11_DigestFinal failed: "; // XXX TODO: find NSS equiv << GetLastError();;
00996         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFNSS_DIGEST_OP_FAILED, NULL);
00997     }
00998     // XXX TODO: bounds check before casting
00999     *pnResultLen = (int)outLen;
01000 
01001 }
01019 IPKIFRawCryptContext* CPKIFNSSRaw::CryptInit(
01022     const CPKIFKeyMaterial& key,
01024     bool pad)
01025 {
01026     LOG_STRING_DEBUG("CPKIFNSSRaw::CryptInit(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
01027     
01028     // the iterative crypt functions are a bad idea with RSA or DSA keys...
01029     if(!key.ContainsSymmetricKeyMaterial())
01030     {
01031         throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, "CryptInit() only makes sense for symmetric keys.");    
01032     }
01033 
01034     // throw bad_alloc... nothing to cleanup
01035     CPKIFNSSRawCryptContext * ctx = new CPKIFNSSRawCryptContext();
01036 
01037     ctx->m_mech = CipherMechForKey(key,pad);
01038 
01039     if(key.GetMode() == PKIFCRYPTO::CBC && NULL == key.GetIV())
01040     {
01041         delete ctx;
01042         throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, CRYPTO_MISSING_IV);
01043     }
01044             
01045     ctx->m_slot = PK11_GetBestSlot(ctx->m_mech,NULL);
01046     if(0 == ctx->m_slot)
01047     {
01048         delete ctx;
01049         // XXX TODO: Find and push NSS err message as well
01050         RAISE_CRYPTO_EXCEPTION("No NSS slot supports this algorithm",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_UNSUPPORTED_ALG,NULL);
01051     }
01052 
01053     SECItem keyItem, ivItem;
01054     keyItem.data = const_cast<unsigned char *>(key.GetSymmetricKey());
01055     keyItem.len = key.GetSymmetricKeyLength();
01056     keyItem.type = siBuffer;
01057     ivItem.data = const_cast<unsigned char *>(key.GetIV());
01058     ivItem.len = PK11_GetIVLength(ctx->m_mech);
01059     ivItem.type = siBuffer;
01060     
01061     // For a raw symmetric key there's no difference between CKA_ENCRYPT and CKA_DECRYPT
01062     ctx->m_sk = PK11_ImportSymKey(ctx->m_slot,ctx->m_mech,PK11_OriginUnwrap,CKA_ENCRYPT, &keyItem, NULL);
01063 
01064     if( 0 == ctx->m_sk )
01065     {
01066         delete ctx;
01067         RAISE_CRYPTO_EXCEPTION("Unable to import raw symmetric key",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_RAW_IMPORT_FAILED,NULL);
01068     }
01069 
01070     // this does nothing if there's no IV
01071     ctx->m_param = PK11_ParamFromIV(ctx->m_mech,&ivItem);
01072     if( 0 == ctx->m_param )
01073     {
01074         delete ctx;
01075         RAISE_CRYPTO_EXCEPTION("Unable to import IV into NSS",TOOLKIT_CRYPTO_NSSRAW,PKIF_NSS_IV_IMPORT_FAILED,NULL);
01076     }
01077     if(key.GetMode() ==  PKIFCRYPTO::ECB)
01078     {
01079         // NSS (perhaps sensibly) will not pad ECB block ciphers
01080         ctx->m_bNeedsPad = pad;
01081         if(pad)
01082         {
01083             ctx->m_blocksize = PK11_GetBlockSize(ctx->m_mech,ctx->m_param);
01084             ctx->m_padbuf = new unsigned char[ctx->m_blocksize];
01085             memset(ctx->m_padbuf,0x00,ctx->m_blocksize);
01086         }
01087 
01088     }
01089     return ctx;
01090 }
01099 void CPKIFNSSRaw::Decrypt(
01102     IPKIFRawCryptContext* cryptContext, 
01104     unsigned char* pData, 
01106     int nDataLen, 
01108     unsigned char* pResult,
01111     int* pnResultLen, 
01114     bool final)
01115 {
01116     CryptFunc<false>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
01117 }
01126 void CPKIFNSSRaw::Encrypt(
01129     IPKIFRawCryptContext* cryptContext, 
01131     unsigned char* pData, 
01133     int nDataLen, 
01135     unsigned char* pResult, 
01138     int* pnResultLen, 
01141     bool final)
01142 {
01143     CryptFunc<true>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
01144 }
01156 template <bool _CryptDirection>
01157 void CPKIFNSSRaw::CryptFunc(
01160     IPKIFRawCryptContext* cryptContext,
01162     unsigned char* pData, 
01164     int nDataLen, 
01166     unsigned char* pResult, 
01168     int* pnResultLen, 
01171     bool final)
01172 {
01173     LOG_STRING_DEBUG("CPKIFNSSRaw CryptFunc(IPKIFRawCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_NSSRAW, 0, NULL);
01174 
01175     CPKIFNSSRawCryptContext* icc = dynamic_cast<CPKIFNSSRawCryptContext*>(cryptContext);
01176     if(!icc || !icc->m_param || !icc->m_slot || !icc->m_sk)
01177     { 
01178         RAISE_CRYPTO_EXCEPTION("CPKIFNSSRaw CryptFunc called with an invalid context.", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, NULL);
01179     }
01180     // the context couldn't be established by init without knowing the direction,
01181     // so the first call needs to set that up
01182     if(!icc->m_ctx)
01183     {
01184         icc->m_ctx = PK11_CreateContextBySymKey(icc->m_mech, _CryptDirection ? CKA_ENCRYPT:CKA_DECRYPT, 
01185             icc->m_sk,icc->m_param);
01186         if(0 == icc->m_ctx)
01187         {
01188             RAISE_CRYPTO_EXCEPTION("Unable to establish symmetric key cipher context",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CREATE_SK_CONTEXT_FAILED,NULL);
01189         }
01190     }
01191     
01192     int maxOut = *pnResultLen;
01193     int inLen = nDataLen;
01194     unsigned char * start = pData;
01195     unsigned char * outBuf = pResult;
01196 
01197     int updateLen = 0;
01198     int padUpdateLen = 0;
01199     *pnResultLen = 0;
01200     unsigned int finalLen = 0;
01201     SECStatus rv = SECSuccess;
01202 
01203     if(_CryptDirection && start && icc->m_bNeedsPad)
01204     {
01205         // check to see if data was saved from the last update
01206         if(icc->m_padlen > 0)
01207         {
01208             for(int i = icc->m_padlen; inLen != 0 && i < icc->m_blocksize; i++)
01209             {
01210                 icc->m_padbuf[i] = *start++;
01211                 inLen--;
01212                 icc->m_padlen++;
01213             }
01214             // if the pad buffer is full, handle that
01215             if(icc->m_padlen == icc->m_blocksize)
01216             {
01217                 rv = PK11_CipherOp(icc->m_ctx,outBuf,&padUpdateLen,maxOut,icc->m_padbuf,icc->m_padlen);
01218                 if(SECSuccess != rv)
01219                 {
01220                     RAISE_CRYPTO_EXCEPTION("Unable to perform cipher operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
01221                 }
01222                 outBuf += padUpdateLen;
01223                 maxOut -= padUpdateLen;
01224                 icc->m_padlen = 0;
01225                 *pnResultLen += padUpdateLen;
01226             }
01227 
01228         }
01229         // if the pad buffer is empty, see if it needs to be filled again
01230         if(icc->m_padlen == 0) {
01231             icc->m_padlen = inLen % icc->m_blocksize;
01232             if(icc->m_padlen > 0) {
01233                 memcpy(icc->m_padbuf,&start[inLen - icc->m_padlen],icc->m_padlen);
01234                 inLen -= icc->m_padlen;
01235             }
01236         }
01237     }
01238 
01239     // if data was supplied, a CipherOp is needed regardless of whether it's final
01240     if(start && inLen > 0)
01241     {
01242         rv = PK11_CipherOp(icc->m_ctx,outBuf,&updateLen,maxOut,start,inLen);
01243         if(SECSuccess != rv)
01244         {
01245             RAISE_CRYPTO_EXCEPTION("Unable to perform cipher operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
01246         }
01247         maxOut -= updateLen;
01248         outBuf += updateLen;
01249         *pnResultLen += updateLen;
01250     }
01251     if(final) {
01252         if(_CryptDirection && icc->m_bNeedsPad)
01253         {
01254             // pad the buffer with values indicating the number of padding bytes, per PKCS#5
01255             unsigned char padbyte = (unsigned char) icc->m_blocksize - icc->m_padlen;
01256             for(int i = icc->m_padlen; i < icc->m_blocksize; i++)
01257             {
01258                 icc->m_padbuf[i] = padbyte;
01259             }
01260             rv = PK11_CipherOp(icc->m_ctx,outBuf,&padUpdateLen,maxOut,icc->m_padbuf,icc->m_blocksize);
01261             if(SECSuccess != rv)
01262             {
01263                 RAISE_CRYPTO_EXCEPTION("Unable to perform cipher operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
01264             }
01265             outBuf += padUpdateLen;
01266             maxOut -= padUpdateLen;
01267             icc->m_padlen = 0;
01268             *pnResultLen += padUpdateLen;
01269         }
01270 
01271         // NSS's function name is poor here.
01272         rv = PK11_DigestFinal(icc->m_ctx,outBuf,&finalLen,maxOut);
01273         if(SECSuccess != rv)
01274         {
01275             RAISE_CRYPTO_EXCEPTION("Unable to finalize cipher operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
01276         }
01277         if(finalLen != 0 && !_CryptDirection && icc->m_bNeedsPad)
01278         {
01279             int padCount = (int)outBuf[finalLen-1];
01280             finalLen -= padCount;
01281         }
01282     }
01283     *pnResultLen += finalLen;
01284     if(*pnResultLen != 0 && !_CryptDirection && icc->m_bNeedsPad)
01285     {
01286         int padCount = (int)pResult[*pnResultLen-1];
01287         *pnResultLen -= padCount;
01288     }
01289 }
01290 
01302 template<bool _CryptDirection>
01303 void _ASymCrypt(
01305     const CPKIFKeyMaterial& key, 
01307     unsigned char* pData, 
01309     int nDataLen, 
01311     unsigned char* pResult, 
01313     int* pnResultLen, 
01315     bool pad)
01316 {
01317     if(! _CryptDirection) {
01318         throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, "Only encryption is supported for raw public keys.");
01319     }
01320     #undef CLEANUP
01321 #define CLEANUP \
01322 { \
01323     if (cert && cert[0])  \
01324     {   CERT_DestroyCertificate(cert[0]); cert[0] = 0; }  \
01325     if (cert)  \
01326     {   PR_Free(cert); cert = 0; }  \
01327     if (pk) \
01328     {   SECKEY_DestroyPublicKey(pk); pk = 0;    }   \
01329 } 
01330 
01331     LOG_STRING_DEBUG("_ASymCrypt(const CPKIFKeyMaterial& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_NSSRAW, 0, NULL);
01332     if(!key.ContainsCertificate()) {
01333         RAISE_CRYPTO_EXCEPTION("CPKIFNSSRaw _ASymCrypt called without a certificate.", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, NULL);
01334     }
01335     SECItem encCert;
01336     // this is safe since the encoded cert never gets modified on import
01337     encCert.data = const_cast< unsigned char *>(key.GetCertificate());
01338     encCert.len = key.GetCertificateLength();
01339     encCert.type = siBuffer;
01340     SECItem * encCerts[1];
01341     encCerts[0] = &encCert;
01342 
01343     // an array of CERTCertificate pointers that will hold the one decoded object
01344     CERTCertificate ** cert = 0;
01345     // NSS public key object that will be extracted from the cert
01346     SECKEYPublicKey * pk = 0;
01347 
01348     // Import certs into a temporary NSS database
01349     SECStatus rv = CERT_ImportCerts(CERT_GetDefaultCertDB(),certUsageUserCertImport,
01350         1,encCerts,&cert,PR_FALSE,PR_FALSE,NULL);
01351 
01352     if(rv != SECSuccess || !cert || !cert[0])
01353     {
01354         CLEANUP;
01355         std::ostringstream os;
01356         os << "CERT_ImportCerts failed: "; // XXX TODO: Find NSS Equivalent << GetLastError();
01357         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL)
01358     }
01359     // these should work for RSA and DSA signatures equally well
01360     pk = CERT_ExtractPublicKey(cert[0]);
01361     if(!pk) {
01362         CLEANUP;
01363         RAISE_CRYPTO_EXCEPTION("CERT_ExtractPublicKey failed", TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_CERT_IMPORT_FAILED, NULL);
01364     }
01365 
01366     if(pad) {
01367         rv = PK11_PubEncryptPKCS1(pk,pResult,pData,nDataLen,NULL);
01368     }else {
01369         rv = PK11_PubEncryptRaw(pk,pResult,pData,nDataLen,NULL);
01370     }
01371     *pnResultLen = SECKEY_PublicKeyStrength(pk);
01372     if(rv != SECSuccess)
01373     {
01374         CLEANUP;
01375         std::ostringstream os;
01376         os << "PK11_PubEncrypt failed: "; // XXX TODO: Find NSS Equivalent << GetLastError();
01377         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO_NSSRAW, PKIFNSS_PUB_ENCRYPT_FAILED, NULL);
01378     }
01379 
01380     CLEANUP;
01381 }

Generated on Mon Nov 15 11:15:55 2010 for PublicKeyInfrastructureFramework(PKIF) by  doxygen 1.5.6