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
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
00206 CPKIFNSSAesKeyWrapCryptContext * ctx = new CPKIFNSSAesKeyWrapCryptContext();
00207
00208
00209 ctx->m_slot = PK11_GetInternalKeySlot();
00210
00211
00212 const unsigned char * kmiv = key.GetIV();
00213 if(kmiv) {
00214 SECItem ivItem;
00215 memset(&ivItem,0x00,sizeof(SECItem));
00216
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
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
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
00272
00273
00274
00275 SECItem ciphersi;
00276 memset(&ciphersi,0x00,sizeof(SECItem));
00277 ciphersi.data = pData;
00278 ciphersi.len = unsignedCipherLength;
00279 unsigned int unsignedPlainLength = unsignedCipherLength - 8;
00280
00281 PK11SymKey * unwrappedKey = PK11_UnwrapSymKey(
00282
00283 icc->m_wrappingkey,
00284
00285 s_kwmech,
00286
00287 icc->m_params,
00288
00289 &ciphersi,
00290
00291 CKK_GENERIC_SECRET,
00292
00293 CKA_ENCRYPT,
00294
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
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
00358 PK11SymKey * tbWrappedKey = PK11_ImportSymKey(icc->m_slot, CKK_GENERIC_SECRET, PK11_OriginGenerated, CKA_ENCRYPT, &tbWrappedSI,0);
00359
00360
00361
00362
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
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
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 }