
/* MD5DEEP - sha15.h
 *
 * By Jesse Kornblum
 *
 * This is a work of the US Government. In accordance with 17 USC 105,
 * copyright protection is not available for any work of the US Government.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

#ifndef __SHA1_H__
#define __SHA1_H__

#define BYTE_ORDER LITTLE_ENDIAN

#define SHA1_BLOCK	64
#define SHA1_LENGTH	20


/* Bytes in hash */
#define HASH_LENGTH        20

/* Characters needed to display hash. This is *usually* twice the
   HASH_LENGTH defined above. This number is used to find and compare
   hashes as part of the matching process. */
#define HASH_STRING_LENGTH 40

/* These supply the hashing code, hash.c, with the names of the 
   functions used in the algorithm to do the real computation. 
   HASH_Init takes a HASH_CONTEXT only
   HASH_Update takes a hash context, the buffer, and its size in bytes
   HASH_Final takes a char to put the sum in and then a context */
#define HASH_CONTEXT       SHA1_CTX
#define HASH_Init(A)       SHA1Init(A)
#define HASH_Update(A,B,C) SHA1Update(A,B,C)
#define HASH_Final(A,B)    SHA1Final(A,B)

/* Define which types of files of known hashes that support this type
   of hash. The values, if given, are the location of the hash value
   in terms of number of commas that preceed the hash. For example,
   if the file format is:
   hash,stuff,junk
   the define should be SUPPORT_FORMAT 0 
   if the file format is
   stuff,junk,hash
   the define should be SUPPORT_FORMAT 2

   Remember that numbers are not necessary for all file types! */ 
#define SUPPORT_PLAIN
#define SUPPORT_BSD

/* Hashkeeper and iLook only have MD5 hashes */
#undef SUPPORT_HASHKEEPER
#undef SUPPORT_ILOOK  

#define SUPPORT_NSRL_15    0
#define SUPPORT_NSRL_20    0 

/* -------------------------------------------------------------- */
/* After this is the algorithm itself. You shouldn't change these */

typedef struct SHA1_Context{
  unsigned long state[5];
  unsigned long count[2];
  unsigned char buffer[SHA1_BLOCK];
} SHA1_CTX;


void SHA1Transform(unsigned long state[5], unsigned char buffer[SHA1_BLOCK]);
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
void SHA1Final(unsigned char digest[SHA1_LENGTH], SHA1_CTX* context);


//POSTING
//gen a password & message-id and pass to sha_lock, returns pointer to cancel-lock
char * sha_lock1(char *secret, int seclen,  char *message, int msglen);

//CANCELING
//use message-id of art to be cancelled, and password, returns cancel-key
char * sha_key1( char *secret, int seclen,  char *message, int msglen);

//verify - use cancel-key header from cancel msg, and cancel-lock header
int sha_verify1( char *key,  char *lock);


#endif /* __SHA1_H__ */

/*
Here are some sort-of plain language descriptions of how to use the
library.

First, your news posting program needs to generate its own Message-ID
headers.  If this isn't already the case, fix that first.

You will also need to add a facility for storing a user password; see
the included RFCs about recommended lengths.  This can be user-generated
or built automatically from random cruft, but however you generate the
password you do have to save it.  This password is the only thing that
will allow you to cancel articles later.

An alternative approach is to generate a unique password for each
article, but then you would need to build a whole little database
monster.


POSTING:

Generate a Message-ID.  Now, pass the pointers and lengths of the password
and message id to sha_lock().  It will return a pointer to your cancel lock.
For example:

	fprintf(art, "Message-ID: %s\n", msgid);
	fprintf(art, "Cancel-Lock: 1:%s\n",
		sha_lock(password, strlen(password), msgid, strlen(msgid));



CANCELING:

This time, you use the Message-ID of the article to be canceled.  We
use sha_key this time to complete the cycle.

	fprintf(art, "Control: cancel %s\n", msg_can);
	fprintf(art, "Cancel-Key: 1:%s\n",
		sha_key(password, strlen(password), msgid, strlen(msgid));



VERIFYING:

This is purely optional at the newsreader level; only servers should
really need to bother.

Extract the Cancel-Key: header from the cancel message.  Fetch the
original article from the server and extract its Cancel-Lock: header. 
Chop off the keywords; we are only interested in the Base-64 thingies.

- If the original article has no lock (or is missing), you can ignore
  the cancel key and use traditional verification, or abort the cancel
  operation if you don't want to trust unauthenticated cancels.

- If the original article has a lock and the cancel has no key, abort
  the cancel operation.

- If both a key and lock are present, strip off the type numbers and
  make sure they're both type 1 (the only kind we know how to handle
  yet).  You can use the lock_strip() function to make this a bit
  easier.

- Finally, you can send pointers to each stripped lock on to
  sha_verify().  If it returns zero, your may delete the article.
  Remember that there may be more than one lock in the header.  Be sure
  to check all locks against the key before giving up.
  */
