|
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/. */ |
|
4 |
|
5 #include "nsSyncJPAKE.h" |
|
6 #include "mozilla/ModuleUtils.h" |
|
7 #include <pk11pub.h> |
|
8 #include <keyhi.h> |
|
9 #include <pkcs11.h> |
|
10 #include <nscore.h> |
|
11 #include <secmodt.h> |
|
12 #include <secport.h> |
|
13 #include <secerr.h> |
|
14 #include <nsDebug.h> |
|
15 #include <nsError.h> |
|
16 #include <base64.h> |
|
17 #include <nsString.h> |
|
18 |
|
19 using mozilla::fallible_t; |
|
20 |
|
21 static bool |
|
22 hex_from_2char(const unsigned char *c2, unsigned char *byteval) |
|
23 { |
|
24 int i; |
|
25 unsigned char offset; |
|
26 *byteval = 0; |
|
27 for (i=0; i<2; i++) { |
|
28 if (c2[i] >= '0' && c2[i] <= '9') { |
|
29 offset = c2[i] - '0'; |
|
30 *byteval |= offset << 4*(1-i); |
|
31 } else if (c2[i] >= 'a' && c2[i] <= 'f') { |
|
32 offset = c2[i] - 'a'; |
|
33 *byteval |= (offset + 10) << 4*(1-i); |
|
34 } else if (c2[i] >= 'A' && c2[i] <= 'F') { |
|
35 offset = c2[i] - 'A'; |
|
36 *byteval |= (offset + 10) << 4*(1-i); |
|
37 } else { |
|
38 return false; |
|
39 } |
|
40 } |
|
41 return true; |
|
42 } |
|
43 |
|
44 static bool |
|
45 fromHex(const char * str, unsigned char * p, size_t sLen) |
|
46 { |
|
47 size_t i; |
|
48 if (sLen & 1) |
|
49 return false; |
|
50 |
|
51 for (i = 0; i < sLen / 2; ++i) { |
|
52 if (!hex_from_2char((const unsigned char *) str + (2*i), |
|
53 (unsigned char *) p + i)) { |
|
54 return false; |
|
55 } |
|
56 } |
|
57 return true; |
|
58 } |
|
59 |
|
60 static nsresult |
|
61 fromHexString(const nsACString & str, unsigned char * p, size_t pMaxLen) |
|
62 { |
|
63 char * strData = (char *) str.Data(); |
|
64 unsigned len = str.Length(); |
|
65 NS_ENSURE_ARG(len / 2 <= pMaxLen); |
|
66 if (!fromHex(strData, p, len)) { |
|
67 return NS_ERROR_INVALID_ARG; |
|
68 } |
|
69 return NS_OK; |
|
70 } |
|
71 |
|
72 static bool |
|
73 toHexString(const unsigned char * str, unsigned len, nsACString & out) |
|
74 { |
|
75 static const char digits[] = "0123456789ABCDEF"; |
|
76 if (!out.SetCapacity(2 * len, fallible_t())) |
|
77 return false; |
|
78 out.SetLength(0); |
|
79 for (unsigned i = 0; i < len; ++i) { |
|
80 out.Append(digits[str[i] >> 4]); |
|
81 out.Append(digits[str[i] & 0x0f]); |
|
82 } |
|
83 return true; |
|
84 } |
|
85 |
|
86 static nsresult |
|
87 mapErrno() |
|
88 { |
|
89 int err = PORT_GetError(); |
|
90 switch (err) { |
|
91 case SEC_ERROR_NO_MEMORY: return NS_ERROR_OUT_OF_MEMORY; |
|
92 default: return NS_ERROR_UNEXPECTED; |
|
93 } |
|
94 } |
|
95 |
|
96 #define NUM_ELEM(x) (sizeof(x) / sizeof (x)[0]) |
|
97 |
|
98 static const char p[] = |
|
99 "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" |
|
100 "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" |
|
101 "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" |
|
102 "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" |
|
103 "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" |
|
104 "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" |
|
105 "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" |
|
106 "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" |
|
107 "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" |
|
108 "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" |
|
109 "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" |
|
110 "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73"; |
|
111 static const char q[] = |
|
112 "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D"; |
|
113 static const char g[] = |
|
114 "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" |
|
115 "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" |
|
116 "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" |
|
117 "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" |
|
118 "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" |
|
119 "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" |
|
120 "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" |
|
121 "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" |
|
122 "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" |
|
123 "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" |
|
124 "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" |
|
125 "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B"; |
|
126 |
|
127 NS_IMETHODIMP nsSyncJPAKE::Round1(const nsACString & aSignerID, |
|
128 nsACString & aGX1, |
|
129 nsACString & aGV1, |
|
130 nsACString & aR1, |
|
131 nsACString & aGX2, |
|
132 nsACString & aGV2, |
|
133 nsACString & aR2) |
|
134 { |
|
135 NS_ENSURE_STATE(round == JPAKENotStarted); |
|
136 NS_ENSURE_STATE(key == nullptr); |
|
137 |
|
138 static CK_MECHANISM_TYPE mechanisms[] = { |
|
139 CKM_NSS_JPAKE_ROUND1_SHA256, |
|
140 CKM_NSS_JPAKE_ROUND2_SHA256, |
|
141 CKM_NSS_JPAKE_FINAL_SHA256 |
|
142 }; |
|
143 |
|
144 PK11SlotInfo * slot = PK11_GetBestSlotMultiple(mechanisms, |
|
145 NUM_ELEM(mechanisms), |
|
146 nullptr); |
|
147 NS_ENSURE_STATE(slot != nullptr); |
|
148 |
|
149 CK_BYTE pBuf[(NUM_ELEM(p) - 1) / 2]; |
|
150 CK_BYTE qBuf[(NUM_ELEM(q) - 1) / 2]; |
|
151 CK_BYTE gBuf[(NUM_ELEM(g) - 1) / 2]; |
|
152 |
|
153 CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND1; |
|
154 NS_ENSURE_STATE(fromHex(p, pBuf, (NUM_ELEM(p) - 1))); |
|
155 NS_ENSURE_STATE(fromHex(q, qBuf, (NUM_ELEM(q) - 1))); |
|
156 NS_ENSURE_STATE(fromHex(g, gBuf, (NUM_ELEM(g) - 1))); |
|
157 CK_ATTRIBUTE keyTemplate[] = { |
|
158 { CKA_NSS_JPAKE_SIGNERID, (CK_BYTE *) aSignerID.Data(), |
|
159 aSignerID.Length() }, |
|
160 { CKA_KEY_TYPE, &keyType, sizeof keyType }, |
|
161 { CKA_PRIME, pBuf, sizeof pBuf }, |
|
162 { CKA_SUBPRIME, qBuf, sizeof qBuf }, |
|
163 { CKA_BASE, gBuf, sizeof gBuf } |
|
164 }; |
|
165 |
|
166 CK_BYTE gx1Buf[NUM_ELEM(p) / 2]; |
|
167 CK_BYTE gv1Buf[NUM_ELEM(p) / 2]; |
|
168 CK_BYTE r1Buf [NUM_ELEM(p) / 2]; |
|
169 CK_BYTE gx2Buf[NUM_ELEM(p) / 2]; |
|
170 CK_BYTE gv2Buf[NUM_ELEM(p) / 2]; |
|
171 CK_BYTE r2Buf [NUM_ELEM(p) / 2]; |
|
172 CK_NSS_JPAKERound1Params rp = { |
|
173 { gx1Buf, sizeof gx1Buf, gv1Buf, sizeof gv1Buf, r1Buf, sizeof r1Buf }, |
|
174 { gx2Buf, sizeof gx2Buf, gv2Buf, sizeof gv2Buf, r2Buf, sizeof r2Buf } |
|
175 }; |
|
176 SECItem paramsItem; |
|
177 paramsItem.data = (unsigned char *) &rp; |
|
178 paramsItem.len = sizeof rp; |
|
179 key = PK11_KeyGenWithTemplate(slot, CKM_NSS_JPAKE_ROUND1_SHA256, |
|
180 CKM_NSS_JPAKE_ROUND1_SHA256, |
|
181 ¶msItem, keyTemplate, |
|
182 NUM_ELEM(keyTemplate), nullptr); |
|
183 nsresult rv = key != nullptr |
|
184 ? NS_OK |
|
185 : mapErrno(); |
|
186 if (rv == NS_OK) { |
|
187 NS_ENSURE_TRUE(toHexString(rp.gx1.pGX, rp.gx1.ulGXLen, aGX1) && |
|
188 toHexString(rp.gx1.pGV, rp.gx1.ulGVLen, aGV1) && |
|
189 toHexString(rp.gx1.pR, rp.gx1.ulRLen, aR1) && |
|
190 toHexString(rp.gx2.pGX, rp.gx2.ulGXLen, aGX2) && |
|
191 toHexString(rp.gx2.pGV, rp.gx2.ulGVLen, aGV2) && |
|
192 toHexString(rp.gx2.pR, rp.gx2.ulRLen, aR2), |
|
193 NS_ERROR_OUT_OF_MEMORY); |
|
194 round = JPAKEBeforeRound2; |
|
195 } |
|
196 return rv; |
|
197 } |
|
198 |
|
199 NS_IMETHODIMP nsSyncJPAKE::Round2(const nsACString & aPeerID, |
|
200 const nsACString & aPIN, |
|
201 const nsACString & aGX3, |
|
202 const nsACString & aGV3, |
|
203 const nsACString & aR3, |
|
204 const nsACString & aGX4, |
|
205 const nsACString & aGV4, |
|
206 const nsACString & aR4, |
|
207 nsACString & aA, |
|
208 nsACString & aGVA, |
|
209 nsACString & aRA) |
|
210 { |
|
211 NS_ENSURE_STATE(round == JPAKEBeforeRound2); |
|
212 NS_ENSURE_STATE(key != nullptr); |
|
213 NS_ENSURE_ARG(!aPeerID.IsEmpty()); |
|
214 |
|
215 /* PIN cannot be equal to zero when converted to a bignum. NSS 3.12.9 J-PAKE |
|
216 assumes that the caller has already done this check. Future versions of |
|
217 NSS J-PAKE will do this check internally. See Bug 609068 Comment 4 */ |
|
218 bool foundNonZero = false; |
|
219 for (size_t i = 0; i < aPIN.Length(); ++i) { |
|
220 if (aPIN[i] != 0) { |
|
221 foundNonZero = true; |
|
222 break; |
|
223 } |
|
224 } |
|
225 NS_ENSURE_ARG(foundNonZero); |
|
226 |
|
227 CK_BYTE gx3Buf[NUM_ELEM(p)/2], gv3Buf[NUM_ELEM(p)/2], r3Buf [NUM_ELEM(p)/2]; |
|
228 CK_BYTE gx4Buf[NUM_ELEM(p)/2], gv4Buf[NUM_ELEM(p)/2], r4Buf [NUM_ELEM(p)/2]; |
|
229 CK_BYTE gxABuf[NUM_ELEM(p)/2], gvABuf[NUM_ELEM(p)/2], rABuf [NUM_ELEM(p)/2]; |
|
230 nsresult rv = fromHexString(aGX3, gx3Buf, sizeof gx3Buf); |
|
231 if (rv == NS_OK) rv = fromHexString(aGV3, gv3Buf, sizeof gv3Buf); |
|
232 if (rv == NS_OK) rv = fromHexString(aR3, r3Buf, sizeof r3Buf); |
|
233 if (rv == NS_OK) rv = fromHexString(aGX4, gx4Buf, sizeof gx4Buf); |
|
234 if (rv == NS_OK) rv = fromHexString(aGV4, gv4Buf, sizeof gv4Buf); |
|
235 if (rv == NS_OK) rv = fromHexString(aR4, r4Buf, sizeof r4Buf); |
|
236 if (rv != NS_OK) |
|
237 return rv; |
|
238 |
|
239 CK_NSS_JPAKERound2Params rp; |
|
240 rp.pSharedKey = (CK_BYTE *) aPIN.Data(); |
|
241 rp.ulSharedKeyLen = aPIN.Length(); |
|
242 rp.gx3.pGX = gx3Buf; rp.gx3.ulGXLen = aGX3.Length() / 2; |
|
243 rp.gx3.pGV = gv3Buf; rp.gx3.ulGVLen = aGV3.Length() / 2; |
|
244 rp.gx3.pR = r3Buf; rp.gx3.ulRLen = aR3 .Length() / 2; |
|
245 rp.gx4.pGX = gx4Buf; rp.gx4.ulGXLen = aGX4.Length() / 2; |
|
246 rp.gx4.pGV = gv4Buf; rp.gx4.ulGVLen = aGV4.Length() / 2; |
|
247 rp.gx4.pR = r4Buf; rp.gx4.ulRLen = aR4 .Length() / 2; |
|
248 rp.A.pGX = gxABuf; rp.A .ulGXLen = sizeof gxABuf; |
|
249 rp.A.pGV = gvABuf; rp.A .ulGVLen = sizeof gxABuf; |
|
250 rp.A.pR = rABuf; rp.A .ulRLen = sizeof gxABuf; |
|
251 |
|
252 // Bug 629090: NSS 3.12.9 J-PAKE fails to check that gx^4 != 1, so check here. |
|
253 bool gx4Good = false; |
|
254 for (unsigned i = 0; i < rp.gx4.ulGXLen; ++i) { |
|
255 if (rp.gx4.pGX[i] > 1 || (rp.gx4.pGX[i] != 0 && i < rp.gx4.ulGXLen - 1)) { |
|
256 gx4Good = true; |
|
257 break; |
|
258 } |
|
259 } |
|
260 NS_ENSURE_ARG(gx4Good); |
|
261 |
|
262 SECItem paramsItem; |
|
263 paramsItem.data = (unsigned char *) &rp; |
|
264 paramsItem.len = sizeof rp; |
|
265 CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND2; |
|
266 CK_ATTRIBUTE keyTemplate[] = { |
|
267 { CKA_NSS_JPAKE_PEERID, (CK_BYTE *) aPeerID.Data(), aPeerID.Length(), }, |
|
268 { CKA_KEY_TYPE, &keyType, sizeof keyType } |
|
269 }; |
|
270 PK11SymKey * newKey = PK11_DeriveWithTemplate(key, |
|
271 CKM_NSS_JPAKE_ROUND2_SHA256, |
|
272 ¶msItem, |
|
273 CKM_NSS_JPAKE_FINAL_SHA256, |
|
274 CKA_DERIVE, 0, |
|
275 keyTemplate, |
|
276 NUM_ELEM(keyTemplate), |
|
277 false); |
|
278 if (newKey != nullptr) { |
|
279 if (toHexString(rp.A.pGX, rp.A.ulGXLen, aA) && |
|
280 toHexString(rp.A.pGV, rp.A.ulGVLen, aGVA) && |
|
281 toHexString(rp.A.pR, rp.A.ulRLen, aRA)) { |
|
282 round = JPAKEAfterRound2; |
|
283 PK11_FreeSymKey(key); |
|
284 key = newKey; |
|
285 return NS_OK; |
|
286 } else { |
|
287 PK11_FreeSymKey(newKey); |
|
288 rv = NS_ERROR_OUT_OF_MEMORY; |
|
289 } |
|
290 } else |
|
291 rv = mapErrno(); |
|
292 |
|
293 return rv; |
|
294 } |
|
295 |
|
296 static nsresult |
|
297 setBase64(const unsigned char * data, unsigned len, nsACString & out) |
|
298 { |
|
299 nsresult rv = NS_OK; |
|
300 const char * base64 = BTOA_DataToAscii(data, len); |
|
301 |
|
302 if (base64 != nullptr) { |
|
303 size_t len = PORT_Strlen(base64); |
|
304 if (out.SetCapacity(len, fallible_t())) { |
|
305 out.SetLength(0); |
|
306 out.Append(base64, len); |
|
307 PORT_Free((void*) base64); |
|
308 } else { |
|
309 rv = NS_ERROR_OUT_OF_MEMORY; |
|
310 } |
|
311 } else { |
|
312 rv = NS_ERROR_OUT_OF_MEMORY; |
|
313 } |
|
314 return rv; |
|
315 } |
|
316 |
|
317 static nsresult |
|
318 base64KeyValue(PK11SymKey * key, nsACString & keyString) |
|
319 { |
|
320 nsresult rv = NS_OK; |
|
321 if (PK11_ExtractKeyValue(key) == SECSuccess) { |
|
322 const SECItem * value = PK11_GetKeyData(key); |
|
323 rv = value != nullptr && value->data != nullptr && value->len > 0 |
|
324 ? setBase64(value->data, value->len, keyString) |
|
325 : NS_ERROR_UNEXPECTED; |
|
326 } else { |
|
327 rv = mapErrno(); |
|
328 } |
|
329 return rv; |
|
330 } |
|
331 |
|
332 static nsresult |
|
333 extractBase64KeyValue(PK11SymKey * keyBlock, CK_ULONG bitPosition, |
|
334 CK_MECHANISM_TYPE destMech, int keySize, |
|
335 nsACString & keyString) |
|
336 { |
|
337 SECItem paramsItem; |
|
338 paramsItem.data = (CK_BYTE *) &bitPosition; |
|
339 paramsItem.len = sizeof bitPosition; |
|
340 PK11SymKey * key = PK11_Derive(keyBlock, CKM_EXTRACT_KEY_FROM_KEY, |
|
341 ¶msItem, destMech, |
|
342 CKA_SIGN, keySize); |
|
343 if (key == nullptr) |
|
344 return mapErrno(); |
|
345 nsresult rv = base64KeyValue(key, keyString); |
|
346 PK11_FreeSymKey(key); |
|
347 return rv; |
|
348 } |
|
349 |
|
350 |
|
351 NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB, |
|
352 const nsACString & aGVB, |
|
353 const nsACString & aRB, |
|
354 const nsACString & aHKDFInfo, |
|
355 nsACString & aAES256Key, |
|
356 nsACString & aHMAC256Key) |
|
357 { |
|
358 static const unsigned AES256_KEY_SIZE = 256 / 8; |
|
359 static const unsigned HMAC_SHA256_KEY_SIZE = 256 / 8; |
|
360 CK_EXTRACT_PARAMS aesBitPosition = 0; |
|
361 CK_EXTRACT_PARAMS hmacBitPosition = aesBitPosition + (AES256_KEY_SIZE * 8); |
|
362 |
|
363 NS_ENSURE_STATE(round == JPAKEAfterRound2); |
|
364 NS_ENSURE_STATE(key != nullptr); |
|
365 |
|
366 CK_BYTE gxBBuf[NUM_ELEM(p)/2], gvBBuf[NUM_ELEM(p)/2], rBBuf [NUM_ELEM(p)/2]; |
|
367 nsresult rv = fromHexString(aB, gxBBuf, sizeof gxBBuf); |
|
368 if (rv == NS_OK) rv = fromHexString(aGVB, gvBBuf, sizeof gvBBuf); |
|
369 if (rv == NS_OK) rv = fromHexString(aRB, rBBuf, sizeof rBBuf); |
|
370 if (rv != NS_OK) |
|
371 return rv; |
|
372 |
|
373 CK_NSS_JPAKEFinalParams rp; |
|
374 rp.B.pGX = gxBBuf; rp.B.ulGXLen = aB .Length() / 2; |
|
375 rp.B.pGV = gvBBuf; rp.B.ulGVLen = aGVB.Length() / 2; |
|
376 rp.B.pR = rBBuf; rp.B.ulRLen = aRB .Length() / 2; |
|
377 SECItem paramsItem; |
|
378 paramsItem.data = (unsigned char *) &rp; |
|
379 paramsItem.len = sizeof rp; |
|
380 PK11SymKey * keyMaterial = PK11_Derive(key, CKM_NSS_JPAKE_FINAL_SHA256, |
|
381 ¶msItem, CKM_NSS_HKDF_SHA256, |
|
382 CKA_DERIVE, 0); |
|
383 PK11SymKey * keyBlock = nullptr; |
|
384 |
|
385 if (keyMaterial == nullptr) |
|
386 rv = mapErrno(); |
|
387 |
|
388 if (rv == NS_OK) { |
|
389 CK_NSS_HKDFParams hkdfParams; |
|
390 hkdfParams.bExtract = CK_TRUE; |
|
391 hkdfParams.pSalt = nullptr; |
|
392 hkdfParams.ulSaltLen = 0; |
|
393 hkdfParams.bExpand = CK_TRUE; |
|
394 hkdfParams.pInfo = (CK_BYTE *) aHKDFInfo.Data(); |
|
395 hkdfParams.ulInfoLen = aHKDFInfo.Length(); |
|
396 paramsItem.data = (unsigned char *) &hkdfParams; |
|
397 paramsItem.len = sizeof hkdfParams; |
|
398 keyBlock = PK11_Derive(keyMaterial, CKM_NSS_HKDF_SHA256, |
|
399 ¶msItem, CKM_EXTRACT_KEY_FROM_KEY, |
|
400 CKA_DERIVE, AES256_KEY_SIZE + HMAC_SHA256_KEY_SIZE); |
|
401 if (keyBlock == nullptr) |
|
402 rv = mapErrno(); |
|
403 } |
|
404 |
|
405 if (rv == NS_OK) { |
|
406 rv = extractBase64KeyValue(keyBlock, aesBitPosition, CKM_AES_CBC, |
|
407 AES256_KEY_SIZE, aAES256Key); |
|
408 } |
|
409 if (rv == NS_OK) { |
|
410 rv = extractBase64KeyValue(keyBlock, hmacBitPosition, CKM_SHA256_HMAC, |
|
411 HMAC_SHA256_KEY_SIZE, aHMAC256Key); |
|
412 } |
|
413 |
|
414 if (rv == NS_OK) { |
|
415 SECStatus srv = PK11_ExtractKeyValue(keyMaterial); |
|
416 NS_ENSURE_TRUE(srv == SECSuccess, NS_ERROR_UNEXPECTED); // XXX leaks |
|
417 SECItem * keyMaterialBytes = PK11_GetKeyData(keyMaterial); |
|
418 NS_ENSURE_TRUE(keyMaterialBytes != nullptr, NS_ERROR_UNEXPECTED); |
|
419 } |
|
420 |
|
421 if (keyBlock != nullptr) |
|
422 PK11_FreeSymKey(keyBlock); |
|
423 if (keyMaterial != nullptr) |
|
424 PK11_FreeSymKey(keyMaterial); |
|
425 |
|
426 return rv; |
|
427 } |
|
428 |
|
429 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSyncJPAKE) |
|
430 NS_DEFINE_NAMED_CID(NS_SYNCJPAKE_CID); |
|
431 |
|
432 nsSyncJPAKE::nsSyncJPAKE() : round(JPAKENotStarted), key(nullptr) { } |
|
433 |
|
434 nsSyncJPAKE::~nsSyncJPAKE() |
|
435 { |
|
436 if (key != nullptr) |
|
437 PK11_FreeSymKey(key); |
|
438 } |
|
439 |
|
440 static const mozilla::Module::CIDEntry kServicesCryptoCIDs[] = { |
|
441 { &kNS_SYNCJPAKE_CID, false, nullptr, nsSyncJPAKEConstructor }, |
|
442 { nullptr } |
|
443 }; |
|
444 |
|
445 static const mozilla::Module::ContractIDEntry kServicesCryptoContracts[] = { |
|
446 { NS_SYNCJPAKE_CONTRACTID, &kNS_SYNCJPAKE_CID }, |
|
447 { nullptr } |
|
448 }; |
|
449 |
|
450 static const mozilla::Module kServicesCryptoModule = { |
|
451 mozilla::Module::kVersion, |
|
452 kServicesCryptoCIDs, |
|
453 kServicesCryptoContracts |
|
454 }; |
|
455 |
|
456 NSMODULE_DEFN(nsServicesCryptoModule) = &kServicesCryptoModule; |