summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/buffer.c216
-rw-r--r--common/hash.c130
-rw-r--r--common/hash.h52
-rw-r--r--common/md5.c36
-rw-r--r--common/md5.h26
-rw-r--r--common/sha1.c164
-rw-r--r--common/sha1.h30
7 files changed, 555 insertions, 99 deletions
diff --git a/common/buffer.c b/common/buffer.c
index 28cab24..a5b18a7 100644
--- a/common/buffer.c
+++ b/common/buffer.c
@@ -47,6 +47,12 @@ void buffer_bump(ha_buffer_t* buf, int count)
}
}
+void ha_bufinit(ha_buffer_t* buf)
+{
+ memset(buf, 0, sizeof(*buf));
+ ha_bufreset(buf);
+}
+
void ha_bufreset(ha_buffer_t* buf)
{
if(!buf->_dt || buf->_al == 0)
@@ -67,12 +73,6 @@ void ha_bufreset(ha_buffer_t* buf)
buf->_pp = buf->_dt;
}
-void ha_bufinit(ha_buffer_t* buf)
-{
- memset(buf, 0, sizeof(*buf));
- ha_bufreset(buf);
-}
-
void ha_buffree(ha_buffer_t* buf)
{
if(buf->_dt)
@@ -82,7 +82,8 @@ void ha_buffree(ha_buffer_t* buf)
buf->_rp = buf->_pp = NULL;
}
-int ha_readline(int fd, ha_buffer_t* buf)
+
+int ha_bufreadline(int fd, ha_buffer_t* buf)
{
int l;
@@ -137,7 +138,7 @@ int ha_readline(int fd, ha_buffer_t* buf)
return 1;
}
-char* ha_parseword(ha_buffer_t* buf, const char* delims)
+char* ha_bufparseword(ha_buffer_t* buf, const char* delims)
{
char* word = NULL;
@@ -185,7 +186,7 @@ char* ha_parseword(ha_buffer_t* buf, const char* delims)
return word;
}
-char* ha_parseline(ha_buffer_t* buf, int trim)
+char* ha_bufparseline(ha_buffer_t* buf, int trim)
{
char* t;
char* line = NULL;
@@ -231,55 +232,93 @@ char* ha_parseline(ha_buffer_t* buf, int trim)
return line;
}
-void ha_bufnext(ha_buffer_t* buf)
-{
- buffer_bump(buf, 1);
-
- if(!ha_buferr(buf))
- {
- buf->_rp++;
- buf->_pp = buf->_rp;
- *(buf->_rp) = 0;
- }
-}
-
-void ha_bufcat(ha_buffer_t* buf, ...)
+char* ha_bufmcat(ha_buffer_t* buf, ...)
{
const char* str;
va_list ap;
va_start(ap, buf);
+ if(ha_buferr(buf))
+ return NULL;
+
+ /* Move up the block pointer if we're not joining strings */
+ if(ha_buflen(buf) > 0 && *(buf->_rp - 1) != 0)
+ buf->_pp = buf->_rp;
+
while((str = va_arg(ap, char*)) != NULL)
{
int len = strlen(str);
- buffer_bump(buf, len);
+ /* Always add one for the terminating char */
+ buffer_bump(buf, len + 1);
if(ha_buferr(buf))
- return;
+ return NULL;
- /* _rpoint points to teh null */
+ /* _rp always points to the next write point */
strcpy(buf->_rp, str);
buf->_rp += len;
}
+
+ buf->_rp++;
+ return buf->_pp;
+}
+
+char* ha_bufcpy(ha_buffer_t* buf, const char* src)
+{
+ size_t len = strlen(src);
+ return ha_bufncpy(buf, src, len);
+}
+
+char* ha_bufncpy(ha_buffer_t* buf, const char* src, size_t len)
+{
+ if(ha_buferr(buf))
+ return NULL;
+
+ /* Move up the block pointer if we're not joining strings */
+ if(ha_buflen(buf) > 0 && *(buf->_rp - 1) != 0)
+ buf->_pp = buf->_rp;
+
+ /* Always add one for the terminating char */
+ buffer_bump(buf, len + 1);
+
+ if(ha_buferr(buf))
+ return NULL;
+
+ memcpy(buf->_rp, src, len * sizeof(char));
+ buf->_rp += (len + 1);
+ *(buf->_rp - 1) = 0;
+ return buf->_pp;
}
void* ha_bufmalloc(ha_buffer_t* buf, size_t sz)
{
void* ret;
- ha_bufnext(buf);
+ if(ha_buferr(buf))
+ return NULL;
+
+ /* TODO: Align memory on an appropriate boundary here */
+
+ /* We're not working with strings so always bump the pointer up */
+ buf->_pp = buf->_rp;
+
buffer_bump(buf, sz);
- buf->_rp += sz;
if(ha_buferr(buf))
return NULL;
- ret = (void*)ha_bufdata(buf);
- ha_bufnext(buf);
+ buf->_rp += sz;
+ return (void*)buf->_pp;
+}
- return ret;
+void* ha_bufmemdup(ha_buffer_t* buf, const void* src, size_t bytes)
+{
+ void* mem = ha_bufmalloc(buf, bytes);
+ if(mem)
+ memcpy(mem, src, bytes);
+ return mem;
}
/*
@@ -311,14 +350,15 @@ static const char BASE64C[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char PAD64C = '=';
-void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
+char* ha_bufenc64(ha_buffer_t* buf, const void* source, size_t len)
{
unsigned char input[3];
unsigned char output[4];
+ unsigned char* src = (unsigned char*)source;
size_t i;
- if(len == -1)
- len = strlen(src);
+ if(ha_buferr(buf))
+ return NULL;
while(2 < len)
{
@@ -332,10 +372,11 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
+ /* This also accounts for the null terminator */
buffer_bump(buf, 5);
if(ha_buferr(buf))
- return;
+ return NULL;
*(buf->_rp++) = BASE64C[output[0]];
*(buf->_rp++) = BASE64C[output[1]];
@@ -355,10 +396,11 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ /* This also accounts for the null terminator */
buffer_bump(buf, 5);
if(ha_buferr(buf))
- return;
+ return NULL;
*(buf->_rp++) = BASE64C[output[0]];
*(buf->_rp++) = BASE64C[output[1]];
@@ -370,17 +412,23 @@ void ha_bufenc64(ha_buffer_t* buf, const char* src, int len)
}
*(buf->_rp++) = '\0';
+ return buf->_pp;
}
-void ha_bufdec64(ha_buffer_t* buf, const char* src)
+void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t bytes)
{
- int state;
+ int state = 0;
int ch;
char* pos;
+ size_t done = 0;
- state = 0;
+ if(ha_buferr(buf))
+ return NULL;
- while((ch = *src++) != '\0')
+ if(bytes == 0)
+ bytes = ~0;
+
+ while((ch = *src++) != '\0' && done < bytes)
{
if(isspace(ch)) /* Skip whitespace anywhere. */
continue;
@@ -401,23 +449,27 @@ void ha_bufdec64(ha_buffer_t* buf, const char* src)
{
case 0:
*(buf->_rp++) = (pos - BASE64C) << 2;
+ done++;
state = 1;
break;
case 1:
*(buf->_rp++) |= (pos - BASE64C) >> 4;
+ done++;
*(buf->_rp) = ((pos - BASE64C) & 0x0f) << 4;
state = 2;
break;
case 2:
*(buf->_rp++) |= (pos - BASE64C) >> 2;
+ done++;
*(buf->_rp) = ((pos - BASE64C) & 0x03) << 6;
state = 3;
break;
case 3:
*(buf->_rp++) |= (pos - BASE64C);
+ done++;
state = 0;
break;
};
@@ -425,5 +477,89 @@ void ha_bufdec64(ha_buffer_t* buf, const char* src)
/* TODO: Validate ending and return error if invalid somehow */
}
- *(buf->_rp++) = '\0';
+ /* If we were asked for a specific amount of bytes, then return null */
+ if(bytes != ~0 && bytes != done)
+ return NULL;
+
+ return buf->_pp;
+}
+
+static const char HEXC[] = "0123456789ABCDEF";
+
+char* ha_bufenchex(ha_buffer_t* buf, const void* source, size_t len)
+{
+ unsigned char* src = (unsigned char*)source;
+ unsigned char j;
+
+ buffer_bump(buf, (len * 2) + 1);
+
+ if(ha_buferr(buf))
+ return NULL;
+
+ while(len > 0)
+ {
+ j = *(src) >> 4 & 0xf;
+ if(j <= 9)
+ *(buf->_rp++) = (j + '0');
+ else
+ *(buf->_rp++) = (j + 'a' - 10);
+
+ j = *(src++) & 0xf;
+ len--;
+
+ if(j <= 9)
+ *(buf->_rp++) = (j + '0');
+ else
+ *(buf->_rp++) = (j + 'a' - 10);
+ }
+
+ *(buf->_rp++) = 0;
+ return buf->_pp;
+}
+
+void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t bytes)
+{
+ unsigned short a;
+ unsigned short b;
+ size_t done = 0;
+ char* pos;
+
+ if(bytes != 0)
+ {
+ buffer_bump(buf, bytes + 1);
+ }
+ else
+ {
+ bytes = ~0;
+ buffer_bump(buf, (strlen(src) / 2) + 1);
+ }
+
+ if(ha_buferr(buf))
+ return NULL;
+
+ while(src[0] && src[1] && done < bytes)
+ {
+ /* Find the position */
+ pos = strchr(HEXC, src[0]);
+ if(pos == 0)
+ break;
+
+ a = HEXC - pos;
+
+ pos = strchr(HEXC, src[1]);
+ if(pos == 0);
+ break;
+
+ b = HEXC - pos;
+
+ *(buf->_rp++) = ((a & 0xf) << 4) | (b & 0xf);
+ src += 2;
+ done++;
+ }
+
+ /* If we were asked for a specific amount of bytes, then return null */
+ if(bytes != ~0 && bytes != done)
+ return NULL;
+
+ return buf->_pp;
}
diff --git a/common/hash.c b/common/hash.c
index 7d67e53..6471803 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -88,10 +88,14 @@ struct hash_t
#ifdef HASH_COPYKEYS
unsigned int klen;
#endif
+#ifdef HASH_CALLBACKS
+ hash_free_val_t f_free;
+ void* arg;
+#endif
};
-#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
+#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
/*
* Hash creation functions.
@@ -102,10 +106,18 @@ static hash_entry_t** alloc_array(hash_t* ht, unsigned int max)
return malloc(sizeof(*(ht->array)) * (max + 1));
}
-#ifdef HASH_COPYKEYS
-hash_t* hash_create(size_t klen)
+#ifdef HASH_CALLBACKS
+ #ifdef HASH_COPYKEYS
+hash_t* hash_create(size_t klen, hash_free_val_t f_free, void* arg)
+ #else
+hash_t* hash_create(hash_free_val_t f_free, void* arg)
+ #endif
#else
+ #ifdef HASH_COPYKEYS
+hash_t* hash_create(size_t klen)
+ #else
hash_t* hash_create()
+ #endif
#endif
{
hash_t* ht = malloc(sizeof(hash_t));
@@ -117,7 +129,10 @@ hash_t* hash_create()
#ifdef HASH_COPYKEYS
ht->klen = klen;
#endif
-
+#ifdef HASH_CALLBACKS
+ ht->f_free = f_free;
+ ht->arg = arg;
+#endif
if(!ht->array)
{
free(ht);
@@ -132,7 +147,13 @@ void hash_free(hash_t* ht)
hash_index_t* hi;
for(hi = hash_first(ht); hi; hi = hash_next(hi))
+ {
+#ifdef HASH_CALLBACKS
+ if(hi->ths->val && ht->f_free)
+ ht->f_free(ht->arg, (void*)hi->ths->val);
+#endif
free(hi->ths);
+ }
if(ht->array)
free(ht->array);
@@ -362,58 +383,64 @@ void* hash_get(hash_t* ht, const void *key, size_t klen)
}
#ifdef HASH_COPYKEYS
-int hash_set(hash_t* ht, const void* key, const void* val)
+int hash_set(hash_t* ht, const void* key, void* val)
{
hash_entry_t** hep = find_entry(ht, key, val);
#else
-int hash_set(hash_t* ht, const void* key, size_t klen, const void* val)
+int hash_set(hash_t* ht, const void* key, size_t klen, void* val)
{
hash_entry_t** hep = find_entry(ht, key, klen, val);
#endif
if(hep && *hep)
{
- if(val)
- {
- /* replace entry */
- (*hep)->val = val;
+#ifdef HASH_CALLBACKS
+ if((*hep)->val && (*hep)->val != val && ht->f_free)
+ ht->f_free(ht->arg, (void*)((*hep)->val));
+#endif
+
+ /* replace entry */
+ (*hep)->val = val;
#ifdef HASH_TIMESTAMP
- /* Update or set the timestamp */
- (*hep)->stamp = time(NULL);
+ /* Update or set the timestamp */
+ (*hep)->stamp = time(NULL);
#endif
- /* check that the collision rate isn't too high */
- if(ht->count > ht->max)
- {
- if(!expand_array(ht))
- return 0;
- }
-
- return 1;
+ /* check that the collision rate isn't too high */
+ if(ht->count > ht->max)
+ {
+ if(!expand_array(ht))
+ return 0;
}
+
+ return 1;
}
return 0;
}
#ifdef HASH_COPYKEYS
-void hash_rem(hash_t* ht, const void* key)
+void* hash_rem(hash_t* ht, const void* key)
{
hash_entry_t** hep = find_entry(ht, key, NULL);
#else
-void hash_rem(hash_t* ht, const void* key, size_t klen)
+void* hash_rem(hash_t* ht, const void* key, size_t klen)
{
hash_entry_t** hep = find_entry(ht, key, klen, NULL);
#endif
+ void* val = NULL;
if(hep && *hep)
{
hash_entry_t* old = *hep;
*hep = (*hep)->next;
--ht->count;
+ val = (void*)old->val;
free(old);
}
+
+ return val;
}
unsigned int hash_count(hash_t* ht)
@@ -426,6 +453,7 @@ int hash_purge(hash_t* ht, time_t stamp)
{
hash_index_t* hi;
int r = 0;
+ void* val;
for(hi = hash_first(ht); hi; hi = hash_next(hi))
{
@@ -433,9 +461,14 @@ int hash_purge(hash_t* ht, time_t stamp)
{
/* No need to check for errors as we're deleting */
#ifdef HASH_COPYKEYS
- hash_rem(ht, KEY_DATA(hi->ths));
+ val = hash_rem(ht, KEY_DATA(hi->ths));
#else
- hash_rem(ht, hi->ths->key, hi->ths->klen);
+ val = hash_rem(ht, hi->ths->key, hi->ths->klen);
+#endif
+
+#ifdef HASH_CALLBACKS
+ if(val && ht->f_free)
+ (ht->f_free)(ht->arg, val);
#endif
r++;
@@ -446,17 +479,58 @@ int hash_purge(hash_t* ht, time_t stamp)
}
#ifdef HASH_COPYKEYS
-void* hash_touch(hash_index_t* hi, const void** key);
+void hash_touch(hash_t* ht, const void* key)
{
hash_entry_t** hep = find_entry(ht, key, NULL);
#else
-void* hash_touch(hash_index_t* hi, const void** key, size_t* klen);
+void hash_touch(hash_t* ht, const void* key, size_t* klen)
{
hash_entry_t** hep = find_entry(ht, key, klen, NULL);
#endif
- if(he && *he)
- ((*he)->stamp) = time(NULL);
+ if(hep && *hep)
+ ((*hep)->stamp) = time(NULL);
+}
+
+int hash_bump(hash_t* ht)
+{
+ hash_index_t* hi;
+ void* key = NULL;
+ void* val = NULL;
+ time_t least = 0;
+#ifndef HASH_COPYKEYS
+ size_t klen = 0;
+#endif
+
+ for(hi = hash_first(ht); hi; hi = hash_next(hi))
+ {
+ if(least == 0 || hi->ths->stamp < least)
+ {
+ least = hi->ths->stamp;
+ key = KEY_DATA(hi->ths);
+#ifndef HASH_COPYKEYS
+ klen = hi->this->klen;
+#endif
+ }
+ }
+
+ if(key)
+ {
+#ifdef HASH_COPYKEYS
+ val = hash_rem(ht, key);
+#else
+ val = hash_rem(ht, key, klen);
+#endif
+
+#ifdef HASH_CALLBACKS
+ if(val && ht->f_free)
+ (ht->f_free)(ht->arg, (void*)val);
+#endif
+
+ return 1;
+ }
+
+ return 0;
}
#endif /* HASH_TIMESTAMP */
diff --git a/common/hash.h b/common/hash.h
index 9e8174c..2b22b64 100644
--- a/common/hash.h
+++ b/common/hash.h
@@ -22,7 +22,7 @@
#define __HASH_H__
/*
- * Options to define. You need to build both this file and
+ * Features to define. You need to build both this file and
* the corresponding hash.c file with whatever options you set here
*/
@@ -32,6 +32,9 @@
/* Keep key values internally */
#define HASH_COPYKEYS 1
+/* Hash callback functionality */
+#define HASH_CALLBACKS 1
+
#ifdef __cplusplus
extern "C" {
@@ -49,16 +52,31 @@ typedef struct hash_t hash_t;
/* Abstract type for scanning hash tables. */
typedef struct hash_index_t hash_index_t;
+/* A callback during remove operations */
+#ifdef HASH_CALLBACKS
+ typedef void (*hash_free_val_t)(void* arg, void* val);
+#endif
+
/* Create a hash table */
-#ifdef HASH_COPYKEYS
- hash_t* hash_create(size_t klen);
+#ifdef HASH_CALLBACKS
+ #ifdef HASH_COPYKEYS
+ hash_t* hash_create(size_t klen, hash_free_val_t f_free, void* arg);
+ #else
+ hash_t* hash_create(hash_free_val_t f_free, void* arg);
+ #endif
#else
- hash_t* hash_create();
-#endif
+ #ifdef HASH_COPYKEYS
+ hash_t* hash_create(size_t klen);
+ #else
+ hash_t* hash_create();
+ #endif
+#endif /* HASH_CALLBACKS */
+
/* To release all resources for a hash table */
void hash_free(hash_t* ht);
+
/**
* Associate a value with a key in a hash table.
*
@@ -70,11 +88,12 @@ void hash_free(hash_t* ht);
* val must not be null
*/
#ifdef HASH_COPYKEYS
- int hash_set(hash_t* ht, const void* key, const void* val);
+ int hash_set(hash_t* ht, const void* key, void* val);
#else
- int hash_set(hash_t* ht, const void* key, size_t klen, const void* val);
+ int hash_set(hash_t* ht, const void* key, size_t klen, void* val);
#endif
+
/**
* Remove a value and key form the hash table
*
@@ -83,11 +102,12 @@ void hash_free(hash_t* ht);
* klen Length of the key. Can be HASH_KEY_STRING to use the string length
*/
#ifdef HASH_COPYKEYS
- void hash_rem(hash_t* ht, const void* key);
+ void* hash_rem(hash_t* ht, const void* key);
#else
- void hash_rem(hash_t* ht, const void* key, size_t klen);
+ void* hash_rem(hash_t* ht, const void* key, size_t klen);
#endif
+
/**
* Look up the value associated with a key in a hash table.
*
@@ -103,6 +123,7 @@ void hash_free(hash_t* ht);
void* hash_get(hash_t* ht, const void* key, size_t klen);
#endif
+
/**
* Start iterating over the entries in a hash table.
*
@@ -114,6 +135,7 @@ void hash_free(hash_t* ht);
*/
hash_index_t* hash_first(hash_t* ht);
+
/**
* Continue iterating over the entries in a hash table.
*
@@ -124,6 +146,7 @@ hash_index_t* hash_first(hash_t* ht);
*/
hash_index_t* hash_next(hash_index_t* hi);
+
/**
* Get the current entry's details from the iteration state.
*
@@ -141,19 +164,26 @@ hash_index_t* hash_next(hash_index_t* hi);
void* hash_this(hash_index_t* hi, const void** key, size_t* klen);
#endif
+
/**
* Purge entries before a certain timestamp
*/
#ifdef HASH_TIMESTAMP
+
int hash_purge(hash_t* ht, time_t stamp);
#ifdef HASH_COPYKEYS
- void hash_touch(hash_index_t* hi, const void** key);
+ void hash_touch(hash_t* ht, const void* key);
#else
- void hash_touch(hash_index_t* hi, const void** key, size_t* klen);
+ void hash_touch(hash_t* ht, const void* key, size_t* klen);
#endif
+
+/* Bumps the oldest out */
+int hash_bump(hash_t* ht);
+
#endif
+
/**
* Get the number of key/value pairs in the hash table.
*
diff --git a/common/md5.c b/common/md5.c
index c909bb3..2f92bec 100644
--- a/common/md5.c
+++ b/common/md5.c
@@ -18,6 +18,8 @@
#include <string.h>
#include "md5.h"
+void md5_transform(unsigned int buf[4], unsigned int const in[16]);
+
#ifdef BIG_ENDIAN
void
byteSwap(unsigned int *buf, unsigned words)
@@ -39,7 +41,7 @@ byteSwap(unsigned int *buf, unsigned words)
* initialization constants.
*/
void
-MD5Init(struct MD5Context *ctx)
+md5_init(md5_ctx_t* ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
@@ -55,9 +57,10 @@ MD5Init(struct MD5Context *ctx)
* of bytes.
*/
void
-MD5Update(struct MD5Context *ctx, const unsigned char* buf, unsigned len)
+md5_update(md5_ctx_t* ctx, const void* b, unsigned len)
{
unsigned int t;
+ const unsigned char* buf = (const unsigned char*)b;
/* Update byte count */
@@ -73,7 +76,7 @@ MD5Update(struct MD5Context *ctx, const unsigned char* buf, unsigned len)
/* First chunk is an odd size */
memcpy((unsigned char *)ctx->in + 64 - t, buf, t);
byteSwap(ctx->in, 16);
- MD5Transform(ctx->buf, ctx->in);
+ md5_transform(ctx->buf, ctx->in);
buf += t;
len -= t;
@@ -81,7 +84,7 @@ MD5Update(struct MD5Context *ctx, const unsigned char* buf, unsigned len)
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteSwap(ctx->in, 16);
- MD5Transform(ctx->buf, ctx->in);
+ md5_transform(ctx->buf, ctx->in);
buf += 64;
len -= 64;
}
@@ -95,7 +98,7 @@ MD5Update(struct MD5Context *ctx, const unsigned char* buf, unsigned len)
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void
-MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+md5_final(unsigned char digest[16], md5_ctx_t* ctx)
{
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
unsigned char *p = (unsigned char *)ctx->in + count;
@@ -109,7 +112,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
if (count < 0) { /* Padding forces an extra block */
memset(p, 0, (unsigned int)count + 8);
byteSwap(ctx->in, 16);
- MD5Transform(ctx->buf, ctx->in);
+ md5_transform(ctx->buf, ctx->in);
p = (unsigned char *)ctx->in;
count = 56;
}
@@ -119,13 +122,30 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
/* Append length in bits and transform */
ctx->in[14] = ctx->bytes[0] << 3;
ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
- MD5Transform(ctx->buf, ctx->in);
+ md5_transform(ctx->buf, ctx->in);
byteSwap(ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
+void
+md5_string(unsigned char digest[MD5_LEN], const char* str)
+{
+ md5_ctx_t md5;
+ md5_init(&md5);
+ md5_update(&md5, str, strlen(str));
+ md5_final(digest, &md5);
+}
+
+int
+md5_strcmp(unsigned char digest[MD5_LEN], const char* str)
+{
+ unsigned char other[MD5_LEN];
+ md5_string(other, str);
+ return memcmp(digest, other, MD5_LEN);
+}
+
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
@@ -144,7 +164,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
* the data and converts bytes into longwords for this routine.
*/
void
-MD5Transform(unsigned int buf[4], unsigned int const in[16])
+md5_transform(unsigned int buf[4], unsigned int const in[16])
{
register unsigned int a, b, c, d;
diff --git a/common/md5.h b/common/md5.h
index 62cbf2b..de431da 100644
--- a/common/md5.h
+++ b/common/md5.h
@@ -15,7 +15,7 @@
* will fill a supplied 16-byte array with the digest.
*
* Changed so as no longer to depend on Colin Plumb's `usual.h'
- * header definitions; now uses stuff from dpkg's config.h
+ * header definitions
* - Ian Jackson <ijackson@nyx.cs.du.edu>.
* Still in the public domain.
*/
@@ -27,20 +27,22 @@ extern "C" {
#ifndef MD5_H
#define MD5_H
+#define MD5_LEN 16
#define md5byte unsigned char
-struct MD5Context {
- unsigned int buf[4];
- unsigned int bytes[2];
- unsigned int in[16];
-};
-
-typedef struct MD5Context MD5_CTX;
+typedef struct md5_ctx
+{
+ unsigned int buf[4];
+ unsigned int bytes[2];
+ unsigned int in[16];
+}
+md5_ctx_t;
-void MD5Init(struct MD5Context *context);
-void MD5Update(struct MD5Context *context, const md5byte* buf, unsigned len);
-void MD5Final(unsigned char digest[16], struct MD5Context *context);
-void MD5Transform(unsigned int buf[4], unsigned int const in[16]);
+void md5_init(md5_ctx_t* context);
+void md5_update(md5_ctx_t* context, const void* buf, unsigned len);
+void md5_final(unsigned char digest[MD5_LEN], md5_ctx_t* context);
+void md5_string(unsigned char digest[MD5_LEN], const char* str);
+int md5_strcmp(unsigned char digest[MD5_LEN], const char* str);
#ifdef __cplusplus
}
diff --git a/common/sha1.c b/common/sha1.c
new file mode 100644
index 0000000..a40732e
--- /dev/null
+++ b/common/sha1.c
@@ -0,0 +1,164 @@
+/*
+ * Fetched from ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c on May 4, 1999
+ * Modified by EPG May 6, 1999
+ */
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+#include <string.h>
+#include "sha1.h"
+
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+
+void SHA1Transform(ulong state[5], const uchar buffer[64]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(ulong state[5], const uchar buffer[64])
+{
+ ulong a, b, c, d, e;
+ typedef union {
+ uchar c[64];
+ ulong l[16];
+ } CHAR64LONG16;
+ CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+ static uchar workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void sha1_init(sha1_ctx_t* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void sha1_update(sha1_ctx_t* context, const void* d, unsigned int len)
+{
+ unsigned int i, j;
+ const uchar* data = (uchar*)d;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void sha1_final(uchar digest[20], sha1_ctx_t* context)
+{
+ ulong i;
+ uchar finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (uchar)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ sha1_update(context, (uchar *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ sha1_update(context, (uchar *)"\0", 1);
+ }
+ sha1_update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (uchar)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+
diff --git a/common/sha1.h b/common/sha1.h
new file mode 100644
index 0000000..37f734f
--- /dev/null
+++ b/common/sha1.h
@@ -0,0 +1,30 @@
+#ifndef __SHA1_H__
+#define __SHA1_H__
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SHA1_LEN 20
+
+typedef struct sha1_ctx
+{
+ unsigned long state[5];
+ unsigned long count[2];
+ unsigned char buffer[64];
+}
+sha1_ctx_t;
+
+void sha1_init(sha1_ctx_t* context);
+void sha1_update(sha1_ctx_t* context, const void* data, unsigned int len);
+void sha1_final(unsigned char digest[SHA1_LEN], sha1_ctx_t* context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SHA1_H__