1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-24 04:04:31 +00:00

Much improved, better stability, lots of fixes

This commit is contained in:
Ylian Saint-Hilaire
2018-01-12 11:50:04 -08:00
parent becf71557f
commit 508646044e
69 changed files with 11803 additions and 4088 deletions

View File

@@ -621,34 +621,39 @@ void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule se
*/
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize)
{
int i;
int ra = 1;
int off = 0;
int receivingAddressLength = sizeof(struct sockaddr_in6);
struct sockaddr_in6 localif;
struct sockaddr_in6 localAddress;
struct ILibAsyncServerSocketModule *RetVal;
memset(&localif, 0, sizeof(struct sockaddr_in6));
if (loopbackFlag != 2 && ILibDetectIPv6Support())
{
// Setup the IPv6 any or loopback address, this socket will also work for IPv4 traffic on IPv6 stack
localif.sin6_family = AF_INET6;
localif.sin6_addr = (loopbackFlag != 0?in6addr_loopback:in6addr_any);
localif.sin6_addr = (loopbackFlag != 0 ? in6addr_loopback : in6addr_any);
localif.sin6_port = htons(PortNumber);
}
else
{
// IPv4-only detected
localif.sin6_family = AF_INET;
#ifdef WINSOCK2
((struct sockaddr_in*)&localif)->sin_addr.S_un.S_addr = htonl((loopbackFlag != 0?INADDR_LOOPBACK:INADDR_ANY));
#ifdef WIN32
((struct sockaddr_in*)&localif)->sin_addr.S_un.S_addr = htonl((loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
#else
((struct sockaddr_in*)&localif)->sin_addr.s_addr = htonl((loopbackFlag != 0?INADDR_LOOPBACK:INADDR_ANY));
((struct sockaddr_in*)&localif)->sin_addr.s_addr = htonl((loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
#endif
((struct sockaddr_in*)&localif)->sin_port = htons(PortNumber);
}
return(ILibCreateAsyncServerSocketModuleWithMemoryEx(Chain, MaxConnections, initialBufferSize, (struct sockaddr*)&localif, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK, ServerUserMappedMemorySize, SessionUserMappedMemorySize));
}
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx(void *Chain, int MaxConnections, int initialBufferSize, struct sockaddr *local, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize)
{
int i;
int ra = 1;
int off = 0;
int receivingAddressLength = sizeof(struct sockaddr_in6);
struct ILibAsyncServerSocketModule *RetVal;
struct sockaddr_in6 localAddress;
// Instantiate a new AsyncServer module
RetVal = (struct ILibAsyncServerSocketModule*)ILibChain_Link_Allocate(sizeof(struct ILibAsyncServerSocketModule), ServerUserMappedMemorySize);
@@ -664,15 +669,14 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
RetVal->MaxConnection = MaxConnections;
RetVal->AsyncSockets = (void**)malloc(MaxConnections * sizeof(void*));
if (RetVal->AsyncSockets == NULL) { free(RetVal); ILIBMARKPOSITION(253); return NULL; }
RetVal->portNumber = (unsigned short)PortNumber;
RetVal->loopbackFlag = loopbackFlag;
RetVal->initialPortNumber = PortNumber;
RetVal->portNumber = ntohs(((struct sockaddr_in6*)local)->sin6_port);
RetVal->initialPortNumber = RetVal->portNumber;
// Get our listening socket
if ((RetVal->ListenSocket = socket(localif.sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
if ((RetVal->ListenSocket = socket(((struct sockaddr_in6*)local)->sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
// Setup the IPv6 & IPv4 support on same socket
if (localif.sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
if (((struct sockaddr_in6*)local)->sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
#ifdef SO_NOSIGPIPE
setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket
@@ -688,9 +692,9 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(v
// Bind the socket
#if defined(WIN32)
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
#else
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
#endif
// Fetch the local port number

View File

@@ -114,6 +114,8 @@ extern const int ILibMemory_ASYNCSERVERSOCKET_CONTAINERSIZE;
#define ILibCreateAsyncServerSocketModule(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK) ILibCreateAsyncServerSocketModuleWithMemory(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK, 0, 0)
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize);
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx(void *Chain, int MaxConnections, int initialBufferSize, struct sockaddr* local, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize);
void *ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule);
void ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *user);

View File

@@ -1960,7 +1960,7 @@ void ILibAsyncSocket_ModuleOnConnect(ILibAsyncSocket_SocketModule socketModule)
\param ssl_ctx SSL_CTX Context object
\param server ILibAsyncSocket_TLS_Mode Configuration
*/
SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server)
SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server, char *hostName)
{
if (socketModule != NULL)
{
@@ -1992,6 +1992,7 @@ SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SS
SSL_set_bio(module->ssl, module->readBio, module->writeBio);
if (server == ILibAsyncSocket_TLS_Mode_Client)
{
if (hostName != NULL) { SSL_set_tlsext_host_name(module->ssl, hostName); }
SSL_set_connect_state(module->ssl);
status = SSL_do_handshake(module->ssl);
if (status <= 0) { status = SSL_get_error(module->ssl, status); }

View File

@@ -212,7 +212,8 @@ typedef enum ILibAsyncSocket_TLS_Mode
#endif
}ILibAsyncSocket_TLS_Mode;
SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server);
SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server, char *hostname);
#define ILibAsyncSocket_SetSSLContext(socketModule, ssl_ctx, tlsMode) ILibAsyncSocket_SetSSLContextEx(socketModule, ssl_ctx, tlsMode, NULL)
SSL_CTX *ILibAsyncSocket_GetSSLContext(ILibAsyncSocket_SocketModule socketModule);
#endif

View File

@@ -21,6 +21,7 @@
#else
#include "md5.h"
#include "sha1.h"
#include "microstack/sha.h"
#include <time.h>
#endif
@@ -561,10 +562,10 @@ int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, i
X509_NAME *cname = NULL;
X509 **x509p = NULL;
EVP_PKEY **pkeyp = NULL;
int hashlen = UTIL_HASHSIZE;
char hash[UTIL_HASHSIZE];
int hashlen = UTIL_SHA384_HASHSIZE;
char hash[UTIL_SHA384_HASHSIZE];
char serial[8];
char nameStr[(UTIL_HASHSIZE * 2) + 2];
char nameStr[(UTIL_SHA384_HASHSIZE * 2) + 2];
BIGNUM *oBigNbr;
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
@@ -616,7 +617,7 @@ int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, i
//util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); // OpenSSL 1.0
X509_pubkey_digest(x, EVP_sha384(), (unsigned char*)hash, (unsigned int*)&hashlen); // OpenSSL 1.1
util_tohex(hash, UTIL_HASHSIZE, nameStr);
util_tohex(hash, UTIL_SHA384_HASHSIZE, nameStr);
X509_NAME_add_entry_by_txt(cname, "CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0);
}
else
@@ -682,7 +683,7 @@ err:
int __fastcall util_keyhash(struct util_cert cert, char* result)
{
int hashlen = UTIL_HASHSIZE;
int hashlen = UTIL_SHA384_HASHSIZE;
if (cert.x509 == NULL) return -1;
//util_sha256((char*)(cert.x509->cert_info->key->public_key->data), cert.x509->cert_info->key->public_key->length, result); // OpenSSL 1.0
X509_pubkey_digest(cert.x509, EVP_sha384(), (unsigned char*)result,(unsigned int *) &hashlen); // OpenSSL 1.1
@@ -691,7 +692,7 @@ int __fastcall util_keyhash(struct util_cert cert, char* result)
int __fastcall util_keyhash2(X509* cert, char* result)
{
int hashlen = UTIL_HASHSIZE;
int hashlen = UTIL_SHA384_HASHSIZE;
if (cert == NULL) return -1;
//util_sha256((char*)(cert->cert_info->key->public_key->data), cert->cert_info->key->public_key->length, result); // OpenSSL 1.0
X509_pubkey_digest(cert, EVP_sha384(), (unsigned char*)result, (unsigned int*)&hashlen); // OpenSSL 1.1
@@ -702,11 +703,11 @@ int __fastcall util_keyhash2(X509* cert, char* result)
int __fastcall util_sign(struct util_cert cert, char* data, int datalen, char** signature)
{
int size = 0;
unsigned int hashsize = UTIL_HASHSIZE;
unsigned int hashsize = UTIL_SHA384_HASHSIZE;
BIO *in = NULL;
PKCS7 *message = NULL;
*signature = NULL;
if (datalen <= UTIL_HASHSIZE) return 0;
if (datalen <= UTIL_SHA384_HASHSIZE) return 0;
// Add hash of the certificate to start of data
X509_digest(cert.x509, EVP_sha384(), (unsigned char*)data, &hashsize);
@@ -730,7 +731,7 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
BIO *out = NULL;
PKCS7 *message = NULL;
char* data2 = NULL;
char hash[UTIL_HASHSIZE];
char hash[UTIL_SHA256_HASHSIZE];
STACK_OF(X509) *st = NULL;
cert->x509 = NULL;
@@ -750,7 +751,7 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
// If data block contains less than 32 bytes, fail.
size = (unsigned int)BIO_get_mem_data(out, &data2);
if (size <= UTIL_HASHSIZE) goto error;
if (size <= UTIL_SHA256_HASHSIZE) goto error;
// Copy the data block
*data = (char*)malloc(size + 1);
@@ -764,11 +765,11 @@ int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert,
sk_X509_free(st);
// Get a full certificate hash of the signer
r = UTIL_HASHSIZE;
r = UTIL_SHA256_HASHSIZE;
X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r);
// Check certificate hash with first 32 bytes of data.
if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error;
if (memcmp(hash, *data, UTIL_SHA256_HASHSIZE) != 0) goto error;
// Approved, cleanup and return.
BIO_free(out);

View File

@@ -35,18 +35,31 @@ BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _I
void __fastcall util_random(int length, char* result);
void __fastcall util_randomtext(int length, char* result);
#define UTIL_HASHSIZE 48
#define NONCE_SIZE 48
#define UTIL_MD5_HASHSIZE 16
#define UTIL_SHA1_HASHSIZE 20
#define UTIL_SHA256_HASHSIZE 32
#define UTIL_SHA384_HASHSIZE 48
#define UTIL_SHA512_HASHSIZE 64
#ifdef MICROSTACK_NOTLS
#include "md5.h"
#include "sha1.h"
#include "microstack/SHA256.h"
#include "microstack/SHA.h"
#define SHA256_CTX struct sha256_ctx
#define SHA256_Init(ctx) __sha256_init_ctx(ctx)
#define SHA256_Update(ctx, data, len) __sha256_process_bytes(data, len, ctx)
#define SHA256_Final(md, ctx) __sha256_finish_ctx(ctx, md)
#define SHA256_CTX SHA256Context
#define SHA512_CTX SHA512Context
#define SHA256_Init(ctx) SHA256Reset (ctx)
#define SHA256_Update(ctx, data, len) SHA256Input(ctx, (uint8_t*)data, len)
#define SHA256_Final(md, ctx) SHA256Result (ctx, md)
#define SHA384_Init(ctx) SHA384Reset (ctx)
#define SHA384_Update(ctx, data, len) SHA384Input(ctx, (uint8_t*)data, len)
#define SHA384_Final(md, ctx) SHA384Result (ctx, md)
#define SHA512_Init(ctx) SHA512Reset (ctx)
#define SHA512_Update(ctx, data, len) SHA512Input(ctx, (uint8_t*)data, len)
#define SHA512_Final(md, ctx) SHA512Result (ctx, md)
#endif

View File

@@ -41,7 +41,7 @@ void CALLBACK ILibIPAddressMonitor_dispatch(
IN DWORD dwFlags
)
{
if (dwError == 0)
if (dwError == 0 && lpOverlapped->hEvent != NULL)
{
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)lpOverlapped->hEvent;
ILibChain_RunOnMicrostackThread(obj->chainLink.ParentChain, ILibIPAddressMonitor_MicrostackThreadDispatch, obj);
@@ -60,6 +60,7 @@ void ILibIPAddressMonitor_Destroy(void *object)
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)object;
#ifdef WIN32
obj->reserved.hEvent = NULL;
closesocket(obj->mSocket);
obj->mSocket = INVALID_SOCKET;
#elif defined(_POSIX)

View File

@@ -5104,9 +5104,17 @@ ILibParseUriResult ILibParseUriEx (const char* URI, size_t URILen, char** Addr,
TempStringLength2 = TempStringLength-result2->FirstResult->datalength;
if (Path != NULL)
{
if ((*Path = (char*)malloc(TempStringLength2 + 1)) == NULL) ILIBCRITICALEXIT(254);
memcpy_s(*Path, TempStringLength2 + 1, TempString + (result2->FirstResult->datalength), TempStringLength2);
(*Path)[TempStringLength2] = '\0';
if ((*Path = (char*)malloc(TempStringLength2 + 2)) == NULL) ILIBCRITICALEXIT(254);
if (TempStringLength2 == 0)
{
(*Path)[0] = '/';
(*Path)[1] = '\0';
}
else
{
memcpy_s(*Path, TempStringLength2 + 2, TempString + (result2->FirstResult->datalength), TempStringLength2);
(*Path)[TempStringLength2] = '\0';
}
}
// Parse Port Number
@@ -5333,7 +5341,7 @@ void ILibSetDirective(struct packetheader *packet, char* Directive, int Directiv
if (packet->ReservedMemory != NULL)
{
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (DirectiveLength + DirectiveObjLength + 2))
if (ILibMemory_AllocateA_Size(packet->ReservedMemory) > (unsigned int)(DirectiveLength + DirectiveObjLength + 2))
{
packet->Directive = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveLength + 1);
packet->DirectiveObj = (char*)ILibMemory_AllocateA_Get(packet->ReservedMemory, (size_t)DirectiveObjLength + 1);

View File

@@ -306,10 +306,10 @@ int ILibIsRunningOnChainThread(void* chain);
#else
#define ILibMemory_AllocateA(bufferLen) ILibMemory_AllocateA_InitMem(alloca(8+bufferLen+sizeof(void*)), (size_t)(8+bufferLen+sizeof(void*)))
#endif
#define ILibMemory_AllocateA_Size(buffer) (((int*)((char*)(buffer)-4))[0])
#define ILibMemory_AllocateA_Size(buffer) (((unsigned int*)((char*)(buffer)-4))[0])
#define ILibMemory_AllocateA_Next(buffer) (((void**)((char*)(buffer)-4-sizeof(void*)))[0])
#define ILibMemory_AllocateA_Raw(buffer) ((void*)((char*)(buffer)-4-sizeof(void*)-4))
#define ILibMemory_AllocateA_RawSize(buffer) (((int*)((char*)(buffer)-4-sizeof(void*)-4))[0])
#define ILibMemory_AllocateA_RawSize(buffer) (((unsigned int*)((char*)(buffer)-4-sizeof(void*)-4))[0])
void* ILibMemory_AllocateA_Get(void *buffer, size_t sz);
void* ILibMemory_AllocateA_InitMem(void *buffer, size_t bufferLen);

View File

@@ -162,6 +162,10 @@ typedef struct ILibProcessPipe_WaitHandle
void *user;
ILibProcessPipe_WaitHandle_Handler callback;
}ILibProcessPipe_WaitHandle;
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr)
{
return(((ILibProcessPipe_Manager_Object*)mgr)->workerThread);
}
int ILibProcessPipe_Manager_WindowsWaitHandles_Remove_Comparer(void *source, void *matchWith)
{
@@ -181,6 +185,7 @@ void __stdcall ILibProcessPipe_WaitHandle_Remove_APC(ULONG_PTR obj)
waiter = (ILibProcessPipe_WaitHandle*)ILibLinkedList_GetDataFromNode(node);
free(waiter);
ILibLinkedList_Remove(node);
SetEvent(manager->updateEvent);
}
free((void*)obj);
}
@@ -497,21 +502,36 @@ ILibProcessPipe_PipeObject* ILibProcessPipe_CreatePipe(ILibProcessPipe_Manager m
return retVal;
}
void ILibProcessPipe_Process_Destroy(ILibProcessPipe_Process_Object *p)
#ifdef WIN32
void __stdcall ILibProcessPipe_Process_Destroy_WinRunThread(ULONG_PTR obj)
{
ILibProcessPipe_Process_Object *p = (ILibProcessPipe_Process_Object*)obj;
if (p->exiting != 0) { return; }
if (p->stdIn != NULL) { ILibProcessPipe_FreePipe(p->stdIn); }
if (p->stdOut != NULL) { ILibProcessPipe_FreePipe(p->stdOut); }
if (p->stdErr != NULL) { ILibProcessPipe_FreePipe(p->stdErr); }
free(p);
}
#ifndef WIN32
void ILibProcessPipe_Process_BrokenPipeSink(ILibProcessPipe_PipeObject* sender)
#endif
void ILibProcessPipe_Process_Destroy(ILibProcessPipe_Process_Object *p)
{
ILibProcessPipe_Process_Object *p = sender->mProcess;
#ifdef WIN32
// We can't destroy this now, because we're on the MicrostackThread. We must destroy this on the WindowsRunLoop Thread.
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_Destroy_WinRunThread, p->parent->workerThread, (ULONG_PTR)p);
#else
if (p->exiting != 0) { return; }
if (p->stdIn != NULL) { ILibProcessPipe_FreePipe(p->stdIn); }
if (p->stdOut != NULL) { ILibProcessPipe_FreePipe(p->stdOut); }
if (p->stdErr != NULL) { ILibProcessPipe_FreePipe(p->stdErr); }
free(p);
#endif
}
#ifndef WIN32
void ILibProcessPipe_Process_BrokenPipeSink(ILibProcessPipe_Pipe sender)
{
ILibProcessPipe_Process_Object *p = ((ILibProcessPipe_PipeObject*)sender)->mProcess;
int status;
if (ILibIsRunningOnChainThread(sender->manager->ChainLink.ParentChain) != 0)
if (ILibIsRunningOnChainThread(((ILibProcessPipe_PipeObject*)sender)->manager->ChainLink.ParentChain) != 0)
{
// This was called from the Reader
if (p->exitHandler != NULL)
@@ -685,13 +705,14 @@ ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx2(ILibProcessPipe_
retVal->stdIn = ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(pipeManager, pipe, extraMemorySize);
retVal->stdIn->mProcess = retVal;
retVal->stdOut = ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(pipeManager, pipe, extraMemorySize);
ILibProcessPipe_Pipe_SetBrokenPipeHandler(retVal->stdOut, ILibProcessPipe_Process_BrokenPipeSink);
retVal->stdOut->mProcess = retVal;
}
else
{
retVal->stdIn = ILibProcessPipe_CreatePipe(pipeManager, 4096, NULL, extraMemorySize);
retVal->stdIn->mProcess = retVal;
retVal->stdOut = ILibProcessPipe_CreatePipe(pipeManager, 4096, &ILibProcessPipe_Process_BrokenPipeSink, extraMemorySize);
retVal->stdOut = ILibProcessPipe_CreatePipe(pipeManager, 4096, (ILibProcessPipe_GenericBrokenPipeHandler) ILibProcessPipe_Process_BrokenPipeSink, extraMemorySize);
retVal->stdOut->mProcess = retVal;
pid = vfork();
}
@@ -859,7 +880,6 @@ void ILibProcessPipe_Process_ReadHandler(void* user)
#endif
ILibLinkedList_Remove(ILibLinkedList_GetNode_Search(pipeObject->manager->ActivePipes, NULL, pipeObject));
if (pipeObject->brokenPipeHandler != NULL)
{
((ILibProcessPipe_GenericBrokenPipeHandler)pipeObject->brokenPipeHandler)(pipeObject);
@@ -1240,6 +1260,11 @@ void ILibProcessPipe_Process_PipeHandler_StdIn(void *user1, void *user2)
}
#ifdef WIN32
void __stdcall ILibProcessPipe_Process_OnExit_ChainSink_DestroySink(ULONG_PTR obj)
{
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)obj;
if (j->exiting == 0) { ILibProcessPipe_Process_Destroy(j); }
}
void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
{
ILibProcessPipe_Process_Object* j = (ILibProcessPipe_Process_Object*)user;
@@ -1250,8 +1275,9 @@ void ILibProcessPipe_Process_OnExit_ChainSink(void *chain, void *user)
j->exiting = 1;
j->exitHandler(j, exitCode, j->userObject);
j->exiting ^= 1;
if (j->exiting == 0) { ILibProcessPipe_Process_Destroy(j); }
// We can't destroy this now, because we're on the MicrostackThread. We must destroy this on the WindowsRunLoop Thread.
QueueUserAPC((PAPCFUNC)ILibProcessPipe_Process_OnExit_ChainSink_DestroySink, j->parent->workerThread, (ULONG_PTR)j);
}
BOOL ILibProcessPipe_Process_OnExit(HANDLE event, void* user)
{

View File

@@ -50,6 +50,7 @@ typedef enum ILibProcessPipe_Pipe_ReaderHandleType
ILibProcessPipe_Pipe_ReaderHandleType_NotOverLapped = 0, //!< Spawn a I/O processing thread
ILibProcessPipe_Pipe_ReaderHandleType_Overlapped = 1 //!< Use Overlapped I/O
}ILibProcessPipe_Pipe_ReaderHandleType;
HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr);
#endif
ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePipe, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);

View File

@@ -247,6 +247,7 @@ typedef struct ILibWebClientDataObject
#ifndef MICROSTACK_NOTLS
ILibWebClient_RequestToken_HTTPS requestMode;
char *sniHost;
#endif
char* CertificateHashPtr; // Points to the certificate hash (next field) if set
@@ -342,7 +343,15 @@ void ILibWebClient_DestroyWebRequest(struct ILibWebRequest *wr)
if (wr == NULL) return;
if (wr != NULL && wr->connectionCloseWasSpecified != 0 && wr->DisconnectSink != NULL) { wr->DisconnectSink(wr->requestToken); }
if (wr->buffered != NULL) { free(wr->buffered); }
if (wr->buffered != NULL)
{
while (wr->buffered != NULL)
{
ILibWebRequest_buffer * rb = wr->buffered->next;
free(wr->buffered);
wr->buffered = rb;
}
}
if (wr->streamedState != NULL)
{
while (ILibQueue_IsEmpty(wr->streamedState->BufferQueue) == 0)
@@ -472,6 +481,9 @@ void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token)
ILibQueue_Destroy(wcdo->RequestQueue);
if (wcdo->DigestData != NULL) { free(ILibMemory_AllocateA_Raw(wcdo->DigestData)); }
#ifndef MICROSTACK_NOTLS
if (wcdo->sniHost != NULL) { free(wcdo->sniHost); }
#endif
free(wcdo);
}
@@ -739,8 +751,11 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
SEM_TRACK(WebClient_TrackLock("ILibWebClient_FinishedResponse", 1, wcdo->Parent);)
sem_wait(&(wcdo->Parent->QLock));
wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue);
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
if (wr != NULL)
{
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
}
SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_FinishedResponse", 2, wcdo->Parent);)
sem_post(&(wcdo->Parent->QLock));
return;
@@ -795,12 +810,12 @@ void ILibWebClient_FinishedResponse(ILibAsyncSocket_SocketModule socketModule, s
//
ILibAsyncSocket_Send(wcdo->SOCK, wr->Buffer[i], wr->BufferLength[i], ILibAsyncSocket_MemoryOwnership_STATIC);
}
while (wr->buffered != NULL)
b = wr->buffered;
while (b != NULL)
{
b = wr->buffered->next;
ILibAsyncSocket_Send(wcdo->SOCK, wr->buffered->buffer, wr->buffered->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
free(wr->buffered);
wr->buffered = b;
ILibAsyncSocket_Send(wcdo->SOCK, b->buffer, b->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = b->next;
}
}
}
@@ -1140,7 +1155,7 @@ void ILibWebClient_ProcessChunk(ILibAsyncSocket_SocketModule socketModule, struc
wcdo->NeedFlush = 0;
ILibWebClient_FinishedResponse_Server(wcdo);
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
//
// Free the resources associated with this chunk
@@ -1556,7 +1571,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wcdo->source.sin_addr.s_addr = ILibAsyncSocket_GetRemoteInterface(socketModule);
wcdo->source.sin_port = htons(ILibAsyncSocket_GetRemotePort(socketModule));
*/
ILibAsyncSocket_GetRemoteInterface(socketModule, (struct sockaddr*)(&wcdo->source));
if (socketModule != NULL) { ILibAsyncSocket_GetRemoteInterface(socketModule, (struct sockaddr*)(&wcdo->source)); }
wcdo->HeaderLength = i + 4;
wcdo->WaitForClose = 1;
@@ -1654,7 +1669,14 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
}
if (wcdo->header->StatusCode >= 100 && wcdo->header->StatusCode <= 199)
{
if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL)
if (wr->requestToken == NULL)
{
int zro = 0;
if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); }
*p_beginPointer += wcdo->HeaderLength;
return;
}
else if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL)
{
// WebSocket
char* skey = ILibGetHeaderLine(wcdo->header, "Sec-WebSocket-Accept", 20);
@@ -1812,7 +1834,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user2,
&(wcdo->PAUSE));
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
wcdo->HeaderLength = 0;
*p_beginPointer = i+4+zero;
@@ -1856,31 +1878,28 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user1,
wr->user2,
&(wcdo->PAUSE));
if (ILibAsyncSocket_IsFree(socketModule)!=0)
if (wcdo->FinHeader == 0)
{
//
// The user sent a response already, so advance the
// beginPointer and return.
//
// If the user sent a response, and it wasn't in relation to a 100 Continue, then the
// user is in ERROR, because the done flag is not set here, which means that
// the entire request did not get received yet. Simply answering the request
// without receiving the entire request, without closing the socket is in
// VIOLATION of the http specification.
//
*p_beginPointer = i + 4;
return;
}
if (socketModule != NULL && ILibAsyncSocket_IsFree(socketModule)!=0)
{
//
// The user closed the socket, so just return
//
return;
}
else
{
if (wcdo->FinHeader==0)
{
//
// The user sent a response already, so advance the
// beginPointer and return.
//
// If the user sent a response, and it wasn't in relation to a 100 Continue, then the
// user is in ERROR, because the done flag is not set here, which means that
// the entire request did not get received yet. Simply answering the request
// without receiving the entire request, without closing the socket is in
// VIOLATION of the http specification.
//
*p_beginPointer = i + 4;
return;
}
}
}
}
@@ -1950,7 +1969,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wr->user2,
&(wcdo->PAUSE));
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
if (wcdo->WaitForClose==0)
{
@@ -1979,7 +1998,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
}
//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}
}
if (ILibAsyncSocket_IsFree(socketModule)==0)
if (socketModule==NULL || ILibAsyncSocket_IsFree(socketModule)==0)
{
//
// If the user said to pause this connection, do so
@@ -2054,12 +2073,11 @@ void ILibWebClient_OnConnect(ILibAsyncSocket_SocketModule socketModule, int Conn
ILibAsyncSocket_Send(socketModule, r->Buffer[i], r->BufferLength[i], (enum ILibAsyncSocket_MemoryOwnership)-1);
}
while (r->buffered != NULL)
b = r->buffered;
while (b != NULL)
{
ILibAsyncSocket_Send(socketModule, r->buffered->buffer, r->buffered->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = r->buffered;
r->buffered = r->buffered->next;
free(b);
ILibAsyncSocket_Send(socketModule, b->buffer, b->bufferLength, ILibAsyncSocket_MemoryOwnership_USER);
b = b->next;
}
if (r->streamedState != NULL)
{
@@ -2214,27 +2232,6 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
wr->user2,
&(wcdo->PAUSE));
if (ILibAsyncSocket_IsFree(socketModule) != 0)
{
//
// If the underlying socket is gone, then Finished Response won't clear
// the pending request
//
SEM_TRACK(WebClient_TrackLock("ILibWebClient_OnDisconnect", 5, wcdo->Parent);)
sem_wait(&(wcdo->Parent->QLock));
wr = (struct ILibWebRequest*)ILibQueue_DeQueue(wcdo->RequestQueue);
SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_OnDisconnect", 6, wcdo->Parent);)
sem_post(&(wcdo->Parent->QLock));
if (wr != NULL)
{
if (wcdo->IsWebSocket != 0)
{
free(((ILibWebClient_WebSocketState*)wr->Buffer[0])->WebSocketFragmentBuffer);
}
wr->connectionCloseWasSpecified = 2;
ILibWebClient_DestroyWebRequest(wr);
}
}
if (wcdo->IsOrphan != 0 || wcdo->IsWebSocket != 0)
{
ILibWebClient_FinishedResponse(socketModule, wcdo);
@@ -2244,20 +2241,6 @@ void ILibWebClient_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, v
{
ILibWebClient_FinishedResponse(socketModule, wcdo);
}
//SEM_TRACK(WebClient_TrackLock("ILibWebClient_OnDisconnect", 7, wcdo->Parent);)
//sem_wait(&(wcdo->Parent->QLock));
//wr = (struct ILibWebRequest*)ILibQueue_PeekQueue(wcdo->RequestQueue);
//SEM_TRACK(WebClient_TrackUnLock("ILibWebClient_OnDisconnect", 8, wcdo->Parent);)
//sem_post(&(wcdo->Parent->QLock));
//if (wr == NULL)
//{
// if (wcdo->IsWebSocket != 0)
// {
// // This was a websocket, so we must destroy the WCDO object, because it won't be destroyed anywhere else
// ILibWebClient_DestroyWebClientDataObject(wcdo);
// }
// return;
//}
}
// Make Another Connection and Continue
@@ -2357,7 +2340,7 @@ void ILibWebClient_PreProcess(void* WebClientModule, fd_set *readset, fd_set *wr
#ifndef MICROSTACK_NOTLS
if (wcm->ssl_ctx != NULL && wcdo->requestMode == ILibWebClient_RequestToken_USE_HTTPS)
{
SSL* ssl = ILibAsyncSocket_SetSSLContext(wcdo->SOCK, wcm->ssl_ctx, 0);
SSL* ssl = ILibAsyncSocket_SetSSLContextEx(wcdo->SOCK, wcm->ssl_ctx, 0, wcdo->sniHost);
if (ssl != NULL && ILibWebClientDataObjectIndex >= 0)
{
SSL_set_ex_data(ssl, ILibWebClientDataObjectIndex, wcdo);
@@ -3256,7 +3239,7 @@ ILibTransport_DoneState ILibWebClient_StreamRequestBody(
if (t != NULL && t->wcdo != NULL)
{
wr = (struct ILibWebRequest*)ILibQueue_PeekTail(t->wcdo->RequestQueue);
wr = t->parent;
if (t->wcdo->SOCK == NULL || ILibQueue_GetCount(t->wcdo->RequestQueue)>1)
{
// Connection not established yet, so buffer the data
@@ -3583,6 +3566,12 @@ void ILibWebClient_Request_SetHTTPS(ILibWebClient_RequestToken reqToken, ILibWeb
{
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->requestMode = requestMode;
}
void ILibWebClient_Request_SetSNI(ILibWebClient_RequestToken reqToken, char *host, int hostLen)
{
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost = ILibMemory_Allocate(hostLen + 1, 0, NULL, NULL);
memcpy_s(((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost, hostLen, host, hostLen);
((struct ILibWebClientDataObject*)ILibWebClient_GetStateObjectFromRequestToken(reqToken))->sniHost[hostLen] = 0;
}
#endif
int ILibWebClient_GetLocalInterface(void* socketModule, struct sockaddr *localAddress)

View File

@@ -257,9 +257,7 @@ void* ILibWebClient_GetChainFromWebStateObject(ILibWebClient_StateObject wcdo);
typedef enum ILibWebClient_RequestToken_HTTPS
{
#ifndef MICROSTACK_NOTLS
ILibWebClient_RequestToken_USE_HTTPS = 0,
#endif
ILibWebClient_RequestToken_USE_HTTP = 1
}ILibWebClient_RequestToken_HTTPS;
@@ -267,6 +265,7 @@ typedef enum ILibWebClient_RequestToken_HTTPS
void ILibWebClient_SetTLS(ILibWebClient_RequestManager manager, void *ssl_ctx, ILibWebClient_OnSslConnection OnSslConnection);
int ILibWebClient_EnableHTTPS(ILibWebClient_RequestManager manager, struct util_cert* leafCert, X509* nonLeafCert, ILibWebClient_OnHttpsConnection OnHttpsConnection);
void ILibWebClient_Request_SetHTTPS(ILibWebClient_RequestToken reqToken, ILibWebClient_RequestToken_HTTPS requestMode);
void ILibWebClient_Request_SetSNI(ILibWebClient_RequestToken reqToken, char *host, int hostLen);
#endif
// Added methods

View File

@@ -1141,7 +1141,7 @@ int ILibWebServer_Digest_ParseAuthenticationHeader2(char* value, int valueLen, c
*token = value;
len = ILibTrimString(token, i);
(*token)[len] = 0;
//(*token)[len] = 0;
*tokenLen = len;
*tokenValue = value + i + 1;
@@ -1157,7 +1157,7 @@ int ILibWebServer_Digest_ParseAuthenticationHeader2(char* value, int valueLen, c
{
len -= 1;
}
(*tokenValue)[len] = 0;
//(*tokenValue)[len] = 0;
*tokenValueLen = len;
return 0;
}
@@ -1190,7 +1190,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
int userRealmLen;
char* nonce = NULL;
char* opaque = NULL;
int opaqueLen;
int opaqueLen, nonceLen;
long long current;
char expiration[8];
char calculatedNonce[33];
@@ -1205,7 +1205,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
ILibWebServer_Digest_ParseAuthenticationHeader(ILibWebServer_Session_GetSystemData(session)->DigestTable, auth, authLen);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "realm", 5, (void**)&userRealm, &userRealmLen);
nonce = (char*)ILibGetEntry(ILibWebServer_Session_GetSystemData(session)->DigestTable, "nonce", 5);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "nonce", 5, (void**)&nonce, &nonceLen);
ILibGetEntryEx(ILibWebServer_Session_GetSystemData(session)->DigestTable, "opaque", 6, (void**)&opaque, &opaqueLen);
if (opaque != NULL && userRealm != NULL && userRealmLen == realmLen && strncmp(userRealm, realm, realmLen) == 0)
@@ -1217,7 +1217,7 @@ int ILibWebServer_Digest_IsCorrectRealmAndNonce(struct ILibWebServer_Session *se
if (((long long*)expiration)[0] < current) { return 0; } // Opaque Block Expired
ILibWebServer_Digest_CalculateNonce(session, ((long long*)expiration)[0], calculatedNonce);
return(strcmp(nonce, calculatedNonce) == 0 ? 1 : 0);
return((nonceLen == 32 && strncmp(nonce, calculatedNonce, 32)) == 0 ? 1 : 0);
}
else
{
@@ -1304,7 +1304,7 @@ ILibExportMethod int ILibWebServer_Digest_ValidatePassword(struct ILibWebServer_
MD5_Final((unsigned char*)val, &mctx);
util_tohex_lower(val, 16, result3);
retVal = strcmp(result3, response) == 0 ? 1 : 0;
retVal = (responseLen == 32 && strncmp(result3, response, 32)) == 0 ? 1 : 0;
// if (retVal == 0) { ILibWebServer_Digest_SendUnauthorized(session, realm, strlen(realm)); }
return retVal;

View File

@@ -59,8 +59,8 @@ typedef struct
struct util_cert selftlscert;
struct util_cert selftlsclientcert;
SSL_CTX* ctx;
char tlsServerCertThumbprint[32];
char g_selfid[UTIL_HASHSIZE];
char tlsServerCertThumbprint[UTIL_SHA256_HASHSIZE];
char g_selfid[UTIL_SHA256_HASHSIZE];
ILibWebRTC_TURN_ConnectFlags mTurnSetting;
struct sockaddr_in6 mTurnServer;

61
microstack/sha-private.h Normal file
View File

@@ -0,0 +1,61 @@
/*************************** sha-private.h ***************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
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
OWNER 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.
*/
/********************** See RFC 4634 for details *********************/
#ifndef _SHA_PRIVATE__H
#define _SHA_PRIVATE__H
/*
* These definitions are defined in FIPS-180-2, section 4.1.
* Ch() and Maj() are defined identically in sections 4.1.1,
* 4.1.2 and 4.1.3.
*
* The definitions used in FIPS-180-2 are as follows:
*/
#ifndef USE_MODIFIED_MACROS
#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* USE_MODIFIED_MACROS */
/*
* The following definitions are equivalent and potentially faster.
*/
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#endif /* USE_MODIFIED_MACROS */
#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
#endif /* _SHA_PRIVATE__H */

303
microstack/sha.h Normal file
View File

@@ -0,0 +1,303 @@
/**************************** sha.h ****************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
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
OWNER 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.
*/
/******************* See RFC 4634 for details ******************/
#ifndef _SHA_H_
#define _SHA_H_
/*
* Description:
* This file implements the Secure Hash Signature Standard
* algorithms as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
* published on August 1, 2002, and the FIPS PUB 180-2 Change
* Notice published on February 28, 2004.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf
*
* The five hashes are defined in these sizes:
* SHA-1 20 byte / 160 bit
* SHA-224 28 byte / 224 bit
* SHA-256 32 byte / 256 bit
* SHA-384 48 byte / 384 bit
* SHA-512 64 byte / 512 bit
*/
#include <stdint.h>
/*
* If you do not have the ISO standard stdint.h header file, then you
* must typedef the following:
* name meaning
* uint64_t unsigned 64 bit integer
* uint32_t unsigned 32 bit integer
* uint8_t unsigned 8 bit integer (i.e., unsigned char)
* int_least16_t integer of >= 16 bits
*
*/
#ifndef _SHA_enum_
#define _SHA_enum_
/*
* All SHA functions return one of these values.
*/
enum
{
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError, /* called Input after FinalBits or Result */
shaBadParam /* passed a bad parameter */
};
#endif /* _SHA_enum_ */
/*
* These constants hold size information for each of the SHA
* hashing operations
*/
enum
{
SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
SHA512_Message_Block_Size = 128,
USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
SHA384HashSize = 48, SHA512HashSize = 64,
USHAMaxHashSize = SHA512HashSize,
SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
};
/*
* These constants are used in the USHA (unified sha) functions.
*/
typedef enum SHAversion
{
SHA1, SHA224, SHA256, SHA384, SHA512
} SHAversion;
/*
* This structure will hold context information for the SHA-1
* hashing operation.
*/
typedef struct SHA1Context
{
uint32_t Intermediate_Hash[SHA1HashSize / 4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA1_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA1Context;
/*
* This structure will hold context information for the SHA-256
* hashing operation.
*/
typedef struct SHA256Context
{
uint32_t Intermediate_Hash[SHA256HashSize / 4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 512-bit message blocks */
uint8_t Message_Block[SHA256_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA256Context;
/*
* This structure will hold context information for the SHA-512
* hashing operation.
*/
typedef struct SHA512Context
{
#ifdef USE_32BIT_ONLY
uint32_t Intermediate_Hash[SHA512HashSize / 4]; /* Message Digest */
uint32_t Length[4]; /* Message length in bits */
#else /* !USE_32BIT_ONLY */
uint64_t Intermediate_Hash[SHA512HashSize / 8]; /* Message Digest */
uint64_t Length_Low, Length_High; /* Message length in bits */
#endif /* USE_32BIT_ONLY */
int_least16_t Message_Block_Index; /* Message_Block array index */
/* 1024-bit message blocks */
uint8_t Message_Block[SHA512_Message_Block_Size];
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the digest corrupted? */
} SHA512Context;
/*
* This structure will hold context information for the SHA-224
* hashing operation. It uses the SHA-256 structure for computation.
*/
typedef struct SHA256Context SHA224Context;
/*
* This structure will hold context information for the SHA-384
* hashing operation. It uses the SHA-512 structure for computation.
*/
typedef struct SHA512Context SHA384Context;
/*
* This structure holds context information for all SHA
* hashing operations.
*/
typedef struct USHAContext
{
int whichSha; /* which SHA is being used */
union
{
SHA1Context sha1Context;
SHA224Context sha224Context;
SHA256Context sha256Context;
SHA384Context sha384Context;
SHA512Context sha512Context;
} ctx;
} USHAContext;
/*
* This structure will hold context information for the HMAC
* keyed hashing operation.
*/
typedef struct HMACContext
{
int whichSha; /* which SHA is being used */
int hashSize; /* hash size of SHA being used */
int blockSize; /* block size of SHA being used */
USHAContext shaContext; /* SHA context */
unsigned char k_opad[USHA_Max_Message_Block_Size];
/* outer padding - key XORd with opad */
} HMACContext;
/*
* Function Prototypes
*/
/* SHA-1 */
extern int SHA1Reset(SHA1Context *);
extern int SHA1Input(SHA1Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA1FinalBits(SHA1Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize]);
/* SHA-224 */
extern int SHA224Reset(SHA224Context *);
extern int SHA224Input(SHA224Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA224FinalBits(SHA224Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA224Result(SHA224Context *,
uint8_t Message_Digest[SHA224HashSize]);
/* SHA-256 */
extern int SHA256Reset(SHA256Context *);
extern int SHA256Input(SHA256Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA256FinalBits(SHA256Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA256Result(SHA256Context *,
uint8_t Message_Digest[SHA256HashSize]);
/* SHA-384 */
extern int SHA384Reset(SHA384Context *);
extern int SHA384Input(SHA384Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA384FinalBits(SHA384Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA384Result(SHA384Context *,
uint8_t Message_Digest[SHA384HashSize]);
/* SHA-512 */
extern int SHA512Reset(SHA512Context *);
extern int SHA512Input(SHA512Context *, const uint8_t * bytes,
unsigned int bytecount);
extern int SHA512FinalBits(SHA512Context *, const uint8_t bits,
unsigned int bitcount);
extern int SHA512Result(SHA512Context *,
uint8_t Message_Digest[SHA512HashSize]);
/* Unified SHA functions, chosen by whichSha */
extern int USHAReset(USHAContext *, SHAversion whichSha);
extern int USHAInput(USHAContext *,
const uint8_t * bytes, unsigned int bytecount);
extern int USHAFinalBits(USHAContext *,
const uint8_t bits, unsigned int bitcount);
extern int USHAResult(USHAContext *,
uint8_t Message_Digest[USHAMaxHashSize]);
extern int USHABlockSize(enum SHAversion whichSha);
extern int USHAHashSize(enum SHAversion whichSha);
extern int USHAHashSizeBits(enum SHAversion whichSha);
/*
* HMAC Keyed-Hashing for Message Authentication, RFC2104,
* for all SHAs.
* This interface allows a fixed-length text input to be used.
*/
extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
const unsigned char *text, /* pointer to data stream */
int text_len, /* length of data stream */
const unsigned char *key, /* pointer to authentication key */
int key_len, /* length of authentication key */
uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
/*
* HMAC Keyed-Hashing for Message Authentication, RFC2104,
* for all SHAs.
* This interface allows any length of text input to be used.
*/
extern int hmacReset(HMACContext * ctx, enum SHAversion whichSha,
const unsigned char *key, int key_len);
extern int hmacInput(HMACContext * ctx, const unsigned char *text,
int text_len);
extern int hmacFinalBits(HMACContext * ctx, const uint8_t bits,
unsigned int bitcount);
extern int hmacResult(HMACContext * ctx, uint8_t digest[USHAMaxHashSize]);
#endif /* _SHA_H_ */

636
microstack/sha224-256.c Normal file
View File

@@ -0,0 +1,636 @@
/*************************** sha224-256.c ***************************/
/*
https://github.com/Yubico/yubico-c-client
Copyright (c) 2006-2013 Yubico AB
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
OWNER 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.
*/
/********************* See RFC 4634 for details *********************/
/*
* Description:
* This file implements the Secure Hash Signature Standard
* algorithms as defined in the National Institute of Standards
* and Technology Federal Information Processing Standards
* Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
* published on August 1, 2002, and the FIPS PUB 180-2 Change
* Notice published on February 28, 2004.
*
* A combined document showing all algorithms is available at
* http://csrc.nist.gov/publications/fips/
* fips180-2/fips180-2withchangenotice.pdf
*
* The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
* message digests for a given data stream. It should take about
* 2**n steps to find a message with the same digest as a given
* message and 2**(n/2) to find any two messages with the same
* digest, when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-224 and SHA-256 are defined in terms of 32-bit "words".
* This code uses <stdint.h> (included via "sha.h") to define 32
* and 8 bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-224 and SHA-256 are designed to work with messages less
* than 2^64 bits long. This implementation uses SHA224/256Input()
* to hash the bits that are a multiple of the size of an 8-bit
* character, and then uses SHA224/256FinalBits() to hash the
* final few bits of the input.
*/
#include "sha.h"
#include "sha-private.h"
/* Define the SHA shift, rotate left and rotate right macro */
#define SHA256_SHR(bits,word) ((word) >> (bits))
#define SHA256_ROTL(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
#define SHA256_ROTR(bits,word) \
(((word) >> (bits)) | ((word) << (32-(bits))))
/* Define the SHA SIGMA and sigma macros */
#define SHA256_SIGMA0(word) \
(SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
#define SHA256_SIGMA1(word) \
(SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
#define SHA256_sigma0(word) \
(SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
#define SHA256_sigma1(word) \
(SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
/*
* add "length" to the length
*/
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? 1 : 0)
/* Local Function Prototypes */
static void SHA224_256Finalize(SHA256Context * context, uint8_t Pad_Byte);
static void SHA224_256PadMessage(SHA256Context * context, uint8_t Pad_Byte);
static void SHA224_256ProcessMessageBlock(SHA256Context * context);
static int SHA224_256Reset(SHA256Context * context, uint32_t * H0);
static int SHA224_256ResultN(SHA256Context * context,
uint8_t Message_Digest[], int HashSize);
/* Initial Hash Values: FIPS-180-2 Change Notice 1 */
static uint32_t SHA224_H0[SHA256HashSize / 4] = {
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
};
/* Initial Hash Values: FIPS-180-2 section 5.3.2 */
static uint32_t SHA256_H0[SHA256HashSize / 4] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
/*
* SHA224Reset
*
* Description:
* This function will initialize the SHA384Context in preparation
* for computing a new SHA224 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int
SHA224Reset(SHA224Context * context)
{
return SHA224_256Reset(context, SHA224_H0);
}
/*
* SHA224Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA 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:
* sha Error Code.
*
*/
int
SHA224Input(SHA224Context * context, const uint8_t * message_array,
unsigned int length)
{
return SHA256Input(context, message_array, length);
}
/*
* SHA224FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int
SHA224FinalBits(SHA224Context * context,
const uint8_t message_bits, unsigned int length)
{
return SHA256FinalBits(context, message_bits, length);
}
/*
* SHA224Result
*
* Description:
* This function will return the 224-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 28th element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int
SHA224Result(SHA224Context * context, uint8_t Message_Digest[SHA224HashSize])
{
return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
}
/*
* SHA256Reset
*
* Description:
* This function will initialize the SHA256Context in preparation
* for computing a new SHA256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*/
int
SHA256Reset(SHA256Context * context)
{
return SHA224_256Reset(context, SHA256_H0);
}
/*
* SHA256Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA 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:
* sha Error Code.
*/
int
SHA256Input(SHA256Context * context, const uint8_t * message_array,
unsigned int length)
{
if (!length)
return shaSuccess;
if (!context || !message_array)
return shaNull;
if (context->Computed)
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
return context->Corrupted;
while (length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);
if (!SHA224_256AddLength(context, 8) &&
(context->Message_Block_Index == SHA256_Message_Block_Size))
SHA224_256ProcessMessageBlock(context);
message_array++;
}
return shaSuccess;
}
/*
* SHA256FinalBits
*
* Description:
* This function will add in any final bits of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_bits: [in]
* The final bits of the message, in the upper portion of the
* byte. (Use 0b###00000 instead of 0b00000### to input the
* three bits ###.)
* length: [in]
* The number of bits in message_bits, between 1 and 7.
*
* Returns:
* sha Error Code.
*/
int
SHA256FinalBits(SHA256Context * context,
const uint8_t message_bits, unsigned int length)
{
uint8_t masks[8] = {
/* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
/* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
/* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
/* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
};
uint8_t markbit[8] = {
/* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
/* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
/* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
/* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
};
if (!length)
return shaSuccess;
if (!context)
return shaNull;
if ((context->Computed) || (length >= 8) || (length == 0))
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
return context->Corrupted;
SHA224_256AddLength(context, length);
SHA224_256Finalize(context, (uint8_t)
((message_bits & masks[length]) | markbit[length]));
return shaSuccess;
}
/*
* SHA256Result
*
* Description:
* This function will return the 256-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 32nd element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*/
int
SHA256Result(SHA256Context * context, uint8_t Message_Digest[])
{
return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
}
/*
* SHA224_256Finalize
*
* Description:
* This helper function finishes off the digest calculations.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* sha Error Code.
*/
static void
SHA224_256Finalize(SHA256Context * context, uint8_t Pad_Byte)
{
int i;
SHA224_256PadMessage(context, Pad_Byte);
/* message may be sensitive, so clear it out */
for (i = 0; i < SHA256_Message_Block_Size; ++i)
context->Message_Block[i] = 0;
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
/*
* SHA224_256PadMessage
*
* 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 helper function will pad
* the message according to those rules by filling the
* Message_Block array accordingly. When it returns, it can be
* assumed that the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* Pad_Byte: [in]
* The last byte to add to the digest before the 0-padding
* and length. This will contain the last bits of the message
* followed by another single bit. If the message was an
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
*
* Returns:
* Nothing.
*/
static void
SHA224_256PadMessage(SHA256Context * context, uint8_t Pad_Byte)
{
/*
* 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 >= (SHA256_Message_Block_Size - 8))
{
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < SHA256_Message_Block_Size)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA224_256ProcessMessageBlock(context);
}
else
context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
context->Message_Block[context->Message_Block_Index++] = 0;
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
context->Message_Block[59] = (uint8_t)(context->Length_High);
context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
context->Message_Block[63] = (uint8_t)(context->Length_Low);
SHA224_256ProcessMessageBlock(context);
}
/*
* SHA224_256ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* context: [in/out]
* The SHA context to update
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the publication.
*/
static void
SHA224_256ProcessMessageBlock(SHA256Context * context)
{
/* Constants defined in FIPS-180-2, section 4.2.2 */
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
int t, t4; /* Loop counter */
uint32_t temp1, temp2; /* Temporary word value */
uint32_t W[64]; /* Word sequence */
uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = t4 = 0; t < 16; t++, t4 += 4)
W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
(((uint32_t)context->Message_Block[t4 + 1]) << 16) |
(((uint32_t)context->Message_Block[t4 + 2]) << 8) |
(((uint32_t)context->Message_Block[t4 + 3]));
for (t = 16; t < 64; t++)
W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] +
SHA256_sigma0(W[t - 15]) + W[t - 16];
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
F = context->Intermediate_Hash[5];
G = context->Intermediate_Hash[6];
H = context->Intermediate_Hash[7];
for (t = 0; t < 64; t++)
{
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + temp1;
D = C;
C = B;
B = A;
A = temp1 + temp2;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Intermediate_Hash[5] += F;
context->Intermediate_Hash[6] += G;
context->Intermediate_Hash[7] += H;
context->Message_Block_Index = 0;
}
/*
* SHA224_256Reset
*
* Description:
* This helper function will initialize the SHA256Context in
* preparation for computing a new SHA256 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
* H0
* The initial hash value to use.
*
* Returns:
* sha Error Code.
*/
static int
SHA224_256Reset(SHA256Context * context, uint32_t * H0)
{
if (!context)
return shaNull;
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = H0[0];
context->Intermediate_Hash[1] = H0[1];
context->Intermediate_Hash[2] = H0[2];
context->Intermediate_Hash[3] = H0[3];
context->Intermediate_Hash[4] = H0[4];
context->Intermediate_Hash[5] = H0[5];
context->Intermediate_Hash[6] = H0[6];
context->Intermediate_Hash[7] = H0[7];
context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}
/*
* SHA224_256ResultN
*
* Description:
* This helper function will return the 224-bit or 256-bit message
* digest into the Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 28th/32nd element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA hash.
* Message_Digest: [out]
* Where the digest is returned.
* HashSize: [in]
* The size of the hash, either 28 or 32.
*
* Returns:
* sha Error Code.
*/
static int
SHA224_256ResultN(SHA256Context * context,
uint8_t Message_Digest[], int HashSize)
{
int i;
if (!context || !Message_Digest)
return shaNull;
if (context->Corrupted)
return context->Corrupted;
if (!context->Computed)
SHA224_256Finalize(context, 0x80);
for (i = 0; i < HashSize; ++i)
Message_Digest[i] = (uint8_t)
(context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
return shaSuccess;
}

1090
microstack/sha384-512.c Normal file

File diff suppressed because it is too large Load Diff