Bug 601645 - JavaScript API for NSS J-PAKE. r=mconnor a=blocking-beta8

This commit is contained in:
Brian Smith 2010-12-09 18:27:48 -08:00
parent 9de6f8bfc9
commit ff1c112075
8 changed files with 712 additions and 1 deletions

View File

@ -50,7 +50,6 @@ tier_app_dirs += $(MOZ_BRANDING_DIRECTORY)
tier_app_dirs += toolkit/components/console/hudservice
ifdef MOZ_SERVICES_SYNC
tier_app_dirs += services/crypto
tier_app_dirs += services/sync
endif

View File

@ -48,6 +48,19 @@ XPIDL_MODULE = services-crypto
XPIDLSRCS = \
IWeaveCrypto.idl \
nsISyncJPAKE.idl \
$(NULL)
LIBRARY_NAME = services-crypto
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = nsServicesCryptoModule
LIBXUL_LIBRARY = 1
FORCE_USE_PIC = 1
MOZILLA_INTERNAL_API = 1
CPPSRCS = \
nsSyncJPAKE.cpp \
$(NULL)
libs::
@ -58,3 +71,9 @@ DIRS += tests
endif
include $(topsrcdir)/config/rules.mk
EXTRA_DSO_LDOPTS += \
$(MOZ_COMPONENT_LIBS) \
$(NSPR_LIBS) \
$(NSS_LIBS) \
$(NULL)

View File

@ -0,0 +1,137 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Sync.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Smith <bsmith@mozilla.com>
* Philipp von Weitershausen <philipp@weitershausen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(5ab02a98-5122-4b90-93cd-f259c4b42e3a)]
interface nsISyncJPAKE : nsISupports
{
/**
* Perform first round of the JPAKE exchange.
*
* @param aSignerID
* String identifying the signer.
* @param aGX1
* Schnorr signature value g^x1, in hex representation.
* @param aGV1
* Schnorr signature value g^v1 (v1 is a random value), in hex
* representation.
* @param aR1
* Schnorr signature value r1 = v1 - x1 * h, in hex representation.
* @param aGX2
* Schnorr signature value g^x2, in hex representation.
* @param aGV2
* Schnorr signature value g^v2 (v2 is a random value), in hex
* representation.
* @param aR2
* Schnorr signature value r2 = v2 - x2 * h, in hex representation.
*/
void round1(in ACString aSignerID,
out ACString aGX1,
out ACString aGV1,
out ACString aR1,
out ACString aGX2,
out ACString aGV2,
out ACString aR2);
/**
* Perform second round of the JPAKE exchange.
*
* @param aPeerID
* String identifying the peer.
* @param aPIN
* String containing the weak secret (PIN).
* @param aGX3
* Schnorr signature value g^x3, in hex representation.
* @param aGV3
* Schnorr signature value g^v3 (v3 is a random value), in hex
* representation.
* @param aR3
* Schnorr signature value r3 = v3 - x3 * h, in hex representation.
* @param aGX4
* Schnorr signature value g^x4, in hex representation.
* @param aGV4
* Schnorr signature value g^v4 (v4 is a random value), in hex
* representation.
* @param aR4
* Schnorr signature value r4 = v4 - x4 * h, in hex representation.
* @param aA
* Schnorr signature value A, in hex representation.
* @param aGVA
* Schnorr signature value g^va (va is a random value), in hex
* representation.
* @param aRA
* Schnorr signature value ra = va - xa * h, in hex representation.
*/
void round2(in ACString aPeerID,
in ACString aPIN,
in ACString aGX3,
in ACString aGV3,
in ACString aR3,
in ACString aGX4,
in ACString aGV4,
in ACString aR4,
out ACString aA,
out ACString aGVA,
out ACString aRA);
/**
* Perform the final step of the JPAKE exchange. This will compute
* the key and expand the key to two keys, an AES256 encryption key
* and a 256 bit HMAC key. It returns a key confirmation value
* (SHA256d of the key) and the encryption and HMAC keys.
*
* @param aB
* Schnorr signature value B, in hex representation.
* @param aGVB
* Schnorr signature value g^vb (vb is a random value), in hex
* representation.
* @param aRB
* Schnorr signature value rb = vb - xb * h, in hex representation.
* @param aAES256Key
* The AES 256 encryption key, in base64 representation.
* @param aHMAC256Key
* The 256 bit HMAC key, in base64 representation.
*/
void final(in ACString aB,
in ACString aGVB,
in ACString aRB,
in ACString aHkdfInfo,
out ACString aAES256Key,
out ACString aHMAC256Key);
};

View File

@ -0,0 +1,476 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Sync.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Smith <bsmith@mozilla.com>
* Philipp von Weitershausen <philipp@weitershausen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSyncJPAKE.h"
#include "mozilla/ModuleUtils.h"
#include <pk11pub.h>
#include <keyhi.h>
#include <pkcs11.h>
#include <nscore.h>
#include <secmodt.h>
#include <secport.h>
#include <secerr.h>
#include <nsDebug.h>
#include <nsError.h>
#include <base64.h>
#include <nsString.h>
static PRBool
hex_from_2char(const unsigned char *c2, unsigned char *byteval)
{
int i;
unsigned char offset;
*byteval = 0;
for (i=0; i<2; i++) {
if (c2[i] >= '0' && c2[i] <= '9') {
offset = c2[i] - '0';
*byteval |= offset << 4*(1-i);
} else if (c2[i] >= 'a' && c2[i] <= 'f') {
offset = c2[i] - 'a';
*byteval |= (offset + 10) << 4*(1-i);
} else if (c2[i] >= 'A' && c2[i] <= 'F') {
offset = c2[i] - 'A';
*byteval |= (offset + 10) << 4*(1-i);
} else {
return PR_FALSE;
}
}
return PR_TRUE;
}
static PRBool
fromHex(const char * str, unsigned char * p, size_t sLen)
{
size_t i;
if (sLen & 1)
return PR_FALSE;
for (i = 0; i < sLen / 2; ++i) {
if (!hex_from_2char((const unsigned char *) str + (2*i),
(unsigned char *) p + i)) {
return PR_FALSE;
}
}
return PR_TRUE;
}
static nsresult
fromHexString(const nsACString & str, unsigned char * p, size_t pMaxLen)
{
char * strData = (char *) str.Data();
unsigned len = str.Length();
NS_ENSURE_ARG(len / 2 <= pMaxLen);
if (!fromHex(strData, p, len)) {
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
static PRBool
toHexString(const unsigned char * str, unsigned len, nsACString & out)
{
static const char digits[] = "0123456789ABCDEF";
if (!out.SetCapacity(2 * len))
return NS_ERROR_OUT_OF_MEMORY;
out.SetLength(0);
for (unsigned i = 0; i < len; ++i) {
out.Append(digits[str[i] >> 4]);
out.Append(digits[str[i] & 0x0f]);
}
return PR_TRUE;
}
static nsresult
mapErrno()
{
int err = PORT_GetError();
switch (err) {
case SEC_ERROR_NO_MEMORY: return NS_ERROR_OUT_OF_MEMORY;
default: return NS_ERROR_UNEXPECTED;
}
}
#define NUM_ELEM(x) (sizeof(x) / sizeof (x)[0])
static const char p[] =
"90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C"
"7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F"
"009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1"
"29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B"
"6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394"
"87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0"
"E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E"
"BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D"
"AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F"
"B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D"
"597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E"
"C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73";
static const char q[] =
"CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D";
static const char g[] =
"5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37"
"F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB"
"805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1"
"F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8"
"A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17"
"A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C"
"4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3"
"9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B"
"9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8"
"E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828"
"E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33"
"787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B";
NS_IMETHODIMP nsSyncJPAKE::Round1(const nsACString & aSignerID,
nsACString & aGX1 NS_OUTPARAM,
nsACString & aGV1 NS_OUTPARAM,
nsACString & aR1 NS_OUTPARAM,
nsACString & aGX2 NS_OUTPARAM,
nsACString & aGV2 NS_OUTPARAM,
nsACString & aR2 NS_OUTPARAM)
{
NS_ENSURE_STATE(round == JPAKENotStarted);
NS_ENSURE_STATE(key == NULL);
static CK_MECHANISM_TYPE mechanisms[] = {
CKM_NSS_JPAKE_ROUND1_SHA256,
CKM_NSS_JPAKE_ROUND2_SHA256,
CKM_NSS_JPAKE_FINAL_SHA256
};
PK11SlotInfo * slot = PK11_GetBestSlotMultiple(mechanisms,
NUM_ELEM(mechanisms), NULL);
NS_ENSURE_STATE(slot != NULL);
CK_BYTE pBuf[(NUM_ELEM(p) - 1) / 2];
CK_BYTE qBuf[(NUM_ELEM(q) - 1) / 2];
CK_BYTE gBuf[(NUM_ELEM(g) - 1) / 2];
CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND1;
NS_ENSURE_STATE(fromHex(p, pBuf, (NUM_ELEM(p) - 1)));
NS_ENSURE_STATE(fromHex(q, qBuf, (NUM_ELEM(q) - 1)));
NS_ENSURE_STATE(fromHex(g, gBuf, (NUM_ELEM(g) - 1)));
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_NSS_JPAKE_SIGNERID, (CK_BYTE *) aSignerID.Data(),
aSignerID.Length() },
{ CKA_KEY_TYPE, &keyType, sizeof keyType },
{ CKA_PRIME, pBuf, sizeof pBuf },
{ CKA_SUBPRIME, qBuf, sizeof qBuf },
{ CKA_BASE, gBuf, sizeof gBuf }
};
CK_BYTE gx1Buf[NUM_ELEM(p) / 2];
CK_BYTE gv1Buf[NUM_ELEM(p) / 2];
CK_BYTE r1Buf [NUM_ELEM(p) / 2];
CK_BYTE gx2Buf[NUM_ELEM(p) / 2];
CK_BYTE gv2Buf[NUM_ELEM(p) / 2];
CK_BYTE r2Buf [NUM_ELEM(p) / 2];
CK_NSS_JPAKERound1Params rp = {
{ gx1Buf, sizeof gx1Buf, gv1Buf, sizeof gv1Buf, r1Buf, sizeof r1Buf },
{ gx2Buf, sizeof gx2Buf, gv2Buf, sizeof gv2Buf, r2Buf, sizeof r2Buf }
};
SECItem paramsItem;
paramsItem.data = (unsigned char *) &rp;
paramsItem.len = sizeof rp;
key = PK11_KeyGenWithTemplate(slot, CKM_NSS_JPAKE_ROUND1_SHA256,
CKM_NSS_JPAKE_ROUND1_SHA256,
&paramsItem, keyTemplate,
NUM_ELEM(keyTemplate), NULL);
nsresult rv = key != NULL
? NS_OK
: mapErrno();
if (rv == NS_OK) {
NS_ENSURE_TRUE(toHexString(rp.gx1.pGX, rp.gx1.ulGXLen, aGX1) &&
toHexString(rp.gx1.pGV, rp.gx1.ulGVLen, aGV1) &&
toHexString(rp.gx1.pR, rp.gx1.ulRLen, aR1) &&
toHexString(rp.gx2.pGX, rp.gx2.ulGXLen, aGX2) &&
toHexString(rp.gx2.pGV, rp.gx2.ulGVLen, aGV2) &&
toHexString(rp.gx2.pR, rp.gx2.ulRLen, aR2),
NS_ERROR_OUT_OF_MEMORY);
round = JPAKEBeforeRound2;
}
return rv;
}
NS_IMETHODIMP nsSyncJPAKE::Round2(const nsACString & aPeerID,
const nsACString & aPIN,
const nsACString & aGX3,
const nsACString & aGV3,
const nsACString & aR3,
const nsACString & aGX4,
const nsACString & aGV4,
const nsACString & aR4,
nsACString & aA NS_OUTPARAM,
nsACString & aGVA NS_OUTPARAM,
nsACString & aRA NS_OUTPARAM)
{
NS_ENSURE_STATE(round == JPAKEBeforeRound2);
NS_ENSURE_STATE(key != NULL);
NS_ENSURE_ARG(!aPeerID.IsEmpty());
/* PIN cannot be equal to zero when converted to a bignum. NSS 3.12.9 J-PAKE
assumes that the caller has already done this check. Future versions of
NSS J-PAKE will do this check internally. See Bug 609068 Comment 4 */
PRBool foundNonZero = PR_FALSE;
for (size_t i = 0; i < aPIN.Length(); ++i) {
if (aPIN[i] != 0) {
foundNonZero = PR_TRUE;
break;
}
}
NS_ENSURE_ARG(foundNonZero);
CK_BYTE gx3Buf[NUM_ELEM(p)/2], gv3Buf[NUM_ELEM(p)/2], r3Buf [NUM_ELEM(p)/2];
CK_BYTE gx4Buf[NUM_ELEM(p)/2], gv4Buf[NUM_ELEM(p)/2], r4Buf [NUM_ELEM(p)/2];
CK_BYTE gxABuf[NUM_ELEM(p)/2], gvABuf[NUM_ELEM(p)/2], rABuf [NUM_ELEM(p)/2];
nsresult rv = fromHexString(aGX3, gx3Buf, sizeof gx3Buf);
if (rv == NS_OK) rv = fromHexString(aGV3, gv3Buf, sizeof gv3Buf);
if (rv == NS_OK) rv = fromHexString(aR3, r3Buf, sizeof r3Buf);
if (rv == NS_OK) rv = fromHexString(aGX4, gx4Buf, sizeof gx4Buf);
if (rv == NS_OK) rv = fromHexString(aGV4, gv4Buf, sizeof gv4Buf);
if (rv == NS_OK) rv = fromHexString(aR4, r4Buf, sizeof r4Buf);
if (rv != NS_OK)
return rv;
CK_NSS_JPAKERound2Params rp;
rp.pSharedKey = (CK_BYTE *) aPIN.Data();
rp.ulSharedKeyLen = aPIN.Length();
rp.gx3.pGX = gx3Buf; rp.gx3.ulGXLen = aGX3.Length() / 2;
rp.gx3.pGV = gv3Buf; rp.gx3.ulGVLen = aGV3.Length() / 2;
rp.gx3.pR = r3Buf; rp.gx3.ulRLen = aR3 .Length() / 2;
rp.gx4.pGX = gx4Buf; rp.gx4.ulGXLen = aGX4.Length() / 2;
rp.gx4.pGV = gv4Buf; rp.gx4.ulGVLen = aGV4.Length() / 2;
rp.gx4.pR = r4Buf; rp.gx4.ulRLen = aR4 .Length() / 2;
rp.A.pGX = gxABuf; rp.A .ulGXLen = sizeof gxABuf;
rp.A.pGV = gvABuf; rp.A .ulGVLen = sizeof gxABuf;
rp.A.pR = rABuf; rp.A .ulRLen = sizeof gxABuf;
SECItem paramsItem;
paramsItem.data = (unsigned char *) &rp;
paramsItem.len = sizeof rp;
CK_KEY_TYPE keyType = CKK_NSS_JPAKE_ROUND2;
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_NSS_JPAKE_PEERID, (CK_BYTE *) aPeerID.Data(), aPeerID.Length(), },
{ CKA_KEY_TYPE, &keyType, sizeof keyType }
};
PK11SymKey * newKey = PK11_DeriveWithTemplate(key,
CKM_NSS_JPAKE_ROUND2_SHA256,
&paramsItem,
CKM_NSS_JPAKE_FINAL_SHA256,
CKA_DERIVE, 0,
keyTemplate,
NUM_ELEM(keyTemplate),
PR_FALSE);
if (newKey != NULL) {
if (toHexString(rp.A.pGX, rp.A.ulGXLen, aA) &&
toHexString(rp.A.pGV, rp.A.ulGVLen, aGVA) &&
toHexString(rp.A.pR, rp.A.ulRLen, aRA)) {
round = JPAKEAfterRound2;
PK11_FreeSymKey(key);
key = newKey;
return NS_OK;
} else {
PK11_FreeSymKey(newKey);
rv = NS_ERROR_OUT_OF_MEMORY;
}
} else
rv = mapErrno();
return rv;
}
static nsresult
setBase64(const unsigned char * data, unsigned len, nsACString & out)
{
nsresult rv = NS_OK;
const char * base64 = BTOA_DataToAscii(data, len);
if (base64 != NULL) {
size_t len = PORT_Strlen(base64);
if (out.SetCapacity(len)) {
out.SetLength(0);
out.Append(base64, len);
PORT_Free((void*) base64);
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
static nsresult
base64KeyValue(PK11SymKey * key, nsACString & keyString)
{
nsresult rv = NS_OK;
if (PK11_ExtractKeyValue(key) == SECSuccess) {
const SECItem * value = PK11_GetKeyData(key);
rv = value != NULL && value->data != NULL && value->len > 0
? setBase64(value->data, value->len, keyString)
: NS_ERROR_UNEXPECTED;
} else {
rv = mapErrno();
}
return rv;
}
static nsresult
extractBase64KeyValue(PK11SymKey * keyBlock, CK_ULONG bitPosition,
CK_MECHANISM_TYPE destMech, int keySize,
nsACString & keyString)
{
SECItem paramsItem;
paramsItem.data = (CK_BYTE *) &bitPosition;
paramsItem.len = sizeof bitPosition;
PK11SymKey * key = PK11_Derive(keyBlock, CKM_EXTRACT_KEY_FROM_KEY,
&paramsItem, destMech,
CKA_SIGN, keySize);
if (key == NULL)
return mapErrno();
nsresult rv = base64KeyValue(key, keyString);
PK11_FreeSymKey(key);
return rv;
}
NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB,
const nsACString & aGVB,
const nsACString & aRB,
const nsACString & aHKDFInfo,
nsACString & aAES256Key NS_OUTPARAM,
nsACString & aHMAC256Key NS_OUTPARAM)
{
static const unsigned AES256_KEY_SIZE = 256 / 8;
static const unsigned HMAC_SHA256_KEY_SIZE = 256 / 8;
CK_EXTRACT_PARAMS aesBitPosition = 0;
CK_EXTRACT_PARAMS hmacBitPosition = aesBitPosition + (AES256_KEY_SIZE * 8);
NS_ENSURE_STATE(round == JPAKEAfterRound2);
NS_ENSURE_STATE(key != NULL);
CK_BYTE gxBBuf[NUM_ELEM(p)/2], gvBBuf[NUM_ELEM(p)/2], rBBuf [NUM_ELEM(p)/2];
nsresult rv = fromHexString(aB, gxBBuf, sizeof gxBBuf);
if (rv == NS_OK) rv = fromHexString(aGVB, gvBBuf, sizeof gvBBuf);
if (rv == NS_OK) rv = fromHexString(aRB, rBBuf, sizeof rBBuf);
if (rv != NS_OK)
return rv;
CK_NSS_JPAKEFinalParams rp;
rp.B.pGX = gxBBuf; rp.B.ulGXLen = aB .Length() / 2;
rp.B.pGV = gvBBuf; rp.B.ulGVLen = aGVB.Length() / 2;
rp.B.pR = rBBuf; rp.B.ulRLen = aRB .Length() / 2;
SECItem paramsItem;
paramsItem.data = (unsigned char *) &rp;
paramsItem.len = sizeof rp;
PK11SymKey * keyMaterial = PK11_Derive(key, CKM_NSS_JPAKE_FINAL_SHA256,
&paramsItem, CKM_NSS_HKDF_SHA256,
CKA_DERIVE, 0);
PK11SymKey * keyBlock = NULL;
if (keyMaterial == NULL)
rv = mapErrno();
if (rv == NS_OK) {
CK_NSS_HKDFParams hkdfParams;
hkdfParams.bExtract = CK_TRUE;
hkdfParams.pSalt = NULL;
hkdfParams.ulSaltLen = 0;
hkdfParams.bExpand = CK_TRUE;
hkdfParams.pInfo = (CK_BYTE *) aHKDFInfo.Data();
hkdfParams.ulInfoLen = aHKDFInfo.Length();
paramsItem.data = (unsigned char *) &hkdfParams;
paramsItem.len = sizeof hkdfParams;
keyBlock = PK11_Derive(keyMaterial, CKM_NSS_HKDF_SHA256,
&paramsItem, CKM_EXTRACT_KEY_FROM_KEY,
CKA_DERIVE, AES256_KEY_SIZE + HMAC_SHA256_KEY_SIZE);
if (keyBlock == NULL)
rv = mapErrno();
}
if (rv == NS_OK) {
rv = extractBase64KeyValue(keyBlock, aesBitPosition, CKM_AES_CBC,
AES256_KEY_SIZE, aAES256Key);
}
if (rv == NS_OK) {
rv = extractBase64KeyValue(keyBlock, hmacBitPosition, CKM_SHA256_HMAC,
HMAC_SHA256_KEY_SIZE, aHMAC256Key);
}
if (rv == NS_OK) {
SECStatus srv = PK11_ExtractKeyValue(keyMaterial);
NS_ENSURE_TRUE(srv == SECSuccess, NS_ERROR_UNEXPECTED); // XXX leaks
SECItem * keyMaterialBytes = PK11_GetKeyData(keyMaterial);
NS_ENSURE_TRUE(keyMaterialBytes != NULL, NS_ERROR_UNEXPECTED);
}
if (keyBlock != NULL)
PK11_FreeSymKey(keyBlock);
if (keyMaterial != NULL)
PK11_FreeSymKey(keyMaterial);
return rv;
}
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSyncJPAKE)
NS_DEFINE_NAMED_CID(NS_SYNCJPAKE_CID);
nsSyncJPAKE::nsSyncJPAKE() : round(JPAKENotStarted), key(NULL) { }
nsSyncJPAKE::~nsSyncJPAKE()
{
if (key != NULL)
PK11_FreeSymKey(key);
}
static const mozilla::Module::CIDEntry kServicesCryptoCIDs[] = {
{ &kNS_SYNCJPAKE_CID, false, NULL, nsSyncJPAKEConstructor },
{ NULL }
};
static const mozilla::Module::ContractIDEntry kServicesCryptoContracts[] = {
{ NS_SYNCJPAKE_CONTRACTID, &kNS_SYNCJPAKE_CID },
{ NULL }
};
static const mozilla::Module kServicesCryptoModule = {
mozilla::Module::kVersion,
kServicesCryptoCIDs,
kServicesCryptoContracts
};
NSMODULE_DEFN(nsServicesCryptoModule) = &kServicesCryptoModule;

View File

@ -0,0 +1,65 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Sync.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Smith <bsmith@mozilla.com>
* Philipp von Weitershausen <philipp@weitershausen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsSyncJPAKE_h__
#define nsSyncJPAKE_h__
#include "nsISyncJPAKE.h"
#define NS_SYNCJPAKE_CONTRACTID \
"@mozilla.org/services-crypto/sync-jpake;1"
#define NS_SYNCJPAKE_CID \
{0x0b9721c0, 0x1805, 0x47c3, {0x86, 0xce, 0x68, 0x13, 0x79, 0x5a, 0x78, 0x3f}}
typedef struct PK11SymKeyStr PK11SymKey;
class nsSyncJPAKE : public nsISyncJPAKE
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISYNCJPAKE
nsSyncJPAKE();
virtual ~nsSyncJPAKE();
private:
enum { JPAKENotStarted, JPAKEBeforeRound2, JPAKEAfterRound2 } round;
PK11SymKey * key;
};
NS_IMPL_ISUPPORTS1(nsSyncJPAKE, nsISyncJPAKE)
#endif // nsSyncJPAKE_h__

View File

@ -350,6 +350,10 @@ DEFINES += -DMOZ_ZIPWRITER
COMPONENT_LIBS += zipwriter
endif
ifdef MOZ_SERVICES_SYNC
COMPONENT_LIBS += services-crypto
endif
ifdef MOZ_DEBUG
ifdef ENABLE_TESTS
COMPONENT_LIBS += gkdebug

View File

@ -233,6 +233,12 @@
#define JSCTYPES_MODULE
#endif
#ifdef MOZ_SERVICES_SYNC
#define SERVICES_CRYPTO_MODULE MODULE(nsServicesCryptoModule)
#else
#define SERVICES_CRYPTO_MODULE
#endif
#if defined(MOZ_APP_COMPONENT_INCLUDE)
#include MOZ_APP_COMPONENT_INCLUDE
#else
@ -288,6 +294,7 @@
WINDOWSPROXY_MODULE \
JSCTYPES_MODULE \
MODULE(jsperf) \
SERVICES_CRYPTO_MODULE \
APP_COMPONENT_MODULES \
/* end of list */

View File

@ -235,6 +235,10 @@ ifdef MOZ_PREF_EXTENSIONS
tier_platform_dirs += extensions/pref
endif
ifdef MOZ_SERVICES_SYNC
tier_platform_dirs += services/crypto
endif
# JavaXPCOM JNI code is compiled into libXUL
ifdef MOZ_JAVAXPCOM
tier_platform_dirs += extensions/java/xpcom/src