Hi,

Attached is a patch against OpenSRF trunk that replaces the body of sha.c to use the gnutls_fingerprint() function.

I did not make any changes to md5.c because the public interface in md5.h looks a bit more complicated than used by sha.h: 3 functions vs. 1. Replacing the md5 implementation with something that uses gnutls_fingerprint(), I leave as an exercise for someone more familiar with that part of the code than myself.

The patch builds on our test system, which is Ubuntu Hardy Heron.

GNUtls is LGPL, so avoids the licensing issues of OpenSSL.

Cheers,
Jason

Index: src/libopensrf/sha.c
===================================================================
--- src/libopensrf/sha.c	(revision 1878)
+++ src/libopensrf/sha.c	(working copy)
@@ -13,252 +13,32 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  * 
- *  Gabber
- *  Copyright (C) 1999-2000 Dave Smith & Julian Missig
+ * Copyright (C) 2009 Jason J.A. Stephenson
  */
 
-
-/* 
-   Implements the Secure Hash Algorithm (SHA1)
-
-   Copyright (C) 1999 Scott G. Miller
-
-   Released under the terms of the GNU General Public License v2
-   see file COPYING for details
-
-   Credits: 
-      Robert Klep <[email protected]>  -- Expansion function fix 
-	  Thomas "temas" Muldowney <[email protected]>:
-	  		-- shahash() for string fun
-			-- Will add the int32 stuff in a few
-	  		
-   ---
-   FIXME: This source takes int to be a 32 bit integer.  This
-   may vary from system to system.  I'd use autoconf if I was familiar
-   with it.  Anyone want to help me out?
+/*
+  Completely gutted and rewritten to use libgnutls on 2009-12-23 by
+  Jason Stephenson <[email protected]>.
 */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
+#include <gnutls/gnutls.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#ifdef MACOS
-#  include <string.h>
-#else
-#  include <sys/stat.h>
-#  include <sys/types.h>
-#endif
-
 #include <string.h>
 
-#ifndef WIN32
-#  include <unistd.h>
-#  define INT64 long long
-#else
-#  include <string.h>
-#  define snprintf _snprintf
-#  define INT64 __int64
-#endif
-
-#define switch_endianness(x) (x<<24 & 0xff000000) | \
-                             (x<<8  & 0x00ff0000) | \
-                             (x>>8  & 0x0000ff00) | \
-                             (x>>24 & 0x000000ff)
-
-/* Initial hash values */
-#define Ai 0x67452301 
-#define Bi 0xefcdab89
-#define Ci 0x98badcfe
-#define Di 0x10325476
-#define Ei 0xc3d2e1f0
-
-/* SHA1 round constants */
-#define K1 0x5a827999
-#define K2 0x6ed9eba1
-#define K3 0x8f1bbcdc 
-#define K4 0xca62c1d6
-
-/* Round functions.  Note that f2() is used in both rounds 2 and 4 */
-#define f1(B,C,D) ((B & C) | ((~B) & D))
-#define f2(B,C,D) (B ^ C ^ D)
-#define f3(B,C,D) ((B & C) | (B & D) | (C & D))
-
-/* left circular shift functions (rotate left) */
-#define rol1(x) ((x<<1) | ((x>>31) & 1))
-#define rol5(A) ((A<<5) | ((A>>27) & 0x1f))
-#define rol30(B) ((B<<30) | ((B>>2) & 0x3fffffff))
-
-/*
-  Hashes 'data', which should be a pointer to 512 bits of data (sixteen
-  32 bit ints), into the ongoing 160 bit hash value (five 32 bit ints)
-  'hash'
-*/
-int 
-sha_hash(int *data, int *hash)  
+char *shahash(const char *str)
 {
-  int W[80];
-  unsigned int A=hash[0], B=hash[1], C=hash[2], D=hash[3], E=hash[4];
-  unsigned int t, x, TEMP;
-
-  for (t=0; t<16; t++) 
-    {
-#ifndef WORDS_BIGENDIAN
-      W[t]=switch_endianness(data[t]);
-#else 
-      W[t]=data[t];
-#endif
-    }
-
-
-  /* SHA1 Data expansion */
-  for (t=16; t<80; t++) 
-    {
-      x=W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
-      W[t]=rol1(x);
-    }
-
-  /* SHA1 main loop (t=0 to 79) 
-   This is broken down into four subloops in order to use
-   the correct round function and constant */
-  for (t=0; t<20; t++) 
-    {
-      TEMP=rol5(A) + f1(B,C,D) + E + W[t] + K1;
-      E=D;
-      D=C;
-      C=rol30(B);
-      B=A;
-      A=TEMP;
-    }
-  for (; t<40; t++) 
-    {
-      TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K2;
-      E=D;
-      D=C;
-      C=rol30(B);
-      B=A;
-      A=TEMP;
-    }
-  for (; t<60; t++) 
-    {
-      TEMP=rol5(A) + f3(B,C,D) + E + W[t] + K3;
-      E=D;
-      D=C;
-      C=rol30(B);
-      B=A;
-      A=TEMP;
-    }
-  for (; t<80; t++) 
-    {
-      TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K4;
-      E=D;
-      D=C;
-      C=rol30(B);
-      B=A;
-      A=TEMP;
-    }
-  hash[0]+=A; 
-  hash[1]+=B;
-  hash[2]+=C;
-  hash[3]+=D;
-  hash[4]+=E;
-  return 0;
-}
-
-/*
-  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
-  intializes it to the start constants of the SHA1 algorithm.  This
-  must be called before using hash in the call to sha_hash
-*/
-int 
-sha_init(int *hash) 
-{
-  hash[0]=Ai;
-  hash[1]=Bi;
-  hash[2]=Ci;
-  hash[3]=Di;
-  hash[4]=Ei;
-  return 0;
-}
-
-int strprintsha(char *dest, int *hashval) 
-{
-	int x;
-	char *hashstr = dest;
-	for (x=0; x<5; x++) 
-	{
-		snprintf(hashstr, 9, "%08x", hashval[x]);
-		hashstr+=8;
-	}
-	//snprintf(hashstr++, 1, "\0");
-	hashstr[0] = '\0';
-	hashstr++;
-
-	return 0;
-}
-
-char *shahash(const char *str) 
-{
-	char read_buffer[65];
-	//int read_buffer[64];
-	int c=1, i;
-       
-	INT64 length=0;
-
-	int strsz;
-	static char final[41];
-	int *hashval;
-
-	hashval = (int *)malloc(20);
-
-	sha_init(hashval);
-
-	strsz = strlen(str);
-
-	if(strsz == 0) 
-	{
-	     memset(read_buffer, 0, 65);
-	     read_buffer[0] = 0x80;
-	     sha_hash((int *)read_buffer, hashval);
-	}
-
-	while (strsz>0) 
-	{
-		memset(read_buffer, 0, 65);
-		strncpy((char*)read_buffer, str, 64);
-		c = strlen((char *)read_buffer);
-		length+=c;
-		strsz-=c;
-		if (strsz<=0) 
-		{
-			length<<=3;	
-			read_buffer[c]=(char)0x80;
-			for (i=c+1; i<64; i++) 
-				read_buffer[i]=0;
-			if (c>55) 
-			{
-				/* we need to do an entire new block */
-				sha_hash((int *)read_buffer, hashval);
-				for (i=0; i<14; i++) 
-					((int*)read_buffer)[i]=0;
-			}      
-#ifndef WORDS_BIGENDIAN
-			for (i=0; i<8; i++) 
-			{
-				read_buffer[56+i]=(char)(length>>(56-(i*8))) & 0xff;
-			}
-#else	
-			memcpy(read_buffer+56, &length, 8);
-#endif
+	gnutls_datum_t in;
+	size_t out_size = 20; /* SHA1 is 160 bits output. */
+	char *out = calloc(out_size + 1, sizeof(char));
+	
+	if (out != NULL) {
+		in.data = str;
+		in.size = (int)strlen(str);
+		if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, out, &out_size) != GNUTLS_E_SUCCESS) {
+			free(out);
+			out = NULL;
 		}
-		
-		sha_hash((int *)read_buffer, hashval);
-		str+=64;
 	}
-
-	strprintsha((char *)final, hashval);
-	free(hashval);
-	return (char *)final;
+	return out;
 }
+
Index: src/libopensrf/Makefile.am
===================================================================
--- src/libopensrf/Makefile.am	(revision 1878)
+++ src/libopensrf/Makefile.am	(working copy)
@@ -109,9 +109,9 @@
 libosrf_json_la_SOURCES = $(JSON_TARGS) $(JSON_DEP) $(JSON_TARGS_HEADS) $(JSON_DEP_HEADS)
 libosrf_json_la_CFLAGS = $(AM_CFLAGS)
 
-libopensrf_la_CFLAGS = $(AM_CFLAGS) $(memcached_CFLAGS)
+libopensrf_la_CFLAGS = $(AM_CFLAGS) $(memcached_CFLAGS) $(gnutls_CFLAGS)
 libopensrf_la_DEPENDENCIES = libosrf_json.la
-libopensrf_la_LIBADD = $(memcached_LIBS)
+libopensrf_la_LIBADD = $(memcached_LIBS) $(gnutls_LIBS)
 
 libopensrf_la_SOURCES = $(TARGS) $(TARGS_HEADS) $(JSON_TARGS) $(JSON_TARGS_HEADS)
 
Index: configure.ac
===================================================================
--- configure.ac	(revision 1878)
+++ configure.ac	(working copy)
@@ -262,6 +262,9 @@
 	PKG_CHECK_MODULES(memcached, libmemcached >= 0.8.0)
 	AC_SUBST(memcached_CFLAGS)
 	AC_SUBST(memcached_LIBS)
+	PKG_CHECK_MODULES(gnutls, gnutls)
+	AC_SUBST(gnutls_CFLAGS)
+	AC_SUBST(gnutls_LIBS)
 
 	#-----------------------------
 	# Checks for header files.
Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

Signed-off-by: 
Jason J.A. Stephenson <[email protected]>
Jason J.A. Stephenson <[email protected]>

Reply via email to