+
+int OPENSSL_hexchar2int(unsigned char c)
+{
+#ifdef CHARSET_EBCDIC
+ c = os_toebcdic[c];
+#endif
+
+ switch (c) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a': case 'A':
+ return 0x0A;
+ case 'b': case 'B':
+ return 0x0B;
+ case 'c': case 'C':
+ return 0x0C;
+ case 'd': case 'D':
+ return 0x0D;
+ case 'e': case 'E':
+ return 0x0E;
+ case 'f': case 'F':
+ return 0x0F;
+ }
+ return -1;
+}
+
+/*
+ * Give a string of hex digits convert to a buffer
+ */
+unsigned char *OPENSSL_hexstr2buf(const char *str, long *len)
+{
+ unsigned char *hexbuf, *q;
+ unsigned char ch, cl;
+ int chi, cli;
+ const unsigned char *p;
+ size_t s;
+
+ s = strlen(str);
+ if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) {
+ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
+ ch = *p++;
+ if (ch == ':')
+ continue;
+ cl = *p++;
+ if (!cl) {
+ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF,
+ CRYPTO_R_ODD_NUMBER_OF_DIGITS);
+ OPENSSL_free(hexbuf);
+ return NULL;
+ }
+ cli = OPENSSL_hexchar2int(cl);
+ chi = OPENSSL_hexchar2int(ch);
+ if (cli < 0 || chi < 0) {
+ OPENSSL_free(hexbuf);
+ CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
+ return NULL;
+ }
+ *q++ = (unsigned char)((chi << 4) | cli);
+ }
+
+ if (len)
+ *len = q - hexbuf;
+ return hexbuf;
+}
+
+/*
+ * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation @@@ (Contents of buffer are always kept in ASCII, also
+ * on EBCDIC machines)
+ */
+char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
+{
+ static const char hexdig[] = "0123456789ABCDEF";
+ char *tmp, *q;
+ const unsigned char *p;
+ int i;
+
+ if (len == 0)
+ {
+ return OPENSSL_zalloc(1);
+ }
+
+ if ((tmp = OPENSSL_malloc(len * 3)) == NULL) {
+ CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ q = tmp;
+ for (i = 0, p = buffer; i < len; i++, p++) {
+ *q++ = hexdig[(*p >> 4) & 0xf];
+ *q++ = hexdig[*p & 0xf];
+ *q++ = ':';
+ }
+ q[-1] = 0;
+#ifdef CHARSET_EBCDIC
+ ebcdic2ascii(tmp, tmp, q - tmp - 1);
+#endif
+
+ return tmp;
+}
+
+int openssl_strerror_r(int errnum, char *buf, size_t buflen)
+{
+#if defined(_MSC_VER) && _MSC_VER>=1400
+ return !strerror_s(buf, buflen, errnum);
+#elif defined(_GNU_SOURCE)
+ return strerror_r(errnum, buf, buflen) != NULL;
+#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
+ (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
+ /*
+ * We can use "real" strerror_r. The OpenSSL version differs in that it
+ * gives 1 on success and 0 on failure for consistency with other OpenSSL
+ * functions. Real strerror_r does it the other way around
+ */
+ return !strerror_r(errnum, buf, buflen);
+#else
+ char *err;
+ /* Fall back to non-thread safe strerror()...its all we can do */
+ if (buflen < 2)
+ return 0;
+ err = strerror(errnum);
+ /* Can this ever happen? */
+ if (err == NULL)
+ return 0;
+ strncpy(buf, err, buflen - 1);
+ buf[buflen - 1] = '\0';
+ return 1;
+#endif
+}