microsoft / SymCrypt

Cryptographic library
MIT License
660 stars 68 forks source link

UB sanitizer reports NULL pointer access via SymCryptEcurveAllocate #10

Closed guidovranken closed 3 years ago

guidovranken commented 3 years ago
#include <symcrypt.h>
#include <stdlib.h>

void SymCryptFatal(UINT32 fatalCode) {
    (void)fatalCode;

    abort();
}
void SymCryptInjectError( PBYTE pbData, SIZE_T cbData ) {
    (void)pbData;
    (void)cbData;
}

PVOID SymCryptCallbackAlloc( SIZE_T nBytes ) {
    return malloc(nBytes);
}

VOID SymCryptCallbackFree( VOID * pMem ) {
    free(pMem);
}

SYMCRYPT_ERROR SymCryptCallbackRandom(PBYTE   pbBuffer, SIZE_T  cbBuffer ) {
    abort();
}

SYMCRYPT_CPU_FEATURES
SymCryptCpuFeaturesNeverPresent(void) {
    return 0;
}

int main(void)
{
    SYMCRYPT_ECURVE* curve = SymCryptEcurveAllocate(SymCryptEcurveParamsNumsP512t1, 0);
    return 0;
}

If compiled with UndefinedBehaviorSanitizer (clang with -fsanitize=undefined, on Linux 64 bit), execution of this program will print:

/mnt/2tb/sym-crash/SymCrypt/lib/fdef_mod.c:53:12: runtime error: member access within null pointer of type 'SYMCRYPT_MODULUS' (aka 'struct _SYMCRYPT_MODULUS')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /mnt/2tb/sym-crash/SymCrypt/lib/fdef_mod.c:53:12 in 
/mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:819:12: runtime error: member access within null pointer of type 'SYMCRYPT_DIVISOR' (aka 'struct _SYMCRYPT_DIVISOR')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:819:12 in 
/mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:195:12: runtime error: member access within null pointer of type 'SYMCRYPT_INT' (aka 'struct _SYMCRYPT_INT')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:195:12 in 
/mnt/2tb/sym-crash/SymCrypt/lib/fdef_mod.c:66:27: runtime error: member access within null pointer of type 'SYMCRYPT_MODULUS' (aka 'struct _SYMCRYPT_MODULUS')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /mnt/2tb/sym-crash/SymCrypt/lib/fdef_mod.c:66:27 in 
/mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:850:55: runtime error: member access within null pointer of type 'SYMCRYPT_DIVISOR' (aka 'struct _SYMCRYPT_DIVISOR')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /mnt/2tb/sym-crash/SymCrypt/lib/fdef_general.c:850:55 in 
NielsFerguson commented 3 years ago

This is due to this macro:

define SYMCRYPT_FIELD_OFFSET(type, field) ((ULONG)(ULONG_PTR)&(((type *)0)->field))

Which is inelegant, but the most portable way to get the field offset that I know of.

nibanks commented 3 years ago

@NielsFerguson FYI, for MsQuic, we have the following abstraction (Linux implementation): https://github.com/microsoft/msquic/blob/4c1527906233a8047068800d8b273852bb41a504/src/inc/msquic_linux.h#L166

#define FIELD_OFFSET(type, field)       offsetof(type, field)
samuel-lee-msft commented 3 years ago

We use offsetof in SymCrypt now too