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