1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/crypto/component/nsSyncJPAKE.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,456 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsSyncJPAKE.h" 1.9 +#include "mozilla/ModuleUtils.h" 1.10 +#include <pk11pub.h> 1.11 +#include <keyhi.h> 1.12 +#include <pkcs11.h> 1.13 +#include <nscore.h> 1.14 +#include <secmodt.h> 1.15 +#include <secport.h> 1.16 +#include <secerr.h> 1.17 +#include <nsDebug.h> 1.18 +#include <nsError.h> 1.19 +#include <base64.h> 1.20 +#include <nsString.h> 1.21 + 1.22 +using mozilla::fallible_t; 1.23 + 1.24 +static bool 1.25 +hex_from_2char(const unsigned char *c2, unsigned char *byteval) 1.26 +{ 1.27 + int i; 1.28 + unsigned char offset; 1.29 + *byteval = 0; 1.30 + for (i=0; i<2; i++) { 1.31 + if (c2[i] >= '0' && c2[i] <= '9') { 1.32 + offset = c2[i] - '0'; 1.33 + *byteval |= offset << 4*(1-i); 1.34 + } else if (c2[i] >= 'a' && c2[i] <= 'f') { 1.35 + offset = c2[i] - 'a'; 1.36 + *byteval |= (offset + 10) << 4*(1-i); 1.37 + } else if (c2[i] >= 'A' && c2[i] <= 'F') { 1.38 + offset = c2[i] - 'A'; 1.39 + *byteval |= (offset + 10) << 4*(1-i); 1.40 + } else { 1.41 + return false; 1.42 + } 1.43 + } 1.44 + return true; 1.45 +} 1.46 + 1.47 +static bool 1.48 +fromHex(const char * str, unsigned char * p, size_t sLen) 1.49 +{ 1.50 + size_t i; 1.51 + if (sLen & 1) 1.52 + return false; 1.53 + 1.54 + for (i = 0; i < sLen / 2; ++i) { 1.55 + if (!hex_from_2char((const unsigned char *) str + (2*i), 1.56 + (unsigned char *) p + i)) { 1.57 + return false; 1.58 + } 1.59 + } 1.60 + return true; 1.61 +} 1.62 + 1.63 +static nsresult 1.64 +fromHexString(const nsACString & str, unsigned char * p, size_t pMaxLen) 1.65 +{ 1.66 + char * strData = (char *) str.Data(); 1.67 + unsigned len = str.Length(); 1.68 + NS_ENSURE_ARG(len / 2 <= pMaxLen); 1.69 + if (!fromHex(strData, p, len)) { 1.70 + return NS_ERROR_INVALID_ARG; 1.71 + } 1.72 + return NS_OK; 1.73 +} 1.74 + 1.75 +static bool 1.76 +toHexString(const unsigned char * str, unsigned len, nsACString & out) 1.77 +{ 1.78 + static const char digits[] = "0123456789ABCDEF"; 1.79 + if (!out.SetCapacity(2 * len, fallible_t())) 1.80 + return false; 1.81 + out.SetLength(0); 1.82 + for (unsigned i = 0; i < len; ++i) { 1.83 + out.Append(digits[str[i] >> 4]); 1.84 + out.Append(digits[str[i] & 0x0f]); 1.85 + } 1.86 + return true; 1.87 +} 1.88 + 1.89 +static nsresult 1.90 +mapErrno() 1.91 +{ 1.92 + int err = PORT_GetError(); 1.93 + switch (err) { 1.94 + case SEC_ERROR_NO_MEMORY: return NS_ERROR_OUT_OF_MEMORY; 1.95 + default: return NS_ERROR_UNEXPECTED; 1.96 + } 1.97 +} 1.98 + 1.99 +#define NUM_ELEM(x) (sizeof(x) / sizeof (x)[0]) 1.100 + 1.101 +static const char p[] = 1.102 + "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" 1.103 + "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" 1.104 + "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" 1.105 + "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" 1.106 + "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" 1.107 + "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" 1.108 + "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" 1.109 + "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" 1.110 + "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" 1.111 + "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" 1.112 + "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" 1.113 + "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73"; 1.114 +static const char q[] = 1.115 + "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D"; 1.116 +static const char g[] = 1.117 + "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" 1.118 + "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" 1.119 + "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" 1.120 + "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" 1.121 + "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" 1.122 + "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" 1.123 + "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" 1.124 + "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" 1.125 + "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" 1.126 + "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" 1.127 + "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" 1.128 + "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B"; 1.129 + 1.130 +NS_IMETHODIMP nsSyncJPAKE::Round1(const nsACString & aSignerID, 1.131 + nsACString & aGX1, 1.132 + nsACString & aGV1, 1.133 + nsACString & aR1, 1.134 + nsACString & aGX2, 1.135 + nsACString & aGV2, 1.136 + nsACString & aR2) 1.137 +{ 1.138 + NS_ENSURE_STATE(round == JPAKENotStarted); 1.139 + NS_ENSURE_STATE(key == nullptr); 1.140 + 1.141 + static CK_MECHANISM_TYPE mechanisms[] = { 1.142 + CKM_NSS_JPAKE_ROUND1_SHA256, 1.143 + CKM_NSS_JPAKE_ROUND2_SHA256, 1.144 + CKM_NSS_JPAKE_FINAL_SHA256 1.145 + }; 1.146 + 1.147 + PK11SlotInfo * slot = PK11_GetBestSlotMultiple(mechanisms, 1.148 + NUM_ELEM(mechanisms), 1.149 + nullptr); 1.150 + NS_ENSURE_STATE(slot != nullptr); 1.151 + 1.152 + CK_BYTE pBuf[(NUM_ELEM(p) - 1) / 2]; 1.153 + CK_BYTE qBuf[(NUM_ELEM(q) - 1) / 2]; 1.154 + CK_BYTE gBuf[(NUM_ELEM(g) - 1) / 2]; 1.155 + 1.156 + CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND1; 1.157 + NS_ENSURE_STATE(fromHex(p, pBuf, (NUM_ELEM(p) - 1))); 1.158 + NS_ENSURE_STATE(fromHex(q, qBuf, (NUM_ELEM(q) - 1))); 1.159 + NS_ENSURE_STATE(fromHex(g, gBuf, (NUM_ELEM(g) - 1))); 1.160 + CK_ATTRIBUTE keyTemplate[] = { 1.161 + { CKA_NSS_JPAKE_SIGNERID, (CK_BYTE *) aSignerID.Data(), 1.162 + aSignerID.Length() }, 1.163 + { CKA_KEY_TYPE, &keyType, sizeof keyType }, 1.164 + { CKA_PRIME, pBuf, sizeof pBuf }, 1.165 + { CKA_SUBPRIME, qBuf, sizeof qBuf }, 1.166 + { CKA_BASE, gBuf, sizeof gBuf } 1.167 + }; 1.168 + 1.169 + CK_BYTE gx1Buf[NUM_ELEM(p) / 2]; 1.170 + CK_BYTE gv1Buf[NUM_ELEM(p) / 2]; 1.171 + CK_BYTE r1Buf [NUM_ELEM(p) / 2]; 1.172 + CK_BYTE gx2Buf[NUM_ELEM(p) / 2]; 1.173 + CK_BYTE gv2Buf[NUM_ELEM(p) / 2]; 1.174 + CK_BYTE r2Buf [NUM_ELEM(p) / 2]; 1.175 + CK_NSS_JPAKERound1Params rp = { 1.176 + { gx1Buf, sizeof gx1Buf, gv1Buf, sizeof gv1Buf, r1Buf, sizeof r1Buf }, 1.177 + { gx2Buf, sizeof gx2Buf, gv2Buf, sizeof gv2Buf, r2Buf, sizeof r2Buf } 1.178 + }; 1.179 + SECItem paramsItem; 1.180 + paramsItem.data = (unsigned char *) &rp; 1.181 + paramsItem.len = sizeof rp; 1.182 + key = PK11_KeyGenWithTemplate(slot, CKM_NSS_JPAKE_ROUND1_SHA256, 1.183 + CKM_NSS_JPAKE_ROUND1_SHA256, 1.184 + ¶msItem, keyTemplate, 1.185 + NUM_ELEM(keyTemplate), nullptr); 1.186 + nsresult rv = key != nullptr 1.187 + ? NS_OK 1.188 + : mapErrno(); 1.189 + if (rv == NS_OK) { 1.190 + NS_ENSURE_TRUE(toHexString(rp.gx1.pGX, rp.gx1.ulGXLen, aGX1) && 1.191 + toHexString(rp.gx1.pGV, rp.gx1.ulGVLen, aGV1) && 1.192 + toHexString(rp.gx1.pR, rp.gx1.ulRLen, aR1) && 1.193 + toHexString(rp.gx2.pGX, rp.gx2.ulGXLen, aGX2) && 1.194 + toHexString(rp.gx2.pGV, rp.gx2.ulGVLen, aGV2) && 1.195 + toHexString(rp.gx2.pR, rp.gx2.ulRLen, aR2), 1.196 + NS_ERROR_OUT_OF_MEMORY); 1.197 + round = JPAKEBeforeRound2; 1.198 + } 1.199 + return rv; 1.200 +} 1.201 + 1.202 +NS_IMETHODIMP nsSyncJPAKE::Round2(const nsACString & aPeerID, 1.203 + const nsACString & aPIN, 1.204 + const nsACString & aGX3, 1.205 + const nsACString & aGV3, 1.206 + const nsACString & aR3, 1.207 + const nsACString & aGX4, 1.208 + const nsACString & aGV4, 1.209 + const nsACString & aR4, 1.210 + nsACString & aA, 1.211 + nsACString & aGVA, 1.212 + nsACString & aRA) 1.213 +{ 1.214 + NS_ENSURE_STATE(round == JPAKEBeforeRound2); 1.215 + NS_ENSURE_STATE(key != nullptr); 1.216 + NS_ENSURE_ARG(!aPeerID.IsEmpty()); 1.217 + 1.218 + /* PIN cannot be equal to zero when converted to a bignum. NSS 3.12.9 J-PAKE 1.219 + assumes that the caller has already done this check. Future versions of 1.220 + NSS J-PAKE will do this check internally. See Bug 609068 Comment 4 */ 1.221 + bool foundNonZero = false; 1.222 + for (size_t i = 0; i < aPIN.Length(); ++i) { 1.223 + if (aPIN[i] != 0) { 1.224 + foundNonZero = true; 1.225 + break; 1.226 + } 1.227 + } 1.228 + NS_ENSURE_ARG(foundNonZero); 1.229 + 1.230 + CK_BYTE gx3Buf[NUM_ELEM(p)/2], gv3Buf[NUM_ELEM(p)/2], r3Buf [NUM_ELEM(p)/2]; 1.231 + CK_BYTE gx4Buf[NUM_ELEM(p)/2], gv4Buf[NUM_ELEM(p)/2], r4Buf [NUM_ELEM(p)/2]; 1.232 + CK_BYTE gxABuf[NUM_ELEM(p)/2], gvABuf[NUM_ELEM(p)/2], rABuf [NUM_ELEM(p)/2]; 1.233 + nsresult rv = fromHexString(aGX3, gx3Buf, sizeof gx3Buf); 1.234 + if (rv == NS_OK) rv = fromHexString(aGV3, gv3Buf, sizeof gv3Buf); 1.235 + if (rv == NS_OK) rv = fromHexString(aR3, r3Buf, sizeof r3Buf); 1.236 + if (rv == NS_OK) rv = fromHexString(aGX4, gx4Buf, sizeof gx4Buf); 1.237 + if (rv == NS_OK) rv = fromHexString(aGV4, gv4Buf, sizeof gv4Buf); 1.238 + if (rv == NS_OK) rv = fromHexString(aR4, r4Buf, sizeof r4Buf); 1.239 + if (rv != NS_OK) 1.240 + return rv; 1.241 + 1.242 + CK_NSS_JPAKERound2Params rp; 1.243 + rp.pSharedKey = (CK_BYTE *) aPIN.Data(); 1.244 + rp.ulSharedKeyLen = aPIN.Length(); 1.245 + rp.gx3.pGX = gx3Buf; rp.gx3.ulGXLen = aGX3.Length() / 2; 1.246 + rp.gx3.pGV = gv3Buf; rp.gx3.ulGVLen = aGV3.Length() / 2; 1.247 + rp.gx3.pR = r3Buf; rp.gx3.ulRLen = aR3 .Length() / 2; 1.248 + rp.gx4.pGX = gx4Buf; rp.gx4.ulGXLen = aGX4.Length() / 2; 1.249 + rp.gx4.pGV = gv4Buf; rp.gx4.ulGVLen = aGV4.Length() / 2; 1.250 + rp.gx4.pR = r4Buf; rp.gx4.ulRLen = aR4 .Length() / 2; 1.251 + rp.A.pGX = gxABuf; rp.A .ulGXLen = sizeof gxABuf; 1.252 + rp.A.pGV = gvABuf; rp.A .ulGVLen = sizeof gxABuf; 1.253 + rp.A.pR = rABuf; rp.A .ulRLen = sizeof gxABuf; 1.254 + 1.255 + // Bug 629090: NSS 3.12.9 J-PAKE fails to check that gx^4 != 1, so check here. 1.256 + bool gx4Good = false; 1.257 + for (unsigned i = 0; i < rp.gx4.ulGXLen; ++i) { 1.258 + if (rp.gx4.pGX[i] > 1 || (rp.gx4.pGX[i] != 0 && i < rp.gx4.ulGXLen - 1)) { 1.259 + gx4Good = true; 1.260 + break; 1.261 + } 1.262 + } 1.263 + NS_ENSURE_ARG(gx4Good); 1.264 + 1.265 + SECItem paramsItem; 1.266 + paramsItem.data = (unsigned char *) &rp; 1.267 + paramsItem.len = sizeof rp; 1.268 + CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND2; 1.269 + CK_ATTRIBUTE keyTemplate[] = { 1.270 + { CKA_NSS_JPAKE_PEERID, (CK_BYTE *) aPeerID.Data(), aPeerID.Length(), }, 1.271 + { CKA_KEY_TYPE, &keyType, sizeof keyType } 1.272 + }; 1.273 + PK11SymKey * newKey = PK11_DeriveWithTemplate(key, 1.274 + CKM_NSS_JPAKE_ROUND2_SHA256, 1.275 + ¶msItem, 1.276 + CKM_NSS_JPAKE_FINAL_SHA256, 1.277 + CKA_DERIVE, 0, 1.278 + keyTemplate, 1.279 + NUM_ELEM(keyTemplate), 1.280 + false); 1.281 + if (newKey != nullptr) { 1.282 + if (toHexString(rp.A.pGX, rp.A.ulGXLen, aA) && 1.283 + toHexString(rp.A.pGV, rp.A.ulGVLen, aGVA) && 1.284 + toHexString(rp.A.pR, rp.A.ulRLen, aRA)) { 1.285 + round = JPAKEAfterRound2; 1.286 + PK11_FreeSymKey(key); 1.287 + key = newKey; 1.288 + return NS_OK; 1.289 + } else { 1.290 + PK11_FreeSymKey(newKey); 1.291 + rv = NS_ERROR_OUT_OF_MEMORY; 1.292 + } 1.293 + } else 1.294 + rv = mapErrno(); 1.295 + 1.296 + return rv; 1.297 +} 1.298 + 1.299 +static nsresult 1.300 +setBase64(const unsigned char * data, unsigned len, nsACString & out) 1.301 +{ 1.302 + nsresult rv = NS_OK; 1.303 + const char * base64 = BTOA_DataToAscii(data, len); 1.304 + 1.305 + if (base64 != nullptr) { 1.306 + size_t len = PORT_Strlen(base64); 1.307 + if (out.SetCapacity(len, fallible_t())) { 1.308 + out.SetLength(0); 1.309 + out.Append(base64, len); 1.310 + PORT_Free((void*) base64); 1.311 + } else { 1.312 + rv = NS_ERROR_OUT_OF_MEMORY; 1.313 + } 1.314 + } else { 1.315 + rv = NS_ERROR_OUT_OF_MEMORY; 1.316 + } 1.317 + return rv; 1.318 +} 1.319 + 1.320 +static nsresult 1.321 +base64KeyValue(PK11SymKey * key, nsACString & keyString) 1.322 +{ 1.323 + nsresult rv = NS_OK; 1.324 + if (PK11_ExtractKeyValue(key) == SECSuccess) { 1.325 + const SECItem * value = PK11_GetKeyData(key); 1.326 + rv = value != nullptr && value->data != nullptr && value->len > 0 1.327 + ? setBase64(value->data, value->len, keyString) 1.328 + : NS_ERROR_UNEXPECTED; 1.329 + } else { 1.330 + rv = mapErrno(); 1.331 + } 1.332 + return rv; 1.333 +} 1.334 + 1.335 +static nsresult 1.336 +extractBase64KeyValue(PK11SymKey * keyBlock, CK_ULONG bitPosition, 1.337 + CK_MECHANISM_TYPE destMech, int keySize, 1.338 + nsACString & keyString) 1.339 +{ 1.340 + SECItem paramsItem; 1.341 + paramsItem.data = (CK_BYTE *) &bitPosition; 1.342 + paramsItem.len = sizeof bitPosition; 1.343 + PK11SymKey * key = PK11_Derive(keyBlock, CKM_EXTRACT_KEY_FROM_KEY, 1.344 + ¶msItem, destMech, 1.345 + CKA_SIGN, keySize); 1.346 + if (key == nullptr) 1.347 + return mapErrno(); 1.348 + nsresult rv = base64KeyValue(key, keyString); 1.349 + PK11_FreeSymKey(key); 1.350 + return rv; 1.351 +} 1.352 + 1.353 + 1.354 +NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB, 1.355 + const nsACString & aGVB, 1.356 + const nsACString & aRB, 1.357 + const nsACString & aHKDFInfo, 1.358 + nsACString & aAES256Key, 1.359 + nsACString & aHMAC256Key) 1.360 +{ 1.361 + static const unsigned AES256_KEY_SIZE = 256 / 8; 1.362 + static const unsigned HMAC_SHA256_KEY_SIZE = 256 / 8; 1.363 + CK_EXTRACT_PARAMS aesBitPosition = 0; 1.364 + CK_EXTRACT_PARAMS hmacBitPosition = aesBitPosition + (AES256_KEY_SIZE * 8); 1.365 + 1.366 + NS_ENSURE_STATE(round == JPAKEAfterRound2); 1.367 + NS_ENSURE_STATE(key != nullptr); 1.368 + 1.369 + CK_BYTE gxBBuf[NUM_ELEM(p)/2], gvBBuf[NUM_ELEM(p)/2], rBBuf [NUM_ELEM(p)/2]; 1.370 + nsresult rv = fromHexString(aB, gxBBuf, sizeof gxBBuf); 1.371 + if (rv == NS_OK) rv = fromHexString(aGVB, gvBBuf, sizeof gvBBuf); 1.372 + if (rv == NS_OK) rv = fromHexString(aRB, rBBuf, sizeof rBBuf); 1.373 + if (rv != NS_OK) 1.374 + return rv; 1.375 + 1.376 + CK_NSS_JPAKEFinalParams rp; 1.377 + rp.B.pGX = gxBBuf; rp.B.ulGXLen = aB .Length() / 2; 1.378 + rp.B.pGV = gvBBuf; rp.B.ulGVLen = aGVB.Length() / 2; 1.379 + rp.B.pR = rBBuf; rp.B.ulRLen = aRB .Length() / 2; 1.380 + SECItem paramsItem; 1.381 + paramsItem.data = (unsigned char *) &rp; 1.382 + paramsItem.len = sizeof rp; 1.383 + PK11SymKey * keyMaterial = PK11_Derive(key, CKM_NSS_JPAKE_FINAL_SHA256, 1.384 + ¶msItem, CKM_NSS_HKDF_SHA256, 1.385 + CKA_DERIVE, 0); 1.386 + PK11SymKey * keyBlock = nullptr; 1.387 + 1.388 + if (keyMaterial == nullptr) 1.389 + rv = mapErrno(); 1.390 + 1.391 + if (rv == NS_OK) { 1.392 + CK_NSS_HKDFParams hkdfParams; 1.393 + hkdfParams.bExtract = CK_TRUE; 1.394 + hkdfParams.pSalt = nullptr; 1.395 + hkdfParams.ulSaltLen = 0; 1.396 + hkdfParams.bExpand = CK_TRUE; 1.397 + hkdfParams.pInfo = (CK_BYTE *) aHKDFInfo.Data(); 1.398 + hkdfParams.ulInfoLen = aHKDFInfo.Length(); 1.399 + paramsItem.data = (unsigned char *) &hkdfParams; 1.400 + paramsItem.len = sizeof hkdfParams; 1.401 + keyBlock = PK11_Derive(keyMaterial, CKM_NSS_HKDF_SHA256, 1.402 + ¶msItem, CKM_EXTRACT_KEY_FROM_KEY, 1.403 + CKA_DERIVE, AES256_KEY_SIZE + HMAC_SHA256_KEY_SIZE); 1.404 + if (keyBlock == nullptr) 1.405 + rv = mapErrno(); 1.406 + } 1.407 + 1.408 + if (rv == NS_OK) { 1.409 + rv = extractBase64KeyValue(keyBlock, aesBitPosition, CKM_AES_CBC, 1.410 + AES256_KEY_SIZE, aAES256Key); 1.411 + } 1.412 + if (rv == NS_OK) { 1.413 + rv = extractBase64KeyValue(keyBlock, hmacBitPosition, CKM_SHA256_HMAC, 1.414 + HMAC_SHA256_KEY_SIZE, aHMAC256Key); 1.415 + } 1.416 + 1.417 + if (rv == NS_OK) { 1.418 + SECStatus srv = PK11_ExtractKeyValue(keyMaterial); 1.419 + NS_ENSURE_TRUE(srv == SECSuccess, NS_ERROR_UNEXPECTED); // XXX leaks 1.420 + SECItem * keyMaterialBytes = PK11_GetKeyData(keyMaterial); 1.421 + NS_ENSURE_TRUE(keyMaterialBytes != nullptr, NS_ERROR_UNEXPECTED); 1.422 + } 1.423 + 1.424 + if (keyBlock != nullptr) 1.425 + PK11_FreeSymKey(keyBlock); 1.426 + if (keyMaterial != nullptr) 1.427 + PK11_FreeSymKey(keyMaterial); 1.428 + 1.429 + return rv; 1.430 +} 1.431 + 1.432 +NS_GENERIC_FACTORY_CONSTRUCTOR(nsSyncJPAKE) 1.433 +NS_DEFINE_NAMED_CID(NS_SYNCJPAKE_CID); 1.434 + 1.435 +nsSyncJPAKE::nsSyncJPAKE() : round(JPAKENotStarted), key(nullptr) { } 1.436 + 1.437 +nsSyncJPAKE::~nsSyncJPAKE() 1.438 +{ 1.439 + if (key != nullptr) 1.440 + PK11_FreeSymKey(key); 1.441 +} 1.442 + 1.443 +static const mozilla::Module::CIDEntry kServicesCryptoCIDs[] = { 1.444 + { &kNS_SYNCJPAKE_CID, false, nullptr, nsSyncJPAKEConstructor }, 1.445 + { nullptr } 1.446 +}; 1.447 + 1.448 +static const mozilla::Module::ContractIDEntry kServicesCryptoContracts[] = { 1.449 + { NS_SYNCJPAKE_CONTRACTID, &kNS_SYNCJPAKE_CID }, 1.450 + { nullptr } 1.451 +}; 1.452 + 1.453 +static const mozilla::Module kServicesCryptoModule = { 1.454 + mozilla::Module::kVersion, 1.455 + kServicesCryptoCIDs, 1.456 + kServicesCryptoContracts 1.457 +}; 1.458 + 1.459 +NSMODULE_DEFN(nsServicesCryptoModule) = &kServicesCryptoModule;