News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Problem with CryptoAPI

Started by Astro, February 24, 2010, 01:27:45 AM

Previous topic - Next topic

Astro

Hi,

I'm whacking my head off a wall here. I just can't see the error.

The following code seems to work, only half way through the hash result it apparently corrupts and produces incorrect data. I just can't see a reason for it. If you look carefully, the complete hash result is there, only in the middle of it there is junk.  :eek  I also have no idea why it is printing more data than it should.

This is simply a test piece for integration into a larger project (when it eventually works). Just build as a console .EXE.

include \masm32\include\masm32rt.inc

include \masm32\include\advapi32.inc
includelib \masm32\lib\advapi32.lib

.386
.model flat,stdcall

.data?
    hCSP DWORD ?
    hHash DWORD ?
    HashParam DWORD ?
    LastErr DWORD ?

.data
    HashLen DWORD 0
    CryptCreateHashResult DWORD 0
    CryptHashDataResult DWORD 0
    CryptHashParamResult DWORD 0
    HashResult DWORD 8 dup (0)

    XPProvider BYTE "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)",0
    DataToHash BYTE "abc",0
    HashResultOut BYTE 33 dup (0)
    ASCIITable BYTE "0123456789abcdef",0
    Hash BYTE "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",0

.code

start:

    push 0
    call SetLastError
   
    ;---------------------------------------------
    ; Get the CSP ready

    push CRYPT_VERIFYCONTEXT
    push PROV_RSA_AES
    push 0 ; Use default provider
    push 0
    lea eax,hCSP
    push eax
    call CryptAcquireContext
   
    call GetLastError
    mov LastErr,eax

    print "CryptAcquireContext: "
    print str$(hCSP),13,10

    print "GetLastError: "
    print str$(LastErr),13,10,10

    push 0
    call SetLastError

    ;---------------------------------------------
    ; Create the hash object

    lea eax, hHash
    push eax
    push 0
    push 0
    push 800Ch ; 800Ch is SHA-256 ; 8004h is CALG_SHA ; 8003 is CALG_MD5
    push hCSP
    call CryptCreateHash
    mov CryptCreateHashResult,eax
    call GetLastError
    mov LastErr,eax

    print "CryptCreateHash: "
    print str$(CryptCreateHashResult),13,10

    print "GetLastError: "
    print str$(LastErr),13,10,10

    push 0
    call SetLastError

    ;---------------------------------------------
    ; Hash some data

    push 0
    push 3
    push offset DataToHash
    push hHash
    call CryptHashData
    mov CryptHashDataResult,eax
    call GetLastError
    mov LastErr,eax
   
    print "CryptHashData: "
    print str$(CryptHashDataResult),13,10

    print "GetLastError: "
    print str$(LastErr),13,10,10

    push 0
    call SetLastError

    ;---------------------------------------------
    ; Get the hash result
    ; 1) call to get the buffer length

    push 0
    lea eax,HashLen
    push eax
    push 0 ; Get buffer length, not the data
    push 2 ; HP_HASHVAL
    push hHash
    call CryptGetHashParam

    ;--------------------------------------------
    ; Get the hash result
    ; 2) call to actually get the hash

    push 0
    lea eax,HashLen
    push eax
    lea eax,HashResult
    push eax
    push 2 ; HP_HASHVAL
    push hHash
    call CryptGetHashParam

    mov CryptHashParamResult,eax
    call GetLastError
    mov LastErr,eax

    print "CryptGetHashParam: "
    print str$(CryptHashParamResult),13,10
   
    print "GetLastError: "
    print str$(LastErr),13,10,10

    print "HashLen: "
    print str$(HashLen),13,10,10

    ;---------------------------------------------
    ; Convert HashResult to ASCII
   
    push 8
    lea eax,HashResultOut
    push eax
    call dw2ascii

    print "Hash check: "
    print offset Hash,13,10
    print "Hash Result "
    print offset HashResultOut,13,10,10

    push hHash
    call CryptDestroyHash

    push 0
    push hCSP
    call CryptReleaseContext

    ret
;===========================================================


dw2ascii proc ptrAscBuf:DWORD,Count:DWORD

    push ebx
    push edi

    mov edi,0

    mov eax,HashResult+[edi*4]
    mov ebx,ptrAscBuf

    mov ecx,0
@@:
    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx+1],dl
    ror eax,4

    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx],dl
    ror eax,4

    add ecx,2

    cmp ecx,8
    jne @B

    xor ecx,ecx
    add ebx,8
    inc edi
    mov eax,HashResult+[edi*4]

    cmp edi,Count
    jne @B

    pop edi
    pop ebx

    ret 8

dw2ascii endp

end start


Best regards,
Robin.

six_L

dw2ascii proc uses esi edi pstr:DWORD, pstrlen:DWORD
        mov eax, pstrlen
        mov ecx, 2d
        mul ecx
        inc eax
        invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, eax
        mov edi, eax
        mov esi, pstr

        push edi
WriteHex:
        xor eax, eax
        lodsb
        invoke wsprintf, edi, CTXT('%02x'), eax
        add edi, 2d
        dec pstrlen
        jnz WriteHex
        pop eax
        ret
dw2ascii endp
regards

joemc

I have also heard CryptoAPI can be used for SSL communication, but i cannot find any working examples.  If you have any good resources for the API please let me know.  Specifically I am trying to use IMAP, but any example code or tutorials would be great. Language does not matter. 

Astro

@six_L: thanks for the code. I'd like to know what is wrong with my code though. I can't understand two things:

1) Where the junk comes from

2) Why it produces more output than the byte buffer can hold.

HashResultOut BYTE 33 dup (0)

I should only be writing 32 bytes to the buffer. The 33rd byte should remain zero regardless of anything else.


@joemc: I suggest you start a new thread on that in the Campus forum. :)

Best regards,
Robin.

six_L

the wrong is in your "dw2ascii" codes.
there are a lot codes about how hex to strings, and better speeds.
if your "dw2ascii" codes modify a bit, then modify; if your "dw2ascii" codes modify a lot, then start new one.

change the thinking way, don't care about where are being the errors
regards

Astro

OK - thanks!!  :bg

Best regards,
Robin.

Astro

OK - I ran some tests on my code, and found something interesting - it is OK up to the 5th element of the DWORD array, but at the 6th element onwards it screws up.

Is there something more fundamental I'm missing that explains this behavior? The test code below works. If you increase the dwrd array to 6, uncomment the 6th mov dwrd... statement and set the count passed to dw2ascii to 6 it screws up. I can't see a good reason for this.

.386
.model flat,stdcall
option casemap:none

include \masm32\include\masm32rt.inc

.data
dwrd DWORD 5 dup (0)
ASCIITable BYTE "0123456789abcdef"
b BYTE 128 dup(0)

.code

start:

    mov [dwrd],12345678h
    mov [dwrd+4],87654321h
    mov [dwrd+8],12345678h
    mov [dwrd+12],87654321h
    mov [dwrd+16],12345678h
    ;mov [dwrd+24],87654321h
    ;mov [dwrd+32],12345678h
    ;mov [dwrd+40],87654321h

    push 5
    lea eax,b
    push eax
    call dw2ascii

    print offset b

    xor eax,eax
    ret
;==========================================================================



; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»

dw2ascii proc ptrAscBuf:DWORD,Count:DWORD

    push ebx
    push edi

    mov edi,0

    mov eax,dwrd+[edi*4]
    mov ebx,ptrAscBuf

    mov ecx,0
@@:
    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx+1],dl
    ror eax,4

    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx],dl
    ror eax,4

    add ecx,2

    cmp ecx,8
    jne @B

    mov ecx,0
    add ebx,8
    inc edi
    mov eax,dwrd+[edi*4]

    cmp edi,Count
    jne @B

    pop edi
    pop ebx

    ret 8

dw2ascii endp

end start


Best regards,
Robin.

Astro

This gets stranger........

Run the code as-is. Note the pattern.

Now set the size of the dwrd array from 9 to 8, and re-build.

.386
.model flat,stdcall
option casemap:none

include \masm32\include\masm32rt.inc

.data
dwrd DWORD 9 dup (0)
ASCIITable BYTE "0123456789abcdef"
b BYTE 128 dup(0)

.code

start:

    mov dwrd,11111111h
    mov [dwrd+4],88888888h
    mov [dwrd+8],11111111h
    mov [dwrd+12],88888888h
    mov [dwrd+16],11111111h
    mov [dwrd+24],88888888h
    mov [dwrd+32],11111111h
    mov [dwrd+40],87654321h

    push 8
    lea eax,b
    push eax
    call dw2ascii

    print offset b

    xor eax,eax
    ret
;==========================================================================



; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»

dw2ascii proc ptrAscBuf:DWORD,Count:DWORD

    push ebx
    push edi

    mov edi,0

    mov eax,dwrd+[edi*4]
    mov ebx,ptrAscBuf

    mov ecx,0
@@:
    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx+1],dl
    ror eax,4

    mov edx,eax
    and edx,0Fh
    mov edx,[offset ASCIITable+edx]
    mov byte ptr [ebx+ecx],dl
    ror eax,4

    add ecx,2

    cmp ecx,8
    jne @B

    mov ecx,0
    add ebx,8
    inc edi
    mov eax,dwrd+[edi*4]

    cmp edi,Count
    jne @B

    pop edi
    pop ebx

    ret 8

dw2ascii endp

end start


:dazzled:

Astro

Hi,

After fixing a glaring bug in my test code (check the offsets in the mov instructions after start: to see them :red ), there isn't a problem with the dw2ascii code that I wrote. I can create a DWORD array of 50 elements and it converts it without issue.

The problem seems to lie with the result returned by CryptGetHashParam in that the complete hash is there, only in the middle of it is junk.

It appears the junk occurs in the same place each time, and is the same length.

The start of the byte array Hash is also apparently corrupted, printing correctly at the start, but being corrupted somewhere along the way.

I just can't see why it is doing what it is doing. The API appears that it allocates the memory, and merely passes a pointer to me to read it, then I have to clear it up afterwards (I know I've not done that yet in the code above).

* sigh *

Best regards,
Robin.

Astro

FOUND IT!!!!!!  :cheekygreen:

EDIT: I can't count. :(

Best regards,
Robin.

hutch--

 :bg

Its usually referred to as "MacroShafted". We have all learnt the virtues of Microsoft documentation.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Astro

You might want to edit your post Hutch! :D

When I've converted it from binary to ASCII it requires twice as much space as the binary data. My ASCII buffer was not long enough. I hadn't appreciated I was taking 4 bytes from the hash and writing it into 8 bytes in the output buffer, doubling its length.

Best regards,
Robin.