Changes On Branch multisession
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch multisession Excluding Merge-Ins

This is equivalent to a diff from d4a341b49d to dcee34b25f

2011-10-04
23:07
Merge the --args FILENAME patch into trunk. check-in: c0274f9962 user: drh tags: trunk
21:28
merging with trunk [d4a341b49dd1b701] before applying --args FILENAME patch, to simplify downstream merge. check-in: 312d522fe4 user: stephan tags: stephan-hack
15:20
Add HMAC-SHA1 implementation. Leaf check-in: dcee34b25f user: dmitry tags: multisession
15:15
Merge protection against timing attacks into trunk. check-in: d4a341b49d user: dmitry tags: trunk
14:38
Merge trunk into dmitry-security branch. Closed-Leaf check-in: f4eb0f5afc user: dmitry tags: dmitry-security
2011-10-03
16:34
Disabling Cache-control: no-store, as it made firefox forget about form field contents on back/forward in history.    Resolution achieved by a minimal consensus at this thread on the mailing list. check-in: 3fac77d7b0 user: viriketo tags: trunk

Changes to src/sha1.c.

   197    197       if (digest) {
   198    198   	for (i = 0; i < 20; i++)
   199    199   	    digest[i] = (unsigned char)
   200    200   		((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
   201    201       }
   202    202   }
   203    203   
          204  +typedef struct HMAC_SHA1Context HMAC_SHA1Context;
          205  +struct HMAC_SHA1Context {
          206  +  SHA1Context inner;
          207  +  SHA1Context outer;
          208  +};
          209  +
          210  +static void HMAC_SHA1Init(
          211  +  HMAC_SHA1Context *context,
          212  +  const unsigned char *key,
          213  +  unsigned int keylen
          214  +){
          215  +  unsigned char pad[64]; /* 64 is SHA-1 block length */
          216  +  unsigned char keyhash[20];
          217  +  unsigned int i;
          218  +  const unsigned char *k = key;
          219  +
          220  +  if( keylen > sizeof(pad) ){
          221  +    /* Key is too big, hash it, and use this hash as a key */
          222  +    SHA1Init(&context->inner);
          223  +    SHA1Update(&context->inner, k, keylen);
          224  +    SHA1Final(&context->inner, keyhash);
          225  +    k = keyhash;
          226  +    keylen = sizeof(keyhash);
          227  +  }
          228  +
          229  +  /* Initialize inner hash */
          230  +  SHA1Init(&context->inner);
          231  +  memset(pad, 0x36, sizeof(pad));
          232  +  for( i=0; i<keylen; i++ ){ pad[i] ^= k[i]; }
          233  +  SHA1Update(&context->inner, pad, sizeof(pad));
          234  +
          235  +  /* Initialize outer hash */
          236  +  SHA1Init(&context->outer);
          237  +  memset(pad, 0x5C, sizeof(pad));
          238  +  for( i=0; i<keylen; i++ ){ pad[i] ^= k[i]; }
          239  +  SHA1Update(&context->outer, pad, sizeof(pad));
          240  +
          241  +  /* Cleanup */
          242  +  memset(keyhash, 0, sizeof(keyhash));
          243  +}
          244  +
          245  +static void HMAC_SHA1Update(
          246  +  HMAC_SHA1Context *context,
          247  +  const unsigned char *data,
          248  +  unsigned int len
          249  +){
          250  +  SHA1Update(&context->inner, data, len);
          251  +}
          252  +
          253  +static void HMAC_SHA1Final(
          254  +  HMAC_SHA1Context *context,
          255  +  unsigned char digest[20]
          256  +){
          257  +  unsigned char innerDigest[20];
          258  +  SHA1Final(&context->inner, innerDigest);
          259  +  /* Mix inner into outer */
          260  +  SHA1Update(&context->outer, innerDigest, sizeof(innerDigest));
          261  +  SHA1Final(&context->outer, digest);
          262  +  /* Cleanup */
          263  +  memset(innerDigest, 0, sizeof(innerDigest));
          264  +}
   204    265   
   205    266   /*
   206    267   ** Convert a digest into base-16.  digest should be declared as
   207    268   ** "unsigned char digest[20]" in the calling function.  The SHA1
   208    269   ** digest is stored in the first 20 bytes.  zBuf should
   209    270   ** be "char zBuf[41]".
   210    271   */
................................................................................
   348    409   
   349    410     SHA1Init(&ctx);
   350    411     SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
   351    412     SHA1Final(&ctx, zResult);
   352    413     DigestToBase16(zResult, zDigest);
   353    414     return mprintf("%s", zDigest);
   354    415   }
          416  +
          417  +/*
          418  +** Compute HMAC-SHA1 of a zero-terminated string.  The
          419  +** result (hex string) is held in memory obtained from mprintf().
          420  +*/
          421  +char *hmac_sign(const char *zKey, const char *zData){
          422  +  HMAC_SHA1Context ctx;
          423  +  unsigned char zResult[20];
          424  +  char zDigest[41];
          425  +
          426  +  HMAC_SHA1Init(&ctx, (unsigned const char *)zKey, strlen(zKey));
          427  +  HMAC_SHA1Update(&ctx, (unsigned const char*)zData, strlen(zData));
          428  +  HMAC_SHA1Final(&ctx, zResult);
          429  +  DigestToBase16(zResult, zDigest);
          430  +  return mprintf("%s", zDigest);
          431  +}
          432  +
          433  +/*
          434  +** Like hmac_sign(), but uses double-HMAC construction:
          435  +** HMAC(HMAC(zKey, zData), zData)
          436  +*/
          437  +char *hmac_double_sign(const char *zKey, const char *zData){
          438  +  HMAC_SHA1Context ctx;
          439  +  unsigned char zInterKey[20], zResult[20];
          440  +  char zDigest[41];
          441  +
          442  +  /* First derive intermediate key */
          443  +  HMAC_SHA1Init(&ctx, (unsigned const char *)zKey, strlen(zKey));
          444  +  HMAC_SHA1Update(&ctx, (unsigned const char*)zData, strlen(zData));
          445  +  HMAC_SHA1Final(&ctx, zInterKey);
          446  +  /* Use intermediate key to sign data */
          447  +  HMAC_SHA1Init(&ctx, zInterKey, sizeof(zInterKey));
          448  +  HMAC_SHA1Update(&ctx, (unsigned const char *)zData, strlen(zData));
          449  +  HMAC_SHA1Final(&ctx, zResult);
          450  +
          451  +  DigestToBase16(zResult, zDigest);
          452  +  return mprintf("%s", zDigest);
          453  +}
          454  +
          455  +/*
          456  +** Constant-time comparison of buffers b1 and b2, which both have length len
          457  +** Returns 0 on successful verification, any other number on failure.
          458  +*/
          459  +static int verify_bytes(
          460  +  const unsigned char *b1,
          461  +  const unsigned char *b2,
          462  +  unsigned int len
          463  +){
          464  +  unsigned int i;
          465  +  unsigned char rc = 0;
          466  +  if( len==0 ) return 1;
          467  +  for( i=0; i<len; i++){
          468  +    rc |= b1[i] ^ b2[i];
          469  +  }
          470  +  return rc;
          471  +}
          472  +
          473  +/*
          474  +** Verify that hex string zDigest (result of hmac_sign) is the one
          475  +** that was used to sign zData with secret key zKey.
          476  +** All strings are zero-terminated.
          477  +** Returns 0 on successful verification, any other number on failure.
          478  +*/
          479  +int hmac_verify(const char *zDigest, const char *zKey, const char *zData)
          480  +{
          481  +  char *zCalcDigest;
          482  +  unsigned int len, i, rc = 0;
          483  +
          484  +  zCalcDigest = hmac_sign(zKey, zData);
          485  +  len = strlen(zCalcDigest);
          486  +  if( len==0 || len != strlen(zDigest) ) return 1;
          487  +  rc = verify_bytes((const unsigned char*)zDigest,
          488  +                    (const unsigned char*)zCalcDigest, len);
          489  +  fossil_free(zCalcDigest);
          490  +  return rc;
          491  +}
          492  +
          493  +/*
          494  +** Like hmac_verify(), but uses double-HMAC.
          495  +*/
          496  +int hmac_double_verify(const char *zDigest, const char *zKey, const char *zData)
          497  +{
          498  +  char *zCalcDigest;
          499  +  unsigned int len, i, rc = 0;
          500  +
          501  +  zCalcDigest = hmac_double_sign(zKey, zData);
          502  +  len = strlen(zCalcDigest);
          503  +  if( len==0 || len != strlen(zDigest) ) return 1;
          504  +  rc = verify_bytes((const unsigned char*)zDigest,
          505  +                    (const unsigned char*)zCalcDigest, len);
          506  +  fossil_free(zCalcDigest);
          507  +  return rc;
          508  +}
   355    509   
   356    510   /*
   357    511   ** Convert a cleartext password for a specific user into a SHA1 hash.
   358    512   ** 
   359    513   ** The algorithm here is:
   360    514   **
   361    515   **       SHA1( project-code + "/" + login + "/" + password )
................................................................................
   458    612       }else{
   459    613         sha1sum_file(g.argv[i], &cksum);
   460    614       }
   461    615       fossil_print("%s  %s\n", blob_str(&cksum), g.argv[i]);
   462    616       blob_reset(&cksum);
   463    617     }
   464    618   }
          619  +
          620  +/*
          621  +** COMMAND: test-hmac
          622  +** %fossil test-hmac secret data
          623  +*/
          624  +void hmac_test(void){
          625  +  assert( g.argc==4 );
          626  +  fossil_print("HMAC(%s, %s) = ", g.argv[2], g.argv[3]);
          627  +  fossil_print("%s\n", hmac_sign(g.argv[2], g.argv[3]));
          628  +}
          629  +
          630  +/*
          631  +** COMMAND: test-hmac-verify
          632  +** %fossil test-hmac-verify digest secret data
          633  +*/
          634  +void hmac_verify_test(void){
          635  +  assert( g.argc==5 );
          636  +  if( hmac_verify(g.argv[2], g.argv[3], g.argv[4])==0 ){
          637  +    fossil_print("successfuly verified\n");
          638  +  }else{
          639  +    fossil_print("not verified\n");
          640  +  }
          641  +}
          642  +