LCOV - code coverage report
Current view: directory - services/crypto/component - nsSyncJPAKE.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 196 183 93.4 %
Date: 2012-06-02 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.7