Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsComponentManagerUtils.h"
6 #include "nsCOMPtr.h"
7 #include "nsKeyModule.h"
8 #include "nsString.h"
9 #include "ScopedNSSTypes.h"
11 using namespace mozilla;
12 using namespace mozilla::psm;
14 NS_IMPL_ISUPPORTS(nsKeyObject, nsIKeyObject)
16 nsKeyObject::nsKeyObject()
17 : mKeyType(0), mSymKey(nullptr), mPrivateKey(nullptr),
18 mPublicKey(nullptr)
19 {
20 }
22 nsKeyObject::~nsKeyObject()
23 {
24 CleanUp();
25 }
27 void
28 nsKeyObject::CleanUp()
29 {
30 switch (mKeyType) {
31 case nsIKeyObject::SYM_KEY:
32 PK11_FreeSymKey(mSymKey);
33 break;
35 case nsIKeyObject::PRIVATE_KEY:
36 PK11_DeleteTokenPrivateKey(mPrivateKey, true /* force */);
37 break;
39 case nsIKeyObject::PUBLIC_KEY:
40 PK11_DeleteTokenPublicKey(mPublicKey);
41 break;
43 default:
44 // probably not initialized, do nothing
45 break;
46 }
47 mKeyType = 0;
48 }
50 //////////////////////////////////////////////////////////////////////////////
51 // nsIKeyObject
53 /* [noscript] void initKey (in short aKeyType, in voidPtr aKey); */
54 NS_IMETHODIMP
55 nsKeyObject::InitKey(int16_t aAlgorithm, void * aKey)
56 {
57 // Clear previous key data if it exists
58 CleanUp();
60 switch (aAlgorithm) {
61 case nsIKeyObject::RC4:
62 case nsIKeyObject::HMAC:
63 mSymKey = reinterpret_cast<PK11SymKey*>(aKey);
65 if (!mSymKey) {
66 NS_ERROR("no symkey");
67 break;
68 }
69 mKeyType = nsIKeyObject::SYM_KEY;
70 break;
72 case nsIKeyObject::AES_CBC:
73 return NS_ERROR_NOT_IMPLEMENTED;
75 default:
76 return NS_ERROR_INVALID_ARG;
77 }
79 // One of these should have been created
80 if (!mSymKey && !mPrivateKey && !mPublicKey)
81 return NS_ERROR_FAILURE;
83 return NS_OK;
84 }
86 /* [noscript] voidPtr getKeyObj (); */
87 NS_IMETHODIMP
88 nsKeyObject::GetKeyObj(void * *_retval)
89 {
90 if (mKeyType == 0)
91 return NS_ERROR_NOT_INITIALIZED;
93 switch (mKeyType) {
94 case nsIKeyObject::SYM_KEY:
95 *_retval = (void*)mSymKey;
96 break;
98 case nsIKeyObject::PRIVATE_KEY:
99 *_retval = (void*)mPublicKey;
100 break;
102 case nsIKeyObject::PUBLIC_KEY:
103 *_retval = (void*)mPrivateKey;
104 break;
106 default:
107 // unknown key type? How did that happen?
108 return NS_ERROR_FAILURE;
109 }
110 return NS_OK;
111 }
113 /* short getType (); */
114 NS_IMETHODIMP
115 nsKeyObject::GetType(int16_t *_retval)
116 {
117 if (mKeyType == 0)
118 return NS_ERROR_NOT_INITIALIZED;
120 *_retval = mKeyType;
121 return NS_OK;
122 }
124 //////////////////////////////////////////////////////////////////////////////
125 // nsIKeyObjectFactory
127 NS_IMPL_ISUPPORTS(nsKeyObjectFactory, nsIKeyObjectFactory)
129 nsKeyObjectFactory::nsKeyObjectFactory()
130 {
131 }
133 /* nsIKeyObject lookupKeyByName (in ACString aName); */
134 NS_IMETHODIMP
135 nsKeyObjectFactory::LookupKeyByName(const nsACString & aName,
136 nsIKeyObject **_retval)
137 {
138 return NS_ERROR_NOT_IMPLEMENTED;
139 }
141 NS_IMETHODIMP
142 nsKeyObjectFactory::UnwrapKey(int16_t aAlgorithm, const uint8_t *aWrappedKey,
143 uint32_t aWrappedKeyLen, nsIKeyObject **_retval)
144 {
145 return NS_ERROR_NOT_IMPLEMENTED;
146 }
148 NS_IMETHODIMP
149 nsKeyObjectFactory::KeyFromString(int16_t aAlgorithm, const nsACString & aKey,
150 nsIKeyObject **_retval)
151 {
152 CK_MECHANISM_TYPE cipherMech;
153 CK_ATTRIBUTE_TYPE cipherOperation;
154 switch (aAlgorithm)
155 {
156 case nsIKeyObject::HMAC:
157 cipherMech = CKM_GENERIC_SECRET_KEY_GEN;
158 cipherOperation = CKA_SIGN;
159 break;
161 case nsIKeyObject::RC4:
162 cipherMech = CKM_RC4;
163 cipherOperation = CKA_ENCRYPT;
164 break;
166 default:
167 return NS_ERROR_INVALID_ARG;
168 }
170 nsresult rv;
171 nsCOMPtr<nsIKeyObject> key =
172 do_CreateInstance(NS_KEYMODULEOBJECT_CONTRACTID, &rv);
173 NS_ENSURE_SUCCESS(rv, rv);
175 // Convert the raw string into a SECItem
176 const nsCString& flatKey = PromiseFlatCString(aKey);
177 SECItem keyItem;
178 keyItem.data = (unsigned char*)flatKey.get();
179 keyItem.len = flatKey.Length();
181 ScopedPK11SlotInfo slot(PK11_GetBestSlot(cipherMech, nullptr));
182 if (!slot) {
183 NS_ERROR("no slot");
184 return NS_ERROR_FAILURE;
185 }
187 PK11SymKey* symKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap,
188 cipherOperation, &keyItem, nullptr);
189 if (!symKey) {
190 return NS_ERROR_FAILURE;
191 }
193 rv = key->InitKey(aAlgorithm, (void*)symKey);
194 NS_ENSURE_SUCCESS(rv, rv);
196 key.swap(*_retval);
197 return NS_OK;
198 }