LibraryMaker Desc file.

Just starting out? Need help? Post your questions and find answers here.
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

LibraryMaker Desc file.

Post by Hatonastick »

I've written a C library that I'm trying to turn into a PureBASIC one, but I really don't understand the example given in the readme file. So far I have this in my PureCrypt.Desc file:
C
0
LIB
0
PureCrypt
;
; PureCrypt library descriptor
;



Now the C functions I have for the PureCrypt API are:
int SHA1Hash(char *buffer, long length, char *result);
int SHA256Hash(char *buffer, long length, char *result);
int SHA512Hash(char *buffer, long length, char *result);
int BlowfishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int BlowfishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);

Now how would I turn the above into something that can be understood by LibraryMaker? Do I need to rewrite anything in my C library to allow better interfacing with PB? If I can get this to work then I'm going to convert some other C libraries I've written to PureBASIC.

I have done a search on here, but have been unable to find any totally relevant information. There was one link to what sounded useful, but it no longer exists. :-/
MushroomHead
User
User
Posts: 15
Joined: Wed Apr 27, 2005 2:55 pm

Post by MushroomHead »

Assuming you have already generated the required LIB files successfully, here's what your desc file would look like (I'm learning too and this is a modified version of the template provided with PB) :-

Code: Select all

;
; Langage used to code th library: ASM or C
C
;
; Number of windows DLL than the library need
0
; Library type (Can be OBJ or LIB)
;
LIB
;
; Number of PureBasic library needed by the library
0
; Help directory name
;
Extension1
;
; Library functions (FunctionName, Arg1, Arg2, ...)
;

SHA1Hash, String, Long, String
Long

SHA256Hash, String, Long, String
Long

SHA512Hash, String, Long, String
Long

BlowfishEncode, String, Long, String, Long, String
Long

BlowfishDecode, String, Long, String, Long, String
Long

TwofishEncode, String, Long, String, Long, String
Long

TwofishDecode, String, Long, String, Long, String
Long

Run the LibraryMaker over the above desc file and it should generate the PB lib ... however remember in the LIB, you must export the above functions using a PB_ prefix e.g. for MSVC

Code: Select all

extern "C" 
{
    extern int PB_SHA1Hash(char *buffer, long length, char *result); 
   {
        //Your code ...
    }

    ..
    ..
}
FloHimself
Enthusiast
Enthusiast
Posts: 229
Joined: Wed May 14, 2003 3:38 pm
Location: Lüneburg - Germany

Post by FloHimself »

I wrote down some notes some time ago, when i wrote my first PB libs.
This is based on PureBasic sample files, with some additional/modified
info for me, so i dont forget about this.

As this are notes for myself and they are some way old, i dont know if
they are correct/outdated/elegant/whatever! But my sample function
signature is matching some of your functions and maybe this is useful to
someone else.

SampleLib.c

Code: Select all

#include <windows.h>

//////////////////////////////////////////////////////////////////////////////
// Step (1) Include PB's debugger stuff.
//          With SendDebuggerError() the debugger can be stopped with some
//          warning message. Useful in "_DEBUG" functions.
//////////////////////////////////////////////////////////////////////////////
extern char *PB_DEBUGGER_ErrorDescription;
extern HWND  PB_DEBUGGER_Window;
extern int	PB_DEBUGGER_Control;

void SendDebuggerError(char*);

void SendDebuggerError(char *text)
{
	if (PB_DEBUGGER_ErrorDescription == 0)
	{
		PB_DEBUGGER_ErrorDescription = text;
		PB_DEBUGGER_Control = 2; // Halt the PureBasic program flow...
		SendMessage(PB_DEBUGGER_Window, WM_COMMAND, 6, 1);
	}
}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// Step (2) Write the C functions you want to export to PureBasic.
//          These functions must be prefixed with "PB_" for PureBasic to 
//          recognize them.
//
// Note:    Functions have to use STDCALL calling convention. 
//////////////////////////////////////////////////////////////////////////////
#define PBCOMMAND   extern _stdcall

PBCOMMAND int PB_SampleCFunction(char*, long, char*);

PBCOMMAND int PB_SampleCFunction(char *buffer, long length, char *result)
{
          int i;
          for (i = 0; i <= length-1; i++)
          {
              result[i] = buffer[length-i-1];
          }
          return 1;
}

//////////////////////////////////////////////////////////////////////////////
// Step (3) Write the C debug functions. They must be suffixed with "_DEBUG".
//          This function for example will raise an error in PB's debugger,
//          if one of the three arguments are NULL (0).
//
// Note:    Functions have to use CDECL calling convention and must use void
//          as return value.
//////////////////////////////////////////////////////////////////////////////
#define PBDEBUG     extern void

PBDEBUG PB_SampleCFunction_DEBUG(char*, long, char*);

PBDEBUG PB_SampleCFunction_DEBUG(char *buffer, long length, char *result)
{
          if (!buffer) 
             SendDebuggerError("Error! [in] *Buffer = 0 !!");

          if (!length) 
             SendDebuggerError("Error! [in] Lenght = 0 !!");

          if (!result) 
             SendDebuggerError("Error! [out] *Buffer = 0 !!");
}
SampleLib.Desc

Code: Select all

;
; Langage used to code the library: ASM or C
C
;
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
MSVCRT
;
; Library type (Can be OBJ or LIB).
LIB
;
; Number of PureBasic libraries needed by your library.
; (additional PureBasic libraries that are needed for linking).
0
;
; Help directory name.
SampleLib
;
; Library functions (FunctionName, Arg1, Arg2, ...);
; First the function name. Its the name of the C function
; that should be exported to PB, without the "PB_" Prefix
; used in C. After function name a comma and a list of 
; arguments seperated by comma aswell. in parentheses
; a argument description that is showed by the PureBasic IDE
; as quick help. After the parentheses a general description 
; can follow.
;
; Translation table for some arguments:
; ANSI C         | PureBasic
; --------------------------
; int *          |  Long
; byte *         |  Long
; int  (32 bits) |  Long
; char *         |  Long / String
; long (32 bits) |  Long
; float          |  Float
; double         |    -  (must be casted to float in C for now)
; char           |  Byte
; void           |  None
; short(16 bits) |  Word
;
SampleCFunction, Long, Long, Long ([in] *Buffer, [in] Length, [out] *Buffer) - My Sample Funktion.
;
; Return value:
; Type of return value and flags for:
; 'InitFunction' (a function which is called automatically
; at the start of a PureBasic program), 
; 'EndFunction' (called at the end, for cleaning)
; and 'DebuggerCheck' (a debugger handler function for this command.)
Long | DebuggerCheck
SampleLib.pb

Code: Select all

InBuffer$  = "foo"
Length     = Len(InBuffer$)
OutBuffer$ = Space(Len(InBuffer$))

Debug SampleCFunction(@InBuffer$, Length, @OutBuffer$)
Debug OutBuffer$

; for testing debugger function
;Debug SampleCFunction(0, Length, @OutBuffer$)
//EDIT: Typo in C Source
Last edited by FloHimself on Thu May 19, 2005 11:23 pm, edited 1 time in total.
My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Thanks very much for your help! It has been invaluable. Will let you know if I get it working. :) Just trying it now.

Ok I have a problem. Library compiles just fine and dandy. LibMaker creates PureCrypt library and places it in the PureBASIC PureLibraries directories as it is supposed to. However when I compile the following program in PureBASIC:
; Attempt to use SHA1Hash.

InBuffer$ = "foo"
Length = Len(InBuffer$)
; Need a 20 byte buffer for the result
OutBuffer$ = Space(20)

Debug SHA1Hash(@InBuffer$, Length, @OutBuffer$)
Debug OutBuffer$

I get a PureBASIC linker error:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_ErrorDescription'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Control'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Window'.
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 7 unresolved external(s).

I'm open to any suggestions. I'm slightly hindered by 3 factors: 1) I haven't written a static library in years. 2) I've spent most of my years programming under UNIX and not windows. 3) I'm not as familiar (yet) with PureBASIC as I'd like to be. So the problem may be with the chair to keyboard interface. :)
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

You seems to use PB_DEBUG_xx but it's PB_DEBUGGER_xx now. It will solve a bunch of unresolved symbols. Also, remove the 'CheckDebugger' flag in the .desc, it will remove another one (you could add it later). The chkstk should be fixed in v3.93, strange..
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

I have at least fixed my major misunderstanding with the DEBUG_ instead of DEBUGGER_. Hmm would my Desc file still be incorrect? It isn't generating any errors, unless I remove the DebuggerCheck lines. Does it need "PB_SHA1Hash_DEBUGGER" and similar functions to be listed in the Desc file as well?

BTW could the other errors be because the functions in my library use unsigned char as opposed to char? ie. SHA1Hash(unsigned char *buffer, long length, unsigned char *result).

Still getting the following errors:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(Actually why am I still getting the above error when I've updated the library with _DEBUG replaced with _DEBUGGER and then run LibraryMaker again? There is no _DEBUG function in my library anymore, only _DEBUGGER)
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 4 unresolved external(s).

My Desc file:
;
; Langage used to code the library: ASM or C
C
;
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
0
;
; Library type (Can be OBJ or LIB).
LIB
;
; Number of PureBasic libraries needed by your library.
; (additional PureBasic libraries that are needed for linking).
0
;
; Help directory name.
PureCrypt
;
; Library functions (FunctionName, Arg1, Arg2, ...);
; First the function name. Its the name of the C function
; that should be exported to PB, without the "PB_" Prefix
; used in C. After function name a comma and a list of
; arguments seperated by comma aswell. in parentheses
; a argument description that is showed by the PureBasic IDE
; as quick help. After the parentheses a general description
; can follow.
;
; Translation table for some arguments:
; ANSI C | PureBasic
; --------------------------
; int * | Long
; byte * | Long
; int (32 bits) | Long
; char * | Long / String
; long (32 bits) | Long
; float | Float
; double | - (must be casted to float in C for now)
; char | Byte
; void | None
; short(16 bits) | Word
;
; Return value:
; Type of return value and flags for:
; 'InitFunction' (a function which is called automatically
; at the start of a PureBasic program),
; 'EndFunction' (called at the end, for cleaning)
; and 'DebuggerCheck' (a debugger handler function for this command.)
;Long | DebuggerCheck

SHA1Hash, Long, Long, Long ([in] *buffer, [in] length, [out] *result) - Returns 20 byte hash.
Long | DebuggerCheck

SHA256Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - Returns 32 byte hash.
Long | DebuggerCheck

SHA512Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - 512 bit secure hash. Returns 64 byte hash.
Long | DebuggerCheck

BlowfishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish encode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck

BlowfishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish decode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck

TwofishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish encode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck

TwofishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish decode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

When you add the DebuggerCheck flag in the .desc, you have to declare a function like this in your C file:

PB_YourFunction_DEBUG() (this time it's not _DEBUGGER ;))
FloHimself
Enthusiast
Enthusiast
Posts: 229
Joined: Wed May 14, 2003 3:38 pm
Location: Lüneburg - Germany

Post by FloHimself »

Hatonastick wrote:Does it need "PB_SHA1Hash_DEBUGGER" and similar functions to be listed in the Desc file as well?
Nope. Don't declare the debugger functions in .desc file.
Hatonastick wrote:POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(Actually why am I still getting the above error when I've updated the library with _DEBUG replaced with _DEBUGGER and then run LibraryMaker again? There is no _DEBUG function in my library anymore, only _DEBUGGER)
Use the "PB_DEBUGGER_" prefix for declaring the extern vars like in:

Code: Select all

extern char *PB_DEBUGGER_ErrorDescription; 
extern HWND  PB_DEBUGGER_Window; 
extern int   PB_DEBUGGER_Control; 
But use the "_DEBUG" suffix for the debugger functions:

Code: Select all

PB_SHA1Hash_DEBUG(char*, long, char*); 
For the other linking errors, what compiler system do you use to compile your c lib?

//EDIT: like always. i'm the second poster :twisted:
My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

Code: Select all

POLINK: error: Unresolved external symbol '___chkstk'.
As Fred said this should be no problem anymore since 3.93
Strange.

Code: Select all

POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'. 
These are part of a CRT (llshl.obj and ullshr.obj).

Normally they are exported as "__allshr" and "__aullshr" which is
what I don't understand. Are you using a Borland compiler by any chance?

Anyway, try this:

Code: Select all

; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
crtmt
Unresolved dependencies gone?
Good programmers don't comment their code. It was hard to write, should be hard to read.
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Ok, no amount of renaming of functions in the library seems to alter in any way the error messages generated by my PureBASIC test program. However having just looked at the Lcc example, I think that maybe I need to rewrite my PureBASIC API functions. The problem might be with them. Maybe. Or maybe it's the compiler I use, which is Pelles C (off shoot of Lcc). I'm definitely using __stdcall calling convention.

Tried this:
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
crtmt

No change...

I deleted the copy of my PureCrypt library in the PureBASIC library directory at one stage - would that mess anything up when I redo it using LibraryMaker? Just wondering because I think it is strange that none of the changes I've made to the library seem to affect the errors in the PureBASIC program. Mind you I'm probably not thinking clearly at the moment.

I think I need sleep. :shock:

Ok, I'm going to (after some sleep) rewrite my library based upon the Lcc example provided in the Library SDK folder - which I'm guessing is still valid in regards to the current release of PureBASIC. Maybe something is messed up with how I've done the library. If that doesn't work, I'm pretty much out of ideas.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

Hatonastick wrote:I deleted the copy of my PureCrypt library in the PureBASIC library directory at one stage - would that mess anything up when I redo it using LibraryMaker?
Wait a minute...

When using the LibrariesMaker, your "objects path" is that of your .lib of course...
The "PureLibraries path" is set to *whatever*/PureBasic/PureLibraries/UserLibraries/, isn't it?
That way the library gets overwritten everytime anyway, so of course
it doesn't matter whether you're deleting it beforehand or not.

You're also restarting the compiler after each change to the library, right?

I'd suggest you to sleep well and re-start from scratch afterwards.
There must be something wrong in the process of building the library.
Maybe start with just one function (no debug-routine) and see what
you get.

We'll get this done, trust me! :D
Good programmers don't comment their code. It was hard to write, should be hard to read.
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Yup - so I don't think the problem is the way I'm using LibraryMaker. I just tried deleting the old library out of desperation. :)

Ok, I will start rewriting the library based on the Lcc example provided with the PureBASIC distribution in the Library SDK directory. I shall start with SHA1 and see how it goes. If I can get that working, the rest will be a cinch.

I'll let you know how it goes. If that doesn't work then it might be possible that Pelles C is the problem.

Actually... I think I'll just try compiling the Lcc example and see if I can get that to work first. :)
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Ok it's not the Pelles C compiler. I compiled the Lcc example into a library, turned it into a PureBASIC library using LibraryMaker, then ran a simple program to access the new functions and it all worked fine.

So now I'll try rewriting my library and just include the source for SHA1 hash.

Ok I have rewritten it but there are still problems when I run the test PB program mentioned above. Just generating half the number of errors. :)

POLINK: warning: Multiple '.data' sections found with different flags (0xc0000040 and 0x60000040).
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(No idea why we are still getting that one)
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: fatal error: 2 unresolved external(s).

Also I am think that maybe I should rewrite how my SHA1Hash function works. Currently it assumes that the buffer provided for the output by the PureBASIC programmer is big enough, when really I should be passing back a string or block of data from the function to PureBASIC somehow - like the StringMultiply() function in the LCCWin Library SDK example.

// Needs to be given a 20 byte buffer for the result
PBINT PB_SHA1Hash(uchar8 *buffer, ulong32 length, uchar8 *result)
{
...
return 1;
}

When it would be better to be able to do something like:
PBSTRING PB_SHA1Hash(uchar8 *buffer, ulong32 length)
{
char *result = PB_StringBase;
...
return result;
}
Although I don't quite understand how that works. Does PureBASIC somehow handle the memory allocation requests when using PB_StringBase? Hmm ok reading up on it, it's a 64kb fixed sized buffer. So I need instead to work out how to use PB_MemoryBase or similar?

I'm starting to think that maybe I should post the library source code as it is and see if anyone can spot the problem.
Last edited by Hatonastick on Fri May 20, 2005 7:17 am, edited 2 times in total.
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

The header file:

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// PureCrypt v1.0a                                                           //
///////////////////////////////////////////////////////////////////////////////
// Contains library defines, macros, structures etc.                         //
///////////////////////////////////////////////////////////////////////////////

// Disable the following line to test your library ////////////////////////////
#define PURELIBRARY

// PureBASIC variables
#ifdef PURELIBRARY
  extern HINSTANCE PB_Instance;
  extern char     *PB_StringBase;
#else
  HINSTANCE PB_Instance;
  char     *PB_StringBase;
#endif

// PureBASIC debugger interface
extern char *PB_DEBUGGER_ErrorDescription;
extern HWND	 PB_DEBUGGER_Window;
extern int	 PB_DEBUGGER_Control;

static void SendDebuggerError(char *Text)
{
	if (PB_DEBUGGER_ErrorDescription == 0)
	{
		PB_DEBUGGER_ErrorDescription = Text;
		PB_DEBUGGER_Control = 2; // Halt the PureBasic program flow...
		SendMessage(PB_DEBUGGER_Window, WM_COMMAND, 6, 1);
	}
}

// Types and Defines //////////////////////////////////////////////////////////

typedef unsigned long long ulong64;
#define CONST64(n) n ## ULL
typedef signed long long   long64;
typedef unsigned long ulong32;
typedef signed long long32;
typedef unsigned char uchar8;

// PureBASIC related defines
#define PBINT extern int _stdcall
#define PBLONG extern long32 _stdcall
#define PBSTRING extern char _stdcall *
#define PBFLOAT extern float _stdcall
#define PBDEBUG extern void 

// Macros /////////////////////////////////////////////////////////////////////

// Remember that these are set for "little endian" machines
#define LOAD32H(x, y)                            \
     { x = ((ulong32)((y)[0] & 255)<<24) | \
           ((ulong32)((y)[1] & 255)<<16) | \
           ((ulong32)((y)[2] & 255)<<8)  | \
           ((ulong32)((y)[3] & 255)); }

#define LOAD32L(x, y)         \
     memcpy(&(x), y, 4);

#define STORE32H(x, y)                                                                     \
     { (y)[0] = (uchar8)(((x)>>24)&255); (y)[1] = (uchar8)(((x)>>16)&255);   \
       (y)[2] = (uchar8)(((x)>>8)&255); (y)[3] = (uchar8)((x)&255); }

#define STORE32L(x, y)        \
     { unsigned long __t = (x); memcpy(y, &__t, 4); }

#define LOAD64H(x, y)                                                      \
   { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
         (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
         (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
         (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }

#define STORE64H(x, y)                                                                     \
   { (y)[0] = (uchar8)(((x)>>56)&255); (y)[1] = (uchar8)(((x)>>48)&255);     \
     (y)[2] = (uchar8)(((x)>>40)&255); (y)[3] = (uchar8)(((x)>>32)&255);     \
     (y)[4] = (uchar8)(((x)>>24)&255); (y)[5] = (uchar8)(((x)>>16)&255);     \
     (y)[6] = (uchar8)(((x)>>8)&255); (y)[7] = (uchar8)((x)&255); }

#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)

#define ROL64(x, y) \
    ( (((x)<<((ulong64)(y)&63)) | \
      (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))

#define ROR64(x, y) \
    ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
      ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))

#define ROL64c(x, y) \
    ( (((x)<<((ulong64)(y)&63)) | \
      (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))

#define ROR64c(x, y) \
    ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
      ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))

#define byte(x, n) (((x) >> (8 * (n))) & 255)

#undef MAX
#undef MIN
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )

#define TRUE 1
#define FALSE 0

///////////////////////////////////////////////////////////////////////////////
// Cryptographic hashes                                                      //
///////////////////////////////////////////////////////////////////////////////

// SHA-1 //////////////////////////////////////////////////////////////////////

typedef struct sha1 {
  ulong64 length;
  ulong32 state[5];
  ulong32 curlen;
  uchar8 buf[64];
} SHA1;

int sha1_compress(SHA1 *md, uchar8 *buf);
int sha1_init(SHA1 *md);
int sha1_done(SHA1 *md, uchar8 *out);
int sha1_process(SHA1 *md, uchar8 *in, ulong32 inlen);
Last edited by Hatonastick on Fri May 20, 2005 5:53 am, edited 2 times in total.
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Ignore PureCryptTables.h - it isn't important. There isn't anything in there that could be causing the problem as it's just a load of constants.
The source:

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// PureCrypt v1.0a                                                           //
///////////////////////////////////////////////////////////////////////////////
// Contains library functions and library test routine.                      //
///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <windows.h>
#include "PureCrypt.h"
#include "PureCryptTables.h"

// PureCrypt API //////////////////////////////////////////////////////////////

// Needs to be given a 20 byte buffer for the result
PBINT PB_SHA1Hash(uchar8 *buffer, ulong32 length, uchar8 *result)
{
  SHA1 md;

  // Have we got input?
  if (buffer && *buffer && result && *result) {
    if (sha1_init(&md) != TRUE)
      return FALSE;

    if (sha1_process(&md, buffer, length) != TRUE)
      return FALSE;

    if (sha1_done(&md, result) != TRUE)
      return FALSE;

    return TRUE;
  } else {
    return FALSE;
  }
}

// Debugger function interface ////////////////////////////////////////////////

// --- All command debug equivalent (name + _DEBUG)
// No more '_stdcall' as the arguments aren't unstacked..

PBDEBUG PB_SHA1Hash_DEBUG(uchar8 *buffer, ulong32 length, uchar8 *result)
{
  if (length == 0)
    SendDebuggerError("0 length input !");
}

// SHA1 Functions /////////////////////////////////////////////////////////////

int  sha1_compress(SHA1 *md, uchar8 *buf)
{
  ulong32 a,b,c,d,e,W[80],i;

  /* copy the state into 512-bits into W[0..15] */
  for (i = 0; i < 16; i++) {
    LOAD32H(W[i], buf + (4*i));
  }

  /* copy state */
  a = md->state[0];
  b = md->state[1];
  c = md->state[2];
  d = md->state[3];
  e = md->state[4];

  /* expand it */
  for (i = 16; i < 80; i++) {
    W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); 
  }

  /* compress */
#ifdef F0
#undef F0
#endif
#define F0(x,y,z)  (z ^ (x & (y ^ z)))
#ifdef FF0
#undef FF0
#endif
#define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);

  /* round one */
  for (i = 0; i < 20; ) {
    FF0(a,b,c,d,e,i++);
    FF0(e,a,b,c,d,i++);
    FF0(d,e,a,b,c,i++);
    FF0(c,d,e,a,b,i++);
    FF0(b,c,d,e,a,i++);
  }

#ifdef F1
#undef F1
#endif
#define F1(x,y,z)  (x ^ y ^ z)
#ifdef FF1
#undef FF1
#endif
#define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);

  /* round two */
  for (; i < 40; )  { 
    FF1(a,b,c,d,e,i++);
    FF1(e,a,b,c,d,i++);
    FF1(d,e,a,b,c,i++);
    FF1(c,d,e,a,b,i++);
    FF1(b,c,d,e,a,i++);
  }

#ifdef F2
#undef F2
#endif
#define F2(x,y,z)  ((x & y) | (z & (x | y)))
#ifdef FF2
#undef FF2
#endif
#define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);

  /* round three */
  for (; i < 60; )  { 
    FF2(a,b,c,d,e,i++);
    FF2(e,a,b,c,d,i++);
    FF2(d,e,a,b,c,i++);
    FF2(c,d,e,a,b,i++);
    FF2(b,c,d,e,a,i++);
  }

#ifdef F3
#undef F3
#endif
#define F3(x,y,z)  (x ^ y ^ z)
#ifdef FF3
#undef FF3
#endif
#define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);

  /* round four */
  for (; i < 80; )  { 
    FF3(a,b,c,d,e,i++);
    FF3(e,a,b,c,d,i++);
    FF3(d,e,a,b,c,i++);
    FF3(c,d,e,a,b,i++);
    FF3(b,c,d,e,a,i++);
  }

  /* store */
  md->state[0] = md->state[0] + a;
  md->state[1] = md->state[1] + b;
  md->state[2] = md->state[2] + c;
  md->state[3] = md->state[3] + d;
  md->state[4] = md->state[4] + e;

  return TRUE;
}

int sha1_init(SHA1 *md)
{
  int i;

  if (md == NULL) return FALSE;
  md->state[0] = 0x67452301UL;
  md->state[1] = 0xefcdab89UL;
  md->state[2] = 0x98badcfeUL;
  md->state[3] = 0x10325476UL;
  md->state[4] = 0xc3d2e1f0UL;
  md->curlen = 0;
  md->length = 0;
  for (i = 0; i < 64; i++)
    md->buf[i] = ' ';
  return TRUE;
}

int sha1_process(SHA1 *md, uchar8 *in, ulong32 inlen)
{
  ulong32 n;
  int blocksize = 64;

  // Check to see we have been passed valid arguments
  if (md == NULL || in == NULL) {
    return FALSE;
  }
  if (md->curlen > sizeof(md->buf)) {
    return FALSE;
  }

  // Process block
  while (inlen > 0) {
    if (md->curlen == 0 && inlen >= blocksize) {
      if ((sha1_compress(md, (unsigned char *)in)) != TRUE) {
        return FALSE;
      }
      md->length += blocksize * 8;
      in += blocksize;
      inlen -= blocksize;
    } else {
      n = MIN(inlen, (blocksize - md->curlen));
      memcpy(md->buf + md->curlen, in, (size_t)n);
      md->curlen += n;
      in += n;
      inlen -= n;
      if (md->curlen == blocksize) {
        if ((sha1_compress(md, md->buf)) != TRUE) {
          return FALSE;
        }
        md->length += 8*blocksize;
        md->curlen = 0;
      }
    }
  }
  return TRUE;
}

int sha1_done(SHA1 *md, uchar8 *out)
{
  int i;

  if (md == NULL || out == NULL) {
    return FALSE;
  }

  if (md->curlen >= sizeof(md->buf)) {
    return FALSE;
  }

  /* increase the length of the message */
  md->length += md->curlen * 8;

  /* append the '1' bit */
  md->buf[md->curlen++] = (unsigned char)0x80;

  /* if the length is currently above 56 bytes we append zeros
   * then compress.  Then we can fall back to padding zeros and length
   * encoding like normal.
   */
  if (md->curlen > 56) {
    while (md->curlen < 64) {
      md->buf[md->curlen++] = (unsigned char)0;
    }
    sha1_compress(md, md->buf);
    md->curlen = 0;
  }

  /* pad upto 56 bytes of zeroes */
  while (md->curlen < 56) {
    md->buf[md->curlen++] = (unsigned char)0;
  }

  /* store length */
  STORE64H(md->length, md->buf+56);
  sha1_compress(md, md->buf);

  /* copy output */
  for (i = 0; i < 5; i++) {
    STORE32H(md->state[i], out+(4*i));
  }
  return TRUE;
}

// Examples of how to interface with PureBASIC ////////////////////////////////

/*
// String return example ------------------------------------------------------------------

PBSTRING PB_StringMultiply(char *String, int NbTimes)
{
  char *ResultString = PB_StringBase;
  int   k;

  if (String && *String)  // It's always good for safety and perfomance to exclude null or empty strings
  {
    int StringLength = strlen(String);

    for (k=0; k<NbTimes; k++)
    {
      strcpy(PB_StringBase, String);
      PB_StringBase += StringLength;  // Increase the output string buffer
    }
  }

  *PB_StringBase = 0;     // Finally write the zero ending string. PB_StringBase contains the result string

  return ResultString;    // Returns the start of the buffer, as it has been passed
}

// Float return example --------------------------------------------------------------------

PBFLOAT PB_FloatReturn()
{
  return 15.21;
}
*/

// Test library ///////////////////////////////////////////////////////////////

#ifndef PURELIBRARY

// Not done yet
int main()
{
  PB_MessageBox(0, "Titre", "Text", 0);
  return 0;
}

#endif
Last edited by Hatonastick on Fri May 20, 2005 5:54 am, edited 2 times in total.
Post Reply