shithub: openh264

Download patch

ref: 58b39c97743ac9374d5318762bc58b3ce8cd90f4
parent: 59c8fd19d0c6284af038a7b2a28cc710d8a6bdef
parent: e88348b76d917e03c4c38114456e32b328b8193c
author: Ethan Hugg <[email protected]>
date: Mon Feb 24 01:27:11 EST 2014

Merge pull request #156 from mstorsjo/avoid-openssl

Get rid of the OpenSSL dependency by bundling a simple SHA1 implementation

--- a/Makefile
+++ b/Makefile
@@ -82,7 +82,7 @@
 H264ENC_LDFLAGS = -L. $(call LINK_LIB,encoder) $(call LINK_LIB,processing) $(call LINK_LIB,common)
 H264ENC_DEPS = $(LIBPREFIX)encoder.$(LIBSUFFIX) $(LIBPREFIX)processing.$(LIBSUFFIX) $(LIBPREFIX)common.$(LIBSUFFIX)
 
-CODEC_UNITTEST_LDFLAGS = -L. -lgtest -ldecoder -lcrypto -lencoder -lprocessing -lcommon
+CODEC_UNITTEST_LDFLAGS = -L. $(call LINK_LIB,gtest) $(call LINK_LIB,decoder) $(call LINK_LIB,encoder) $(call LINK_LIB,processing) $(call LINK_LIB,common)
 CODEC_UNITTEST_DEPS = $(LIBPREFIX)gtest.$(LIBSUFFIX) $(LIBPREFIX)decoder.$(LIBSUFFIX) $(LIBPREFIX)encoder.$(LIBSUFFIX) $(LIBPREFIX)processing.$(LIBSUFFIX) $(LIBPREFIX)common.$(LIBSUFFIX)
 
 .PHONY: test gtest-bootstrap clean
--- a/build/platform-darwin.mk
+++ b/build/platform-darwin.mk
@@ -2,7 +2,7 @@
 ASM = nasm
 SHAREDLIBSUFFIX = dylib
 SHARED = -dynamiclib
-CFLAGS += -Wno-deprecated-declarations -Werror -fPIC -DMACOS -DMT_ENABLED -MMD -MP
+CFLAGS += -Werror -fPIC -DMACOS -DMT_ENABLED -MMD -MP
 LDFLAGS += -lpthread
 ASMFLAGS += --prefix _ -DNOPREFIX
 ifeq ($(ENABLE64BIT), Yes)
--- a/build/platform-msvc-common.mk
+++ b/build/platform-msvc-common.mk
@@ -2,7 +2,7 @@
 CXX=cl
 AR=lib
 CXX_O=-Fo$@
-CFLAGS += -nologo -W3 -EHsc -fp:precise -Zc:wchar_t -Zc:forScope
+CFLAGS += -nologo -W3 -EHsc -fp:precise -Zc:wchar_t -Zc:forScope -DGTEST_HAS_TR1_TUPLE=0
 CXX_LINK_O=-nologo -Fe$@
 AR_OPTS=-nologo -out:$@
 CFLAGS_OPT=-O2 -Ob1 -Oy- -Zi -GF -Gm- -GS -Gy -MD -DNDEBUG
--- a/test/BaseDecoderTest.h
+++ b/test/BaseDecoderTest.h
@@ -1,7 +1,7 @@
 #ifndef __BASEDECODERTEST_H__
 #define __BASEDECODERTEST_H__
 
-#include <stdint.h>
+#include "test_stdint.h"
 #include <limits.h>
 #include <fstream>
 #include "codec_api.h"
--- a/test/decode_encode_test.cpp
+++ b/test/decode_encode_test.cpp
@@ -6,7 +6,7 @@
 #include "BaseDecoderTest.h"
 #include "BaseEncoderTest.h"
 
-static void UpdateHashFromFrame(const SFrameBSInfo& info, SHA_CTX* ctx) {
+static void UpdateHashFromFrame(const SFrameBSInfo& info, SHA1Context* ctx) {
   for (int i = 0; i < info.iLayerNum; ++i) {
     const SLayerBSInfo& layerInfo = info.sLayerInfo[i];
     int layerSize = 0;
@@ -13,7 +13,7 @@
     for (int j = 0; j < layerInfo.iNalCount; ++j) {
       layerSize += layerInfo.iNalLengthInByte[j];
     }
-    SHA1_Update(ctx, layerInfo.pBsBuf, layerSize);
+    SHA1Input(ctx, layerInfo.pBsBuf, layerSize);
   }
 }
 
@@ -49,7 +49,7 @@
     if (HasFatalFailure()) {
       return;
     }
-    SHA1_Init(&ctx_);
+    SHA1Reset(&ctx_);
   }
 
   virtual void TearDown() {
@@ -87,7 +87,7 @@
   }
 
  protected:
-  SHA_CTX ctx_;
+  SHA1Context ctx_;
   BufferedData buf_;
 };
 
@@ -97,7 +97,7 @@
   ASSERT_TRUE(Open(p.fileName));
   EncodeStream(this, p.width, p.height, p.frameRate, this);
   unsigned char digest[SHA_DIGEST_LENGTH];
-  SHA1_Final(digest, &ctx_);
+  SHA1Result(&ctx_, digest);
   if (!HasFatalFailure()) {
     ASSERT_TRUE(CompareHash(digest, p.hashStr));
   }
--- a/test/decoder_test.cpp
+++ b/test/decoder_test.cpp
@@ -2,10 +2,10 @@
 #include "utils/HashFunctions.h"
 #include "BaseDecoderTest.h"
 
-static void UpdateHashFromPlane(SHA_CTX* ctx, const uint8_t* plane,
+static void UpdateHashFromPlane(SHA1Context* ctx, const uint8_t* plane,
     int width, int height, int stride) {
   for (int i = 0; i < height; i++) {
-    SHA1_Update(ctx, plane, width);
+    SHA1Input(ctx, plane, width);
     plane += stride;
   }
 }
@@ -36,7 +36,7 @@
     if (HasFatalFailure()) {
       return;
     }
-    SHA1_Init(&ctx_);
+    SHA1Reset(&ctx_);
   }
   virtual void onDecodeFrame(const Frame& frame) {
     const Plane& y = frame.y;
@@ -47,7 +47,7 @@
     UpdateHashFromPlane(&ctx_, v.data, v.width, v.height, v.stride);
   }
  protected:
-  SHA_CTX ctx_;
+  SHA1Context ctx_;
 };
 
 TEST_P(DecoderOutputTest, CompareOutput) {
@@ -55,7 +55,7 @@
   DecodeFile(p.fileName, this);
 
   unsigned char digest[SHA_DIGEST_LENGTH];
-  SHA1_Final(digest, &ctx_);
+  SHA1Result(&ctx_, digest);
   if (!HasFatalFailure()) {
     ASSERT_TRUE(CompareHash(digest, p.hashStr));
   }
--- a/test/encoder_test.cpp
+++ b/test/encoder_test.cpp
@@ -2,7 +2,7 @@
 #include "utils/HashFunctions.h"
 #include "BaseEncoderTest.h"
 
-static void UpdateHashFromFrame(const SFrameBSInfo& info, SHA_CTX* ctx) {
+static void UpdateHashFromFrame(const SFrameBSInfo& info, SHA1Context* ctx) {
   for (int i = 0; i < info.iLayerNum; ++i) {
     const SLayerBSInfo& layerInfo = info.sLayerInfo[i];
     int layerSize = 0;
@@ -9,7 +9,7 @@
     for (int j = 0; j < layerInfo.iNalCount; ++j) {
       layerSize += layerInfo.iNalLengthInByte[j];
     }
-    SHA1_Update(ctx, layerInfo.pBsBuf, layerSize);
+    SHA1Input(ctx, layerInfo.pBsBuf, layerSize);
   }
 }
 
@@ -41,13 +41,13 @@
     if (HasFatalFailure()) {
       return;
     }
-    SHA1_Init(&ctx_);
+    SHA1Reset(&ctx_);
   }
   virtual void onEncodeFrame(const SFrameBSInfo& frameInfo) {
     UpdateHashFromFrame(frameInfo, &ctx_);
   }
  protected:
-  SHA_CTX ctx_;
+  SHA1Context ctx_;
 };
 
 
@@ -56,7 +56,7 @@
   EncodeFile(p.fileName, p.width, p.height, p.frameRate, this);
 
   unsigned char digest[SHA_DIGEST_LENGTH];
-  SHA1_Final(digest, &ctx_);
+  SHA1Result(&ctx_, digest);
   if (!HasFatalFailure()) {
     ASSERT_TRUE(CompareHash(digest, p.hashStr));
   }
--- /dev/null
+++ b/test/sha1.c
@@ -1,0 +1,399 @@
+/*!
+ * \copy
+ *     Copyright (c)  1998, 2009 Paul E. Jones <[email protected]>
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ *  Description:
+ *      This file implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      The Secure Hashing Standard, which uses the Secure Hashing
+ *      Algorithm (SHA), produces a 160-bit message digest for a
+ *      given data stream.  In theory, it is highly improbable that
+ *      two messages will produce the same message digest.  Therefore,
+ *      this algorithm can serve as a means of providing a "fingerprint"
+ *      for a message.
+ *
+ *  Portability Issues:
+ *      SHA-1 is defined in terms of 32-bit "words".  This code was
+ *      written with the expectation that the processor has at least
+ *      a 32-bit machine word size.  If the machine word size is larger,
+ *      the code should still function properly.  One caveat to that
+ *      is that the input functions taking characters and character
+ *      arrays assume that only 8 bits of information are stored in each
+ *      character.
+ *
+ *  Caveats:
+ *      SHA-1 is designed to work with messages less than 2^64 bits
+ *      long. Although SHA-1 allows a message digest to be generated for
+ *      messages of any number of bits less than 2^64, this
+ *      implementation only works with messages with a length that is a
+ *      multiple of the size of an 8-bit character.
+ *
+ */
+
+#include "sha1.h"
+
+/*
+ *  Define the circular shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+                ((((word) << (bits)) & 0xFFFFFFFF) | \
+                ((word) >> (32-(bits))))
+
+/* Function prototypes */
+void SHA1ProcessMessageBlock(SHA1Context *);
+void SHA1PadMessage(SHA1Context *);
+
+/*
+ *  SHA1Reset
+ *
+ *  Description:
+ *      This function will initialize the SHA1Context in preparation
+ *      for computing a new message digest.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to reset.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1Reset(SHA1Context *context)
+{
+    context->Length_Low             = 0;
+    context->Length_High            = 0;
+    context->Message_Block_Index    = 0;
+
+    context->Message_Digest[0]      = 0x67452301;
+    context->Message_Digest[1]      = 0xEFCDAB89;
+    context->Message_Digest[2]      = 0x98BADCFE;
+    context->Message_Digest[3]      = 0x10325476;
+    context->Message_Digest[4]      = 0xC3D2E1F0;
+
+    context->Computed   = 0;
+    context->Corrupted  = 0;
+}
+
+/*
+ *  SHA1Result
+ *
+ *  Description:
+ *      This function will return the 160-bit message digest into the
+ *      digest array provided as a parameter.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to use to calculate the SHA-1 hash.
+ *      digest: [out]
+ *          An array of characters where the digest is written.
+ *
+ *  Returns:
+ *      1 if successful, 0 if it failed.
+ *
+ *  Comments:
+ *
+ */
+int SHA1Result(SHA1Context *context, unsigned char *digest)
+{
+    int i;
+
+    if (context->Corrupted)
+    {
+        return 0;
+    }
+
+    if (!context->Computed)
+    {
+        SHA1PadMessage(context);
+        context->Computed = 1;
+    }
+
+    for (i = 0; i < SHA_DIGEST_LENGTH; i++)
+        digest[i] = context->Message_Digest[i / 4] >> (8 * (3 - (i % 4)));
+
+    return 1;
+}
+
+/*
+ *  SHA1Input
+ *
+ *  Description:
+ *      This function accepts an array of octets as the next portion of
+ *      the message.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The SHA-1 context to update
+ *      message_array: [in]
+ *          An array of characters representing the next portion of the
+ *          message.
+ *      length: [in]
+ *          The length of the message in message_array
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1Input(     SHA1Context         *context,
+                    const unsigned char *message_array,
+                    unsigned            length)
+{
+    if (!length)
+    {
+        return;
+    }
+
+    if (context->Computed || context->Corrupted)
+    {
+        context->Corrupted = 1;
+        return;
+    }
+
+    while(length-- && !context->Corrupted)
+    {
+        context->Message_Block[context->Message_Block_Index++] =
+                                                (*message_array & 0xFF);
+
+        context->Length_Low += 8;
+        /* Force it to 32 bits */
+        context->Length_Low &= 0xFFFFFFFF;
+        if (context->Length_Low == 0)
+        {
+            context->Length_High++;
+            /* Force it to 32 bits */
+            context->Length_High &= 0xFFFFFFFF;
+            if (context->Length_High == 0)
+            {
+                /* Message is too long */
+                context->Corrupted = 1;
+            }
+        }
+
+        if (context->Message_Block_Index == 64)
+        {
+            SHA1ProcessMessageBlock(context);
+        }
+
+        message_array++;
+    }
+}
+
+/*
+ *  SHA1ProcessMessageBlock
+ *
+ *  Description:
+ *      This function will process the next 512 bits of the message
+ *      stored in the Message_Block array.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *      Many of the variable names in the SHAContext, especially the
+ *      single character names, were used because those were the names
+ *      used in the publication.
+ *
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+    const unsigned K[] =            /* Constants defined in SHA-1   */
+    {
+        0x5A827999,
+        0x6ED9EBA1,
+        0x8F1BBCDC,
+        0xCA62C1D6
+    };
+    int         t;                  /* Loop counter                 */
+    unsigned    temp;               /* Temporary word value         */
+    unsigned    W[80];              /* Word sequence                */
+    unsigned    A, B, C, D, E;      /* Word buffers                 */
+
+    /*
+     *  Initialize the first 16 words in the array W
+     */
+    for(t = 0; t < 16; t++)
+    {
+        W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
+    }
+
+    for(t = 16; t < 80; t++)
+    {
+       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = context->Message_Digest[0];
+    B = context->Message_Digest[1];
+    C = context->Message_Digest[2];
+    D = context->Message_Digest[3];
+    E = context->Message_Digest[4];
+
+    for(t = 0; t < 20; t++)
+    {
+        temp =  SHA1CircularShift(5,A) +
+                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 20; t < 40; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 40; t < 60; t++)
+    {
+        temp = SHA1CircularShift(5,A) +
+               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 60; t < 80; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    context->Message_Digest[0] =
+                        (context->Message_Digest[0] + A) & 0xFFFFFFFF;
+    context->Message_Digest[1] =
+                        (context->Message_Digest[1] + B) & 0xFFFFFFFF;
+    context->Message_Digest[2] =
+                        (context->Message_Digest[2] + C) & 0xFFFFFFFF;
+    context->Message_Digest[3] =
+                        (context->Message_Digest[3] + D) & 0xFFFFFFFF;
+    context->Message_Digest[4] =
+                        (context->Message_Digest[4] + E) & 0xFFFFFFFF;
+
+    context->Message_Block_Index = 0;
+}
+
+/*
+ *  SHA1PadMessage
+ *
+ *  Description:
+ *      According to the standard, the message must be padded to an even
+ *      512 bits.  The first padding bit must be a '1'.  The last 64
+ *      bits represent the length of the original message.  All bits in
+ *      between should be 0.  This function will pad the message
+ *      according to those rules by filling the Message_Block array
+ *      accordingly.  It will also call SHA1ProcessMessageBlock()
+ *      appropriately.  When it returns, it can be assumed that the
+ *      message digest has been computed.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to pad
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1PadMessage(SHA1Context *context)
+{
+    /*
+     *  Check to see if the current message block is too small to hold
+     *  the initial padding bits and length.  If so, we will pad the
+     *  block, process it, and then continue padding into a second
+     *  block.
+     */
+    if (context->Message_Block_Index > 55)
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 64)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+
+        SHA1ProcessMessageBlock(context);
+
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+    else
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+
+    /*
+     *  Store the message length as the last 8 octets
+     */
+    context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
+    context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
+    context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
+    context->Message_Block[59] = (context->Length_High) & 0xFF;
+    context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
+    context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
+    context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
+    context->Message_Block[63] = (context->Length_Low) & 0xFF;
+
+    SHA1ProcessMessageBlock(context);
+}
--- /dev/null
+++ b/test/sha1.h
@@ -1,0 +1,86 @@
+/*!
+ * \copy
+ *     Copyright (c)  1998, 2009 Paul E. Jones <[email protected]>
+ *     All rights reserved.
+ *
+ *     Redistribution and use in source and binary forms, with or without
+ *     modification, are permitted provided that the following conditions
+ *     are met:
+ *
+ *        * Redistributions of source code must retain the above copyright
+ *          notice, this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above copyright
+ *          notice, this list of conditions and the following disclaimer in
+ *          the documentation and/or other materials provided with the
+ *          distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *     POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ *  Description:
+ *      This class implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      Many of the variable names in the SHA1Context, especially the
+ *      single character names, were used because those were the names
+ *      used in the publication.
+ *
+ *      Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *  This structure will hold context information for the hashing
+ *  operation
+ */
+typedef struct SHA1Context
+{
+    unsigned Message_Digest[5]; /* Message Digest (output)          */
+
+    unsigned Length_Low;        /* Message length in bits           */
+    unsigned Length_High;       /* Message length in bits           */
+
+    unsigned char Message_Block[64]; /* 512-bit message blocks      */
+    int Message_Block_Index;    /* Index into message block array   */
+
+    int Computed;               /* Is the digest computed?          */
+    int Corrupted;              /* Is the message digest corruped?  */
+} SHA1Context;
+
+/*
+ *  Function Prototypes
+ */
+void SHA1Reset(SHA1Context *);
+int SHA1Result(SHA1Context *, unsigned char *);
+void SHA1Input( SHA1Context *,
+                const unsigned char *,
+                unsigned);
+
+#define SHA_DIGEST_LENGTH 20
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/test/targets.mk
+++ b/test/targets.mk
@@ -12,6 +12,7 @@
 
 CODEC_UNITTEST_C_SRCS=\
 	$(CODEC_UNITTEST_SRCDIR)/c_interface_test.c\
+	$(CODEC_UNITTEST_SRCDIR)/sha1.c\
 
 CODEC_UNITTEST_OBJS += $(CODEC_UNITTEST_C_SRCS:.c=.o)
 
--- /dev/null
+++ b/test/test_stdint.h
@@ -1,0 +1,22 @@
+#ifndef TEST_STDINT_H
+#define TEST_STDINT_H
+
+#ifndef _MSC_VER
+
+#include <stdint.h>
+
+#else
+
+typedef signed char      int8_t  ;
+typedef unsigned char    uint8_t ;
+typedef short            int16_t ;
+typedef unsigned short   uint16_t;
+typedef int              int32_t ;
+typedef unsigned int     uint32_t;
+typedef __int64          int64_t ;
+typedef unsigned __int64 uint64_t;
+typedef short            int_least16_t;
+
+#endif
+
+#endif //TEST_STDINT_H
--- a/test/utils/BufferedData.h
+++ b/test/utils/BufferedData.h
@@ -3,7 +3,7 @@
 
 #include <stddef.h>
 #include <stdlib.h>
-#include <stdint.h>
+#include "../test_stdint.h"
 #include <algorithm>
 
 class BufferedData {
--- a/test/utils/HashFunctions.h
+++ b/test/utils/HashFunctions.h
@@ -3,7 +3,7 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <openssl/sha.h>
+#include "../sha1.h"
 
 static bool CompareHash(const unsigned char* digest, const char* hashStr) {
   char hashStrCmp[SHA_DIGEST_LENGTH * 2 + 1];