Blame SOURCES/0056-strcasecmp.patch

021e03
diff --git a/apps/ca.c b/apps/ca.c
021e03
index 24883615ed6b..8a2b31579549 100644
021e03
--- a/apps/ca.c
021e03
+++ b/apps/ca.c
021e03
@@ -2367,7 +2367,7 @@ static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg)
021e03
 
021e03
     case REV_CRL_REASON:
021e03
         for (i = 0; i < 8; i++) {
021e03
-            if (strcasecmp(rev_arg, crl_reasons[i]) == 0) {
021e03
+            if (OPENSSL_strcasecmp(rev_arg, crl_reasons[i]) == 0) {
021e03
                 reason = crl_reasons[i];
021e03
                 break;
021e03
             }
021e03
@@ -2584,7 +2584,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
021e03
     }
021e03
     if (reason_str) {
021e03
         for (i = 0; i < NUM_REASONS; i++) {
021e03
-            if (strcasecmp(reason_str, crl_reasons[i]) == 0) {
021e03
+            if (OPENSSL_strcasecmp(reason_str, crl_reasons[i]) == 0) {
021e03
                 reason_code = i;
021e03
                 break;
021e03
             }
021e03
diff --git a/apps/cmp.c b/apps/cmp.c
021e03
index 9ea5cee4124d..5c6bcdad0a64 100644
021e03
--- a/apps/cmp.c
021e03
+++ b/apps/cmp.c
021e03
@@ -1745,7 +1745,7 @@ static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
021e03
     valptr[0] = '\0';
021e03
     valptr++;
021e03
 
021e03
-    if (strncasecmp(valptr, "int:", 4) != 0) {
021e03
+    if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) {
021e03
         CMP_err("missing 'int:' in -geninfo option");
021e03
         return 0;
021e03
     }
021e03
diff --git a/apps/ecparam.c b/apps/ecparam.c
021e03
index 12eed703de69..ecce36be71a2 100644
021e03
--- a/apps/ecparam.c
021e03
+++ b/apps/ecparam.c
021e03
@@ -229,7 +229,7 @@ int ecparam_main(int argc, char **argv)
021e03
                        point_format, 0);
021e03
         *p = OSSL_PARAM_construct_end();
021e03
 
021e03
-        if (strcasecmp(curve_name, "SM2") == 0)
021e03
+        if (OPENSSL_strcasecmp(curve_name, "SM2") == 0)
021e03
             gctx_params = EVP_PKEY_CTX_new_from_name(NULL, "sm2", NULL);
021e03
         else
021e03
             gctx_params = EVP_PKEY_CTX_new_from_name(NULL, "ec", NULL);
021e03
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
021e03
index 30da6e8a8cb8..227da4982d14 100644
021e03
--- a/apps/lib/apps.c
021e03
+++ b/apps/lib/apps.c
021e03
@@ -688,8 +688,8 @@ int load_cert_certs(const char *uri,
021e03
     int ret = 0;
021e03
     char *pass_string;
021e03
 
021e03
-    if (exclude_http && (strncasecmp(uri, "http://", 7) == 0
021e03
-                         || strncasecmp(uri, "https://", 8) == 0)) {
021e03
+    if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0
021e03
+                         || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) {
021e03
         BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
021e03
         return ret;
021e03
     }
021e03
@@ -1182,20 +1182,20 @@ int set_name_ex(unsigned long *flags, const char *arg)
021e03
 
021e03
 int set_dateopt(unsigned long *dateopt, const char *arg)
021e03
 {
021e03
-    if (strcasecmp(arg, "rfc_822") == 0)
021e03
+    if (OPENSSL_strcasecmp(arg, "rfc_822") == 0)
021e03
         *dateopt = ASN1_DTFLGS_RFC822;
021e03
-    else if (strcasecmp(arg, "iso_8601") == 0)
021e03
+    else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0)
021e03
         *dateopt = ASN1_DTFLGS_ISO8601;
021e03
     return 0;
021e03
 }
021e03
 
021e03
 int set_ext_copy(int *copy_type, const char *arg)
021e03
 {
021e03
-    if (strcasecmp(arg, "none") == 0)
021e03
+    if (OPENSSL_strcasecmp(arg, "none") == 0)
021e03
         *copy_type = EXT_COPY_NONE;
021e03
-    else if (strcasecmp(arg, "copy") == 0)
021e03
+    else if (OPENSSL_strcasecmp(arg, "copy") == 0)
021e03
         *copy_type = EXT_COPY_ADD;
021e03
-    else if (strcasecmp(arg, "copyall") == 0)
021e03
+    else if (OPENSSL_strcasecmp(arg, "copyall") == 0)
021e03
         *copy_type = EXT_COPY_ALL;
021e03
     else
021e03
         return 0;
021e03
@@ -1275,7 +1275,7 @@ static int set_table_opts(unsigned long *flags, const char *arg,
021e03
     }
021e03
 
021e03
     for (ptbl = in_tbl; ptbl->name; ptbl++) {
021e03
-        if (strcasecmp(arg, ptbl->name) == 0) {
021e03
+        if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) {
021e03
             *flags &= ~ptbl->mask;
021e03
             if (c)
021e03
                 *flags |= ptbl->flag;
021e03
diff --git a/apps/lib/engine_loader.c b/apps/lib/engine_loader.c
021e03
index c093f31e1b39..42775a89f361 100644
021e03
--- a/apps/lib/engine_loader.c
021e03
+++ b/apps/lib/engine_loader.c
021e03
@@ -71,7 +71,7 @@ static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
021e03
     char *keyid = NULL;
021e03
     OSSL_STORE_LOADER_CTX *ctx = NULL;
021e03
 
021e03
-    if (strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1)
021e03
+    if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1)
021e03
         != 0)
021e03
         return NULL;
021e03
     p += sizeof(ENGINE_SCHEME_COLON) - 1;
021e03
diff --git a/apps/lib/http_server.c b/apps/lib/http_server.c
021e03
index 03faac7707b7..df9575e2cd21 100644
021e03
--- a/apps/lib/http_server.c
021e03
+++ b/apps/lib/http_server.c
021e03
@@ -453,10 +453,11 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq,
021e03
         }
021e03
         *line_end = '\0';
021e03
         /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
021e03
-        if (found_keep_alive != NULL && strcasecmp(key, "Connection") == 0) {
021e03
-            if (strcasecmp(value, "keep-alive") == 0)
021e03
+        if (found_keep_alive != NULL
021e03
+            && OPENSSL_strcasecmp(key, "Connection") == 0) {
021e03
+            if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
021e03
                 *found_keep_alive = 1;
021e03
-            else if (strcasecmp(value, "close") == 0)
021e03
+            else if (OPENSSL_strcasecmp(value, "close") == 0)
021e03
                 *found_keep_alive = 0;
021e03
         }
021e03
     }
021e03
diff --git a/apps/lib/names.c b/apps/lib/names.c
021e03
index 5e2e7e147c7f..462703c6462b 100644
021e03
--- a/apps/lib/names.c
021e03
+++ b/apps/lib/names.c
021e03
@@ -11,14 +11,11 @@
021e03
 #include <openssl/bio.h>
021e03
 #include <openssl/safestack.h>
021e03
 #include "names.h"
021e03
-
021e03
-#ifdef _WIN32
021e03
-# define strcasecmp _stricmp
021e03
-#endif
021e03
+#include "openssl/crypto.h"
021e03
 
021e03
 int name_cmp(const char * const *a, const char * const *b)
021e03
 {
021e03
-    return strcasecmp(*a, *b);
021e03
+    return OPENSSL_strcasecmp(*a, *b);
021e03
 }
021e03
 
021e03
 void collect_names(const char *name, void *vdata)
021e03
diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c
021e03
index 1b27699b9d49..4d9a69b29e03 100644
021e03
--- a/apps/lib/vms_term_sock.c
021e03
+++ b/apps/lib/vms_term_sock.c
021e03
@@ -132,7 +132,7 @@ int main (int argc, char *argv[], char *envp[])
021e03
         len;
021e03
 
021e03
     LogMessage ("Enter 'q' or 'Q' to quit ...");
021e03
-    while (strcasecmp (TermBuff, "Q")) {
021e03
+    while (OPENSSL_strcasecmp (TermBuff, "Q")) {
021e03
         /*
021e03
         ** Create the terminal socket
021e03
         */
021e03
diff --git a/apps/list.c b/apps/list.c
021e03
index 9732d6625a05..620ce0083134 100644
021e03
--- a/apps/list.c
021e03
+++ b/apps/list.c
021e03
@@ -71,7 +71,7 @@ static void legacy_cipher_fn(const EVP_CIPHER *c,
021e03
 {
021e03
     if (select_name != NULL
021e03
         && (c == NULL
021e03
-            || strcasecmp(select_name,  EVP_CIPHER_get0_name(c)) != 0))
021e03
+            || OPENSSL_strcasecmp(select_name,  EVP_CIPHER_get0_name(c)) != 0))
021e03
         return;
021e03
     if (c != NULL) {
021e03
         BIO_printf(arg, "  %s\n", EVP_CIPHER_get0_name(c));
021e03
@@ -370,7 +370,7 @@ DEFINE_STACK_OF(EVP_RAND)
021e03
 
021e03
 static int rand_cmp(const EVP_RAND * const *a, const EVP_RAND * const *b)
021e03
 {
021e03
-    int ret = strcasecmp(EVP_RAND_get0_name(*a), EVP_RAND_get0_name(*b));
021e03
+    int ret = OPENSSL_strcasecmp(EVP_RAND_get0_name(*a), EVP_RAND_get0_name(*b));
021e03
 
021e03
     if (ret == 0)
021e03
         ret = strcmp(OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*a)),
021e03
@@ -404,7 +404,7 @@ static void list_random_generators(void)
021e03
         const EVP_RAND *m = sk_EVP_RAND_value(rands, i);
021e03
 
021e03
         if (select_name != NULL
021e03
-            && strcasecmp(EVP_RAND_get0_name(m), select_name) != 0)
021e03
+            && OPENSSL_strcasecmp(EVP_RAND_get0_name(m), select_name) != 0)
021e03
             continue;
021e03
         BIO_printf(bio_out, "  %s", EVP_RAND_get0_name(m));
021e03
         BIO_printf(bio_out, " @ %s\n",
021e03
@@ -463,7 +463,7 @@ static void display_random(const char *name, EVP_RAND_CTX *drbg)
021e03
         if (gettables != NULL)
021e03
             for (; gettables->key != NULL; gettables++) {
021e03
                 /* State has been dealt with already, so ignore */
021e03
-                if (strcasecmp(gettables->key, OSSL_RAND_PARAM_STATE) == 0)
021e03
+                if (OPENSSL_strcasecmp(gettables->key, OSSL_RAND_PARAM_STATE) == 0)
021e03
                     continue;
021e03
                 /* Outside of verbose mode, we skip non-string values */
021e03
                 if (gettables->data_type != OSSL_PARAM_UTF8_STRING
021e03
diff --git a/apps/rehash.c b/apps/rehash.c
021e03
index fb6c08c420ca..e4a4e14fd497 100644
021e03
--- a/apps/rehash.c
021e03
+++ b/apps/rehash.c
021e03
@@ -214,7 +214,7 @@ static int handle_symlink(const char *filename, const char *fullpath)
021e03
         return -1;
021e03
     for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) {
021e03
         const char *suffix = suffixes[type];
021e03
-        if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
021e03
+        if (OPENSSL_strncasecmp(suffix, &filename[i], strlen(suffix)) == 0)
021e03
             break;
021e03
     }
021e03
     i += strlen(suffixes[type]);
021e03
@@ -249,7 +249,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
021e03
     if ((ext = strrchr(filename, '.')) == NULL)
021e03
         goto end;
021e03
     for (i = 0; i < OSSL_NELEM(extensions); i++) {
021e03
-        if (strcasecmp(extensions[i], ext + 1) == 0)
021e03
+        if (OPENSSL_strcasecmp(extensions[i], ext + 1) == 0)
021e03
             break;
021e03
     }
021e03
     if (i >= OSSL_NELEM(extensions))
021e03
diff --git a/apps/s_server.c b/apps/s_server.c
021e03
index ccaec3124bf4..e93cfa1e2c7a 100644
021e03
--- a/apps/s_server.c
021e03
+++ b/apps/s_server.c
021e03
@@ -432,7 +432,7 @@ static int ssl_servername_cb(SSL *s, int *ad, void *arg)
021e03
         return SSL_TLSEXT_ERR_NOACK;
021e03
 
021e03
     if (servername != NULL) {
021e03
-        if (strcasecmp(servername, p->servername))
021e03
+        if (OPENSSL_strcasecmp(servername, p->servername))
021e03
             return p->extension_error;
021e03
         if (ctx2 != NULL) {
021e03
             BIO_printf(p->biodebug, "Switching server context.\n");
021e03
diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c
021e03
index ddf68b576f88..fe9fc0dd43ba 100644
021e03
--- a/crypto/LPdir_unix.c
021e03
+++ b/crypto/LPdir_unix.c
021e03
@@ -141,7 +141,8 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
021e03
             p--;
021e03
         if (p > (*ctx)->entry_name && p[-1] == ';')
021e03
             p[-1] = '\0';
021e03
-        if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0)
021e03
+        if (OPENSSL_strcasecmp((*ctx)->entry_name,
021e03
+                               (*ctx)->previous_entry_name) == 0)
021e03
             goto again;
021e03
     }
021e03
 #endif
021e03
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
021e03
index 031a6c936ad1..0de5785c2745 100644
021e03
--- a/crypto/asn1/ameth_lib.c
021e03
+++ b/crypto/asn1/ameth_lib.c
021e03
@@ -10,7 +10,6 @@
021e03
 /* We need to use some engine deprecated APIs */
021e03
 #define OPENSSL_SUPPRESS_DEPRECATED
021e03
 
021e03
-#include "e_os.h"               /* for strncasecmp */
021e03
 #include "internal/cryptlib.h"
021e03
 #include <stdio.h>
021e03
 #include <openssl/asn1t.h>
021e03
@@ -134,7 +133,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
021e03
         if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
021e03
             continue;
021e03
         if ((int)strlen(ameth->pem_str) == len
021e03
-            && strncasecmp(ameth->pem_str, str, len) == 0)
021e03
+            && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
021e03
             return ameth;
021e03
     }
021e03
     return NULL;
021e03
diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c
021e03
index ecff2be02e1f..59d42daf4a1c 100644
021e03
--- a/crypto/asn1/asn1_gen.c
021e03
+++ b/crypto/asn1/asn1_gen.c
021e03
@@ -10,7 +10,6 @@
021e03
 #include "internal/cryptlib.h"
021e03
 #include <openssl/asn1.h>
021e03
 #include <openssl/x509v3.h>
021e03
-#include "e_os.h" /* strncasecmp() */
021e03
 
021e03
 #define ASN1_GEN_FLAG           0x10000
021e03
 #define ASN1_GEN_FLAG_IMP       (ASN1_GEN_FLAG|1)
021e03
@@ -565,7 +564,8 @@ static int asn1_str2tag(const char *tagstr, int len)
021e03
 
021e03
     tntmp = tnst;
021e03
     for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
021e03
-        if ((len == tntmp->len) && (strncasecmp(tntmp->strnam, tagstr, len) == 0))
021e03
+        if ((len == tntmp->len)
021e03
+            && (OPENSSL_strncasecmp(tntmp->strnam, tagstr, len) == 0))
021e03
             return tntmp->tag;
021e03
     }
021e03
 
021e03
diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
021e03
index c05c3c6b109d..6fe8427dc5e6 100644
021e03
--- a/crypto/conf/conf_def.c
021e03
+++ b/crypto/conf/conf_def.c
021e03
@@ -11,7 +11,7 @@
021e03
 
021e03
 #include <stdio.h>
021e03
 #include <string.h>
021e03
-#include "e_os.h" /* strcasecmp and struct stat */
021e03
+#include "e_os.h" /* struct stat */
021e03
 #ifdef __TANDEM
021e03
 # include <sys/types.h> /* needed for stat.h */
021e03
 # include <sys/stat.h> /* struct stat */
021e03
@@ -192,11 +192,11 @@ static int def_load(CONF *conf, const char *name, long *line)
021e03
 /* Parse a boolean value and fill in *flag. Return 0 on error. */
021e03
 static int parsebool(const char *pval, int *flag)
021e03
 {
021e03
-    if (strcasecmp(pval, "on") == 0
021e03
-            || strcasecmp(pval, "true") == 0) {
021e03
+    if (OPENSSL_strcasecmp(pval, "on") == 0
021e03
+            || OPENSSL_strcasecmp(pval, "true") == 0) {
021e03
         *flag = 1;
021e03
-    } else if (strcasecmp(pval, "off") == 0
021e03
-            || strcasecmp(pval, "false") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(pval, "off") == 0
021e03
+            || OPENSSL_strcasecmp(pval, "false") == 0) {
021e03
         *flag = 0;
021e03
     } else {
021e03
         ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA);
021e03
@@ -839,8 +839,10 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
021e03
         namelen = strlen(filename);
021e03
 
021e03
 
021e03
-        if ((namelen > 5 && strcasecmp(filename + namelen - 5, ".conf") == 0)
021e03
-            || (namelen > 4 && strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
021e03
+        if ((namelen > 5
021e03
+             && OPENSSL_strcasecmp(filename + namelen - 5, ".conf") == 0)
021e03
+             || (namelen > 4
021e03
+                 && OPENSSL_strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
021e03
             size_t newlen;
021e03
             char *newpath;
021e03
             BIO *bio;
021e03
diff --git a/crypto/context.c b/crypto/context.c
021e03
index 3333af4c534e..4fef24cadd5a 100644
021e03
--- a/crypto/context.c
021e03
+++ b/crypto/context.c
021e03
@@ -14,6 +14,7 @@
021e03
 #include "internal/core.h"
021e03
 #include "internal/bio.h"
021e03
 #include "internal/provider.h"
021e03
+#include "crypto/ctype.h"
021e03
 
021e03
 # include <sys/types.h>
021e03
 # include <sys/stat.h>
021e03
@@ -150,7 +151,8 @@ static CRYPTO_THREAD_LOCAL default_context_thread_local;
021e03
 {
021e03
 	 read_kernel_fips_flag();
021e03
     return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)
021e03
-        && context_init(&default_context_int);
021e03
+        && context_init(&default_context_int)
021e03
+        && ossl_init_casecmp();
021e03
 }
021e03
 
021e03
 void ossl_lib_ctx_default_deinit(void)
021e03
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
021e03
index 55248affc663..7e11ab1c8845 100644
021e03
--- a/crypto/core_namemap.c
021e03
+++ b/crypto/core_namemap.c
021e03
@@ -7,7 +7,6 @@
021e03
  * https://www.openssl.org/source/license.html
021e03
  */
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp */
021e03
 #include "internal/namemap.h"
021e03
 #include <openssl/lhash.h>
021e03
 #include "crypto/lhash.h"      /* ossl_lh_strcasehash */
021e03
@@ -49,7 +48,7 @@ static unsigned long namenum_hash(const NAMENUM_ENTRY *n)
021e03
 
021e03
 static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b)
021e03
 {
021e03
-    return strcasecmp(a->name, b->name);
021e03
+    return OPENSSL_strcasecmp(a->name, b->name);
021e03
 }
021e03
 
021e03
 static void namenum_free(NAMENUM_ENTRY *n)
021e03
diff --git a/crypto/ctype.c b/crypto/ctype.c
021e03
index 83c24a546f53..321306eb5f50 100644
021e03
--- a/crypto/ctype.c
021e03
+++ b/crypto/ctype.c
021e03
@@ -12,6 +12,19 @@
021e03
 #include "crypto/ctype.h"
021e03
 #include <openssl/ebcdic.h>
021e03
 
021e03
+#include <openssl/crypto.h>
021e03
+#include "internal/core.h"
021e03
+#include "internal/thread_once.h"
021e03
+
021e03
+#ifndef OPENSSL_SYS_WINDOWS
021e03
+#include <strings.h>
021e03
+#endif
021e03
+#include <locale.h>
021e03
+
021e03
+#ifdef OPENSSL_SYS_MACOSX
021e03
+#include <xlocale.h>
021e03
+#endif
021e03
+
021e03
 /*
021e03
  * Define the character classes for each character in the seven bit ASCII
021e03
  * character set.  This is independent of the host's character set, characters
021e03
@@ -278,3 +291,90 @@ int ossl_ascii_isdigit(const char inchar) {
021e03
         return 1;
021e03
     return 0;
021e03
 }
021e03
+
021e03
+/* str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
021e03
+ * https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */
021e03
+
021e03
+#if (defined OPENSSL_SYS_WINDOWS) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L)
021e03
+
021e03
+# if defined OPENSSL_SYS_WINDOWS
021e03
+# define locale_t _locale_t
021e03
+# define freelocale _free_locale
021e03
+# define strcasecmp_l _stricmp_l
021e03
+# define strncasecmp_l _strnicmp_l
021e03
+# endif
021e03
+
021e03
+# ifndef FIPS_MODULE
021e03
+static locale_t loc;
021e03
+
021e03
+static int locale_base_inited = 0;
021e03
+static CRYPTO_ONCE locale_base = CRYPTO_ONCE_STATIC_INIT;
021e03
+static CRYPTO_ONCE locale_base_deinit = CRYPTO_ONCE_STATIC_INIT;
021e03
+
021e03
+void *ossl_c_locale() {
021e03
+    return (void *)loc;
021e03
+}
021e03
+
021e03
+DEFINE_RUN_ONCE_STATIC(ossl_init_locale_base)
021e03
+{
021e03
+# ifdef OPENSSL_SYS_WINDOWS
021e03
+    loc = _create_locale(LC_COLLATE, "C");
021e03
+# else
021e03
+    loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
021e03
+# endif
021e03
+    locale_base_inited = 1;
021e03
+    return (loc == (locale_t) 0) ? 0 : 1;
021e03
+}
021e03
+
021e03
+DEFINE_RUN_ONCE_STATIC(ossl_deinit_locale_base)
021e03
+{
021e03
+    if (locale_base_inited && loc) {
021e03
+        freelocale(loc);
021e03
+        loc = NULL;
021e03
+    }
021e03
+    return 1;
021e03
+}
021e03
+
021e03
+int ossl_init_casecmp()
021e03
+{
021e03
+   return RUN_ONCE(&locale_base, ossl_init_locale_base);
021e03
+}
021e03
+
021e03
+void ossl_deinit_casecmp() {
021e03
+    (void)RUN_ONCE(&locale_base_deinit, ossl_deinit_locale_base);
021e03
+}
021e03
+# endif
021e03
+
021e03
+int OPENSSL_strcasecmp(const char *s1, const char *s2)
021e03
+{
021e03
+    return strcasecmp_l(s1, s2, (locale_t)ossl_c_locale());
021e03
+}
021e03
+
021e03
+int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
021e03
+{
021e03
+    return strncasecmp_l(s1, s2, n, (locale_t)ossl_c_locale());
021e03
+}
021e03
+#else
021e03
+# ifndef FIPS_MODULE
021e03
+void *ossl_c_locale() {
021e03
+    return NULL;
021e03
+}
021e03
+# endif
021e03
+
021e03
+int ossl_init_casecmp() {
021e03
+    return 1;
021e03
+}
021e03
+
021e03
+void ossl_deinit_casecmp() {
021e03
+}
021e03
+
021e03
+int OPENSSL_strcasecmp(const char *s1, const char *s2)
021e03
+{
021e03
+    return strcasecmp(s1, s2);
021e03
+}
021e03
+
021e03
+int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
021e03
+{
021e03
+    return strncasecmp(s1, s2, n);
021e03
+}
021e03
+#endif
021e03
diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c
021e03
index c71f4053da6c..7608cbae5a28 100644
021e03
--- a/crypto/dh/dh_group_params.c
021e03
+++ b/crypto/dh/dh_group_params.c
021e03
@@ -23,7 +23,6 @@
021e03
 #include <openssl/objects.h>
021e03
 #include "internal/nelem.h"
021e03
 #include "crypto/dh.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 static DH *dh_param_init(OSSL_LIB_CTX *libctx, const DH_NAMED_GROUP *group)
021e03
 {
021e03
diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c
021e03
index 381da71f33a8..0d84a3332296 100644
021e03
--- a/crypto/ec/ec_backend.c
021e03
+++ b/crypto/ec/ec_backend.c
021e03
@@ -54,7 +54,7 @@ int ossl_ec_encoding_name2id(const char *name)
021e03
         return OPENSSL_EC_NAMED_CURVE;
021e03
 
021e03
     for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
021e03
-        if (strcasecmp(name, encoding_nameid_map[i].ptr) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, encoding_nameid_map[i].ptr) == 0)
021e03
             return encoding_nameid_map[i].id;
021e03
     }
021e03
     return -1;
021e03
@@ -91,7 +91,7 @@ static int ec_check_group_type_name2id(const char *name)
021e03
         return 0;
021e03
 
021e03
     for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
021e03
-        if (strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
021e03
             return check_group_type_nameid_map[i].id;
021e03
     }
021e03
     return -1;
021e03
@@ -136,7 +136,7 @@ int ossl_ec_pt_format_name2id(const char *name)
021e03
         return (int)POINT_CONVERSION_UNCOMPRESSED;
021e03
 
021e03
     for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
021e03
-        if (strcasecmp(name, format_nameid_map[i].ptr) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, format_nameid_map[i].ptr) == 0)
021e03
             return format_nameid_map[i].id;
021e03
     }
021e03
     return -1;
021e03
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
021e03
index 2ee8284eaff3..ecd53fee008a 100644
021e03
--- a/crypto/ec/ec_lib.c
021e03
+++ b/crypto/ec/ec_lib.c
021e03
@@ -22,7 +22,6 @@
021e03
 #include "crypto/ec.h"
021e03
 #include "internal/nelem.h"
021e03
 #include "ec_local.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 /* functions for EC_GROUP objects */
021e03
 
021e03
@@ -1581,9 +1580,10 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
021e03
         ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
021e03
         goto err;
021e03
     }
021e03
-    if (strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
021e03
+    if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
021e03
         is_prime_field = 1;
021e03
-    } else if (strcasecmp(ptmp->data, SN_X9_62_characteristic_two_field) == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(ptmp->data,
021e03
+                                  SN_X9_62_characteristic_two_field) == 0) {
021e03
         is_prime_field = 0;
021e03
     } else {
021e03
         /* Invalid field */
021e03
diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c
021e03
index 10a38b6f82a7..de6d3def3101 100644
021e03
--- a/crypto/encode_decode/decoder_lib.c
021e03
+++ b/crypto/encode_decode/decoder_lib.c
021e03
@@ -789,7 +789,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
021e03
          */
021e03
         trace_data_structure = data_structure;
021e03
         if (data_type != NULL && data_structure != NULL
021e03
-            && strcasecmp(data_structure, "type-specific") == 0)
021e03
+            && OPENSSL_strcasecmp(data_structure, "type-specific") == 0)
021e03
             data_structure = NULL;
021e03
 
021e03
         OSSL_TRACE_BEGIN(DECODER) {
021e03
@@ -850,7 +850,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
021e03
          * that's the case, we do this extra check.
021e03
          */
021e03
         if (decoder == NULL && ctx->start_input_type != NULL
021e03
-            && strcasecmp(ctx->start_input_type, new_input_type) != 0) {
021e03
+            && OPENSSL_strcasecmp(ctx->start_input_type, new_input_type) != 0) {
021e03
             OSSL_TRACE_BEGIN(DECODER) {
021e03
                 BIO_printf(trc_out,
021e03
                            "(ctx %p) %s [%u] the start input type '%s' doesn't match the input type of the considered decoder, skipping...\n",
021e03
@@ -896,7 +896,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
021e03
          */
021e03
         if (data_structure != NULL
021e03
             && (new_input_structure == NULL
021e03
-                || strcasecmp(data_structure, new_input_structure) != 0)) {
021e03
+                || OPENSSL_strcasecmp(data_structure,
021e03
+                                      new_input_structure) != 0)) {
021e03
             OSSL_TRACE_BEGIN(DECODER) {
021e03
                 BIO_printf(trc_out,
021e03
                            "(ctx %p) %s [%u] the previous decoder's data structure doesn't match the input structure of the considered decoder, skipping...\n",
021e03
@@ -915,7 +916,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
021e03
             && ctx->input_structure != NULL
021e03
             && new_input_structure != NULL) {
021e03
             data->flag_input_structure_checked = 1;
021e03
-            if (strcasecmp(new_input_structure, ctx->input_structure) != 0) {
021e03
+            if (OPENSSL_strcasecmp(new_input_structure,
021e03
+                                   ctx->input_structure) != 0) {
021e03
                 OSSL_TRACE_BEGIN(DECODER) {
021e03
                     BIO_printf(trc_out,
021e03
                                "(ctx %p) %s [%u] the previous decoder's data structure doesn't match the input structure given by the user, skipping...\n",
021e03
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
021e03
index 475117a463af..833061d873ed 100644
021e03
--- a/crypto/encode_decode/decoder_pkey.c
021e03
+++ b/crypto/encode_decode/decoder_pkey.c
021e03
@@ -18,7 +18,6 @@
021e03
 #include "crypto/evp.h"
021e03
 #include "crypto/decoder.h"
021e03
 #include "encoder_local.h"
021e03
-#include "e_os.h"                /* strcasecmp on Windows */
021e03
 
021e03
 int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
021e03
                                     const unsigned char *kstr,
021e03
diff --git a/crypto/encode_decode/encoder_lib.c b/crypto/encode_decode/encoder_lib.c
021e03
index cfd9275172f5..2a83af825c2d 100644
021e03
--- a/crypto/encode_decode/encoder_lib.c
021e03
+++ b/crypto/encode_decode/encoder_lib.c
021e03
@@ -7,7 +7,6 @@
021e03
  * https://www.openssl.org/source/license.html
021e03
  */
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp on Windows */
021e03
 #include <openssl/core_names.h>
021e03
 #include <openssl/bio.h>
021e03
 #include <openssl/encoder.h>
021e03
@@ -453,8 +452,8 @@ static int encoder_process(struct encoder_process_data_st *data)
021e03
          */
021e03
         if (top) {
021e03
             if (data->ctx->output_type != NULL
021e03
-                && strcasecmp(current_output_type,
021e03
-                              data->ctx->output_type) != 0) {
021e03
+                && OPENSSL_strcasecmp(current_output_type,
021e03
+                                      data->ctx->output_type) != 0) {
021e03
                 OSSL_TRACE_BEGIN(ENCODER) {
021e03
                     BIO_printf(trc_out,
021e03
                                "[%d]    Skipping because current encoder output type (%s) != desired output type (%s)\n",
021e03
@@ -482,8 +481,8 @@ static int encoder_process(struct encoder_process_data_st *data)
021e03
          */
021e03
         if (data->ctx->output_structure != NULL
021e03
             && current_output_structure != NULL) {
021e03
-            if (strcasecmp(data->ctx->output_structure,
021e03
-                           current_output_structure) != 0) {
021e03
+            if (OPENSSL_strcasecmp(data->ctx->output_structure,
021e03
+                                   current_output_structure) != 0) {
021e03
                 OSSL_TRACE_BEGIN(ENCODER) {
021e03
                     BIO_printf(trc_out,
021e03
                                "[%d]    Skipping because current encoder output structure (%s) != ctx output structure (%s)\n",
021e03
diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c
021e03
index c37edf966d7e..3a24317cf4d6 100644
021e03
--- a/crypto/encode_decode/encoder_pkey.c
021e03
+++ b/crypto/encode_decode/encoder_pkey.c
021e03
@@ -7,7 +7,6 @@
021e03
  * https://www.openssl.org/source/license.html
021e03
  */
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp on Windows */
021e03
 #include <openssl/err.h>
021e03
 #include <openssl/ui.h>
021e03
 #include <openssl/params.h>
021e03
diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c
021e03
index e3a5c82e9957..09d0ed9d3aae 100644
021e03
--- a/crypto/engine/tb_asnmth.c
021e03
+++ b/crypto/engine/tb_asnmth.c
021e03
@@ -152,7 +152,7 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
021e03
         e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
021e03
         if (ameth != NULL
021e03
             && ((int)strlen(ameth->pem_str) == len)
021e03
-            && strncasecmp(ameth->pem_str, str, len) == 0)
021e03
+            && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
021e03
             return ameth;
021e03
     }
021e03
     return NULL;
021e03
@@ -177,7 +177,7 @@ static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
021e03
         e->pkey_asn1_meths(e, &ameth, NULL, nid);
021e03
         if (ameth != NULL
021e03
                 && ((int)strlen(ameth->pem_str) == lk->len)
021e03
-                && strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) {
021e03
+                && OPENSSL_strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) {
021e03
             lk->e = e;
021e03
             lk->ameth = ameth;
021e03
             return;
021e03
diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
021e03
index 961ca116b32f..0aa1c23beec7 100644
021e03
--- a/crypto/evp/ctrl_params_translate.c
021e03
+++ b/crypto/evp/ctrl_params_translate.c
021e03
@@ -37,8 +37,6 @@
021e03
 #include "crypto/dh.h"
021e03
 #include "crypto/ec.h"
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp() for Windows */
021e03
-
021e03
 struct translation_ctx_st;       /* Forwarding */
021e03
 struct translation_st;           /* Forwarding */
021e03
 
021e03
@@ -905,7 +903,7 @@ static int fix_kdf_type(enum state state,
021e03
 
021e03
         /* Convert KDF type strings to numbers */
021e03
         for (; kdf_type_map->kdf_type_str != NULL; kdf_type_map++)
021e03
-            if (strcasecmp(ctx->p2, kdf_type_map->kdf_type_str) == 0) {
021e03
+            if (OPENSSL_strcasecmp(ctx->p2, kdf_type_map->kdf_type_str) == 0) {
021e03
                 ctx->p1 = kdf_type_map->kdf_type_num;
021e03
                 ret = 1;
021e03
                 break;
021e03
@@ -2469,10 +2467,11 @@ lookup_translation(struct translation_st *tmpl,
021e03
              * cmd name in the template.
021e03
              */
021e03
             if (item->ctrl_str != NULL
021e03
-                && strcasecmp(tmpl->ctrl_str, item->ctrl_str) == 0)
021e03
+                && OPENSSL_strcasecmp(tmpl->ctrl_str, item->ctrl_str) == 0)
021e03
                 ctrl_str = tmpl->ctrl_str;
021e03
             else if (item->ctrl_hexstr != NULL
021e03
-                     && strcasecmp(tmpl->ctrl_hexstr, item->ctrl_hexstr) == 0)
021e03
+                     && OPENSSL_strcasecmp(tmpl->ctrl_hexstr,
021e03
+                                           item->ctrl_hexstr) == 0)
021e03
                 ctrl_hexstr = tmpl->ctrl_hexstr;
021e03
             else
021e03
                 continue;
021e03
@@ -2500,7 +2499,8 @@ lookup_translation(struct translation_st *tmpl,
021e03
             if ((item->action_type != NONE
021e03
                  && tmpl->action_type != item->action_type)
021e03
                 || (item->param_key != NULL
021e03
-                    && strcasecmp(tmpl->param_key, item->param_key) != 0))
021e03
+                    && OPENSSL_strcasecmp(tmpl->param_key,
021e03
+                                          item->param_key) != 0))
021e03
                 continue;
021e03
         } else {
021e03
             return NULL;
021e03
diff --git a/crypto/evp/ec_support.c b/crypto/evp/ec_support.c
021e03
index 8550be65e785..aa3c7fa4efc7 100644
021e03
--- a/crypto/evp/ec_support.c
021e03
+++ b/crypto/evp/ec_support.c
021e03
@@ -10,7 +10,7 @@
021e03
 #include <string.h>
021e03
 #include <openssl/ec.h>
021e03
 #include "crypto/ec.h"
021e03
-#include "e_os.h" /* strcasecmp required by windows */
021e03
+#include "internal/nelem.h"
021e03
 
021e03
 typedef struct ec_name2nid_st {
021e03
     const char *name;
021e03
@@ -139,7 +139,7 @@ int ossl_ec_curve_name2nid(const char *name)
021e03
             return nid;
021e03
 
021e03
         for (i = 0; i < OSSL_NELEM(curve_list); i++) {
021e03
-            if (strcasecmp(curve_list[i].name, name) == 0)
021e03
+            if (OPENSSL_strcasecmp(curve_list[i].name, name) == 0)
021e03
                 return curve_list[i].nid;
021e03
         }
021e03
     }
021e03
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
021e03
index 24092cfd5be0..da3ef28b3d18 100644
021e03
--- a/crypto/evp/evp_lib.c
021e03
+++ b/crypto/evp/evp_lib.c
021e03
@@ -15,7 +15,6 @@
021e03
 
021e03
 #include <stdio.h>
021e03
 #include <string.h>
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include "internal/cryptlib.h"
021e03
 #include <openssl/evp.h>
021e03
 #include <openssl/objects.h>
021e03
@@ -1170,17 +1169,17 @@ EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq,
021e03
 
021e03
     va_start(args, type);
021e03
 
021e03
-    if (strcasecmp(type, "RSA") == 0) {
021e03
+    if (OPENSSL_strcasecmp(type, "RSA") == 0) {
021e03
         bits = va_arg(args, size_t);
021e03
         params[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits);
021e03
-    } else if (strcasecmp(type, "EC") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "EC") == 0) {
021e03
         name = va_arg(args, char *);
021e03
         params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
021e03
                                                      name, 0);
021e03
-    } else if (strcasecmp(type, "ED25519") != 0
021e03
-               && strcasecmp(type, "X25519") != 0
021e03
-               && strcasecmp(type, "ED448") != 0
021e03
-               && strcasecmp(type, "X448") != 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "ED25519") != 0
021e03
+               && OPENSSL_strcasecmp(type, "X25519") != 0
021e03
+               && OPENSSL_strcasecmp(type, "ED448") != 0
021e03
+               && OPENSSL_strcasecmp(type, "X448") != 0) {
021e03
         ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
021e03
         goto end;
021e03
     }
021e03
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
021e03
index 27138af56421..668607a72360 100644
021e03
--- a/crypto/evp/p_lib.c
021e03
+++ b/crypto/evp/p_lib.c
021e03
@@ -50,8 +50,6 @@
021e03
 #include "internal/provider.h"
021e03
 #include "evp_local.h"
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp on Windows */
021e03
-
021e03
 static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
021e03
                          int len, EVP_KEYMGMT *keymgmt);
021e03
 static void evp_pkey_free_it(EVP_PKEY *key);
021e03
@@ -1018,7 +1016,7 @@ int evp_pkey_name2type(const char *name)
021e03
     size_t i;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
021e03
-        if (strcasecmp(name, standard_name2type[i].ptr) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, standard_name2type[i].ptr) == 0)
021e03
             return (int)standard_name2type[i].id;
021e03
     }
021e03
 
021e03
diff --git a/crypto/ffc/ffc_dh.c b/crypto/ffc/ffc_dh.c
021e03
index e9f597c46c00..266cb30bc245 100644
021e03
--- a/crypto/ffc/ffc_dh.c
021e03
+++ b/crypto/ffc/ffc_dh.c
021e03
@@ -10,7 +10,6 @@
021e03
 #include "internal/ffc.h"
021e03
 #include "internal/nelem.h"
021e03
 #include "crypto/bn_dh.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 #ifndef OPENSSL_NO_DH
021e03
 
021e03
@@ -84,7 +83,7 @@ const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name)
021e03
     size_t i;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
021e03
-        if (strcasecmp(dh_named_groups[i].name, name) == 0)
021e03
+        if (OPENSSL_strcasecmp(dh_named_groups[i].name, name) == 0)
021e03
             return &dh_named_groups[i];
021e03
     }
021e03
     return NULL;
021e03
diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c
021e03
index 6e025a06be6e..500189e49fc0 100644
021e03
--- a/crypto/ffc/ffc_params.c
021e03
+++ b/crypto/ffc/ffc_params.c
021e03
@@ -12,7 +12,6 @@
021e03
 #include "internal/ffc.h"
021e03
 #include "internal/param_build_set.h"
021e03
 #include "internal/nelem.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 #ifndef FIPS_MODULE
021e03
 # include <openssl/asn1.h> /* ossl_ffc_params_print */
021e03
diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c
021e03
index 33e7b82b9e8c..8133a04936c5 100644
021e03
--- a/crypto/http/http_client.c
021e03
+++ b/crypto/http/http_client.c
021e03
@@ -322,7 +322,7 @@ static int add1_headers(OSSL_HTTP_REQ_CTX *rctx,
021e03
 
021e03
     for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
021e03
         hdr = sk_CONF_VALUE_value(headers, i);
021e03
-        if (add_host && strcasecmp("host", hdr->name) == 0)
021e03
+        if (add_host && OPENSSL_strcasecmp("host", hdr->name) == 0)
021e03
             add_host = 0;
021e03
         if (!OSSL_HTTP_REQ_CTX_add1_header(rctx, hdr->name, hdr->value))
021e03
             return 0;
021e03
@@ -666,13 +666,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
021e03
         }
021e03
         if (value != NULL && line_end != NULL) {
021e03
             if (rctx->state == OHS_REDIRECT
021e03
-                    && strcasecmp(key, "Location") == 0) {
021e03
+                    && OPENSSL_strcasecmp(key, "Location") == 0) {
021e03
                 rctx->redirection_url = value;
021e03
                 return 0;
021e03
             }
021e03
             if (rctx->expected_ct != NULL
021e03
-                    && strcasecmp(key, "Content-Type") == 0) {
021e03
-                if (strcasecmp(rctx->expected_ct, value) != 0) {
021e03
+                    && OPENSSL_strcasecmp(key, "Content-Type") == 0) {
021e03
+                if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0) {
021e03
                     ERR_raise_data(ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE,
021e03
                                    "expected=%s, actual=%s",
021e03
                                    rctx->expected_ct, value);
021e03
@@ -682,12 +682,12 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
021e03
             }
021e03
 
021e03
             /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */
021e03
-            if (strcasecmp(key, "Connection") == 0) {
021e03
-                if (strcasecmp(value, "keep-alive") == 0)
021e03
+            if (OPENSSL_strcasecmp(key, "Connection") == 0) {
021e03
+                if (OPENSSL_strcasecmp(value, "keep-alive") == 0)
021e03
                     found_keep_alive = 1;
021e03
-                else if (strcasecmp(value, "close") == 0)
021e03
+                else if (OPENSSL_strcasecmp(value, "close") == 0)
021e03
                     found_keep_alive = 0;
021e03
-            } else if (strcasecmp(key, "Content-Length") == 0) {
021e03
+            } else if (OPENSSL_strcasecmp(key, "Content-Length") == 0) {
021e03
                 resp_len = (size_t)strtoul(value, &line_end, 10);
021e03
                 if (line_end == value || *line_end != '\0') {
021e03
                     ERR_raise_data(ERR_LIB_HTTP,
021e03
diff --git a/crypto/init.c b/crypto/init.c
021e03
index 6a27d1a8e440..1569c35a6b96 100644
021e03
--- a/crypto/init.c
021e03
+++ b/crypto/init.c
021e03
@@ -32,6 +32,7 @@
021e03
 #include "crypto/store.h"
021e03
 #include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
021e03
 #include <openssl/trace.h>
021e03
+#include "crypto/ctype.h"
021e03
 
021e03
 static int stopped = 0;
021e03
 static uint64_t optsdone = 0;
021e03
@@ -447,6 +448,9 @@ void OPENSSL_cleanup(void)
021e03
     OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n");
021e03
     ossl_trace_cleanup();
021e03
 
021e03
+    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_deinit_casecmp()\n");
021e03
+    ossl_deinit_casecmp();
021e03
+
021e03
     base_inited = 0;
021e03
 }
021e03
 
021e03
@@ -460,6 +464,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
021e03
     uint64_t tmp;
021e03
     int aloaddone = 0;
021e03
 
021e03
+    if (!ossl_init_casecmp())
021e03
+        return 0;
021e03
+
021e03
    /* Applications depend on 0 being returned when cleanup was already done */
021e03
     if (stopped) {
021e03
         if (!(opts & OPENSSL_INIT_BASE_ONLY))
021e03
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
021e03
index 92152eeb6674..7596d720e964 100644
021e03
--- a/crypto/objects/o_names.c
021e03
+++ b/crypto/objects/o_names.c
021e03
@@ -21,23 +21,6 @@
021e03
 #include "obj_local.h"
021e03
 #include "e_os.h"
021e03
 
021e03
-/*
021e03
- * We define this wrapper for two reasons. Firstly, later versions of
021e03
- * DEC C add linkage information to certain functions, which makes it
021e03
- * tricky to use them as values to regular function pointers.
021e03
- * Secondly, in the EDK2 build environment, the strcasecmp function is
021e03
- * actually an external function with the Microsoft ABI, so we can't
021e03
- * transparently assign function pointers to it.
021e03
- */
021e03
-#if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI)
021e03
-static int obj_strcasecmp(const char *a, const char *b)
021e03
-{
021e03
-    return strcasecmp(a, b);
021e03
-}
021e03
-#else
021e03
-#define obj_strcasecmp strcasecmp
021e03
-#endif
021e03
-
021e03
 /*
021e03
  * I use the ex_data stuff to manage the identifiers for the obj_name_types
021e03
  * that applications may define.  I only really use the free function field.
021e03
@@ -111,7 +94,7 @@ int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *),
021e03
             goto out;
021e03
         }
021e03
         name_funcs->hash_func = ossl_lh_strcasehash;
021e03
-        name_funcs->cmp_func = obj_strcasecmp;
021e03
+        name_funcs->cmp_func = OPENSSL_strcasecmp;
021e03
         push = sk_NAME_FUNCS_push(name_funcs_stack, name_funcs);
021e03
 
021e03
         if (!push) {
021e03
@@ -145,7 +128,7 @@ static int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b)
021e03
             ret = sk_NAME_FUNCS_value(name_funcs_stack,
021e03
                                       a->type)->cmp_func(a->name, b->name);
021e03
         } else
021e03
-            ret = strcasecmp(a->name, b->name);
021e03
+            ret = OPENSSL_strcasecmp(a->name, b->name);
021e03
     }
021e03
     return ret;
021e03
 }
021e03
diff --git a/crypto/params_dup.c b/crypto/params_dup.c
021e03
index 6a58b52f65cb..d92176da46e5 100644
021e03
--- a/crypto/params_dup.c
021e03
+++ b/crypto/params_dup.c
021e03
@@ -11,7 +11,6 @@
021e03
 #include <openssl/params.h>
021e03
 #include <openssl/param_build.h>
021e03
 #include "internal/param_build_set.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 #define OSSL_PARAM_ALLOCATED_END    127
021e03
 #define OSSL_PARAM_MERGE_LIST_MAX   128
021e03
@@ -142,7 +141,7 @@ static int compare_params(const void *left, const void *right)
021e03
     const OSSL_PARAM *l = *(const OSSL_PARAM **)left;
021e03
     const OSSL_PARAM *r = *(const OSSL_PARAM **)right;
021e03
 
021e03
-    return strcasecmp(l->key, r->key);
021e03
+    return OPENSSL_strcasecmp(l->key, r->key);
021e03
 }
021e03
 
021e03
 OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2)
021e03
@@ -205,7 +204,7 @@ OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2)
021e03
             break;
021e03
         }
021e03
         /* consume the list element with the smaller key */
021e03
-        diff = strcasecmp((*p1cur)->key, (*p2cur)->key);
021e03
+        diff = OPENSSL_strcasecmp((*p1cur)->key, (*p2cur)->key);
021e03
         if (diff == 0) {
021e03
             /* If the keys are the same then throw away the list1 element */
021e03
             *dst++ = **p2cur;
021e03
diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c
021e03
index 8954ec724617..c5691395c424 100644
021e03
--- a/crypto/property/property_parse.c
021e03
+++ b/crypto/property/property_parse.c
021e03
@@ -45,7 +45,7 @@ static int match(const char *t[], const char m[], size_t m_len)
021e03
 {
021e03
     const char *s = *t;
021e03
 
021e03
-    if (strncasecmp(s, m, m_len) == 0) {
021e03
+    if (OPENSSL_strncasecmp(s, m, m_len) == 0) {
021e03
         *t = skip_space(s + m_len);
021e03
         return 1;
021e03
     }
021e03
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
021e03
index afe3521186ca..c453d3226133 100644
021e03
--- a/crypto/rand/rand_lib.c
021e03
+++ b/crypto/rand/rand_lib.c
021e03
@@ -768,22 +768,22 @@ static int random_conf_init(CONF_IMODULE *md, const CONF *cnf)
021e03
 
021e03
     for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
021e03
         cval = sk_CONF_VALUE_value(elist, i);
021e03
-        if (strcasecmp(cval->name, "random") == 0) {
021e03
+        if (OPENSSL_strcasecmp(cval->name, "random") == 0) {
021e03
             if (!random_set_string(&dgbl->rng_name, cval->value))
021e03
                 return 0;
021e03
-        } else if (strcasecmp(cval->name, "cipher") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(cval->name, "cipher") == 0) {
021e03
             if (!random_set_string(&dgbl->rng_cipher, cval->value))
021e03
                 return 0;
021e03
-        } else if (strcasecmp(cval->name, "digest") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(cval->name, "digest") == 0) {
021e03
             if (!random_set_string(&dgbl->rng_digest, cval->value))
021e03
                 return 0;
021e03
-        } else if (strcasecmp(cval->name, "properties") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(cval->name, "properties") == 0) {
021e03
             if (!random_set_string(&dgbl->rng_propq, cval->value))
021e03
                 return 0;
021e03
-        } else if (strcasecmp(cval->name, "seed") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(cval->name, "seed") == 0) {
021e03
             if (!random_set_string(&dgbl->seed_name, cval->value))
021e03
                 return 0;
021e03
-        } else if (strcasecmp(cval->name, "seed_properties") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(cval->name, "seed_properties") == 0) {
021e03
             if (!random_set_string(&dgbl->seed_propq, cval->value))
021e03
                 return 0;
021e03
         } else {
021e03
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
021e03
index ad1623dd1444..254ebdb24287 100644
021e03
--- a/crypto/rsa/rsa_backend.c
021e03
+++ b/crypto/rsa/rsa_backend.c
021e03
@@ -27,8 +27,6 @@
021e03
 #include "crypto/rsa.h"
021e03
 #include "rsa_local.h"
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp for Windows() */
021e03
-
021e03
 /*
021e03
  * The intention with the "backend" source file is to offer backend support
021e03
  * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
021e03
@@ -275,8 +273,8 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
021e03
         else if (!OSSL_PARAM_get_utf8_ptr(param_mgf, &mgfname))
021e03
             return 0;
021e03
 
021e03
-        if (strcasecmp(param_mgf->data,
021e03
-                       ossl_rsa_mgf_nid2name(default_maskgenalg_nid)) != 0)
021e03
+        if (OPENSSL_strcasecmp(param_mgf->data,
021e03
+                               ossl_rsa_mgf_nid2name(default_maskgenalg_nid)) != 0)
021e03
             return 0;
021e03
     }
021e03
 
021e03
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
021e03
index 7dcb939066f2..42bf9d555a36 100644
021e03
--- a/crypto/store/store_lib.c
021e03
+++ b/crypto/store/store_lib.c
021e03
@@ -93,7 +93,7 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
021e03
     OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
021e03
     if ((p = strchr(scheme_copy, ':')) != NULL) {
021e03
         *p++ = '\0';
021e03
-        if (strcasecmp(scheme_copy, "file") != 0) {
021e03
+        if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
021e03
             if (strncmp(p, "//", 2) == 0)
021e03
                 schemes_n--;         /* Invalidate the file scheme */
021e03
             schemes[schemes_n++] = scheme_copy;
021e03
diff --git a/crypto/store/store_result.c b/crypto/store/store_result.c
021e03
index 1306b270bbaf..6f83da4beb02 100644
021e03
--- a/crypto/store/store_result.c
021e03
+++ b/crypto/store/store_result.c
021e03
@@ -457,7 +457,7 @@ static int try_cert(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
021e03
 
021e03
         /* If we have a data type, it should be a PEM name */
021e03
         if (data->data_type != NULL
021e03
-            && (strcasecmp(data->data_type, PEM_STRING_X509_TRUSTED) == 0))
021e03
+            && (OPENSSL_strcasecmp(data->data_type, PEM_STRING_X509_TRUSTED) == 0))
021e03
             ignore_trusted = 0;
021e03
 
021e03
         if (d2i_X509_AUX(&cert, (const unsigned char **)&data->octet_data,
021e03
diff --git a/crypto/trace.c b/crypto/trace.c
021e03
index 40941990e673..d790409a2d62 100644
021e03
--- a/crypto/trace.c
021e03
+++ b/crypto/trace.c
021e03
@@ -19,8 +19,6 @@
021e03
 #include "internal/refcount.h"
021e03
 #include "crypto/cryptlib.h"
021e03
 
021e03
-#include "e_os.h"                /* strcasecmp for Windows */
021e03
-
021e03
 #ifndef OPENSSL_NO_TRACE
021e03
 
021e03
 static CRYPTO_RWLOCK *trace_lock = NULL;
021e03
@@ -158,7 +156,7 @@ int OSSL_trace_get_category_num(const char *name)
021e03
     size_t i;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(trace_categories); i++)
021e03
-        if (strcasecmp(name, trace_categories[i].name) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, trace_categories[i].name) == 0)
021e03
             return trace_categories[i].num;
021e03
     return -1; /* not found */
021e03
 }
021e03
diff --git a/crypto/x509/v3_tlsf.c b/crypto/x509/v3_tlsf.c
021e03
index 6a613d64e6aa..9927c083b115 100644
021e03
--- a/crypto/x509/v3_tlsf.c
021e03
+++ b/crypto/x509/v3_tlsf.c
021e03
@@ -108,7 +108,7 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method,
021e03
             extval = val->name;
021e03
 
021e03
         for (j = 0; j < OSSL_NELEM(tls_feature_tbl); j++)
021e03
-            if (strcasecmp(extval, tls_feature_tbl[j].name) == 0)
021e03
+            if (OPENSSL_strcasecmp(extval, tls_feature_tbl[j].name) == 0)
021e03
                 break;
021e03
         if (j < OSSL_NELEM(tls_feature_tbl))
021e03
             tlsextid = tls_feature_tbl[j].num;
021e03
diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c
021e03
index ff049c897bae..6e4ef26ed608 100644
021e03
--- a/crypto/x509/v3_utl.c
021e03
+++ b/crypto/x509/v3_utl.c
021e03
@@ -715,7 +715,7 @@ static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
021e03
     }
021e03
     /* IDNA labels cannot match partial wildcards */
021e03
     if (!allow_idna &&
021e03
-        subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0)
021e03
+        subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
021e03
         return 0;
021e03
     /* The wildcard may match a literal '*' */
021e03
     if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
021e03
@@ -775,7 +775,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
021e03
                    || ('A' <= p[i] && p[i] <= 'Z')
021e03
                    || ('0' <= p[i] && p[i] <= '9')) {
021e03
             if ((state & LABEL_START) != 0
021e03
-                && len - i >= 4 && strncasecmp((char *)&p[i], "xn--", 4) == 0)
021e03
+                && len - i >= 4 && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
021e03
                 state |= LABEL_IDNA;
021e03
             state &= ~(LABEL_HYPHEN | LABEL_START);
021e03
         } else if (p[i] == '.') {
021e03
diff --git a/doc/build.info b/doc/build.info
021e03
index c1d98a4ca669..7e86de588aed 100644
021e03
--- a/doc/build.info
021e03
+++ b/doc/build.info
021e03
@@ -1531,6 +1531,10 @@ DEPEND[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
021e03
 GENERATE[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
021e03
 DEPEND[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
021e03
 GENERATE[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
021e03
+DEPEND[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
021e03
+GENERATE[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
021e03
+DEPEND[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
021e03
+GENERATE[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
021e03
 DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
021e03
 GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
021e03
 DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
021e03
@@ -3110,6 +3114,7 @@ html/man3/OPENSSL_load_builtin_modules.html \
021e03
 html/man3/OPENSSL_malloc.html \
021e03
 html/man3/OPENSSL_s390xcap.html \
021e03
 html/man3/OPENSSL_secure_malloc.html \
021e03
+html/man3/OPENSSL_strcasecmp.html \
021e03
 html/man3/OSSL_CMP_CTX_new.html \
021e03
 html/man3/OSSL_CMP_HDR_get0_transactionID.html \
021e03
 html/man3/OSSL_CMP_ITAV_set0.html \
021e03
@@ -3704,6 +3709,7 @@ man/man3/OPENSSL_load_builtin_modules.3 \
021e03
 man/man3/OPENSSL_malloc.3 \
021e03
 man/man3/OPENSSL_s390xcap.3 \
021e03
 man/man3/OPENSSL_secure_malloc.3 \
021e03
+man/man3/OPENSSL_strcasecmp.3 \
021e03
 man/man3/OSSL_CMP_CTX_new.3 \
021e03
 man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
021e03
 man/man3/OSSL_CMP_ITAV_set0.3 \
021e03
diff --git a/doc/man3/OPENSSL_strcasecmp.pod b/doc/man3/OPENSSL_strcasecmp.pod
021e03
new file mode 100644
021e03
index 000000000000..1bb8b18c5013
021e03
--- /dev/null
021e03
+++ b/doc/man3/OPENSSL_strcasecmp.pod
021e03
@@ -0,0 +1,47 @@
021e03
+=pod
021e03
+
021e03
+=head1 NAME
021e03
+
021e03
+OPENSSL_strcasecmp, OPENSSL_strncasecmp - compare two strings ignoring case
021e03
+
021e03
+=head1 SYNOPSIS
021e03
+
021e03
+ #include <openssl/crypto.h>
021e03
+
021e03
+ int OPENSSL_strcasecmp(const char *s1, const char *s2);
021e03
+ int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
021e03
+
021e03
+=head1 DESCRIPTION
021e03
+
021e03
+The OPENSSL_strcasecmp function performs a byte-by-byte comparison of the strings
021e03
+B<s1> and B<s2>, ignoring the case of the characters.
021e03
+
021e03
+The OPENSSL_strncasecmp function is similar, except that it compares no more than
021e03
+B<n> bytes of B<s1> and B<s2>.
021e03
+
021e03
+In POSIX-compatible system and on Windows these functions use "C" locale for
021e03
+case insensitive. Otherwise the comparison is done in current locale.
021e03
+
021e03
+=head1 RETURN VALUES
021e03
+
021e03
+Both functions return an integer less than, equal to, or greater than zero if
021e03
+s1 is found, respectively, to be less than, to match, or be greater than s2.
021e03
+
021e03
+=head1 NOTES
021e03
+
021e03
+OpenSSL extensively uses case insensitive comparison of ASCII strings. Though
021e03
+OpenSSL itself is locale-agnostic, the applications using OpenSSL libraries may
021e03
+unpredictably suffer when they use localization (e.g. Turkish locale is
021e03
+well-known with a specific I/i cases). These functions use C locale for string
021e03
+comparison.
021e03
+
021e03
+=head1 COPYRIGHT
021e03
+
021e03
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
021e03
+
021e03
+Licensed under the Apache License 2.0 (the "License").  You may not use
021e03
+this file except in compliance with the License.  You can obtain a copy
021e03
+in the file LICENSE in the source distribution or at
021e03
+L<https://www.openssl.org/source/license.html>.
021e03
+
021e03
+=cut
021e03
diff --git a/e_os.h b/e_os.h
021e03
index e1608ae55d7d..5490a48fcd48 100644
021e03
--- a/e_os.h
021e03
+++ b/e_os.h
021e03
@@ -249,8 +249,6 @@ FILE *__iob_func();
021e03
 /***********************************************/
021e03
 
021e03
 # if defined(OPENSSL_SYS_WINDOWS)
021e03
-#  define strcasecmp _stricmp
021e03
-#  define strncasecmp _strnicmp
021e03
 #  if (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
021e03
 #   define open _open
021e03
 #   define fdopen _fdopen
021e03
diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c
021e03
index fa01317db5eb..a9c10d375a58 100644
021e03
--- a/engines/e_devcrypto.c
021e03
+++ b/engines/e_devcrypto.c
021e03
@@ -1159,9 +1159,9 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
021e03
     case DEVCRYPTO_CMD_CIPHERS:
021e03
         if (p == NULL)
021e03
             return 1;
021e03
-        if (strcasecmp((const char *)p, "ALL") == 0) {
021e03
+        if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
021e03
             devcrypto_select_all_ciphers(selected_ciphers);
021e03
-        } else if (strcasecmp((const char*)p, "NONE") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
021e03
             memset(selected_ciphers, 0, sizeof(selected_ciphers));
021e03
         } else {
021e03
             new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
021e03
@@ -1179,9 +1179,9 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
021e03
     case DEVCRYPTO_CMD_DIGESTS:
021e03
         if (p == NULL)
021e03
             return 1;
021e03
-        if (strcasecmp((const char *)p, "ALL") == 0) {
021e03
+        if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
021e03
             devcrypto_select_all_digests(selected_digests);
021e03
-        } else if (strcasecmp((const char*)p, "NONE") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp((const char*)p, "NONE") == 0) {
021e03
             memset(selected_digests, 0, sizeof(selected_digests));
021e03
         } else {
021e03
             new_list=OPENSSL_zalloc(sizeof(selected_digests));
021e03
diff --git a/engines/e_loader_attic.c b/engines/e_loader_attic.c
021e03
index 391ed33d5e3a..f6de29c0c33a 100644
021e03
--- a/engines/e_loader_attic.c
021e03
+++ b/engines/e_loader_attic.c
021e03
@@ -14,7 +14,6 @@
021e03
 /* We need to use some engine deprecated APIs */
021e03
 #define OPENSSL_SUPPRESS_DEPRECATED
021e03
 
021e03
-/* #include "e_os.h" */
021e03
 #include <string.h>
021e03
 #include <sys/stat.h>
021e03
 #include <ctype.h>
021e03
@@ -44,7 +43,6 @@ DEFINE_STACK_OF(OSSL_STORE_INFO)
021e03
 
021e03
 #ifdef _WIN32
021e03
 # define stat _stat
021e03
-# define strncasecmp _strnicmp
021e03
 #endif
021e03
 
021e03
 #ifndef S_ISDIR
021e03
@@ -971,12 +969,12 @@ static OSSL_STORE_LOADER_CTX *file_open_ex
021e03
      * There's a special case if the URI also contains an authority, then
021e03
      * the full URI shouldn't be used as a path anywhere.
021e03
      */
021e03
-    if (strncasecmp(uri, "file:", 5) == 0) {
021e03
+    if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
021e03
         const char *p = &uri[5];
021e03
 
021e03
         if (strncmp(&uri[5], "//", 2) == 0) {
021e03
             path_data_n--;           /* Invalidate using the full URI */
021e03
-            if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
021e03
+            if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
021e03
                 p = &uri[16];
021e03
             } else if (uri[7] == '/') {
021e03
                 p = &uri[7];
021e03
@@ -1466,7 +1464,8 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
021e03
     /*
021e03
      * First, check the basename
021e03
      */
021e03
-    if (strncasecmp(name, ctx->_.dir.search_name, len) != 0 || name[len] != '.')
021e03
+    if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
021e03
+        || name[len] != '.')
021e03
         return 0;
021e03
     p = &name[len + 1];
021e03
 
021e03
diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c
021e03
index 0506faa6285b..5d31b31c11f1 100644
021e03
--- a/engines/e_ossltest.c
021e03
+++ b/engines/e_ossltest.c
021e03
@@ -42,10 +42,6 @@
021e03
 
021e03
 #include "e_ossltest_err.c"
021e03
 
021e03
-#ifdef _WIN32
021e03
-# define strncasecmp _strnicmp
021e03
-#endif
021e03
-
021e03
 /* Engine Id and Name */
021e03
 static const char *engine_ossltest_id = "ossltest";
021e03
 static const char *engine_ossltest_name = "OpenSSL Test engine support";
021e03
@@ -383,7 +379,7 @@ static EVP_PKEY *load_key(ENGINE *eng, const char *key_id, int pub,
021e03
     BIO *in;
021e03
     EVP_PKEY *key;
021e03
 
021e03
-    if (strncasecmp(key_id, "ot:", 3) != 0)
021e03
+    if (OPENSSL_strncasecmp(key_id, "ot:", 3) != 0)
021e03
         return NULL;
021e03
     key_id += 3;
021e03
 
021e03
diff --git a/include/crypto/ctype.h b/include/crypto/ctype.h
021e03
index a35c137e8431..44fa9a8ae930 100644
021e03
--- a/include/crypto/ctype.h
021e03
+++ b/include/crypto/ctype.h
021e03
@@ -80,4 +80,6 @@ int ossl_ascii_isdigit(const char inchar);
021e03
 # define ossl_isbase64(c)       (ossl_ctype_check((c), CTYPE_MASK_base64))
021e03
 # define ossl_isasn1print(c)    (ossl_ctype_check((c), CTYPE_MASK_asn1print))
021e03
 
021e03
+int ossl_init_casecmp(void);
021e03
+void ossl_deinit_casecmp(void);
021e03
 #endif
021e03
diff --git a/include/internal/core.h b/include/internal/core.h
021e03
index d9dc424164c9..b63af84787af 100644
021e03
--- a/include/internal/core.h
021e03
+++ b/include/internal/core.h
021e03
@@ -63,4 +63,6 @@ __owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx);
021e03
 int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx);
021e03
 int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);
021e03
 
021e03
+void *ossl_c_locale(void);
021e03
+
021e03
 #endif
021e03
diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in
021e03
index c56885d2d6ff..7232f647e8a3 100644
021e03
--- a/include/openssl/crypto.h.in
021e03
+++ b/include/openssl/crypto.h.in
021e03
@@ -133,6 +133,8 @@ int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
021e03
                           const char *str, const char sep);
021e03
 unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
021e03
 int OPENSSL_hexchar2int(unsigned char c);
021e03
+int OPENSSL_strcasecmp(const char *s1, const char *s2);
021e03
+int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
021e03
 
021e03
 # define OPENSSL_MALLOC_MAX_NELEMS(type)  (((1U<<(sizeof(int)*8-1))-1)/sizeof(type))
021e03
 
021e03
diff --git a/providers/common/capabilities.c b/providers/common/capabilities.c
021e03
index f6d95197f07c..e1e1961b2329 100644
021e03
--- a/providers/common/capabilities.c
021e03
+++ b/providers/common/capabilities.c
021e03
@@ -217,7 +217,7 @@ static int tls_group_capability(OSSL_CALLBACK *cb, void *arg)
021e03
 int ossl_prov_get_capabilities(void *provctx, const char *capability,
021e03
                                OSSL_CALLBACK *cb, void *arg)
021e03
 {
021e03
-    if (strcasecmp(capability, "TLS-GROUP") == 0)
021e03
+    if (OPENSSL_strcasecmp(capability, "TLS-GROUP") == 0)
021e03
         return tls_group_capability(cb, arg);
021e03
 
021e03
     /* We don't support this capability */
021e03
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
021e03
index f4605dcd6ce5..fc17a958ce26 100644
021e03
--- a/providers/fips/fipsprov.c
021e03
+++ b/providers/fips/fipsprov.c
021e03
@@ -22,6 +22,7 @@
021e03
 #include "prov/provider_util.h"
021e03
 #include "prov/seeding.h"
021e03
 #include "self_test.h"
021e03
+#include "internal/core.h"
021e03
 
021e03
 static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
021e03
 static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
021e03
@@ -35,6 +36,22 @@ static OSSL_FUNC_provider_gettable_params_fn fips_gettable_params;
021e03
 static OSSL_FUNC_provider_get_params_fn fips_get_params;
021e03
 static OSSL_FUNC_provider_query_operation_fn fips_query;
021e03
 
021e03
+/* Locale object accessor functions */
021e03
+#ifdef OPENSSL_SYS_MACOSX
021e03
+# include <xlocale.h>
021e03
+#else
021e03
+# include <locale.h>
021e03
+#endif
021e03
+
021e03
+#if defined OPENSSL_SYS_WINDOWS
021e03
+# define locale_t _locale_t
021e03
+# define freelocale _free_locale
021e03
+#endif
021e03
+static locale_t loc;
021e03
+
021e03
+static int fips_init_casecmp(void);
021e03
+static void fips_deinit_casecmp(void);
021e03
+
021e03
 #define ALGC(NAMES, FUNC, CHECK) { { NAMES, FIPS_DEFAULT_PROPERTIES, FUNC }, CHECK }
021e03
 #define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
021e03
 #define ALGCU(NAMES, FUNC, CHECK) { { NAMES, FIPS_UNAPPROVED_PROPERTIES, FUNC }, CHECK }
021e03
@@ -486,6 +503,23 @@ static const OSSL_ALGORITHM *fips_query(void *provctx, int operation_id,
021e03
     return NULL;
021e03
 }
021e03
 
021e03
+void *ossl_c_locale() {
021e03
+    return (void *)loc;
021e03
+}
021e03
+
021e03
+static int fips_init_casecmp(void) {
021e03
+# ifdef OPENSSL_SYS_WINDOWS
021e03
+    loc = _create_locale(LC_COLLATE, "C");
021e03
+# else
021e03
+    loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
021e03
+# endif
021e03
+    return (loc == (locale_t) 0) ? 0 : 1;
021e03
+}
021e03
+
021e03
+static void fips_deinit_casecmp(void) {
021e03
+    freelocale(loc);
021e03
+}
021e03
+
021e03
 static void fips_teardown(void *provctx)
021e03
 {
021e03
     OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
021e03
@@ -498,6 +532,7 @@ static void fips_intern_teardown(void *provctx)
021e03
      * We know that the library context is the same as for the outer provider,
021e03
      * so no need to destroy it here.
021e03
      */
021e03
+    fips_deinit_casecmp();
021e03
     ossl_prov_ctx_free(provctx);
021e03
 }
021e03
 
021e03
@@ -547,6 +582,8 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
021e03
 
021e03
     memset(&selftest_params, 0, sizeof(selftest_params));
021e03
 
021e03
+    if (!fips_init_casecmp())
021e03
+        return 0;
021e03
     if (!ossl_prov_seeding_from_dispatch(in))
021e03
         return 0;
021e03
     for (; in->function_id != 0; in++) {
021e03
diff --git a/providers/implementations/ciphers/cipher_cts.c b/providers/implementations/ciphers/cipher_cts.c
021e03
index cb3372c646aa..5c48f37c9527 100644
021e03
--- a/providers/implementations/ciphers/cipher_cts.c
021e03
+++ b/providers/implementations/ciphers/cipher_cts.c
021e03
@@ -46,7 +46,6 @@
021e03
  *      Otherwise it is the same as CS2.
021e03
  */
021e03
 
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include <openssl/core_names.h>
021e03
 #include "prov/ciphercommon.h"
021e03
 #include "internal/nelem.h"
021e03
@@ -92,7 +91,7 @@ int ossl_cipher_cbc_cts_mode_name2id(const char *name)
021e03
     size_t i;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
021e03
-        if (strcasecmp(name, cts_modes[i].name) == 0)
021e03
+        if (OPENSSL_strcasecmp(name, cts_modes[i].name) == 0)
021e03
             return (int)cts_modes[i].id;
021e03
     }
021e03
     return -1;
021e03
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
021e03
index 667d5e9619ff..89f304b41816 100644
021e03
--- a/providers/implementations/kdfs/hkdf.c
021e03
+++ b/providers/implementations/kdfs/hkdf.c
021e03
@@ -199,11 +199,11 @@ static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
021e03
 
021e03
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
021e03
         if (p->data_type == OSSL_PARAM_UTF8_STRING) {
021e03
-            if (strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
021e03
+            if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
021e03
                 ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
021e03
-            } else if (strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
021e03
+            } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
021e03
                 ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
021e03
-            } else if (strcasecmp(p->data, "EXPAND_ONLY") == 0) {
021e03
+            } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) {
021e03
                 ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
021e03
             } else {
021e03
                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
021e03
diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c
021e03
index 5f30b037d94e..6be7f45fc58a 100644
021e03
--- a/providers/implementations/kdfs/kbkdf.c
021e03
+++ b/providers/implementations/kdfs/kbkdf.c
021e03
@@ -298,10 +298,11 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
021e03
     }
021e03
 
021e03
     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE);
021e03
-    if (p != NULL && strncasecmp("counter", p->data, p->data_size) == 0) {
021e03
+    if (p != NULL
021e03
+        && OPENSSL_strncasecmp("counter", p->data, p->data_size) == 0) {
021e03
         ctx->mode = COUNTER;
021e03
     } else if (p != NULL
021e03
-               && strncasecmp("feedback", p->data, p->data_size) == 0) {
021e03
+               && OPENSSL_strncasecmp("feedback", p->data, p->data_size) == 0) {
021e03
         ctx->mode = FEEDBACK;
021e03
     } else if (p != NULL) {
021e03
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
021e03
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
021e03
index 74a0f7e1f3e6..e0b5971a3b7a 100644
021e03
--- a/providers/implementations/kdfs/tls1_prf.c
021e03
+++ b/providers/implementations/kdfs/tls1_prf.c
021e03
@@ -172,7 +172,7 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
021e03
         return 1;
021e03
 
021e03
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
021e03
-        if (strcasecmp(p->data, SN_md5_sha1) == 0) {
021e03
+        if (OPENSSL_strcasecmp(p->data, SN_md5_sha1) == 0) {
021e03
             if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
021e03
                                                    OSSL_MAC_NAME_HMAC,
021e03
                                                    NULL, SN_md5, libctx)
021e03
diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c
021e03
index 313ab133b33a..bfc3da690875 100644
021e03
--- a/providers/implementations/kem/rsa_kem.c
021e03
+++ b/providers/implementations/kem/rsa_kem.c
021e03
@@ -12,8 +12,8 @@
021e03
  * internal use.
021e03
  */
021e03
 #include "internal/deprecated.h"
021e03
+#include "internal/nelem.h"
021e03
 
021e03
-#include "e_os.h"  /* strcasecmp */
021e03
 #include <openssl/crypto.h>
021e03
 #include <openssl/evp.h>
021e03
 #include <openssl/core_dispatch.h>
021e03
@@ -69,7 +69,7 @@ static int name2id(const char *name, const OSSL_ITEM *map, size_t sz)
021e03
         return -1;
021e03
 
021e03
     for (i = 0; i < sz; ++i) {
021e03
-        if (strcasecmp(map[i].ptr, name) == 0)
021e03
+        if (OPENSSL_strcasecmp(map[i].ptr, name) == 0)
021e03
             return map[i].id;
021e03
     }
021e03
     return -1;
021e03
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
021e03
index 885bd62eeaae..2ab69f5f32f5 100644
021e03
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
021e03
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
021e03
@@ -13,7 +13,6 @@
021e03
  */
021e03
 #include "internal/deprecated.h"
021e03
 
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include <openssl/core_dispatch.h>
021e03
 #include <openssl/core_names.h>
021e03
 #include <openssl/bn.h>
021e03
@@ -90,7 +89,7 @@ static int dsa_gen_type_name2id(const char *name)
021e03
     size_t i;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(dsatype2id); ++i) {
021e03
-        if (strcasecmp(dsatype2id[i].name, name) == 0)
021e03
+        if (OPENSSL_strcasecmp(dsatype2id[i].name, name) == 0)
021e03
             return dsatype2id[i].id;
021e03
     }
021e03
     return -1;
021e03
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
021e03
index f564a470ac04..68bb35e4cbe1 100644
021e03
--- a/providers/implementations/keymgmt/ec_kmgmt.c
021e03
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
021e03
@@ -13,7 +13,6 @@
021e03
  */
021e03
 #include "internal/deprecated.h"
021e03
 
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include <string.h>
021e03
 #include <openssl/core_dispatch.h>
021e03
 #include <openssl/core_names.h>
021e03
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
021e03
index 99d685735e2f..2a7f867aa56b 100644
021e03
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
021e03
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
021e03
@@ -9,8 +9,6 @@
021e03
 
021e03
 #include <assert.h>
021e03
 #include <string.h>
021e03
-/* For strcasecmp on Windows */
021e03
-#include "e_os.h"
021e03
 #include <openssl/core_dispatch.h>
021e03
 #include <openssl/core_names.h>
021e03
 #include <openssl/params.h>
021e03
@@ -546,7 +544,7 @@ static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
021e03
         }
021e03
         if (p->data_type != OSSL_PARAM_UTF8_STRING
021e03
                 || groupname == NULL
021e03
-                || strcasecmp(p->data, groupname) != 0) {
021e03
+                || OPENSSL_strcasecmp(p->data, groupname) != 0) {
021e03
             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
021e03
             return 0;
021e03
         }
021e03
diff --git a/providers/implementations/keymgmt/mac_legacy_kmgmt.c b/providers/implementations/keymgmt/mac_legacy_kmgmt.c
021e03
index ec34a3ee7131..ecfd2eaaa5c0 100644
021e03
--- a/providers/implementations/keymgmt/mac_legacy_kmgmt.c
021e03
+++ b/providers/implementations/keymgmt/mac_legacy_kmgmt.c
021e03
@@ -26,7 +26,6 @@
021e03
 #include "prov/providercommon.h"
021e03
 #include "prov/provider_ctx.h"
021e03
 #include "prov/macsignature.h"
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 
021e03
 static OSSL_FUNC_keymgmt_new_fn mac_new;
021e03
 static OSSL_FUNC_keymgmt_free_fn mac_free;
021e03
diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c
021e03
index dbe57b0d2898..c51eb4b4e581 100644
021e03
--- a/providers/implementations/rands/drbg_ctr.c
021e03
+++ b/providers/implementations/rands/drbg_ctr.c
021e03
@@ -14,7 +14,6 @@
021e03
 #include <openssl/rand.h>
021e03
 #include <openssl/aes.h>
021e03
 #include <openssl/proverr.h>
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include "crypto/modes.h"
021e03
 #include "internal/thread_once.h"
021e03
 #include "prov/implementations.h"
021e03
@@ -690,7 +689,7 @@ static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
021e03
         if (p->data_type != OSSL_PARAM_UTF8_STRING
021e03
                 || p->data_size < ctr_str_len)
021e03
             return 0;
021e03
-        if (strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
021e03
+        if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
021e03
             ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
021e03
             return 0;
021e03
         }
021e03
diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c
021e03
index 325e855333e9..9460136bca0b 100644
021e03
--- a/providers/implementations/signature/rsa_sig.c
021e03
+++ b/providers/implementations/signature/rsa_sig.c
021e03
@@ -13,7 +13,6 @@
021e03
  */
021e03
 #include "internal/deprecated.h"
021e03
 
021e03
-#include "e_os.h" /* strcasecmp */
021e03
 #include <string.h>
021e03
 #include <openssl/crypto.h>
021e03
 #include <openssl/core_dispatch.h>
021e03
@@ -854,7 +853,7 @@ static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
021e03
 
021e03
     if (mdname != NULL
021e03
         /* was rsa_setup_md already called in rsa_signverify_init()? */
021e03
-        && (mdname[0] == '\0' || strcasecmp(prsactx->mdname, mdname) != 0)
021e03
+        && (mdname[0] == '\0' || OPENSSL_strcasecmp(prsactx->mdname, mdname) != 0)
021e03
         && !rsa_setup_md(prsactx, mdname, prsactx->propq))
021e03
         return 0;
021e03
 
021e03
diff --git a/providers/implementations/storemgmt/file_store.c b/providers/implementations/storemgmt/file_store.c
021e03
index fef2b1d2900f..fceef73b7c09 100644
021e03
--- a/providers/implementations/storemgmt/file_store.c
021e03
+++ b/providers/implementations/storemgmt/file_store.c
021e03
@@ -9,8 +9,6 @@
021e03
 
021e03
 /* This file has quite some overlap with engines/e_loader_attic.c */
021e03
 
021e03
-#include "e_os.h"                /* To get strncasecmp() on Windows */
021e03
-
021e03
 #include <string.h>
021e03
 #include <sys/stat.h>
021e03
 #include <ctype.h>  /* isdigit */
021e03
@@ -220,12 +218,12 @@ static void *file_open(void *provctx, const char *uri)
021e03
      * There's a special case if the URI also contains an authority, then
021e03
      * the full URI shouldn't be used as a path anywhere.
021e03
      */
021e03
-    if (strncasecmp(uri, "file:", 5) == 0) {
021e03
+    if (OPENSSL_strncasecmp(uri, "file:", 5) == 0) {
021e03
         const char *p = &uri[5];
021e03
 
021e03
         if (strncmp(&uri[5], "//", 2) == 0) {
021e03
             path_data_n--;           /* Invalidate using the full URI */
021e03
-            if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
021e03
+            if (OPENSSL_strncasecmp(&uri[7], "localhost/", 10) == 0) {
021e03
                 p = &uri[16];
021e03
             } else if (uri[7] == '/') {
021e03
                 p = &uri[7];
021e03
@@ -592,7 +590,8 @@ static int file_name_check(struct file_ctx_st *ctx, const char *name)
021e03
     /*
021e03
      * First, check the basename
021e03
      */
021e03
-    if (strncasecmp(name, ctx->_.dir.search_name, len) != 0 || name[len] != '.')
021e03
+    if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0
021e03
+        || name[len] != '.')
021e03
         return 0;
021e03
     p = &name[len + 1];
021e03
 
021e03
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
021e03
index deb0c9aaa650..ae97c38b1597 100644
021e03
--- a/ssl/ssl_conf.c
021e03
+++ b/ssl/ssl_conf.c
021e03
@@ -148,7 +148,8 @@ static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
021e03
     if (namelen == -1) {
021e03
         if (strcmp(tbl->name, name))
021e03
             return 0;
021e03
-    } else if (tbl->namelen != namelen || strncasecmp(tbl->name, name, namelen))
021e03
+    } else if (tbl->namelen != namelen
021e03
+               || OPENSSL_strncasecmp(tbl->name, name, namelen))
021e03
         return 0;
021e03
     ssl_set_option(cctx, tbl->name_flags, tbl->option_value, onoff);
021e03
     return 1;
021e03
@@ -232,8 +233,8 @@ static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
021e03
 
021e03
     /* Ignore values supported by 1.0.2 for the automatic selection */
021e03
     if ((cctx->flags & SSL_CONF_FLAG_FILE)
021e03
-            && (strcasecmp(value, "+automatic") == 0
021e03
-                || strcasecmp(value, "automatic") == 0))
021e03
+            && (OPENSSL_strcasecmp(value, "+automatic") == 0
021e03
+                || OPENSSL_strcasecmp(value, "automatic") == 0))
021e03
         return 1;
021e03
     if ((cctx->flags & SSL_CONF_FLAG_CMDLINE) &&
021e03
         strcmp(value, "auto") == 0)
021e03
@@ -812,7 +813,7 @@ static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
021e03
             strncmp(*pcmd, cctx->prefix, cctx->prefixlen))
021e03
             return 0;
021e03
         if (cctx->flags & SSL_CONF_FLAG_FILE &&
021e03
-            strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
021e03
+            OPENSSL_strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen))
021e03
             return 0;
021e03
         *pcmd += cctx->prefixlen;
021e03
     } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) {
021e03
@@ -854,7 +855,7 @@ static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
021e03
                     return t;
021e03
             }
021e03
             if (cctx->flags & SSL_CONF_FLAG_FILE) {
021e03
-                if (t->str_file && strcasecmp(t->str_file, cmd) == 0)
021e03
+                if (t->str_file && OPENSSL_strcasecmp(t->str_file, cmd) == 0)
021e03
                     return t;
021e03
             }
021e03
         }
021e03
diff --git a/test/bntest.c b/test/bntest.c
021e03
index 4c1ee0c13b6d..c5894c157b3c 100644
021e03
--- a/test/bntest.c
021e03
+++ b/test/bntest.c
021e03
@@ -10,9 +10,6 @@
021e03
 #include <errno.h>
021e03
 #include <stdio.h>
021e03
 #include <string.h>
021e03
-#ifdef __TANDEM
021e03
-# include <strings.h> /* strcasecmp */
021e03
-#endif
021e03
 #include <ctype.h>
021e03
 
021e03
 #include <openssl/bn.h>
021e03
@@ -23,10 +20,6 @@
021e03
 #include "internal/numbers.h"
021e03
 #include "testutil.h"
021e03
 
021e03
-#ifdef OPENSSL_SYS_WINDOWS
021e03
-# define strcasecmp _stricmp
021e03
-#endif
021e03
-
021e03
 /*
021e03
  * Things in boring, not in openssl.
021e03
  */
021e03
@@ -64,7 +57,7 @@ static const char *findattr(STANZA *s, const char *key)
021e03
     PAIR *pp = s->pairs;
021e03
 
021e03
     for ( ; --i >= 0; pp++)
021e03
-        if (strcasecmp(pp->key, key) == 0)
021e03
+        if (OPENSSL_strcasecmp(pp->key, key) == 0)
021e03
             return pp->value;
021e03
     return NULL;
021e03
 }
021e03
diff --git a/test/build.info b/test/build.info
021e03
index 0f379e11e222..14a84f00a258 100644
021e03
--- a/test/build.info
021e03
+++ b/test/build.info
021e03
@@ -37,7 +37,7 @@ IF[{- !$disabled{tests} -}]
021e03
           sanitytest rsa_complex exdatatest bntest \
021e03
           ecstresstest gmdifftest pbelutest \
021e03
           destest mdc2test sha_test \
021e03
-          exptest pbetest \
021e03
+          exptest pbetest localetest \
021e03
           evp_pkey_provided_test evp_test evp_extra_test evp_extra_test2 \
021e03
           evp_fetch_prov_test evp_libctx_test ossl_store_test \
021e03
           v3nametest v3ext \
021e03
@@ -135,6 +135,10 @@ IF[{- !$disabled{tests} -}]
021e03
   INCLUDE[exptest]=../include ../apps/include
021e03
   DEPEND[exptest]=../libcrypto libtestutil.a
021e03
 
021e03
+  SOURCE[localetest]=localetest.c
021e03
+  INCLUDE[localetest]=../include ../apps/include
021e03
+  DEPEND[localetest]=../libcrypto libtestutil.a
021e03
+
021e03
   SOURCE[pbetest]=pbetest.c
021e03
   INCLUDE[pbetest]=../include ../apps/include
021e03
   DEPEND[pbetest]=../libcrypto libtestutil.a
021e03
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
021e03
index 826e558cc0cd..3b597617791a 100644
021e03
--- a/test/evp_extra_test.c
021e03
+++ b/test/evp_extra_test.c
021e03
@@ -35,7 +35,6 @@
021e03
 #include "internal/nelem.h"
021e03
 #include "internal/sizes.h"
021e03
 #include "crypto/evp.h"
021e03
-#include "../e_os.h" /* strcasecmp */
021e03
 
021e03
 static OSSL_LIB_CTX *testctx = NULL;
021e03
 static char *testpropq = NULL;
021e03
@@ -1739,7 +1738,7 @@ static int ec_export_get_encoding_cb(const OSSL_PARAM params[], void *arg)
021e03
         return 0;
021e03
 
021e03
     for (i = 0; i < OSSL_NELEM(ec_encodings); i++) {
021e03
-        if (strcasecmp(enc_name, ec_encodings[i].encoding_name) == 0) {
021e03
+        if (OPENSSL_strcasecmp(enc_name, ec_encodings[i].encoding_name) == 0) {
021e03
             *enc = ec_encodings[i].encoding;
021e03
             break;
021e03
         }
021e03
diff --git a/test/evp_libctx_test.c b/test/evp_libctx_test.c
021e03
index e2663dc02998..9b2f4a016893 100644
021e03
--- a/test/evp_libctx_test.c
021e03
+++ b/test/evp_libctx_test.c
021e03
@@ -33,7 +33,6 @@
021e03
 #include "testutil.h"
021e03
 #include "internal/nelem.h"
021e03
 #include "crypto/bn_dh.h"   /* _bignum_ffdhe2048_p */
021e03
-#include "../e_os.h"        /* strcasecmp */
021e03
 
021e03
 static OSSL_LIB_CTX *libctx = NULL;
021e03
 static OSSL_PROVIDER *nullprov = NULL;
021e03
@@ -478,7 +477,7 @@ static int test_cipher_reinit_partialupdate(int test_id)
021e03
 
021e03
 static int name_cmp(const char * const *a, const char * const *b)
021e03
 {
021e03
-    return strcasecmp(*a, *b);
021e03
+    return OPENSSL_strcasecmp(*a, *b);
021e03
 }
021e03
 
021e03
 static void collect_cipher_names(EVP_CIPHER *cipher, void *cipher_names_list)
021e03
diff --git a/test/evp_test.c b/test/evp_test.c
021e03
index 7a5b9345e0db..8a0758f857a5 100644
021e03
--- a/test/evp_test.c
021e03
+++ b/test/evp_test.c
021e03
@@ -12,7 +12,6 @@
021e03
 #include <string.h>
021e03
 #include <stdlib.h>
021e03
 #include <ctype.h>
021e03
-#include "../e_os.h" /* strcasecmp */
021e03
 #include <openssl/evp.h>
021e03
 #include <openssl/pem.h>
021e03
 #include <openssl/err.h>
021e03
@@ -3886,9 +3885,9 @@ void cleanup_tests(void)
021e03
     OSSL_LIB_CTX_free(libctx);
021e03
 }
021e03
 
021e03
-#define STR_STARTS_WITH(str, pre) strncasecmp(pre, str, strlen(pre)) == 0
021e03
+#define STR_STARTS_WITH(str, pre) OPENSSL_strncasecmp(pre, str, strlen(pre)) == 0
021e03
 #define STR_ENDS_WITH(str, pre)                                                \
021e03
-strlen(str) < strlen(pre) ? 0 : (strcasecmp(pre, str + strlen(str) - strlen(pre)) == 0)
021e03
+strlen(str) < strlen(pre) ? 0 : (OPENSSL_strcasecmp(pre, str + strlen(str) - strlen(pre)) == 0)
021e03
 
021e03
 static int is_digest_disabled(const char *name)
021e03
 {
021e03
@@ -3897,31 +3896,31 @@ static int is_digest_disabled(const char *name)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_MD2
021e03
-    if (strcasecmp(name, "MD2") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "MD2") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_MDC2
021e03
-    if (strcasecmp(name, "MDC2") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "MDC2") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_MD4
021e03
-    if (strcasecmp(name, "MD4") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "MD4") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_MD5
021e03
-    if (strcasecmp(name, "MD5") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "MD5") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_RMD160
021e03
-    if (strcasecmp(name, "RIPEMD160") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "RIPEMD160") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_SM3
021e03
-    if (strcasecmp(name, "SM3") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "SM3") == 0)
021e03
         return 1;
021e03
 #endif
021e03
 #ifdef OPENSSL_NO_WHIRLPOOL
021e03
-    if (strcasecmp(name, "WHIRLPOOL") == 0)
021e03
+    if (OPENSSL_strcasecmp(name, "WHIRLPOOL") == 0)
021e03
         return 1;
021e03
 #endif
021e03
     return 0;
021e03
diff --git a/test/helpers/ssl_test_ctx.c b/test/helpers/ssl_test_ctx.c
021e03
index 1374b04cf02f..7236ffd4a6ac 100644
021e03
--- a/test/helpers/ssl_test_ctx.c
021e03
+++ b/test/helpers/ssl_test_ctx.c
021e03
@@ -16,21 +16,17 @@
021e03
 #include "ssl_test_ctx.h"
021e03
 #include "../testutil.h"
021e03
 
021e03
-#ifdef OPENSSL_SYS_WINDOWS
021e03
-# define strcasecmp _stricmp
021e03
-#endif
021e03
-
021e03
 static const int default_app_data_size = 256;
021e03
 /* Default set to be as small as possible to exercise fragmentation. */
021e03
 static const int default_max_fragment_size = 512;
021e03
 
021e03
 static int parse_boolean(const char *value, int *result)
021e03
 {
021e03
-    if (strcasecmp(value, "Yes") == 0) {
021e03
+    if (OPENSSL_strcasecmp(value, "Yes") == 0) {
021e03
         *result = 1;
021e03
         return 1;
021e03
     }
021e03
-    else if (strcasecmp(value, "No") == 0) {
021e03
+    else if (OPENSSL_strcasecmp(value, "No") == 0) {
021e03
         *result = 0;
021e03
         return 1;
021e03
     }
021e03
diff --git a/test/localetest.c b/test/localetest.c
021e03
new file mode 100644
021e03
index 000000000000..3db66b7a9e5f
021e03
--- /dev/null
021e03
+++ b/test/localetest.c
021e03
@@ -0,0 +1,122 @@
021e03
+
021e03
+#include <stdio.h>
021e03
+#include <string.h>
021e03
+#include <openssl/x509.h>
021e03
+#include "testutil.h"
021e03
+#include "testutil/output.h"
021e03
+
021e03
+#include <stdio.h>
021e03
+#include <stdlib.h>
021e03
+#include <locale.h>
021e03
+#ifdef OPENSSL_SYS_WINDOWS
021e03
+# define strcasecmp _stricmp
021e03
+#else
021e03
+# include <strings.h>
021e03
+#endif
021e03
+
021e03
+int setup_tests(void)
021e03
+{
021e03
+  const unsigned char der_bytes[] = {
021e03
+  0x30, 0x82, 0x03, 0x09, 0x30, 0x82, 0x01, 0xf1, 0xa0, 0x03, 0x02, 0x01,
021e03
+  0x02, 0x02, 0x14, 0x08, 0xe0, 0x8c, 0xd3, 0xf3, 0xbf, 0x2c, 0xf2, 0x0d,
021e03
+  0x0a, 0x75, 0xd1, 0xe8, 0xea, 0xbe, 0x70, 0x61, 0xd9, 0x67, 0xf9, 0x30,
021e03
+  0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
021e03
+  0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
021e03
+  0x03, 0x0c, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
021e03
+  0x30, 0x1e, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x34, 0x31, 0x31, 0x31, 0x34,
021e03
+  0x31, 0x39, 0x35, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x31,
021e03
+  0x31, 0x31, 0x34, 0x31, 0x39, 0x35, 0x37, 0x5a, 0x30, 0x14, 0x31, 0x12,
021e03
+  0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x6c, 0x6f, 0x63,
021e03
+  0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
021e03
+  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
021e03
+  0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
021e03
+  0x01, 0x01, 0x00, 0xc3, 0x1f, 0x5c, 0x56, 0x46, 0x8d, 0x69, 0xb6, 0x48,
021e03
+  0x3c, 0xbf, 0xe2, 0x0f, 0xa7, 0x4a, 0x44, 0x72, 0x74, 0x36, 0xfe, 0xe8,
021e03
+  0x2f, 0x10, 0x4a, 0xe9, 0x46, 0x45, 0x72, 0x5e, 0x48, 0xdd, 0x75, 0xab,
021e03
+  0xd9, 0x63, 0x91, 0x37, 0x93, 0x46, 0x28, 0x7e, 0x45, 0x94, 0x4b, 0x8a,
021e03
+  0xd5, 0x05, 0x2b, 0x9a, 0x01, 0x96, 0x30, 0xde, 0xcc, 0x14, 0x2d, 0x06,
021e03
+  0x09, 0x1b, 0x7d, 0x50, 0x14, 0x99, 0x36, 0x6b, 0x97, 0x6e, 0xc9, 0xb1,
021e03
+  0x69, 0x70, 0xcd, 0x9b, 0x74, 0x24, 0x9a, 0xe2, 0xd4, 0xc0, 0x1e, 0xbc,
021e03
+  0xec, 0xf6, 0x7a, 0xbb, 0xa0, 0x53, 0x93, 0xf8, 0x68, 0x9a, 0x18, 0xa1,
021e03
+  0xa1, 0x5c, 0x47, 0x93, 0xd1, 0x4c, 0x36, 0x8c, 0x00, 0xb3, 0x66, 0xda,
021e03
+  0xf1, 0x05, 0xb2, 0x3a, 0xad, 0x7e, 0x4b, 0xf3, 0xd3, 0x93, 0xfa, 0x59,
021e03
+  0x09, 0x9c, 0x60, 0x37, 0x69, 0x61, 0xe8, 0x5a, 0x33, 0xc6, 0xb2, 0x1a,
021e03
+  0xba, 0x36, 0xe2, 0xb3, 0x58, 0xe9, 0x73, 0x01, 0x2d, 0x36, 0x48, 0x36,
021e03
+  0x94, 0xe4, 0xb2, 0xa4, 0x5b, 0xdf, 0x3d, 0x5f, 0x62, 0x9f, 0xd9, 0xf3,
021e03
+  0x24, 0x0c, 0xf0, 0x2f, 0x71, 0x44, 0x79, 0x13, 0x70, 0x95, 0xa7, 0xbe,
021e03
+  0xea, 0x0a, 0x08, 0x0a, 0xa6, 0x4b, 0xe9, 0x58, 0x6b, 0xa4, 0xc2, 0xed,
021e03
+  0x74, 0x1e, 0xb0, 0x3b, 0x59, 0xd5, 0xe6, 0xdb, 0x8f, 0x58, 0x6a, 0xa3,
021e03
+  0x7d, 0x52, 0x40, 0xec, 0x72, 0xb7, 0xba, 0x7e, 0x30, 0x9d, 0x12, 0x57,
021e03
+  0xf2, 0x48, 0xae, 0x80, 0x0d, 0x0a, 0xf4, 0xfd, 0x24, 0xed, 0xd8, 0x05,
021e03
+  0xb2, 0x96, 0x44, 0x02, 0x3e, 0x6e, 0x25, 0xb0, 0xc4, 0x93, 0xda, 0xfe,
021e03
+  0x78, 0xd9, 0xbb, 0xd2, 0x71, 0x69, 0x70, 0x7f, 0xba, 0xf7, 0xb0, 0x4f,
021e03
+  0x14, 0xf7, 0x98, 0x71, 0x01, 0x6c, 0xec, 0x6f, 0x76, 0x03, 0x59, 0xff,
021e03
+  0xe2, 0xba, 0x8d, 0xd9, 0x21, 0x08, 0xb3, 0x02, 0x03, 0x01, 0x00, 0x01,
021e03
+  0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
021e03
+  0x16, 0x04, 0x14, 0x59, 0xb8, 0x6e, 0x1a, 0x72, 0xe9, 0x27, 0x1e, 0xbf,
021e03
+  0x80, 0x87, 0x0f, 0xa9, 0xd0, 0x06, 0x6a, 0x11, 0x30, 0x77, 0x8e, 0x30,
021e03
+  0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
021e03
+  0x59, 0xb8, 0x6e, 0x1a, 0x72, 0xe9, 0x27, 0x1e, 0xbf, 0x80, 0x87, 0x0f,
021e03
+  0xa9, 0xd0, 0x06, 0x6a, 0x11, 0x30, 0x77, 0x8e, 0x30, 0x0f, 0x06, 0x03,
021e03
+  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
021e03
+  0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
021e03
+  0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x98, 0x76, 0x9e,
021e03
+  0x3c, 0xfc, 0x3f, 0x58, 0xe8, 0xf2, 0x1f, 0x2e, 0x11, 0xa2, 0x59, 0xfa,
021e03
+  0x27, 0xb5, 0xec, 0x9d, 0x97, 0x05, 0x06, 0x2c, 0x95, 0xa5, 0x28, 0x88,
021e03
+  0x86, 0xeb, 0x4e, 0x8a, 0x62, 0xe9, 0x87, 0x78, 0xd8, 0x18, 0x22, 0x4e,
021e03
+  0xb1, 0x8d, 0x46, 0x4a, 0x4c, 0x6e, 0x7c, 0x53, 0x62, 0x2c, 0xf2, 0x7a,
021e03
+  0x95, 0xa0, 0x1a, 0x30, 0x18, 0x6a, 0x31, 0x6f, 0x3f, 0x55, 0x25, 0x9f,
021e03
+  0x67, 0x60, 0x68, 0x99, 0x0f, 0x41, 0x09, 0xc8, 0xe2, 0x04, 0x33, 0x22,
021e03
+  0x1a, 0xe9, 0xf3, 0xae, 0xce, 0xb6, 0x83, 0x64, 0x78, 0x66, 0x14, 0xc9,
021e03
+  0x54, 0xc8, 0x34, 0x70, 0x96, 0xaf, 0x16, 0xcd, 0xb8, 0xdf, 0x81, 0x7e,
021e03
+  0xf0, 0xa6, 0x7d, 0xc1, 0x13, 0xb2, 0x76, 0x3a, 0xd5, 0x7e, 0x68, 0x8c,
021e03
+  0xd5, 0x00, 0x70, 0x82, 0x23, 0x7e, 0x5e, 0xc9, 0x31, 0x2f, 0x33, 0x54,
021e03
+  0xaa, 0xaf, 0xcd, 0xe9, 0x38, 0x9a, 0x23, 0x53, 0xad, 0x4e, 0x72, 0xa7,
021e03
+  0x6f, 0x47, 0x60, 0xc9, 0xd3, 0x06, 0x9b, 0x7a, 0x21, 0xc6, 0xe9, 0xdb,
021e03
+  0x3c, 0xaa, 0xc0, 0x21, 0x29, 0x5f, 0x44, 0x6a, 0x45, 0x90, 0x73, 0x5e,
021e03
+  0x6d, 0x78, 0x82, 0xcb, 0x42, 0xe6, 0xba, 0x67, 0xb2, 0xe6, 0xa2, 0x15,
021e03
+  0x04, 0xea, 0x69, 0xae, 0x3e, 0xc0, 0x0c, 0x10, 0x99, 0xec, 0xa9, 0xb0,
021e03
+  0x7e, 0xe8, 0x94, 0xe2, 0xf3, 0xaf, 0xf7, 0x9f, 0x65, 0xe7, 0xd7, 0xe2,
021e03
+  0x49, 0xfa, 0x52, 0x7d, 0xb5, 0xfd, 0xa0, 0xa5, 0xe0, 0x49, 0xa7, 0x3d,
021e03
+  0x94, 0x20, 0x2d, 0xec, 0x8c, 0x22, 0xa5, 0xa4, 0x43, 0xfa, 0x7e, 0xd0,
021e03
+  0x50, 0x21, 0xb8, 0x67, 0x18, 0x44, 0x69, 0x8f, 0xdd, 0x47, 0x41, 0xc6,
021e03
+  0x35, 0xe0, 0xe9, 0x2e, 0x41, 0xa9, 0x6f, 0x41, 0xee, 0xb9, 0xbd, 0x45,
021e03
+  0xf3, 0x88, 0xc1, 0x23, 0x35, 0x96, 0xba, 0xf8, 0xcd, 0x4b, 0x83, 0x73,
021e03
+  0x5f
021e03
+};
021e03
+
021e03
+    char str1[] = "SubjectPublicKeyInfo", str2[] = "subjectpublickeyinfo";
021e03
+    int res;
021e03
+    X509 *cert = NULL;
021e03
+    X509_PUBKEY *cert_pubkey = NULL;
021e03
+    const unsigned char *p = der_bytes;
021e03
+
021e03
+    TEST_ptr(setlocale(LC_ALL, ""));
021e03
+
021e03
+    res = strcasecmp(str1, str2);
021e03
+    TEST_note("Case-insensitive comparison via strcasecmp in current locale %s\n", res ? "failed" : "succeeded");
021e03
+
021e03
+    TEST_false(OPENSSL_strcasecmp(str1, str2));
021e03
+
021e03
+    cert = d2i_X509(NULL, &p, sizeof(der_bytes));
021e03
+    if (!TEST_ptr(cert))
021e03
+        return 0;
021e03
+
021e03
+    cert_pubkey = X509_get_X509_PUBKEY(cert);
021e03
+    if (!TEST_ptr(cert_pubkey)) {
021e03
+        X509_free(cert);
021e03
+        return 0;
021e03
+    }
021e03
+
021e03
+    if (!TEST_ptr(X509_PUBKEY_get0(cert_pubkey))) {
021e03
+        X509_free(cert);
021e03
+        return 0;
021e03
+    }
021e03
+
021e03
+    X509_free(cert);
021e03
+    return 1;
021e03
+}
021e03
+
021e03
+void cleanup_tests(void)
021e03
+{
021e03
+}
021e03
diff --git a/test/params_conversion_test.c b/test/params_conversion_test.c
021e03
index 9422ef14734a..710c2a9a2e9f 100644
021e03
--- a/test/params_conversion_test.c
021e03
+++ b/test/params_conversion_test.c
021e03
@@ -15,10 +15,6 @@
021e03
 /* On machines that dont support <inttypes.h> just disable the tests */
021e03
 #if !defined(OPENSSL_NO_INTTYPES_H)
021e03
 
021e03
-# ifdef OPENSSL_SYS_WINDOWS
021e03
-#  define strcasecmp _stricmp
021e03
-# endif
021e03
-
021e03
 # ifdef OPENSSL_SYS_VMS
021e03
 #  define strtoumax strtoull
021e03
 #  define strtoimax strtoll
021e03
@@ -62,7 +58,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
 
021e03
     for (i = 0; i < s->numpairs; i++, pp++) {
021e03
         p = "";
021e03
-        if (strcasecmp(pp->key, "type") == 0) {
021e03
+        if (OPENSSL_strcasecmp(pp->key, "type") == 0) {
021e03
             if (type != NULL) {
021e03
                 TEST_info("Line %d: multiple type lines", s->curr);
021e03
                 return 0;
021e03
@@ -72,48 +68,48 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
                 TEST_info("Line %d: unknown type line", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-        } else if (strcasecmp(pp->key, "int32") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(pp->key, "int32") == 0) {
021e03
             if (def_i32++) {
021e03
                 TEST_info("Line %d: multiple int32 lines", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-            if (strcasecmp(pp->value, "invalid") != 0) {
021e03
+            if (OPENSSL_strcasecmp(pp->value, "invalid") != 0) {
021e03
                 pc->valid_i32 = 1;
021e03
                 pc->i32 = (int32_t)strtoimax(pp->value, &p, 10);
021e03
             }
021e03
-        } else if (strcasecmp(pp->key, "int64") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(pp->key, "int64") == 0) {
021e03
             if (def_i64++) {
021e03
                 TEST_info("Line %d: multiple int64 lines", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-            if (strcasecmp(pp->value, "invalid") != 0) {
021e03
+            if (OPENSSL_strcasecmp(pp->value, "invalid") != 0) {
021e03
                 pc->valid_i64 = 1;
021e03
                 pc->i64 = (int64_t)strtoimax(pp->value, &p, 10);
021e03
             }
021e03
-        } else if (strcasecmp(pp->key, "uint32") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(pp->key, "uint32") == 0) {
021e03
             if (def_u32++) {
021e03
                 TEST_info("Line %d: multiple uint32 lines", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-            if (strcasecmp(pp->value, "invalid") != 0) {
021e03
+            if (OPENSSL_strcasecmp(pp->value, "invalid") != 0) {
021e03
                 pc->valid_u32 = 1;
021e03
                 pc->u32 = (uint32_t)strtoumax(pp->value, &p, 10);
021e03
             }
021e03
-        } else if (strcasecmp(pp->key, "uint64") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(pp->key, "uint64") == 0) {
021e03
             if (def_u64++) {
021e03
                 TEST_info("Line %d: multiple uint64 lines", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-            if (strcasecmp(pp->value, "invalid") != 0) {
021e03
+            if (OPENSSL_strcasecmp(pp->value, "invalid") != 0) {
021e03
                 pc->valid_u64 = 1;
021e03
                 pc->u64 = (uint64_t)strtoumax(pp->value, &p, 10);
021e03
             }
021e03
-        } else if (strcasecmp(pp->key, "double") == 0) {
021e03
+        } else if (OPENSSL_strcasecmp(pp->key, "double") == 0) {
021e03
             if (def_d++) {
021e03
                 TEST_info("Line %d: multiple double lines", s->curr);
021e03
                 return 0;
021e03
             }
021e03
-            if (strcasecmp(pp->value, "invalid") != 0) {
021e03
+            if (OPENSSL_strcasecmp(pp->value, "invalid") != 0) {
021e03
                 pc->valid_d = 1;
021e03
                 pc->d = strtod(pp->value, &p);
021e03
             }
021e03
@@ -133,7 +129,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
         return 0;
021e03
     }
021e03
 
021e03
-    if (strcasecmp(type, "int32") == 0) {
021e03
+    if (OPENSSL_strcasecmp(type, "int32") == 0) {
021e03
         if (!TEST_true(def_i32) || !TEST_true(pc->valid_i32)) {
021e03
             TEST_note("errant int32 on line %d", s->curr);
021e03
             return 0;
021e03
@@ -142,7 +138,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
         pc->datum = &datum_i32;
021e03
         pc->ref = &ref_i32;
021e03
         pc->size = sizeof(ref_i32);
021e03
-    } else if (strcasecmp(type, "int64") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "int64") == 0) {
021e03
         if (!TEST_true(def_i64) || !TEST_true(pc->valid_i64)) {
021e03
             TEST_note("errant int64 on line %d", s->curr);
021e03
             return 0;
021e03
@@ -151,7 +147,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
         pc->datum = &datum_i64;
021e03
         pc->ref = &ref_i64;
021e03
         pc->size = sizeof(ref_i64);
021e03
-    } else if (strcasecmp(type, "uint32") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "uint32") == 0) {
021e03
         if (!TEST_true(def_u32) || !TEST_true(pc->valid_u32)) {
021e03
             TEST_note("errant uint32 on line %d", s->curr);
021e03
             return 0;
021e03
@@ -160,7 +156,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
         pc->datum = &datum_u32;
021e03
         pc->ref = &ref_u32;
021e03
         pc->size = sizeof(ref_u32);
021e03
-    } else if (strcasecmp(type, "uint64") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "uint64") == 0) {
021e03
         if (!TEST_true(def_u64) || !TEST_true(pc->valid_u64)) {
021e03
             TEST_note("errant uint64 on line %d", s->curr);
021e03
             return 0;
021e03
@@ -169,7 +165,7 @@ static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s)
021e03
         pc->datum = &datum_u64;
021e03
         pc->ref = &ref_u64;
021e03
         pc->size = sizeof(ref_u64);
021e03
-    } else if (strcasecmp(type, "double") == 0) {
021e03
+    } else if (OPENSSL_strcasecmp(type, "double") == 0) {
021e03
         if (!TEST_true(def_d) || !TEST_true(pc->valid_d)) {
021e03
             TEST_note("errant double on line %d", s->curr);
021e03
             return 0;
021e03
diff --git a/test/recipes/02-test_localetest.t b/test/recipes/02-test_localetest.t
021e03
new file mode 100644
021e03
index 000000000000..1bccd57d4c63
021e03
--- /dev/null
021e03
+++ b/test/recipes/02-test_localetest.t
021e03
@@ -0,0 +1,24 @@
021e03
+#! /usr/bin/env perl
021e03
+# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
021e03
+# Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
021e03
+#
021e03
+# Licensed under the Apache License 2.0 (the "License").  You may not use
021e03
+# this file except in compliance with the License.  You can obtain a copy
021e03
+# in the file LICENSE in the source distribution or at
021e03
+# https://www.openssl.org/source/license.html
021e03
+
021e03
+use OpenSSL::Test;
021e03
+use OpenSSL::Test::Utils;
021e03
+
021e03
+setup("locale tests");
021e03
+
021e03
+plan skip_all => "Locale tests not available on Windows or VMS"
021e03
+    if $^O =~ /^(VMS|MSWin32)$/;
021e03
+
021e03
+plan tests => 2;
021e03
+
021e03
+$ENV{LANG} = "C";
021e03
+ok(run(test(["localetest"])), "running localetest");
021e03
+
021e03
+$ENV{LANG} = "tr_TR.UTF-8";
021e03
+ok(run(test(["localetest"])), "running localetest with Turkish locale");
021e03
diff --git a/test/ssl_old_test.c b/test/ssl_old_test.c
021e03
index b07b98062494..5fb54a3a2eb1 100644
021e03
--- a/test/ssl_old_test.c
021e03
+++ b/test/ssl_old_test.c
021e03
@@ -216,7 +216,7 @@ static int servername_cb(SSL *s, int *ad, void *arg)
021e03
 
021e03
     if (servername) {
021e03
         if (s_ctx2 != NULL && sn_server2 != NULL &&
021e03
-            !strcasecmp(servername, sn_server2)) {
021e03
+            !OPENSSL_strcasecmp(servername, sn_server2)) {
021e03
             BIO_printf(bio_stdout, "Switching server context.\n");
021e03
             SSL_set_SSL_CTX(s, s_ctx2);
021e03
         }
021e03
diff --git a/test/v3nametest.c b/test/v3nametest.c
021e03
index 06d713b2feb1..ce1f4949fef2 100644
021e03
--- a/test/v3nametest.c
021e03
+++ b/test/v3nametest.c
021e03
@@ -15,10 +15,6 @@
021e03
 #include "internal/nelem.h"
021e03
 #include "testutil.h"
021e03
 
021e03
-#ifdef OPENSSL_SYS_WINDOWS
021e03
-# define strcasecmp _stricmp
021e03
-#endif
021e03
-
021e03
 static const char *const names[] = {
021e03
     "a", "b", ".", "*", "@",
021e03
     ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
021e03
@@ -287,7 +283,7 @@ static int run_cert(X509 *crt, const char *nameincert,
021e03
     int failed = 0;
021e03
 
021e03
     for (; *pname != NULL; ++pname) {
021e03
-        int samename = strcasecmp(nameincert, *pname) == 0;
021e03
+        int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
021e03
         size_t namelen = strlen(*pname);
021e03
         char *name = OPENSSL_malloc(namelen + 1);
021e03
         int match, ret;
021e03
diff --git a/util/libcrypto.num b/util/libcrypto.num
021e03
index 10b4e57d7969..1b9b23878e83 100644
021e03
--- a/util/libcrypto.num
021e03
+++ b/util/libcrypto.num
021e03
@@ -5425,3 +5425,5 @@ ASN1_item_d2i_ex                        5552	3_0_0	EXIST::FUNCTION:
021e03
 ossl_safe_getenv                        ?	3_0_0	EXIST::FUNCTION:
021e03
 ossl_ctx_legacy_digest_signatures_allowed ?	3_0_1	EXIST::FUNCTION:
021e03
 ossl_ctx_legacy_digest_signatures_allowed_set ?	3_0_1	EXIST::FUNCTION:
021e03
+OPENSSL_strcasecmp                      ?	3_0_1	EXIST::FUNCTION:
021e03
+OPENSSL_strncasecmp                     ?	3_0_1	EXIST::FUNCTION: