From 024d8a1340caad92c1ac44f4f7f7ad554a066937 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 10:26:05 +0200 Subject: [PATCH 1/9] Add `LTC_ALIGN_BUF()` Signed-off-by: Steffen Jaeckel --- demos/gcm-file/gcm_filehandle.c | 4 +--- src/encauth/gcm/gcm_memory.c | 4 +--- src/headers/tomcrypt_cfg.h | 2 +- src/headers/tomcrypt_private.h | 21 +++++++++++++++++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/demos/gcm-file/gcm_filehandle.c b/demos/gcm-file/gcm_filehandle.c index 11c55a62b..6065f966d 100644 --- a/demos/gcm-file/gcm_filehandle.c +++ b/demos/gcm-file/gcm_filehandle.c @@ -98,9 +98,7 @@ int gcm_filehandle( int cipher, * but again it's only for SSE2 anyways, so who cares? */ #ifdef LTC_GCM_TABLES_SSE2 - if ((unsigned long)gcm & 15) { - gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15))); - } + gcm = LTC_ALIGN_BUF(gcm, 16); #endif if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { diff --git a/src/encauth/gcm/gcm_memory.c b/src/encauth/gcm/gcm_memory.c index 4da5d5423..6de0b3092 100644 --- a/src/encauth/gcm/gcm_memory.c +++ b/src/encauth/gcm/gcm_memory.c @@ -70,9 +70,7 @@ int gcm_memory( int cipher, * but again it's only for SSE2 anyways, so who cares? */ #ifdef LTC_GCM_TABLES_SSE2 - if ((unsigned long)gcm & 15) { - gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15))); - } + gcm = LTC_ALIGN_BUF(gcm, 16); #endif if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { diff --git a/src/headers/tomcrypt_cfg.h b/src/headers/tomcrypt_cfg.h index 35af30083..3d90d03cc 100644 --- a/src/headers/tomcrypt_cfg.h +++ b/src/headers/tomcrypt_cfg.h @@ -209,7 +209,7 @@ LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); typedef unsigned __int64 ulong64; typedef __int64 long64; #else - #define CONST64(n) n ## ULL + #define CONST64(n) n ## uLL typedef unsigned long long ulong64; typedef long long long64; #endif diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index aa251e2ac..041bdd639 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -6,9 +6,30 @@ /* * Internal Macros */ +/* Static assertion */ +#define LTC_STATIC_ASSERT(msg, cond) typedef char ltc_static_assert_##msg[(cond) ? 1 : -1]; #define LTC_PAD_MASK (0xF000U) +#if defined(ENDIAN_64BITWORD) + #define CONSTPTR(n) CONST64(n) +#else + #define CONSTPTR(n) n ## uL +#endif + +LTC_STATIC_ASSERT(correct_CONSTPTR_size, sizeof(CONSTPTR(1)) == sizeof(void*)) + +/* Poor-man's `uintptr_t` since we can't use stdint.h + * c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */ +typedef size_t ltc_uintptr; + +LTC_STATIC_ASSERT(correct_ltc_uintptr_size, sizeof(ltc_uintptr) == sizeof(void*)) + +/* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address. + * Make sure that the buffer that is passed is huge enough. + */ +#define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&((unsigned char*)(buf))[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1))))) + /* `NULL` as defined by the standard is not guaranteed to be of a pointer * type. In order to make sure that in vararg API's a pointer type is used, * define our own version and use that one internally. From 1c36997bd0b8b2483a0187b9122cbe0a9021de16 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 2 Oct 2023 10:24:33 +0200 Subject: [PATCH 2/9] Ensure that AES key is always correctly aligned Aligning a `struct` member via `attribute(align())` is not guaranteed to work. Change the approach to use an opaque buffer and always manually align the start pointers of the keys. c.f. https://github.com/DCIT/perl-CryptX/issues/95 Signed-off-by: Steffen Jaeckel --- src/ciphers/aes/aes.c | 6 +++++- src/ciphers/aes/aesni.c | 6 +++++- src/headers/tomcrypt_cipher.h | 5 +++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ciphers/aes/aes.c b/src/ciphers/aes/aes.c index 0f46b748a..3a5d0dbb8 100644 --- a/src/ciphers/aes/aes.c +++ b/src/ciphers/aes/aes.c @@ -96,7 +96,7 @@ static ulong32 setup_mix2(ulong32 temp) int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int i; - ulong32 temp, *rk; + ulong32 temp, *rk, *K; #ifndef ENCRYPT_ONLY ulong32 *rrk; #endif @@ -112,6 +112,10 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s } skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; + K = LTC_ALIGN_BUF(skey->rijndael.K, 16); + skey->rijndael.eK = K; + K += 60; + skey->rijndael.dK = K; /* setup the forward key */ i = 0; diff --git a/src/ciphers/aes/aesni.c b/src/ciphers/aes/aesni.c index 6f98779ec..113aaf676 100644 --- a/src/ciphers/aes/aesni.c +++ b/src/ciphers/aes/aesni.c @@ -46,7 +46,7 @@ int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_ { int i; __m128i temp; - ulong32 *rk; + ulong32 *rk, *K; ulong32 *rrk; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); @@ -60,6 +60,10 @@ int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_ } skey->rijndael.Nr = keylen / 4 + 6; + K = LTC_ALIGN_BUF(skey->rijndael.K, 16); + skey->rijndael.eK = K; + K += 60; + skey->rijndael.dK = K; /* setup the forward key */ i = 0; diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h index aba28a271..06e612474 100644 --- a/src/headers/tomcrypt_cipher.h +++ b/src/headers/tomcrypt_cipher.h @@ -35,9 +35,10 @@ struct saferp_key { #ifdef LTC_RIJNDAEL struct rijndael_key { - ulong32 eK[60] LTC_ALIGN(16); - ulong32 dK[60] LTC_ALIGN(16); + ulong32 *eK; + ulong32 *dK; int Nr; + unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; }; #endif From d3a297c341a8329d503627e3378acaa50c6c0587 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 4 Oct 2023 14:53:34 +0200 Subject: [PATCH 3/9] Add option to disable AES-NI at compile time One can now define `LTC_NO_AES_NI` to disable AES-NI. Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_custom.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 8575c1cc8..129f0245f 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -179,7 +179,9 @@ #define LTC_RC6 #define LTC_SAFERP #define LTC_RIJNDAEL -#define LTC_AES_NI +#ifndef LTC_NO_AES_NI + #define LTC_AES_NI +#endif #define LTC_XTEA /* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ From c48673234c03e5226c767ed54bd55a15290aecac Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 4 Oct 2023 15:33:13 +0200 Subject: [PATCH 4/9] Always determine manually whether CC is clang This is required 1. when cross-compiling 2. to enable/disable the specific compiler warnings Tested on `bash`, `dash`, `zsh` and FreeBSD `sh`. Signed-off-by: Steffen Jaeckel --- makefile_include.mk | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/makefile_include.mk b/makefile_include.mk index f933b36b6..e4e7ad34a 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -13,16 +13,15 @@ ifndef CROSS_COMPILE CROSS_COMPILE:= endif -# We only need to go through this dance of determining the right compiler if we're using -# cross compilation, otherwise $(CC) is fine as-is. +ifneq (,$(shell printf "#ifdef __clang__\nCLANG\n#endif\n" | $(CC) -E - | grep CLANG)) + CC_IS_CLANG := 1 +else + CC_IS_CLANG := 0 +endif # Clang + ifneq (,$(CROSS_COMPILE)) ifeq ($(origin CC),default) -CSTR := "\#ifdef __clang__\nCLANG\n\#endif\n" -ifeq ($(PLATFORM),FreeBSD) - # XXX: FreeBSD needs extra escaping for some reason - CSTR := $$$(CSTR) -endif -ifneq (,$(shell echo $(CSTR) | $(CC) -E - | grep CLANG)) +ifeq ($(CC_IS_CLANG), 1) CC := $(CROSS_COMPILE)clang else CC := $(CROSS_COMPILE)gcc @@ -124,7 +123,7 @@ LTC_CFLAGS += -Os -DLTC_SMALL_CODE endif # LTC_SMALL -ifneq ($(findstring clang,$(CC)),) +ifeq ($(CC_IS_CLANG), 1) LTC_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header LTC_CFLAGS += -Wno-missing-field-initializers -Wno-missing-braces -Wno-incomplete-setjmp-declaration -Wno-cast-align LTC_CFLAGS += -Wno-declaration-after-statement From 7aaa8ebe198a2d82152b2933751c7a07982f4f71 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 10:24:38 +0200 Subject: [PATCH 5/9] Re-order struct members In order to memory-align the used buffers for keys, IVs etc. we re-order the struct members of ciphers, modes and encauth. There's no guarantee that this works, but it improves the chances. Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_cipher.h | 72 +++++++++++++++++------------------ src/headers/tomcrypt_mac.h | 29 +++++++------- 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h index 06e612474..8b6f8781f 100644 --- a/src/headers/tomcrypt_cipher.h +++ b/src/headers/tomcrypt_cipher.h @@ -35,10 +35,10 @@ struct saferp_key { #ifdef LTC_RIJNDAEL struct rijndael_key { + unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; ulong32 *eK; ulong32 *dK; int Nr; - unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; }; #endif @@ -129,24 +129,24 @@ struct khazad_key { #ifdef LTC_ANUBIS struct anubis_key { - int keyBits; - int R; ulong32 roundKeyEnc[18 + 1][4]; ulong32 roundKeyDec[18 + 1][4]; + int keyBits; + int R; }; #endif #ifdef LTC_MULTI2 struct multi2_key { - int N; ulong32 uk[8]; + int N; }; #endif #ifdef LTC_CAMELLIA struct camellia_key { - int R; ulong64 kw[4], k[24], kl[6]; + int R; }; #endif @@ -247,60 +247,60 @@ typedef union Symmetric_key { #ifdef LTC_ECB_MODE /** A block cipher ECB structure */ typedef struct { + /** The scheduled key */ + symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen; - /** The scheduled key */ - symmetric_key key; } symmetric_ECB; #endif #ifdef LTC_CFB_MODE /** A block cipher CFB structure */ typedef struct { - /** The index of the cipher chosen */ - int cipher, - /** The block size of the given cipher */ - blocklen, - /** The padding offset */ - padlen; /** The current IV */ unsigned char IV[MAXBLOCKSIZE], /** The pad used to encrypt/decrypt */ pad[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; } symmetric_CFB; #endif #ifdef LTC_OFB_MODE /** A block cipher OFB structure */ typedef struct { + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE]; - /** The scheduled key */ - symmetric_key key; } symmetric_OFB; #endif #ifdef LTC_CBC_MODE /** A block cipher CBC structure */ typedef struct { - /** The index of the cipher chosen */ - int cipher, - /** The block size of the given cipher */ - blocklen; /** The current IV */ unsigned char IV[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; } symmetric_CBC; #endif @@ -308,6 +308,13 @@ typedef struct { #ifdef LTC_CTR_MODE /** A block cipher CTR structure */ typedef struct { + /** The counter */ + unsigned char ctr[MAXBLOCKSIZE]; + /** The pad used to encrypt/decrypt */ + unsigned char pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; + /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ @@ -318,13 +325,6 @@ typedef struct { mode, /** counter width */ ctrlen; - - /** The counter */ - unsigned char ctr[MAXBLOCKSIZE]; - /** The pad used to encrypt/decrypt */ - unsigned char pad[MAXBLOCKSIZE] LTC_ALIGN(16); - /** The scheduled key */ - symmetric_key key; } symmetric_CTR; #endif @@ -332,9 +332,6 @@ typedef struct { #ifdef LTC_LRW_MODE /** A LRW structure */ typedef struct { - /** The index of the cipher chosen (must be a 128-bit block cipher) */ - int cipher; - /** The current IV */ unsigned char IV[16], @@ -351,25 +348,28 @@ typedef struct { /** The pre-computed multiplication table */ unsigned char PC[16][256][16]; #endif + + /** The index of the cipher chosen (must be a 128-bit block cipher) */ + int cipher; } symmetric_LRW; #endif #ifdef LTC_F8_MODE /** A block cipher F8 structure */ typedef struct { + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + MIV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen; - /** The current IV */ - unsigned char IV[MAXBLOCKSIZE], - MIV[MAXBLOCKSIZE]; /** Current block count */ ulong32 blockcnt; - /** The scheduled key */ - symmetric_key key; } symmetric_F8; #endif diff --git a/src/headers/tomcrypt_mac.h b/src/headers/tomcrypt_mac.h index c8f4a3227..f6738f697 100644 --- a/src/headers/tomcrypt_mac.h +++ b/src/headers/tomcrypt_mac.h @@ -358,10 +358,10 @@ typedef struct { unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */ aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */ adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */ - int adata_buffer_bytes; /* bytes in AAD buffer */ - unsigned long ablock_index; /* index # for current adata (AAD) block */ symmetric_key key; /* scheduled key for cipher */ + int adata_buffer_bytes; /* bytes in AAD buffer */ + unsigned long ablock_index; /* index # for current adata (AAD) block */ unsigned long block_index; /* index # for current data block */ int cipher, /* cipher idx */ tag_len, /* length of tag */ @@ -407,7 +407,12 @@ int ocb3_test(void); #define CCM_DECRYPT LTC_DECRYPT typedef struct { + unsigned char PAD[16], /* flags | Nonce N | l(m) */ + ctr[16], + CTRPAD[16]; + symmetric_key K; + int cipher, /* which cipher */ taglen, /* length of the tag (encoded in M value) */ x; /* index in PAD */ @@ -419,10 +424,7 @@ typedef struct { current_aadlen, /* length of the currently provided add */ noncelen; /* length of the nonce */ - unsigned char PAD[16], /* flags | Nonce N | l(m) */ - ctr[16], - CTRPAD[16], - CTRlen; + unsigned char CTRlen; } ccm_state; int ccm_init(ccm_state *ccm, int cipher, @@ -478,13 +480,18 @@ extern const unsigned char gcm_shift_table[]; #define LTC_GCM_MODE_TEXT 2 typedef struct { - symmetric_key K; unsigned char H[16], /* multiplier */ X[16], /* accumulator */ Y[16], /* counter */ Y_0[16], /* initial counter */ buf[16]; /* buffer for stuff */ +#ifdef LTC_GCM_TABLES + unsigned char PC[16][256][16]; /* 16 tables of 8x128 */ +#endif + + symmetric_key K; + int cipher, /* which cipher */ ivmode, /* Which mode is the IV in? */ mode, /* mode the GCM code is in */ @@ -492,14 +499,6 @@ typedef struct { ulong64 totlen, /* 64-bit counter used for IV and AAD */ pttotlen; /* 64-bit counter for the PT */ - -#ifdef LTC_GCM_TABLES - unsigned char PC[16][256][16] /* 16 tables of 8x128 */ -#ifdef LTC_GCM_TABLES_SSE2 -LTC_ALIGN(16) -#endif -; -#endif } gcm_state; void gcm_mult_h(const gcm_state *gcm, unsigned char *I); From 97edea362a34cb89b0e83bb503bde9e13ae817ba Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 10:42:18 +0200 Subject: [PATCH 6/9] Fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` src/encauth/ccm/ccm_memory.c: In function ‘ccm_memory’: src/encauth/ccm/ccm_memory.c:164:17: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 164 | PAD[x++] = (unsigned char)((len >> 24) & 255); | ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/encauth/ccm/ccm_memory.c:43:19: note: at offset 16 into destination object ‘PAD’ of size 16 43 | unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real; | ^~~ ``` Multiple reviews and tests determined that this can't happen, but most likely computers are better in finding out such stuff (or it was a false positive). Signed-off-by: Steffen Jaeckel --- src/encauth/ccm/ccm_memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/encauth/ccm/ccm_memory.c b/src/encauth/ccm/ccm_memory.c index fdb5172e0..45951ff93 100644 --- a/src/encauth/ccm/ccm_memory.c +++ b/src/encauth/ccm/ccm_memory.c @@ -161,6 +161,9 @@ int ccm_memory(int cipher, PAD[x++] = 0; } for (; y < L; y++) { + if (x >= sizeof(PAD)) { + return CRYPT_INVALID_ARG; + } PAD[x++] = (unsigned char)((len >> 24) & 255); len <<= 8; } From d9b25936fb7437210575e2203bb9550ab52281c0 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 10:53:06 +0200 Subject: [PATCH 7/9] Fix CMake with MSVC Reported by @pineappleiceberg in [0] [0] https://github.com/libtom/libtomcrypt/issues/577#issuecomment-1722545061 Signed-off-by: Steffen Jaeckel --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index eeb857754..eb40d2854 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,9 @@ include(CheckIPOSupported) include(CMakePackageConfigHelpers) # for potential builds against gnump include(FindPkgConfig) +# for potential builds with MSVC +include(CMakePushCheckState) +include(CheckSymbolExists) # default is "No tests" option(BUILD_TESTING "" OFF) include(CTest) From 124e020437715b0d2647ed12632fa10e2cfe9234 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 11:04:22 +0200 Subject: [PATCH 8/9] Add missing package name suffix to CMake/CPack Fixes e98e0a64e69716e069604c3f95f1e5070bbea842 Signed-off-by: Steffen Jaeckel --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb40d2854..b28ca0b9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,6 +300,15 @@ else() set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/) endif() +# make sure untagged versions get a different package name +execute_process(COMMAND git describe --exact-match --tags ERROR_QUIET RESULT_VARIABLE REPO_HAS_TAG) +if(REPO_HAS_TAG EQUAL 0) + set(PACKAGE_NAME_SUFFIX "") +else() + set(PACKAGE_NAME_SUFFIX "-git") + message(STATUS "Use -git suffix") +endif() + # default CPack generators set(CPACK_GENERATOR TGZ STGZ) From e4adaafd908ab04c00b77073b716f49fd5a67676 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 5 Oct 2023 12:34:33 +0200 Subject: [PATCH 9/9] Fix make incompatibility Since make version 4.3 [0] the `#` sign inside a string is handled differently. Fix that. [0] https://lists.gnu.org/archive/html/info-gnu/2020-01/msg00004.html Signed-off-by: Steffen Jaeckel --- makefile_include.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile_include.mk b/makefile_include.mk index e4e7ad34a..f76798c41 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -13,7 +13,8 @@ ifndef CROSS_COMPILE CROSS_COMPILE:= endif -ifneq (,$(shell printf "#ifdef __clang__\nCLANG\n#endif\n" | $(CC) -E - | grep CLANG)) +H := \# +ifeq (CLANG,$(shell printf "$(H)ifdef __clang__\nCLANG\n$(H)endif\n" | $(CC) -E - | grep CLANG)) CC_IS_CLANG := 1 else CC_IS_CLANG := 0