michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsKeyModule.h" michael@0: #include "nsString.h" michael@0: #include "ScopedNSSTypes.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::psm; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsKeyObject, nsIKeyObject) michael@0: michael@0: nsKeyObject::nsKeyObject() michael@0: : mKeyType(0), mSymKey(nullptr), mPrivateKey(nullptr), michael@0: mPublicKey(nullptr) michael@0: { michael@0: } michael@0: michael@0: nsKeyObject::~nsKeyObject() michael@0: { michael@0: CleanUp(); michael@0: } michael@0: michael@0: void michael@0: nsKeyObject::CleanUp() michael@0: { michael@0: switch (mKeyType) { michael@0: case nsIKeyObject::SYM_KEY: michael@0: PK11_FreeSymKey(mSymKey); michael@0: break; michael@0: michael@0: case nsIKeyObject::PRIVATE_KEY: michael@0: PK11_DeleteTokenPrivateKey(mPrivateKey, true /* force */); michael@0: break; michael@0: michael@0: case nsIKeyObject::PUBLIC_KEY: michael@0: PK11_DeleteTokenPublicKey(mPublicKey); michael@0: break; michael@0: michael@0: default: michael@0: // probably not initialized, do nothing michael@0: break; michael@0: } michael@0: mKeyType = 0; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: // nsIKeyObject michael@0: michael@0: /* [noscript] void initKey (in short aKeyType, in voidPtr aKey); */ michael@0: NS_IMETHODIMP michael@0: nsKeyObject::InitKey(int16_t aAlgorithm, void * aKey) michael@0: { michael@0: // Clear previous key data if it exists michael@0: CleanUp(); michael@0: michael@0: switch (aAlgorithm) { michael@0: case nsIKeyObject::RC4: michael@0: case nsIKeyObject::HMAC: michael@0: mSymKey = reinterpret_cast(aKey); michael@0: michael@0: if (!mSymKey) { michael@0: NS_ERROR("no symkey"); michael@0: break; michael@0: } michael@0: mKeyType = nsIKeyObject::SYM_KEY; michael@0: break; michael@0: michael@0: case nsIKeyObject::AES_CBC: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: michael@0: default: michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: // One of these should have been created michael@0: if (!mSymKey && !mPrivateKey && !mPublicKey) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* [noscript] voidPtr getKeyObj (); */ michael@0: NS_IMETHODIMP michael@0: nsKeyObject::GetKeyObj(void * *_retval) michael@0: { michael@0: if (mKeyType == 0) michael@0: return NS_ERROR_NOT_INITIALIZED; michael@0: michael@0: switch (mKeyType) { michael@0: case nsIKeyObject::SYM_KEY: michael@0: *_retval = (void*)mSymKey; michael@0: break; michael@0: michael@0: case nsIKeyObject::PRIVATE_KEY: michael@0: *_retval = (void*)mPublicKey; michael@0: break; michael@0: michael@0: case nsIKeyObject::PUBLIC_KEY: michael@0: *_retval = (void*)mPrivateKey; michael@0: break; michael@0: michael@0: default: michael@0: // unknown key type? How did that happen? michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* short getType (); */ michael@0: NS_IMETHODIMP michael@0: nsKeyObject::GetType(int16_t *_retval) michael@0: { michael@0: if (mKeyType == 0) michael@0: return NS_ERROR_NOT_INITIALIZED; michael@0: michael@0: *_retval = mKeyType; michael@0: return NS_OK; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: // nsIKeyObjectFactory michael@0: michael@0: NS_IMPL_ISUPPORTS(nsKeyObjectFactory, nsIKeyObjectFactory) michael@0: michael@0: nsKeyObjectFactory::nsKeyObjectFactory() michael@0: { michael@0: } michael@0: michael@0: /* nsIKeyObject lookupKeyByName (in ACString aName); */ michael@0: NS_IMETHODIMP michael@0: nsKeyObjectFactory::LookupKeyByName(const nsACString & aName, michael@0: nsIKeyObject **_retval) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsKeyObjectFactory::UnwrapKey(int16_t aAlgorithm, const uint8_t *aWrappedKey, michael@0: uint32_t aWrappedKeyLen, nsIKeyObject **_retval) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsKeyObjectFactory::KeyFromString(int16_t aAlgorithm, const nsACString & aKey, michael@0: nsIKeyObject **_retval) michael@0: { michael@0: CK_MECHANISM_TYPE cipherMech; michael@0: CK_ATTRIBUTE_TYPE cipherOperation; michael@0: switch (aAlgorithm) michael@0: { michael@0: case nsIKeyObject::HMAC: michael@0: cipherMech = CKM_GENERIC_SECRET_KEY_GEN; michael@0: cipherOperation = CKA_SIGN; michael@0: break; michael@0: michael@0: case nsIKeyObject::RC4: michael@0: cipherMech = CKM_RC4; michael@0: cipherOperation = CKA_ENCRYPT; michael@0: break; michael@0: michael@0: default: michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: nsresult rv; michael@0: nsCOMPtr key = michael@0: do_CreateInstance(NS_KEYMODULEOBJECT_CONTRACTID, &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // Convert the raw string into a SECItem michael@0: const nsCString& flatKey = PromiseFlatCString(aKey); michael@0: SECItem keyItem; michael@0: keyItem.data = (unsigned char*)flatKey.get(); michael@0: keyItem.len = flatKey.Length(); michael@0: michael@0: ScopedPK11SlotInfo slot(PK11_GetBestSlot(cipherMech, nullptr)); michael@0: if (!slot) { michael@0: NS_ERROR("no slot"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: PK11SymKey* symKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, michael@0: cipherOperation, &keyItem, nullptr); michael@0: if (!symKey) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: rv = key->InitKey(aAlgorithm, (void*)symKey); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: key.swap(*_retval); michael@0: return NS_OK; michael@0: }