services/crypto/component/nsSyncJPAKE.cpp

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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

mercurial