Fossil

Changes On Branch multisession
Login

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

Changes In Branch multisession Excluding Merge-Ins

This is equivalent to a diff from d4a341b4 to dcee34b2

2011-10-04
23:07
Merge the --args FILENAME patch into trunk. (check-in: c0274f99 user: drh tags: trunk)
21:28
merging with trunk [d4a341b49dd1b701] before applying --args FILENAME patch, to simplify downstream merge. (check-in: 312d522f user: stephan tags: stephan-hack)
15:20
Add HMAC-SHA1 implementation. (Leaf check-in: dcee34b2 user: dmitry tags: multisession)
15:15
Merge protection against timing attacks into trunk. (check-in: d4a341b4 user: dmitry tags: trunk)
14:38
Merge trunk into dmitry-security branch. (Closed-Leaf check-in: f4eb0f5a 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: 3fac77d7 user: viriketo tags: trunk)

Changes to src/sha1.c.

197
198
199
200
201
202
203





























































204
205
206
207
208
209
210
...
348
349
350
351
352
353
354





























































































355
356
357
358
359
360
361
...
458
459
460
461
462
463
464
























    if (digest) {
	for (i = 0; i < 20; i++)
	    digest[i] = (unsigned char)
		((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
    }
}































































/*
** Convert a digest into base-16.  digest should be declared as
** "unsigned char digest[20]" in the calling function.  The SHA1
** digest is stored in the first 20 bytes.  zBuf should
** be "char zBuf[41]".
*/
................................................................................

  SHA1Init(&ctx);
  SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
  SHA1Final(&ctx, zResult);
  DigestToBase16(zResult, zDigest);
  return mprintf("%s", zDigest);
}






























































































/*
** Convert a cleartext password for a specific user into a SHA1 hash.
** 
** The algorithm here is:
**
**       SHA1( project-code + "/" + login + "/" + password )
................................................................................
    }else{
      sha1sum_file(g.argv[i], &cksum);
    }
    fossil_print("%s  %s\n", blob_str(&cksum), g.argv[i]);
    blob_reset(&cksum);
  }
}































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
    if (digest) {
	for (i = 0; i < 20; i++)
	    digest[i] = (unsigned char)
		((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
    }
}

typedef struct HMAC_SHA1Context HMAC_SHA1Context;
struct HMAC_SHA1Context {
  SHA1Context inner;
  SHA1Context outer;
};

static void HMAC_SHA1Init(
  HMAC_SHA1Context *context,
  const unsigned char *key,
  unsigned int keylen
){
  unsigned char pad[64]; /* 64 is SHA-1 block length */
  unsigned char keyhash[20];
  unsigned int i;
  const unsigned char *k = key;

  if( keylen > sizeof(pad) ){
    /* Key is too big, hash it, and use this hash as a key */
    SHA1Init(&context->inner);
    SHA1Update(&context->inner, k, keylen);
    SHA1Final(&context->inner, keyhash);
    k = keyhash;
    keylen = sizeof(keyhash);
  }

  /* Initialize inner hash */
  SHA1Init(&context->inner);
  memset(pad, 0x36, sizeof(pad));
  for( i=0; i<keylen; i++ ){ pad[i] ^= k[i]; }
  SHA1Update(&context->inner, pad, sizeof(pad));

  /* Initialize outer hash */
  SHA1Init(&context->outer);
  memset(pad, 0x5C, sizeof(pad));
  for( i=0; i<keylen; i++ ){ pad[i] ^= k[i]; }
  SHA1Update(&context->outer, pad, sizeof(pad));

  /* Cleanup */
  memset(keyhash, 0, sizeof(keyhash));
}

static void HMAC_SHA1Update(
  HMAC_SHA1Context *context,
  const unsigned char *data,
  unsigned int len
){
  SHA1Update(&context->inner, data, len);
}

static void HMAC_SHA1Final(
  HMAC_SHA1Context *context,
  unsigned char digest[20]
){
  unsigned char innerDigest[20];
  SHA1Final(&context->inner, innerDigest);
  /* Mix inner into outer */
  SHA1Update(&context->outer, innerDigest, sizeof(innerDigest));
  SHA1Final(&context->outer, digest);
  /* Cleanup */
  memset(innerDigest, 0, sizeof(innerDigest));
}

/*
** Convert a digest into base-16.  digest should be declared as
** "unsigned char digest[20]" in the calling function.  The SHA1
** digest is stored in the first 20 bytes.  zBuf should
** be "char zBuf[41]".
*/
................................................................................

  SHA1Init(&ctx);
  SHA1Update(&ctx, (unsigned const char*)zIn, strlen(zIn));
  SHA1Final(&ctx, zResult);
  DigestToBase16(zResult, zDigest);
  return mprintf("%s", zDigest);
}

/*
** Compute HMAC-SHA1 of a zero-terminated string.  The
** result (hex string) is held in memory obtained from mprintf().
*/
char *hmac_sign(const char *zKey, const char *zData){
  HMAC_SHA1Context ctx;
  unsigned char zResult[20];
  char zDigest[41];

  HMAC_SHA1Init(&ctx, (unsigned const char *)zKey, strlen(zKey));
  HMAC_SHA1Update(&ctx, (unsigned const char*)zData, strlen(zData));
  HMAC_SHA1Final(&ctx, zResult);
  DigestToBase16(zResult, zDigest);
  return mprintf("%s", zDigest);
}

/*
** Like hmac_sign(), but uses double-HMAC construction:
** HMAC(HMAC(zKey, zData), zData)
*/
char *hmac_double_sign(const char *zKey, const char *zData){
  HMAC_SHA1Context ctx;
  unsigned char zInterKey[20], zResult[20];
  char zDigest[41];

  /* First derive intermediate key */
  HMAC_SHA1Init(&ctx, (unsigned const char *)zKey, strlen(zKey));
  HMAC_SHA1Update(&ctx, (unsigned const char*)zData, strlen(zData));
  HMAC_SHA1Final(&ctx, zInterKey);
  /* Use intermediate key to sign data */
  HMAC_SHA1Init(&ctx, zInterKey, sizeof(zInterKey));
  HMAC_SHA1Update(&ctx, (unsigned const char *)zData, strlen(zData));
  HMAC_SHA1Final(&ctx, zResult);

  DigestToBase16(zResult, zDigest);
  return mprintf("%s", zDigest);
}

/*
** Constant-time comparison of buffers b1 and b2, which both have length len
** Returns 0 on successful verification, any other number on failure.
*/
static int verify_bytes(
  const unsigned char *b1,
  const unsigned char *b2,
  unsigned int len
){
  unsigned int i;
  unsigned char rc = 0;
  if( len==0 ) return 1;
  for( i=0; i<len; i++){
    rc |= b1[i] ^ b2[i];
  }
  return rc;
}

/*
** Verify that hex string zDigest (result of hmac_sign) is the one
** that was used to sign zData with secret key zKey.
** All strings are zero-terminated.
** Returns 0 on successful verification, any other number on failure.
*/
int hmac_verify(const char *zDigest, const char *zKey, const char *zData)
{
  char *zCalcDigest;
  unsigned int len, i, rc = 0;

  zCalcDigest = hmac_sign(zKey, zData);
  len = strlen(zCalcDigest);
  if( len==0 || len != strlen(zDigest) ) return 1;
  rc = verify_bytes((const unsigned char*)zDigest,
                    (const unsigned char*)zCalcDigest, len);
  fossil_free(zCalcDigest);
  return rc;
}

/*
** Like hmac_verify(), but uses double-HMAC.
*/
int hmac_double_verify(const char *zDigest, const char *zKey, const char *zData)
{
  char *zCalcDigest;
  unsigned int len, i, rc = 0;

  zCalcDigest = hmac_double_sign(zKey, zData);
  len = strlen(zCalcDigest);
  if( len==0 || len != strlen(zDigest) ) return 1;
  rc = verify_bytes((const unsigned char*)zDigest,
                    (const unsigned char*)zCalcDigest, len);
  fossil_free(zCalcDigest);
  return rc;
}

/*
** Convert a cleartext password for a specific user into a SHA1 hash.
** 
** The algorithm here is:
**
**       SHA1( project-code + "/" + login + "/" + password )
................................................................................
    }else{
      sha1sum_file(g.argv[i], &cksum);
    }
    fossil_print("%s  %s\n", blob_str(&cksum), g.argv[i]);
    blob_reset(&cksum);
  }
}

/*
** COMMAND: test-hmac
** %fossil test-hmac secret data
*/
void hmac_test(void){
  assert( g.argc==4 );
  fossil_print("HMAC(%s, %s) = ", g.argv[2], g.argv[3]);
  fossil_print("%s\n", hmac_sign(g.argv[2], g.argv[3]));
}

/*
** COMMAND: test-hmac-verify
** %fossil test-hmac-verify digest secret data
*/
void hmac_verify_test(void){
  assert( g.argc==5 );
  if( hmac_verify(g.argv[2], g.argv[3], g.argv[4])==0 ){
    fossil_print("successfuly verified\n");
  }else{
    fossil_print("not verified\n");
  }
}