Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -7888,6 +7888,99 @@ #define INIT_CAPSICUM #endif +#if SANITIZER_INTERCEPT_SHA1 +INTERCEPTOR(void, SHA1Init, void *context) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context); + REAL(SHA1Init)(context); + if (context) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz); +} +INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len); + if (data && len > 0) + COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); + if (context) + COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); + REAL(SHA1Update)(context, data, len); + if (context) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz); +} +INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context); + if (context) + COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); + REAL(SHA1Final)(digest, context); + if (digest) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20); +} +INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer); + if (state) + COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5); + if (buffer) + COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64); + REAL(SHA1Transform)(state, buffer); + if (state) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5); +} +INTERCEPTOR(char *, SHA1End, void *context, char *buf) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf); + if (context) + COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz); + char *ret = REAL(SHA1End)(context, buf); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); + return ret; +} +INTERCEPTOR(char *, SHA1File, char *filename, char *buf) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf); + if (filename) + COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); + char *ret = REAL(SHA1File)(filename, buf); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); + return ret; +} +INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset, + OFF_T length) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length); + if (filename) + COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1); + char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); + return ret; +} +INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf); + if (data) + COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); + char *ret = REAL(SHA1Data)(data, len, buf); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length); + return ret; +} +#define INIT_SHA1 \ + COMMON_INTERCEPT_FUNCTION(SHA1Init); \ + COMMON_INTERCEPT_FUNCTION(SHA1Update); \ + COMMON_INTERCEPT_FUNCTION(SHA1Final); \ + COMMON_INTERCEPT_FUNCTION(SHA1Transform); \ + COMMON_INTERCEPT_FUNCTION(SHA1End); \ + COMMON_INTERCEPT_FUNCTION(SHA1File); \ + COMMON_INTERCEPT_FUNCTION(SHA1FileChunk); \ + COMMON_INTERCEPT_FUNCTION(SHA1Data) +#else +#define INIT_SHA1 +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = @@ -8158,6 +8251,7 @@ INIT_STATVFS1; INIT_STRTOI; INIT_CAPSICUM; + INIT_SHA1; INIT___PRINTF_CHK; } Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -535,5 +535,6 @@ #define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD #define SANITIZER_INTERCEPT_STRTOI SI_NETBSD #define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD +#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H Index: lib/sanitizer_common/sanitizer_platform_limits_netbsd.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -2225,6 +2225,9 @@ extern const int si_SEGV_MAPERR; extern const int si_SEGV_ACCERR; + +extern const unsigned SHA1_CTX_sz; +extern const unsigned SHA1_return_length; } // namespace __sanitizer #define CHECK_TYPE_SIZE(TYPE) \ Index: lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -2101,6 +2101,9 @@ const int modctl_unload = MODCTL_UNLOAD; const int modctl_stat = MODCTL_STAT; const int modctl_exists = MODCTL_EXISTS; + +const unsigned SHA1_CTX_sz = sizeof(SHA1_CTX); +const unsigned SHA1_return_length = SHA1_DIGEST_STRING_LENGTH; } // namespace __sanitizer using namespace __sanitizer; Index: test/sanitizer_common/TestCases/NetBSD/sha1.cc =================================================================== --- test/sanitizer_common/TestCases/NetBSD/sha1.cc +++ test/sanitizer_common/TestCases/NetBSD/sha1.cc @@ -0,0 +1,171 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include + +void test1() { + SHA1_CTX ctx; + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + uint8_t digest[SHA1_DIGEST_LENGTH]; + + SHA1Init(&ctx); + SHA1Update(&ctx, entropy, __arraycount(entropy)); + SHA1Final(digest, &ctx); + + printf("test1: '"); + for (size_t i = 0; i < __arraycount(digest); i++) + printf("%02x", digest[i]); + printf("'\n"); +} + +void local_SHA1Update(SHA1_CTX *context, const uint8_t *data, unsigned int len) +{ + unsigned int a, b; + + b = context->count[0]; + context->count[0] += len << 3; + if (context->count[0] < b) + context->count[1] += (len >> 29) + 1; + b = (b >> 3) & 63; + if ((b + len) > 63) { + memcpy(&context->buffer[b], data, (a = 64 - b)); + SHA1Transform(context->state, context->buffer); + for ( ; a + 63 < len; a += 64) + SHA1Transform(context->state, &data[a]); + b = 0; + } else { + a = 0; + } + memcpy(&context->buffer[b], &data[a], len - a); +} + +void test2() { + SHA1_CTX ctx; + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + uint8_t digest[SHA1_DIGEST_LENGTH]; + + SHA1Init(&ctx); + local_SHA1Update(&ctx, entropy, __arraycount(entropy)); + SHA1Final(digest, &ctx); + + printf("test2: '"); + for (size_t i = 0; i < __arraycount(digest); i++) + printf("%02x", digest[i]); + printf("'\n"); +} + +void test3() { + SHA1_CTX ctx; + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + char digest[SHA1_DIGEST_STRING_LENGTH]; + + SHA1Init(&ctx); + SHA1Update(&ctx, entropy, __arraycount(entropy)); + char *p = SHA1End(&ctx, digest); + assert(p == digest); + + printf("test3: '%s'\n", digest); +} + +void test4() { + SHA1_CTX ctx; + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + + SHA1Init(&ctx); + SHA1Update(&ctx, entropy, __arraycount(entropy)); + char *p = SHA1End(&ctx, NULL); + assert(strlen(p) == SHA1_DIGEST_STRING_LENGTH - 1); + + printf("test4: '%s'\n", p); + + free(p); +} + +void test5() { + char digest[SHA1_DIGEST_STRING_LENGTH]; + + char *p = SHA1File("/etc/fstab", digest); + assert(p == digest); + + printf("test5: '%s'\n", p); +} + +void test6() { + char *p = SHA1File("/etc/fstab", NULL); + assert(strlen(p) == SHA1_DIGEST_STRING_LENGTH - 1); + + printf("test6: '%s'\n", p); + + free(p); +} + +void test7() { + char digest[SHA1_DIGEST_STRING_LENGTH]; + + char *p = SHA1FileChunk("/etc/fstab", digest, 10, 20); + assert(p == digest); + + printf("test7: '%s'\n", p); +} + +void test8() { + char *p = SHA1FileChunk("/etc/fstab", NULL, 10, 20); + assert(strlen(p) == SHA1_DIGEST_STRING_LENGTH - 1); + + printf("test8: '%s'\n", p); + + free(p); +} + +void test9() { + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + char digest[SHA1_DIGEST_STRING_LENGTH]; + + char *p = SHA1Data(entropy, __arraycount(entropy), digest); + assert(p == digest); + + printf("test9: '%s'\n", p); +} + +void test10() { + uint8_t entropy[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + + char *p = SHA1Data(entropy, __arraycount(entropy), NULL); + assert(strlen(p) == SHA1_DIGEST_STRING_LENGTH - 1); + + printf("test10: '%s'\n", p); + + free(p); +} + +int main(void) { + printf("SHA1\n"); + + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); + test9(); + test10(); + + // CHECK: SHA1 + // CHECK: test1: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + // CHECK: test2: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + // CHECK: test3: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + // CHECK: test4: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + // CHECK: test5: '{{.*}}' + // CHECK: test6: '{{.*}}' + // CHECK: test7: '{{.*}}' + // CHECK: test8: '{{.*}}' + // CHECK: test9: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + // CHECK: test10: '57d1b759bf3d1811135748cb0328c73b51fa6f57' + + return 0; +}