diff -r b4e909a9ef0b browser/build.mk --- a/browser/build.mk Wed Dec 15 08:45:58 2010 +0100 +++ b/browser/build.mk Wed Dec 15 11:18:35 2010 +0100 @@ -45,17 +45,17 @@ ifdef MOZ_EXTENSIONS tier_app_dirs += extensions endif tier_app_dirs += $(MOZ_BRANDING_DIRECTORY) tier_app_dirs += toolkit/components/console/hudservice ifdef MOZ_SERVICES_SYNC -tier_app_dirs += services/sync +tier_app_dirs += services endif tier_app_dirs += browser # Never add other tier_app_dirs after browser. They won't get packaged # properly on mac. installer: @$(MAKE) -C browser/installer installer diff -r b4e909a9ef0b browser/installer/package-manifest.in --- a/browser/installer/package-manifest.in Wed Dec 15 08:45:58 2010 +0100 +++ b/browser/installer/package-manifest.in Wed Dec 15 11:18:35 2010 +0100 @@ -225,16 +225,17 @@ @BINPATH@/components/proxyObject.xpt @BINPATH@/components/rdf.xpt @BINPATH@/components/satchel.xpt @BINPATH@/components/saxparser.xpt @BINPATH@/components/sessionstore.xpt #ifdef MOZ_SERVICES_SYNC @BINPATH@/components/services-crypto.xpt #endif +@BINPATH@/components/services-crypto-component.xpt @BINPATH@/components/shellservice.xpt @BINPATH@/components/shistory.xpt @BINPATH@/components/spellchecker.xpt @BINPATH@/components/storage.xpt @BINPATH@/components/toolkitprofile.xpt #ifdef MOZ_ENABLE_XREMOTE @BINPATH@/components/toolkitremote.xpt #endif diff -r b4e909a9ef0b services/crypto/Makefile.in --- a/services/crypto/Makefile.in Wed Dec 15 08:45:58 2010 +0100 +++ b/services/crypto/Makefile.in Wed Dec 15 11:18:35 2010 +0100 @@ -43,37 +43,18 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = services-crypto 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:: $(PYTHON) $(topsrcdir)/config/nsinstall.py $(srcdir)/modules/* $(FINAL_TARGET)/modules/services-crypto ifdef ENABLE_TESTS DIRS += tests endif include $(topsrcdir)/config/rules.mk - -EXTRA_DSO_LDOPTS += \ - $(MOZ_COMPONENT_LIBS) \ - $(NSPR_LIBS) \ - $(NSS_LIBS) \ - $(NULL) diff -r b4e909a9ef0b services/crypto/component/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/Makefile.in Wed Dec 15 11:18:35 2010 +0100 @@ -0,0 +1,75 @@ +# +# ***** 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 mozilla.org code. +# +# 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): +# Philipp von Weitershausen +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = services-crypto +XPIDL_MODULE = services-crypto-component + +XPIDLSRCS = \ + 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) + +ifdef ENABLE_TESTS +DIRS += tests +endif + +include $(topsrcdir)/config/rules.mk + +EXTRA_DSO_LDOPTS += \ + $(MOZ_COMPONENT_LIBS) \ + $(NSPR_LIBS) \ + $(NSS_LIBS) \ + $(NULL) diff -r b4e909a9ef0b services/crypto/component/nsISyncJPAKE.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/nsISyncJPAKE.idl Wed Dec 15 11:18:35 2010 +0100 @@ -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 + * Philipp von Weitershausen + * + * 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); +}; diff -r b4e909a9ef0b services/crypto/component/nsSyncJPAKE.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/nsSyncJPAKE.cpp Wed Dec 15 11:18:35 2010 +0100 @@ -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 + * Philipp von Weitershausen + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, + ¶msItem, 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, + ¶msItem, + 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, + ¶msItem, 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, + ¶msItem, 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, + ¶msItem, 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; diff -r b4e909a9ef0b services/crypto/component/nsSyncJPAKE.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/nsSyncJPAKE.h Wed Dec 15 11:18:35 2010 +0100 @@ -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 + * Philipp von Weitershausen + * + * 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__ diff -r b4e909a9ef0b services/crypto/component/tests/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/tests/Makefile.in Wed Dec 15 11:18:35 2010 +0100 @@ -0,0 +1,50 @@ +# +# ***** 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 mozilla.org code. +# +# 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): +# Philipp von Weitershausen +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = services/crypto/components/tests + +include $(DEPTH)/config/autoconf.mk + +MODULE = test_services_crypto +XPCSHELL_TESTS = unit + +include $(topsrcdir)/config/rules.mk diff -r b4e909a9ef0b services/crypto/component/tests/unit/test_jpake.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/crypto/component/tests/unit/test_jpake.js Wed Dec 15 11:18:35 2010 +0100 @@ -0,0 +1,197 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +// Ensure PSM is initialized. +Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports); + +function do_check_throws(func) { + let have_error = false; + try { + func(); + } catch(ex) { + dump("Was expecting an exception. Caught: " + ex + "\n"); + have_error = true; + } + do_check_true(have_error); +} + +function test_success() { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + let a_gx1 = {}; + let a_gv1 = {}; + let a_r1 = {}; + let a_gx2 = {}; + let a_gv2 = {}; + let a_r2 = {}; + + let b_gx1 = {}; + let b_gv1 = {}; + let b_r1 = {}; + let b_gx2 = {}; + let b_gv2 = {}; + let b_r2 = {}; + + a.round1("alice", a_gx1, a_gv1, a_r1, a_gx2, a_gv2, a_r2); + b.round1("bob", b_gx1, b_gv1, b_r1, b_gx2, b_gv2, b_r2); + + let a_A = {}; + let a_gva = {}; + let a_ra = {}; + + let b_A = {}; + let b_gva = {}; + let b_ra = {}; + + a.round2("bob", "sekrit", b_gx1.value, b_gv1.value, b_r1.value, + b_gx2.value, b_gv2.value, b_r2.value, a_A, a_gva, a_ra); + b.round2("alice", "sekrit", a_gx1.value, a_gv1.value, a_r1.value, + a_gx2.value, a_gv2.value, a_r2.value, b_A, b_gva, b_ra); + + let a_aes = {}; + let a_hmac = {}; + let b_aes = {}; + let b_hmac = {}; + + a.final(b_A.value, b_gva.value, b_ra.value, "ohai", a_aes, a_hmac); + b.final(a_A.value, a_gva.value, a_ra.value, "ohai", b_aes, b_hmac); + + do_check_eq(a_aes.value, b_aes.value); + do_check_eq(a_hmac.value, b_hmac.value); +} + +function test_failure(modlen) { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + let a_gx1 = {}; + let a_gv1 = {}; + let a_r1 = {}; + let a_gx2 = {}; + let a_gv2 = {}; + let a_r2 = {}; + + let b_gx1 = {}; + let b_gv1 = {}; + let b_r1 = {}; + let b_gx2 = {}; + let b_gv2 = {}; + let b_r2 = {}; + + a.round1("alice", a_gx1, a_gv1, a_r1, a_gx2, a_gv2, a_r2); + b.round1("bob", b_gx1, b_gv1, b_r1, b_gx2, b_gv2, b_r2); + + let a_A = {}; + let a_gva = {}; + let a_ra = {}; + + let b_A = {}; + let b_gva = {}; + let b_ra = {}; + + // Note how the PINs are different (secret vs. sekrit) + a.round2("bob", "secret", b_gx1.value, b_gv1.value, b_r1.value, + b_gx2.value, b_gv2.value, b_r2.value, a_A, a_gva, a_ra); + b.round2("alice", "sekrit", a_gx1.value, a_gv1.value, a_r1.value, + a_gx2.value, a_gv2.value, a_r2.value, b_A, b_gva, b_ra); + + let a_aes = {}; + let a_hmac = {}; + let b_aes = {}; + let b_hmac = {}; + + a.final(b_A.value, b_gva.value, b_ra.value, "ohai", a_aes, a_hmac); + b.final(a_A.value, a_gva.value, a_ra.value, "ohai", b_aes, b_hmac); + + do_check_neq(a_aes.value, b_aes.value); + do_check_neq(a_hmac.value, b_hmac.value); +} + +function test_same_signerids() { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + let gx1 = {}; + let gv1 = {}; + let r1 = {}; + let gx2 = {}; + let gv2 = {}; + let r2 = {}; + + a.round1("alice", {}, {}, {}, {}, {}, {}); + b.round1("alice", gx1, gv1, r1, gx2, gv2, r2); + do_check_throws(function() { + a.round2("alice", "sekrit", gx1.value, gv1.value, r1.value, + gx2.value, gv2.value, r2.value, {}, {}, {}); + }); +} + +function test_bad_zkp() { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + let gx1 = {}; + let gv1 = {}; + let r1 = {}; + let gx2 = {}; + let gv2 = {}; + let r2 = {}; + + a.round1("alice", {}, {}, {}, {}, {}, {}); + b.round1("bob", gx1, gv1, r1, gx2, gv2, r2); + do_check_throws(function() { + a.round2("invalid", "sekrit", gx1.value, gv1.value, r1.value, + gx2.value, gv2.value, r2.value, {}, {}, {}); + }); +} + +function test_invalid_input_round2() { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + a.round1("alice", {}, {}, {}, {}, {}, {}); + do_check_throws(function() { + a.round2("invalid", "sekrit", "some", "real", "garbage", + "even", "more", "garbage", {}, {}, {}); + }); +} + +function test_invalid_input_final() { + let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] + .createInstance(Ci.nsISyncJPAKE); + + let gx1 = {}; + let gv1 = {}; + let r1 = {}; + let gx2 = {}; + let gv2 = {}; + let r2 = {}; + + a.round1("alice", {}, {}, {}, {}, {}, {}); + b.round1("bob", gx1, gv1, r1, gx2, gv2, r2); + a.round2("bob", "sekrit", gx1.value, gv1.value, r1.value, + gx2.value, gv2.value, r2.value, {}, {}, {}); + do_check_throws(function() { + a.final("some", "garbage", "alright", "foobar-info", {}, {}); + }); +} + +function run_test() { + test_success(); + test_failure(); + test_same_signerids(); + test_bad_zkp(); + test_invalid_input_round2(); + test_invalid_input_final(); +} diff -r b4e909a9ef0b services/crypto/nsISyncJPAKE.idl --- a/services/crypto/nsISyncJPAKE.idl Wed Dec 15 08:45:58 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/* ***** 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 - * Philipp von Weitershausen - * - * 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); -}; diff -r b4e909a9ef0b services/crypto/nsSyncJPAKE.cpp --- a/services/crypto/nsSyncJPAKE.cpp Wed Dec 15 08:45:58 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,476 +0,0 @@ -/* ***** 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 - * Philipp von Weitershausen - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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, - ¶msItem, 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, - ¶msItem, - 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, - ¶msItem, 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, - ¶msItem, 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, - ¶msItem, 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; diff -r b4e909a9ef0b services/crypto/nsSyncJPAKE.h --- a/services/crypto/nsSyncJPAKE.h Wed Dec 15 08:45:58 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* ***** 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 - * Philipp von Weitershausen - * - * 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__ diff -r b4e909a9ef0b services/crypto/tests/unit/test_jpake.js --- a/services/crypto/tests/unit/test_jpake.js Wed Dec 15 08:45:58 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -// Ensure PSM is initialized. -Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports); - -function do_check_throws(func) { - let have_error = false; - try { - func(); - } catch(ex) { - dump("Was expecting an exception. Caught: " + ex + "\n"); - have_error = true; - } - do_check_true(have_error); -} - -function test_success() { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - let a_gx1 = {}; - let a_gv1 = {}; - let a_r1 = {}; - let a_gx2 = {}; - let a_gv2 = {}; - let a_r2 = {}; - - let b_gx1 = {}; - let b_gv1 = {}; - let b_r1 = {}; - let b_gx2 = {}; - let b_gv2 = {}; - let b_r2 = {}; - - a.round1("alice", a_gx1, a_gv1, a_r1, a_gx2, a_gv2, a_r2); - b.round1("bob", b_gx1, b_gv1, b_r1, b_gx2, b_gv2, b_r2); - - let a_A = {}; - let a_gva = {}; - let a_ra = {}; - - let b_A = {}; - let b_gva = {}; - let b_ra = {}; - - a.round2("bob", "sekrit", b_gx1.value, b_gv1.value, b_r1.value, - b_gx2.value, b_gv2.value, b_r2.value, a_A, a_gva, a_ra); - b.round2("alice", "sekrit", a_gx1.value, a_gv1.value, a_r1.value, - a_gx2.value, a_gv2.value, a_r2.value, b_A, b_gva, b_ra); - - let a_aes = {}; - let a_hmac = {}; - let b_aes = {}; - let b_hmac = {}; - - a.final(b_A.value, b_gva.value, b_ra.value, "ohai", a_aes, a_hmac); - b.final(a_A.value, a_gva.value, a_ra.value, "ohai", b_aes, b_hmac); - - do_check_eq(a_aes.value, b_aes.value); - do_check_eq(a_hmac.value, b_hmac.value); -} - -function test_failure(modlen) { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - let a_gx1 = {}; - let a_gv1 = {}; - let a_r1 = {}; - let a_gx2 = {}; - let a_gv2 = {}; - let a_r2 = {}; - - let b_gx1 = {}; - let b_gv1 = {}; - let b_r1 = {}; - let b_gx2 = {}; - let b_gv2 = {}; - let b_r2 = {}; - - a.round1("alice", a_gx1, a_gv1, a_r1, a_gx2, a_gv2, a_r2); - b.round1("bob", b_gx1, b_gv1, b_r1, b_gx2, b_gv2, b_r2); - - let a_A = {}; - let a_gva = {}; - let a_ra = {}; - - let b_A = {}; - let b_gva = {}; - let b_ra = {}; - - // Note how the PINs are different (secret vs. sekrit) - a.round2("bob", "secret", b_gx1.value, b_gv1.value, b_r1.value, - b_gx2.value, b_gv2.value, b_r2.value, a_A, a_gva, a_ra); - b.round2("alice", "sekrit", a_gx1.value, a_gv1.value, a_r1.value, - a_gx2.value, a_gv2.value, a_r2.value, b_A, b_gva, b_ra); - - let a_aes = {}; - let a_hmac = {}; - let b_aes = {}; - let b_hmac = {}; - - a.final(b_A.value, b_gva.value, b_ra.value, "ohai", a_aes, a_hmac); - b.final(a_A.value, a_gva.value, a_ra.value, "ohai", b_aes, b_hmac); - - do_check_neq(a_aes.value, b_aes.value); - do_check_neq(a_hmac.value, b_hmac.value); -} - -function test_same_signerids() { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - let gx1 = {}; - let gv1 = {}; - let r1 = {}; - let gx2 = {}; - let gv2 = {}; - let r2 = {}; - - a.round1("alice", {}, {}, {}, {}, {}, {}); - b.round1("alice", gx1, gv1, r1, gx2, gv2, r2); - do_check_throws(function() { - a.round2("alice", "sekrit", gx1.value, gv1.value, r1.value, - gx2.value, gv2.value, r2.value, {}, {}, {}); - }); -} - -function test_bad_zkp() { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - let gx1 = {}; - let gv1 = {}; - let r1 = {}; - let gx2 = {}; - let gv2 = {}; - let r2 = {}; - - a.round1("alice", {}, {}, {}, {}, {}, {}); - b.round1("bob", gx1, gv1, r1, gx2, gv2, r2); - do_check_throws(function() { - a.round2("invalid", "sekrit", gx1.value, gv1.value, r1.value, - gx2.value, gv2.value, r2.value, {}, {}, {}); - }); -} - -function test_invalid_input_round2() { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - a.round1("alice", {}, {}, {}, {}, {}, {}); - do_check_throws(function() { - a.round2("invalid", "sekrit", "some", "real", "garbage", - "even", "more", "garbage", {}, {}, {}); - }); -} - -function test_invalid_input_final() { - let a = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - let b = Cc["@mozilla.org/services-crypto/sync-jpake;1"] - .createInstance(Ci.nsISyncJPAKE); - - let gx1 = {}; - let gv1 = {}; - let r1 = {}; - let gx2 = {}; - let gv2 = {}; - let r2 = {}; - - a.round1("alice", {}, {}, {}, {}, {}, {}); - b.round1("bob", gx1, gv1, r1, gx2, gv2, r2); - a.round2("bob", "sekrit", gx1.value, gv1.value, r1.value, - gx2.value, gv2.value, r2.value, {}, {}, {}); - do_check_throws(function() { - a.final("some", "garbage", "alright", "foobar-info", {}, {}); - }); -} - -function run_test() { - test_success(); - test_failure(); - test_same_signerids(); - test_bad_zkp(); - test_invalid_input_round2(); - test_invalid_input_final(); -} diff -r b4e909a9ef0b toolkit/library/libxul-config.mk --- a/toolkit/library/libxul-config.mk Wed Dec 15 08:45:58 2010 +0100 +++ b/toolkit/library/libxul-config.mk Wed Dec 15 11:18:35 2010 +0100 @@ -345,19 +345,17 @@ DEFINES += -DMOZ_SPELLCHECK COMPONENT_LIBS += spellchecker endif ifdef MOZ_ZIPWRITER 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 endif endif ifdef MOZ_APP_COMPONENT_LIBS diff -r b4e909a9ef0b toolkit/library/nsStaticXULComponents.cpp --- a/toolkit/library/nsStaticXULComponents.cpp Wed Dec 15 08:45:58 2010 +0100 +++ b/toolkit/library/nsStaticXULComponents.cpp Wed Dec 15 11:18:35 2010 +0100 @@ -228,21 +228,17 @@ #endif #if defined(BUILD_CTYPES) #define JSCTYPES_MODULE MODULE(jsctypes) #else #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 #define APP_COMPONENT_MODULES #endif #define XUL_MODULES \ diff -r b4e909a9ef0b toolkit/toolkit-tiers.mk --- a/toolkit/toolkit-tiers.mk Wed Dec 15 08:45:58 2010 +0100 +++ b/toolkit/toolkit-tiers.mk Wed Dec 15 11:18:35 2010 +0100 @@ -230,19 +230,17 @@ tier_platform_dirs += security/manager else tier_platform_dirs += security/manager/boot/public security/manager/ssl/public endif ifdef MOZ_PREF_EXTENSIONS tier_platform_dirs += extensions/pref endif -ifdef MOZ_SERVICES_SYNC -tier_platform_dirs += services/crypto -endif +tier_platform_dirs += services/crypto/component # JavaXPCOM JNI code is compiled into libXUL ifdef MOZ_JAVAXPCOM tier_platform_dirs += extensions/java/xpcom/src endif ifndef BUILD_STATIC_LIBS ifneq (,$(MOZ_ENABLE_GTK2))