#include <linux/config.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/route.h>

#include "sha.h"

void shaSignPacket(const struct iphdr *ih, const char *key, int offset, int len, char *staging, char *signptr)
{
	unsigned char k_ipad[65];    /* inner padding -
                                      * key XORd with ipad
                                      */
        unsigned char k_opad[65];    /* outer padding -
                                      * key XORd with opad
                                      */
	sha_context context;
	sha_digest digest;
	int n;

	/* build staging area */
	memcpy(staging,&ih->saddr,4);
	memcpy(staging+4,&ih->daddr,4);
	memcpy(staging+8,(char *)ih+ih->ihl*4+offset,len);

	/* start out by storing key in pads */
        memset( k_ipad,0, sizeof k_ipad);
        memset( k_opad, 0,sizeof k_opad);
        memcpy( k_ipad, key, strlen(key));
        memcpy(k_opad, key, strlen(key));

        /* XOR key with ipad and opad values */
        for (n=0; n<64; n++) {
                k_ipad[n] ^= 0x36;
                k_opad[n] ^= 0x5c;
        }
        /*
         * perform inner MD5
         */
        shaInit(&context,1);                 /* init context for 1st pass */
        shaUpdate(&context, k_ipad, 64);      /* start with inner pad */
        shaUpdate(&context, staging, 8+len); /* then text of datagram */
        shaFinal(&context, digest);          /* finish up 1st pass */
        /*
         * perform outer MD5
         */
        shaInit(&context,1);                   /* init context for 2nd */

        shaUpdate(&context, k_opad, 64);     /* start with outer pad */
        shaUpdate(&context, digest, 20);     /* then results of 1st
                                              * hash */
        shaFinal(&context, digest);          /* finish up 2nd pass */

	memcpy(signptr,digest,20);
}
