PKIFNSSAesKeyWrap.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFNSSAesKeyWrap.h"
00010 #include "PKIFNSSAesKeyWrapCryptContext.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 
00029 
00030 static CK_MECHANISM_TYPE s_kwmech = CKM_NETSCAPE_AES_KEY_WRAP;
00031 
00032 
00041 CPKIFNSSAesKeyWrap::CPKIFNSSAesKeyWrap(void)
00042 {
00043     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::CPKIFNSSAesKeyWrap(void)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00044 }
00052 CPKIFNSSAesKeyWrap::~CPKIFNSSAesKeyWrap(void)
00053 {
00054     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::~CPKIFNSSAesKeyWrap(void)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00055 }
00063 void CPKIFNSSAesKeyWrap::Initialize()
00064 {
00065     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::Initialize()", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00066 }
00075 bool CPKIFNSSAesKeyWrap::SupportsAlgorithm(
00077     const CPKIFKeyMaterial& key)
00078 {
00079     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::SupportsAlgorithm(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00080     if(key.ContainsSymmetricKeyMaterial())
00081     {   
00082         PKIFCRYPTO::SYMKEY_ALG ska = key.GetSymmetricKeyAlgorithm();
00083         if(PKIFCRYPTO::AES128Wrap == ska || PKIFCRYPTO::AES192Wrap == ska || PKIFCRYPTO::AES256Wrap  == ska)
00084             return true;
00085     }
00086     return false;
00087 }
00088 
00096 void CPKIFNSSAesKeyWrap::Decrypt(   
00098     const CPKIFKeyMaterial& key,
00100     unsigned char* pData, 
00102     int nDataLen, 
00104     unsigned char* pResult, 
00107     int* pnResultLen, 
00111     bool pad)
00112 {
00113     if(key.ContainsSymmetricKeyMaterial()) 
00114     {
00115         CPKIFNSSAesKeyWrapCryptContext * ctx = static_cast<CPKIFNSSAesKeyWrapCryptContext *>(this->CryptInit(key,pad));
00116         try {
00117             Decrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00118         } catch(...) {
00119             delete ctx;
00120             throw;
00121         }
00122         delete ctx;
00123     } 
00124 }
00132 void CPKIFNSSAesKeyWrap::Encrypt(
00134     const CPKIFKeyMaterial& key,
00136     unsigned char* pData, 
00138     int nDataLen, 
00140     unsigned char* pResult, 
00143     int* pnResultLen, 
00147     bool pad)
00148 {
00149     if(key.ContainsSymmetricKeyMaterial()) {
00150         CPKIFNSSAesKeyWrapCryptContext * ctx = static_cast<CPKIFNSSAesKeyWrapCryptContext *>(this->CryptInit(key,pad));
00151         try {
00152             Encrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00153         } catch(...) {
00154             delete ctx;
00155             throw;
00156         }
00157         delete ctx;
00158     } 
00159 }
00160 
00173 IPKIFRawCryptContext* CPKIFNSSAesKeyWrap::CryptInit(
00176     const CPKIFKeyMaterial& key,
00178     bool pad)
00179 {
00180     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::CryptInit(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00181     
00182     // AES keys only here.
00183     if(!key.ContainsSymmetricKeyMaterial())
00184     {
00185         throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, "CryptInit() only makes sense for symmetric keys.");    
00186     }
00187     PKIFCRYPTO::SYMKEY_ALG ka = key.GetSymmetricKeyAlgorithm();
00188     CK_MECHANISM_TYPE kmmech;
00189     switch(ka) {
00190         case PKIFCRYPTO::AES:
00191         case PKIFCRYPTO::AES128:
00192         case PKIFCRYPTO::AES192:
00193         case PKIFCRYPTO::AES256:
00194         case PKIFCRYPTO::AES128Wrap:
00195         case PKIFCRYPTO::AES192Wrap:
00196         case PKIFCRYPTO::AES256Wrap:
00197             kmmech = CKM_AES_KEY_GEN;
00198             break;
00199         default:
00200             throw CPKIFCryptoException(TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, "Key material not usable for AES key wrap");
00201             break;
00202             
00203     }
00204 
00205     // throw bad_alloc... nothing to cleanup
00206     CPKIFNSSAesKeyWrapCryptContext * ctx = new CPKIFNSSAesKeyWrapCryptContext();
00207 
00208     
00209     ctx->m_slot = PK11_GetInternalKeySlot();
00210 
00211     // AES key wrap IVs are 64 bits if used
00212     const unsigned char * kmiv = key.GetIV();
00213     if(kmiv) {
00214         SECItem ivItem;
00215         memset(&ivItem,0x00,sizeof(SECItem));
00216         // this gets copied by ParamFromIV
00217         ivItem.data = const_cast<unsigned char *>(kmiv);
00218         ivItem.len = 8;
00219         ctx->m_params = PK11_ParamFromIV(kmmech,&ivItem);
00220     } else {
00221         ctx->m_params = PK11_ParamFromIV(kmmech,0);
00222     }
00223     
00224     SECItem kekItem;
00225     memset(&kekItem,0x00,sizeof(SECItem));
00226     // safe, since import will copy it
00227     kekItem.data = const_cast<unsigned char *>(key.GetSymmetricKey());
00228     kekItem.len = key.GetSymmetricKeyLength();
00229     ctx->m_wrappingkey = PK11_ImportSymKey(ctx->m_slot, kmmech, PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT|CKA_WRAP|CKA_UNWRAP,&kekItem,0);
00230 
00231     return ctx;
00232 }
00241 void CPKIFNSSAesKeyWrap::Decrypt(
00244     IPKIFRawCryptContext* cryptContext, 
00246     unsigned char* pData, 
00248     int nDataLen, 
00250     unsigned char* pResult,
00253     int* pnResultLen, 
00256     bool final)
00257 {
00258     CPKIFNSSAesKeyWrapCryptContext* icc = dynamic_cast<CPKIFNSSAesKeyWrapCryptContext*>(cryptContext);
00259     if(!icc)
00260     { 
00261         RAISE_CRYPTO_EXCEPTION("CPKIFNSSAesKeyWrap called with an invalid context.", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, NULL);
00262     }
00263 
00264     // all the data needs to be available in 1 shot for the public nss API
00265     if(!final)
00266     {
00267         RAISE_CRYPTO_EXCEPTION("CPKIFNSSAesKeyWrap::Decrypt can only be called once per context", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT,NULL);
00268     }
00269 
00270     unsigned int unsignedCipherLength = nDataLen;
00271     /*SECStatus s = AESKeyWrap_Decrypt(icc->m_ctxDec, pResult,
00272             &usignedcipherTextLength, *pnResultLen,
00273             pData, nDataLen);*/
00274 
00275     SECItem ciphersi;
00276     memset(&ciphersi,0x00,sizeof(SECItem));
00277     ciphersi.data = pData;
00278     ciphersi.len = unsignedCipherLength; // key wrap always pads with 64 bits
00279     unsigned int unsignedPlainLength = unsignedCipherLength - 8;
00280     // CKK_GENERIC_SECRET allows us to go through this high level interface without being able to tell NSS  just what we're unwrapping
00281     PK11SymKey * unwrappedKey = PK11_UnwrapSymKey(
00282                     // the KEK, which must be available in the module
00283                     icc->m_wrappingkey,
00284                     // the only mechanism supported by this class is 3394's algorithm
00285                     s_kwmech,
00286                     // this will transmit the IV if one is used
00287                     icc->m_params,
00288                     // the actual ciphertext
00289                     &ciphersi,
00290                     // import the key material without knowing what kind it is
00291                     CKK_GENERIC_SECRET,
00292                     // a safe value since all we're doing is exporting the key
00293                     CKA_ENCRYPT,
00294                     // key size of the key being unwrapped
00295                     unsignedPlainLength);
00296     if(0 == unwrappedKey)
00297     {
00298         RAISE_CRYPTO_EXCEPTION("Unable to perform cipher operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
00299     }
00300     
00301     SECStatus res = PK11_ExtractKeyValue(unwrappedKey);
00302     if(SECSuccess != res)
00303     {
00304         RAISE_CRYPTO_EXCEPTION("Unable to access plaintext",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
00305     }
00306     SECItem * uwkeydata = PK11_GetKeyData(unwrappedKey);
00307     if(!uwkeydata)
00308     {
00309         RAISE_CRYPTO_EXCEPTION("Unable to copy plaintext",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
00310     }
00311     memcpy(pResult,uwkeydata->data,uwkeydata->len);
00312     *pnResultLen = uwkeydata->len;
00313 
00314 }
00315 
00324 void CPKIFNSSAesKeyWrap::Encrypt(
00327     IPKIFRawCryptContext* cryptContext, 
00329     unsigned char* pData, 
00331     int nDataLen, 
00333     unsigned char* pResult, 
00336     int* pnResultLen, 
00339     bool final)
00340 {
00341     CPKIFNSSAesKeyWrapCryptContext* icc = dynamic_cast<CPKIFNSSAesKeyWrapCryptContext*>(cryptContext);
00342     if(!icc)
00343     { 
00344         RAISE_CRYPTO_EXCEPTION("CPKIFNSSAesKeyWrap called with an invalid context.", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT, NULL);
00345     }
00346 
00347     // all the data needs to be available in 1 shot for the public nss API
00348     if(!final)
00349     {
00350         RAISE_CRYPTO_EXCEPTION("CPKIFNSSAesKeyWrap::Encrypt can only be called once per context", TOOLKIT_CRYPTO_NSSRAW, COMMON_INVALID_INPUT,NULL);
00351     }
00352 
00353     SECItem tbWrappedSI;
00354     memset(&tbWrappedSI,0x00,sizeof(SECItem));
00355     tbWrappedSI.data = pData;
00356     tbWrappedSI.len = nDataLen;
00357     // import the plaintext to NSS as a generic secret blob since we can't be certain what it is at this point.
00358     PK11SymKey * tbWrappedKey = PK11_ImportSymKey(icc->m_slot, CKK_GENERIC_SECRET, PK11_OriginGenerated, CKA_ENCRYPT, &tbWrappedSI,0);
00359     /*
00360     SECStatus s = AESKeyWrap_Encrypt(icc->m_ctxEnc, pResult,
00361             &upnResultLen, *pnResultLen,
00362             pData, nDataLen);*/
00363     if(0 == tbWrappedKey)
00364     {
00365         RAISE_CRYPTO_EXCEPTION("Unable to import key material for wrap",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
00366     }
00367     SECItem wrappedKeySI;
00368     memset(&wrappedKeySI,0x00,sizeof(SECItem));
00369     wrappedKeySI.data = pResult;
00370     wrappedKeySI.len = *pnResultLen;
00371 
00372     SECStatus res = PK11_WrapSymKey(s_kwmech,icc->m_params,icc->m_wrappingkey,tbWrappedKey,&wrappedKeySI);
00373     PK11_FreeSymKey(tbWrappedKey);
00374     if(SECSuccess != res)
00375     {
00376         RAISE_CRYPTO_EXCEPTION("Unable to perform key wrap operation",TOOLKIT_CRYPTO_NSSRAW,PKIFNSS_CIPHER_OP_FAILED,NULL);
00377     }
00378     *pnResultLen = wrappedKeySI.len;
00379 }
00390 void CPKIFNSSAesKeyWrap::Sign(
00392     const CPKIFKeyMaterial& key,
00394     unsigned char* pHashData, 
00396     int nHashDataLen, 
00398     unsigned char* pSignature, 
00401     int* nSignatureLen,
00403     PKIFCRYPTO::HASH_ALG hashAlg
00404     )
00405 {
00406     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::Sign(const CPKIFKeyMaterial& key,...)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00407     // Don't do raw signature generation since we don't have a way of slinging raw private keys around
00408     RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00409 }
00410 
00428 IPKIFRawCryptContext* CPKIFNSSAesKeyWrap::HMACInit(const CPKIFKeyMaterial &key, PKIFCRYPTO::HASH_ALG ha)
00429 {
00430     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::HMACInit(const CPKIFKeyMaterial& key, HASH_ALG ha)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00431     RAISE_CRYPTO_EXCEPTION("MAC operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00432     return NULL;
00433 }
00434 
00447 void CPKIFNSSAesKeyWrap::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)
00448 {
00449     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00450     RAISE_CRYPTO_EXCEPTION("MAC operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00451 }
00452 
00465 void CPKIFNSSAesKeyWrap::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)
00466 {
00467     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00468     RAISE_CRYPTO_EXCEPTION("MAC operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00469 }
00470 
00479 bool CPKIFNSSAesKeyWrap::VerifyCertificate(
00482     const CPKIFCertificate& issCert, 
00485     const CPKIFCertificate& subCert)
00486 {
00487     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::VerifyCertificate(const CPKIFCertificate& issCert, const CPKIFCertificate& subCert)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00488     RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00489     return false;
00490 }
00491 
00492 //support RSA w/ SHA1 (DSS and MD5)
00502 bool CPKIFNSSAesKeyWrap::Verify(
00504     const CPKIFKeyMaterial& key,
00506     unsigned char* pHashData, 
00508     int nHashDataLen, 
00510     unsigned char* pSignature, 
00512     int nSignatureLen,
00514     PKIFCRYPTO::HASH_ALG hashAlg
00515     )
00516 {
00517     LOG_STRING_DEBUG("CPKIFNSSAesKeyWrap::VerifyCertificate(const CPKIFCertificate& issCert, const CPKIFCertificate& subCert)", TOOLKIT_CRYPTO_NSSRAW, 0, this);
00518     RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented by this class.", TOOLKIT_CRYPTO_NSSRAW, COMMON_NOT_IMPLEMENTED, this);
00519     return false;
00520 }

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