Support the EBCDIC character set and BS2000/OSD-POSIX (work in progress).

Submitted by: Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>
diff --git a/crypto/Makefile.ssl b/crypto/Makefile.ssl
index f155434..3c4b957 100644
--- a/crypto/Makefile.ssl
+++ b/crypto/Makefile.ssl
@@ -39,7 +39,7 @@
 
 SRC= $(LIBSRC)
 
-EXHEADER= crypto.h tmdiff.h opensslv.h opensslconf.h
+EXHEADER= crypto.h tmdiff.h opensslv.h opensslconf.h ebcdic.h
 HEADER=	cryptlib.h date.h $(EXHEADER)
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c
index 84440cc..226474f 100644
--- a/crypto/asn1/a_gentm.c
+++ b/crypto/asn1/a_gentm.c
@@ -65,6 +65,18 @@
 
 int i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a, unsigned char **pp)
 	{
+#ifdef CHARSET_EBCDIC
+	/* KLUDGE! We convert to ascii before writing DER */
+	int len;
+	char tmp[24];
+	ASN1_STRING tmpstr = *(ASN1_STRING *)a;
+
+	len = tmpstr.length;
+	ebcdic2ascii(tmp, tmpstr.data, (len >= sizeof tmp) ? sizeof tmp : len);
+	tmpstr.data = tmp;
+
+	a = (ASN1_GENERALIZEDTIME *) &tmpstr;
+#endif
 	return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
 		V_ASN1_GENERALIZEDTIME,V_ASN1_UNIVERSAL));
 	}
@@ -82,6 +94,9 @@
 		ASN1err(ASN1_F_D2I_ASN1_GENERALIZEDTIME,ERR_R_NESTED_ASN1_ERROR);
 		return(NULL);
 		}
+#ifdef CHARSET_EBCDIC
+	ascii2ebcdic(ret->data, ret->data, ret->length);
+#endif
 	if (!ASN1_GENERALIZEDTIME_check(ret))
 		{
 		ASN1err(ASN1_F_D2I_ASN1_GENERALIZEDTIME,ASN1_R_INVALID_TIME_FORMAT);
@@ -202,5 +217,8 @@
 		ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
 	s->length=strlen(p);
 	s->type=V_ASN1_GENERALIZEDTIME;
+#ifdef CHARSET_EBCDIC_not
+	ebcdic2ascii(s->data, s->data, s->length);
+#endif
 	return(s);
 	}
diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c
index 3d76290..cdec7a1 100644
--- a/crypto/asn1/a_print.c
+++ b/crypto/asn1/a_print.c
@@ -95,6 +95,7 @@
 	while ((*s) && (len-- != 0))
 		{
 		c= *(s++);
+#ifndef CHARSET_EBCDIC
 		if (!(	((c >= 'a') && (c <= 'z')) ||
 			((c >= 'A') && (c <= 'Z')) ||
 			(c == ' ') ||
@@ -108,6 +109,13 @@
 			ia5=1;
 		if (c&0x80)
 			t61=1;
+#else
+		if (!isalnum(c) && (c != ' ') &&
+		    strchr("'()+,-./:=?", c) == NULL)
+			ia5=1;
+		if (os_toascii[c] & 0x80)
+			t61=1;
+#endif
 		}
 	if (t61) return(V_ASN1_T61STRING);
 	if (ia5) return(V_ASN1_IA5STRING);
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c
index 718992d..c1690a5 100644
--- a/crypto/asn1/a_time.c
+++ b/crypto/asn1/a_time.c
@@ -68,6 +68,21 @@
 
 int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
 	{
+#ifdef CHARSET_EBCDIC
+	/* KLUDGE! We convert to ascii before writing DER */
+	char tmp[24];
+	ASN1_STRING tmpstr;
+
+	if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) {
+	    int len;
+
+	    tmpstr = *(ASN1_STRING *)a;
+	    len = tmpstr.length;
+	    ebcdic2ascii(tmp, tmpstr.data, (len >= sizeof tmp) ? sizeof tmp : len);
+	    tmpstr.data = tmp;
+	    a = (ASN1_GENERALIZEDTIME *) &tmpstr;
+	}
+#endif
 	if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
 				return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
 				     a->type ,V_ASN1_UNIVERSAL));
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c
index 2c605ef..688199f 100644
--- a/crypto/asn1/a_utctm.c
+++ b/crypto/asn1/a_utctm.c
@@ -68,8 +68,20 @@
 
 int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
 	{
+#ifndef CHARSET_EBCDIC
 	return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
 		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
+#else
+	/* KLUDGE! We convert to ascii before writing DER */
+	int len;
+	char tmp[24];
+	ASN1_STRING x = *(ASN1_STRING *)a;
+
+	len = x.length;
+	ebcdic2ascii(tmp, x.data, (len >= sizeof tmp) ? sizeof tmp : len);
+	x.data = tmp;
+	return i2d_ASN1_bytes(&x, pp, V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
+#endif
 	}
 
 
@@ -85,6 +97,9 @@
 		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ERR_R_NESTED_ASN1_ERROR);
 		return(NULL);
 		}
+#ifdef CHARSET_EBCDIC
+	ascii2ebcdic(ret->data, ret->data, ret->length);
+#endif
 	if (!ASN1_UTCTIME_check(ret))
 		{
 		ASN1err(ASN1_F_D2I_ASN1_UTCTIME,ASN1_R_INVALID_TIME_FORMAT);
@@ -238,5 +253,8 @@
 		ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
 	s->length=strlen(p);
 	s->type=V_ASN1_UTCTIME;
+#ifdef CHARSET_EBCDIC_not
+	ebcdic2ascii(s->data, s->data, s->length);
+#endif
 	return(s);
 	}
diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c
index 4d6c9b2..d81c50d 100644
--- a/crypto/asn1/f_int.c
+++ b/crypto/asn1/f_int.c
@@ -117,9 +117,18 @@
 
 		for (j=0; j<i; j++)
 			{
+#ifndef CHARSET_EBCDIC
 			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
 				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
 				((buf[j] >= 'A') && (buf[j] <= 'F'))))
+#else
+			/* This #ifdef is not strictly necessary, since
+			 * the characters A...F a...f 0...9 are contiguous
+			 * (yes, even in EBCDIC - but not the whole alphabet).
+			 * Nevertheless, isxdigit() is faster.
+			 */
+			if (!isxdigit(buf[j]))
+#endif
 				{
 				i=j;
 				break;
diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c
index 9bcc5a9..e6e9b9d 100644
--- a/crypto/asn1/f_string.c
+++ b/crypto/asn1/f_string.c
@@ -123,9 +123,18 @@
 
 		for (j=i-1; j>0; j--)
 			{
+#ifndef CHARSET_EBCDIC
 			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
 				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
 				((buf[j] >= 'A') && (buf[j] <= 'F'))))
+#else
+			/* This #ifdef is not strictly necessary, since
+			 * the characters A...F a...f 0...9 are contiguous
+			 * (yes, even in EBCDIC - but not the whole alphabet).
+			 * Nevertheless, isxdigit() is faster.
+			 */
+			if (!isxdigit(buf[j]))
+#endif
 				{
 				i=j;
 				break;
diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c
index 517290b..6f26427 100644
--- a/crypto/asn1/t_x509.c
+++ b/crypto/asn1/t_x509.c
@@ -357,6 +357,7 @@
 	c=s;
 	for (;;)
 		{
+#ifndef CHARSET_EBCDIC
 		if (	((*s == '/') &&
 				((s[1] >= 'A') && (s[1] <= 'Z') && (
 					(s[2] == '=') ||
@@ -364,6 +365,15 @@
 					(s[3] == '='))
 				 ))) ||
 			(*s == '\0'))
+#else
+		if (	((*s == '/') &&
+				(isupper(s[1]) && (
+					(s[2] == '=') ||
+					(isupper(s[2]) &&
+					(s[3] == '='))
+				 ))) ||
+			(*s == '\0'))
+#endif
 			{
 			if ((l <= 0) && !first)
 				{
diff --git a/crypto/bf/bftest.c b/crypto/bf/bftest.c
index 80182c0..5ff14b1 100644
--- a/crypto/bf/bftest.c
+++ b/crypto/bf/bftest.c
@@ -72,6 +72,10 @@
 #else
 #include <openssl/blowfish.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 char *bf_key[2]={
 	"abcdefghijklmnopqrstuvwxyz",
 	"Who is John Galt?"
@@ -351,9 +355,16 @@
 	unsigned char out[8]; 
 	BF_LONG len;
 
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(cbc_data, cbc_data, strlen(cbc_data));
+#endif
+
 	printf("testing blowfish in raw ecb mode\n");
 	for (n=0; n<2; n++)
 		{
+#ifdef CHARSET_EBCDIC
+		ebcdic2ascii(bf_key[n], bf_key[n], strlen(bf_key[n]));
+#endif
 		BF_set_key(&key,strlen(bf_key[n]),(unsigned char *)bf_key[n]);
 
 		data[0]=bf_plain[n][0];
diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c
index 71bbce8..a7cd828 100644
--- a/crypto/bio/b_dump.c
+++ b/crypto/bio/b_dump.c
@@ -102,7 +102,13 @@
       if (((i*DUMP_WIDTH)+j)>=len)
 	break;
       ch=((unsigned char)*((char *)(s)+i*DUMP_WIDTH+j)) & 0xff;
+#ifndef CHARSET_EBCDIC
       sprintf(tmp,"%c",((ch>=' ')&&(ch<='~'))?ch:'.');
+#else
+      sprintf(tmp,"%c",((ch>=os_toascii[' '])&&(ch<=os_toascii['~']))
+	      ? os_toebcdic[ch]
+	      : '.');
+#endif
       strcat(buf,tmp);
     }
     strcat(buf,"\n");
diff --git a/crypto/conf/conf_lcl.h b/crypto/conf/conf_lcl.h
index 4e5644e..f9a015d 100644
--- a/crypto/conf/conf_lcl.h
+++ b/crypto/conf/conf_lcl.h
@@ -71,6 +71,7 @@
 #define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \
 					CONF_PUNCTUATION)
 
+#ifndef CHARSET_EBCDIC
 #define IS_COMMENT(a)		(CONF_COMMENT&(CONF_type[(a)&0x7f]))
 #define IS_EOF(a)		((a) == '\0')
 #define IS_ESC(a)		((a) == '\\')
@@ -81,6 +82,19 @@
 				(CONF_type[(a)&0x7f]&CONF_ALPHA_NUMERIC_PUNCT)
 #define IS_QUOTE(a)		(CONF_type[(a)&0x7f]&CONF_QUOTE)
 
+#else /*CHARSET_EBCDIC*/
+
+#define IS_COMMENT(a)		(CONF_COMMENT&(CONF_type[os_toascii[a]&0x7f]))
+#define IS_EOF(a)		(os_toascii[a] == '\0')
+#define IS_ESC(a)		(os_toascii[a] == '\\')
+#define IS_NUMER(a)		(CONF_type[os_toascii[a]&0x7f]&CONF_NUMBER)
+#define IS_WS(a)		(CONF_type[os_toascii[a]&0x7f]&CONF_WS)
+#define IS_ALPHA_NUMERIC(a)	(CONF_type[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC)
+#define IS_ALPHA_NUMERIC_PUNCT(a) \
+				(CONF_type[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC_PUNCT)
+#define IS_QUOTE(a)		(CONF_type[os_toascii[a]&0x7f]&CONF_QUOTE)
+#endif /*CHARSET_EBCDIC*/
+
 static unsigned short CONF_type[128]={
 	0x008,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
 	0x000,0x010,0x010,0x000,0x000,0x010,0x000,0x000,
diff --git a/crypto/crypto.h b/crypto/crypto.h
index 283261c..8297b7d 100644
--- a/crypto/crypto.h
+++ b/crypto/crypto.h
@@ -70,6 +70,10 @@
 #include <openssl/stack.h>
 #include <openssl/opensslv.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 /* Backward compatibility to SSLeay */
 /* This is more to be used to check the correct DLL is being used
  * in the MS world. */
diff --git a/crypto/des/fcrypt.c b/crypto/des/fcrypt.c
index db24541..697167b 100644
--- a/crypto/des/fcrypt.c
+++ b/crypto/des/fcrypt.c
@@ -1,5 +1,13 @@
 /* NOCW */
 #include <stdio.h>
+#ifdef _OSD_POSIX
+#ifndef CHARSET_EBCDIC
+#define CHARSET_EBCDIC 1
+#endif
+#endif
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
 
 /* This version of crypt has been developed from my MIT compatable
  * DES library.
@@ -67,7 +75,37 @@
 	{
 	static char buff[14];
 
+#ifndef CHARSET_EBCDIC
 	return(des_fcrypt(buf,salt,buff));
+#else
+	char e_salt[2+1];
+	char e_buf[32+1];	/* replace 32 by 8 ? */
+	char *ret;
+
+	/* Copy at most 2 chars of salt */
+	if ((e_salt[0] = salt[0]) != '\0')
+	    e_salt[1] = salt[1];
+
+	/* Copy at most 32 chars of password */
+	strncpy (e_buf, buf, sizeof(e_buf));
+
+	/* Make sure we have a delimiter */
+	e_salt[sizeof(e_salt)-1] = e_buf[sizeof(e_buf)-1] = '\0';
+
+	/* Convert the e_salt to ASCII, as that's what des_fcrypt works on */
+	ebcdic2ascii(e_salt, e_salt, sizeof e_salt);
+
+	/* Convert the cleartext password to ASCII */
+	ebcdic2ascii(e_buf, e_buf, sizeof e_buf);
+
+	/* Encrypt it (from/to ASCII) */
+	ret = des_fcrypt(e_buf,e_salt,buff);
+
+	/* Convert the result back to EBCDIC */
+	ascii2ebcdic(ret, ret, strlen(ret));
+	
+	return ret;
+#endif
 	}
 
 
@@ -90,10 +128,17 @@
 	 * crypt to "*".  This was found when replacing the crypt in
 	 * our shared libraries.  People found that the disbled
 	 * accounts effectivly had no passwd :-(. */
+#ifndef CHARSET_EBCDIC
 	x=ret[0]=((salt[0] == '\0')?'A':salt[0]);
 	Eswap0=con_salt[x]<<2;
 	x=ret[1]=((salt[1] == '\0')?'A':salt[1]);
 	Eswap1=con_salt[x]<<6;
+#else
+	x=ret[0]=((salt[0] == '\0')?os_toascii['A']:salt[0]);
+	Eswap0=con_salt[x]<<2;
+	x=ret[1]=((salt[1] == '\0')?os_toascii['A']:salt[1]);
+	Eswap1=con_salt[x]<<6;
+#endif
 
 /* EAY
 r=strlen(buf);
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 47bc5fa..e028e4c 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -246,6 +246,25 @@
 	{
 	ERR_STATE *es;
 
+#ifdef _OSD_POSIX
+	/* In the BS2000-OSD POSIX subsystem, the compiler generates
+	 * path names in the form "*POSIX(/etc/passwd)".
+	 * This dirty hack strips them to something sensible.
+	 * @@@ We shouldn't modify a const string, though.
+	 */
+	if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
+		char *end;
+
+		/* Skip the "*POSIX(" prefix */
+		file += sizeof("*POSIX(")-1;
+		end = &file[strlen(file)-1];
+		if (*end == ')')
+			*end = '\0';
+		/* Optional: use the basename of the path only. */
+		if ((end = strrchr(file, '/')) != NULL)
+			file = &end[1];
+	}
+#endif
 	es=ERR_get_state();
 
 	es->top=(es->top+1)%ERR_NUM_ERRORS;
diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c
index 20d6ec6..0152624 100644
--- a/crypto/evp/encode.c
+++ b/crypto/evp/encode.c
@@ -60,8 +60,19 @@
 #include "cryptlib.h"
 #include <openssl/evp.h>
 
+#ifndef CHARSET_EBCDIC
 #define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
 #define conv_ascii2bin(a)	(data_ascii2bin[(a)&0x7f])
+#else
+/* We assume that PEM encoded files are EBCDIC files
+ * (i.e., printable text files). Convert them here while decoding.
+ * When encoding, output is EBCDIC (text) format again.
+ * (No need for conversion in the conv_bin2ascii macro, as the
+ * underlying textstring data_bin2ascii[] is already EBCDIC)
+ */
+#define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
+#define conv_ascii2bin(a)	(data_ascii2bin[os_toascii[a]&0x7f])
+#endif
 
 /* 64 char lines
  * pad input with 0
diff --git a/crypto/hmac/hmactest.c b/crypto/hmac/hmactest.c
index 15eb0c4..9a67dff 100644
--- a/crypto/hmac/hmactest.c
+++ b/crypto/hmac/hmactest.c
@@ -69,6 +69,10 @@
 #else
 #include <openssl/hmac.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 struct test_st
 	{
 	unsigned char key[16];
@@ -116,6 +120,13 @@
 	int i,err=0;
 	char *p;
 
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(test[0].data, test[0].data, test[0].data_len);
+	ebcdic2ascii(test[1].data, test[1].data, test[1].data_len);
+	ebcdic2ascii(test[2].key,  test[2].key,  test[2].key_len);
+	ebcdic2ascii(test[2].data, test[2].data, test[2].data_len);
+#endif
+
 	for (i=0; i<4; i++)
 		{
 		p=pt(HMAC(EVP_md5(),
diff --git a/crypto/md2/md2_one.c b/crypto/md2/md2_one.c
index 17b288b..7157299 100644
--- a/crypto/md2/md2_one.c
+++ b/crypto/md2/md2_one.c
@@ -70,7 +70,23 @@
 
 	if (md == NULL) md=m;
 	MD2_Init(&c);
+#ifndef CHARSET_EBCDIC
 	MD2_Update(&c,d,n);
+#else
+	{
+		char temp[1024];
+		unsigned long chunk;
+
+		while (n > 0)
+		{
+			chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
+			ebcdic2ascii(temp, d, chunk);
+			MD2_Update(&c,temp,chunk);
+			n -= chunk;
+			d += chunk;
+		}
+	}
+#endif
 	MD2_Final(md,&c);
 	memset(&c,0,sizeof(c));	/* Security consideration */
 	return(md);
diff --git a/crypto/md2/md2test.c b/crypto/md2/md2test.c
index 63404b1..461d124 100644
--- a/crypto/md2/md2test.c
+++ b/crypto/md2/md2test.c
@@ -69,6 +69,10 @@
 #else
 #include <openssl/md2.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 char *test[]={
 	"",
 	"a",
diff --git a/crypto/md5/md5.c b/crypto/md5/md5.c
index ef65a1d..7ed0024 100644
--- a/crypto/md5/md5.c
+++ b/crypto/md5/md5.c
@@ -64,7 +64,10 @@
 
 void do_fp(FILE *f);
 void pt(unsigned char *md);
+#ifndef _OSD_POSIX
 int read(int, void *, unsigned int);
+#endif
+
 int main(int argc, char **argv)
 	{
 	int i,err=0;
diff --git a/crypto/md5/md5_one.c b/crypto/md5/md5_one.c
index c98721f..4b10e7f 100644
--- a/crypto/md5/md5_one.c
+++ b/crypto/md5/md5_one.c
@@ -60,6 +60,10 @@
 #include <string.h>
 #include <openssl/md5.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 unsigned char *MD5(unsigned char *d, unsigned long n, unsigned char *md)
 	{
 	MD5_CTX c;
@@ -67,7 +71,23 @@
 
 	if (md == NULL) md=m;
 	MD5_Init(&c);
+#ifndef CHARSET_EBCDIC
 	MD5_Update(&c,d,n);
+#else
+	{
+		char temp[1024];
+		unsigned long chunk;
+
+		while (n > 0)
+		{
+			chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
+			ebcdic2ascii(temp, d, chunk);
+			MD5_Update(&c,temp,chunk);
+			n -= chunk;
+			d += chunk;
+		}
+	}
+#endif
 	MD5_Final(md,&c);
 	memset(&c,0,sizeof(c)); /* security consideration */
 	return(md);
diff --git a/crypto/mdc2/mdc2test.c b/crypto/mdc2/mdc2test.c
index 6fc6c0e..0b1134b 100644
--- a/crypto/mdc2/mdc2test.c
+++ b/crypto/mdc2/mdc2test.c
@@ -73,6 +73,10 @@
 #else
 #include <openssl/mdc2.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 static unsigned char pad1[16]={
 	0x42,0xE5,0x0C,0xD2,0x24,0xBA,0xCE,0xBA,
 	0x76,0x0B,0xDD,0x2B,0xD4,0x09,0x28,0x1A
@@ -91,6 +95,10 @@
 	MDC2_CTX c;
 	static char *text="Now is the time for all ";
 
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(text,text,strlen(text));
+#endif
+
 	MDC2_Init(&c);
 	MDC2_Update(&c,(unsigned char *)text,strlen(text));
 	MDC2_Final(&(md[0]),&c);
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index 0b24b14..d56edcd 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -497,6 +497,17 @@
 		else
 			return(p);
 		}
+#ifdef CHARSET_EBCDIC
+/* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and
+ * I don't have perl (yet), we revert to a *LINEAR* search
+ * when the object wasn't found in the binary search.
+ */
+	for (i=0; i<num; ++i) {
+		p= &(base[i*size]);
+		if ((*cmp)(key,p) == 0)
+			return p;
+	}
+#endif
 	return(NULL);
 	}
 
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index 2446430..f1693ac 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -286,6 +286,10 @@
 				PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
 				goto err;
 				}
+#ifdef CHARSET_EBCDIC
+			/* Convert the pass phrase from EBCDIC */
+			ebcdic2ascii(buf, buf, klen);
+#endif
 			kstr=(unsigned char *)buf;
 			}
 		RAND_seed(data,i);/* put in the RSA key. */
@@ -345,6 +349,11 @@
 		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ);
 		return(0);
 		}
+#ifdef CHARSET_EBCDIC
+	/* Convert the pass phrase from EBCDIC */
+	ebcdic2ascii(buf, buf, klen);
+#endif
+
 	EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
 		(unsigned char *)buf,klen,1,key,NULL);
 
@@ -394,9 +403,15 @@
 	for (;;)
 		{
 		c= *header;
+#ifndef CHARSET_EBCDIC
 		if (!(	((c >= 'A') && (c <= 'Z')) || (c == '-') ||
 			((c >= '0') && (c <= '9'))))
 			break;
+#else
+		if (!(	isupper(c) || (c == '-') ||
+			isdigit(c)))
+			break;
+#endif
 		header++;
 		}
 	*header='\0';
diff --git a/crypto/ripemd/rmd160.c b/crypto/ripemd/rmd160.c
index 8481e44..4f8b88a 100644
--- a/crypto/ripemd/rmd160.c
+++ b/crypto/ripemd/rmd160.c
@@ -64,7 +64,10 @@
 
 void do_fp(FILE *f);
 void pt(unsigned char *md);
+#ifndef _OSD_POSIX
 int read(int, void *, unsigned int);
+#endif
+
 int main(int argc, char **argv)
 	{
 	int i,err=0;
diff --git a/crypto/ripemd/rmdtest.c b/crypto/ripemd/rmdtest.c
index 8a19f29..5e93d46 100644
--- a/crypto/ripemd/rmdtest.c
+++ b/crypto/ripemd/rmdtest.c
@@ -69,6 +69,10 @@
 #else
 #include <openssl/ripemd.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 char *test[]={
 	"",
 	"a",
@@ -104,6 +108,9 @@
 	i=1;
 	while (*P != NULL)
 		{
+#ifdef CHARSET_EBCDIC
+		ebcdic2ascii((char *)*P, (char *)*P, strlen((char *)*P));
+#endif
 		p=pt(RIPEMD160(&(P[0][0]),(unsigned long)strlen((char *)*P),NULL));
 		if (strcmp(p,(char *)*R) != 0)
 			{
diff --git a/crypto/sha/sha1.c b/crypto/sha/sha1.c
index 3c81a96..d350c88 100644
--- a/crypto/sha/sha1.c
+++ b/crypto/sha/sha1.c
@@ -64,7 +64,10 @@
 
 void do_fp(FILE *f);
 void pt(unsigned char *md);
+#ifndef _OSD_POSIX
 int read(int, void *, unsigned int);
+#endif
+
 int main(int argc, char **argv)
 	{
 	int i,err=0;
diff --git a/crypto/sha/sha1test.c b/crypto/sha/sha1test.c
index 6a34a9a..9400ad2 100644
--- a/crypto/sha/sha1test.c
+++ b/crypto/sha/sha1test.c
@@ -69,6 +69,10 @@
 #else
 #include <openssl/sha.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 #undef SHA_0 /* FIPS 180 */
 #define  SHA_1 /* FIPS 180-1 */
 
@@ -105,6 +109,11 @@
 	SHA_CTX c;
 	unsigned char md[SHA_DIGEST_LENGTH];
 
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(test[0], test[0], strlen(test[0]));
+	ebcdic2ascii(test[1], test[1], strlen(test[1]));
+#endif
+
 	P=(unsigned char **)test;
 	R=(unsigned char **)ret;
 	i=1;
@@ -125,6 +134,9 @@
 		}
 
 	memset(buf,'a',1000);
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(buf, buf, 1000);
+#endif /*CHARSET_EBCDIC*/
 	SHA1_Init(&c);
 	for (i=0; i<1000; i++)
 		SHA1_Update(&c,buf,1000);
diff --git a/crypto/sha/shatest.c b/crypto/sha/shatest.c
index 6ebcbb1..2b0744d 100644
--- a/crypto/sha/shatest.c
+++ b/crypto/sha/shatest.c
@@ -69,6 +69,10 @@
 #else
 #include <openssl/sha.h>
 
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
 #define SHA_0 /* FIPS 180 */
 #undef  SHA_1 /* FIPS 180-1 */
 
@@ -105,6 +109,11 @@
 	SHA_CTX c;
 	unsigned char md[SHA_DIGEST_LENGTH];
 
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(test[0], test[0], strlen(test[0]));
+	ebcdic2ascii(test[1], test[1], strlen(test[1]));
+#endif
+
 	P=(unsigned char **)test;
 	R=(unsigned char **)ret;
 	i=1;
@@ -125,6 +134,9 @@
 		}
 
 	memset(buf,'a',1000);
+#ifdef CHARSET_EBCDIC
+	ebcdic2ascii(buf, buf, 1000);
+#endif /*CHARSET_EBCDIC*/
 	SHA_Init(&c);
 	for (i=0; i<1000; i++)
 		SHA_Update(&c,buf,1000);
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index b283a62..691b71f 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -75,6 +75,9 @@
 	static char hex[17]="0123456789ABCDEF";
 	int gs_doit[4];
 	char tmp_buf[80];
+#ifdef CHARSET_EBCDIC
+	char ebcdic_buf[1024];
+#endif
 
 	if (buf == NULL)
 		{
@@ -110,6 +113,19 @@
 		type=ne->value->type;
 		num=ne->value->length;
 		q=ne->value->data;
+#ifdef CHARSET_EBCDIC
+                if (type == V_ASN1_GENERALSTRING ||
+		    type == V_ASN1_VISIBLESTRING ||
+		    type == V_ASN1_PRINTABLESTRING ||
+		    type == V_ASN1_TELETEXSTRING ||
+		    type == V_ASN1_VISIBLESTRING ||
+		    type == V_ASN1_IA5STRING) {
+                        ascii2ebcdic(ebcdic_buf, q,
+				     (num > sizeof ebcdic_buf)
+				     ? sizeof ebcdic_buf : num);
+                        q=ebcdic_buf;
+		}
+#endif
 
 		if ((type == V_ASN1_GENERALSTRING) && ((num%4) == 0))
 			{
@@ -132,7 +148,12 @@
 			{
 			if (!gs_doit[j&3]) continue;
 			l2++;
+#ifndef CHARSET_EBCDIC
 			if ((q[j] < ' ') || (q[j] > '~')) l2+=3;
+#else
+			if ((os_toascii[q[j]] < os_toascii[' ']) ||
+			    (os_toascii[q[j]] > os_toascii['~'])) l2+=3;
+#endif
 			}
 
 		lold=l;
@@ -152,11 +173,14 @@
 		memcpy(p,s,(unsigned int)l1); p+=l1;
 		*(p++)='=';
 
+#ifndef CHARSET_EBCDIC /* q was assigned above already. */
 		q=ne->value->data;
+#endif
 
 		for (j=0; j<num; j++)
 			{
 			if (!gs_doit[j&3]) continue;
+#ifndef CHARSET_EBCDIC
 			n=q[j];
 			if ((n < ' ') || (n > '~'))
 				{
@@ -167,6 +191,19 @@
 				}
 			else
 				*(p++)=n;
+#else
+			n=os_toascii[q[j]];
+			if ((n < os_toascii[' ']) ||
+			    (n > os_toascii['~']))
+				{
+				*(p++)='\\';
+				*(p++)='x';
+				*(p++)=hex[(n>>4)&0x0f];
+				*(p++)=hex[n&0x0f];
+				}
+			else
+				*(p++)=q[j];
+#endif
 			}
 		*p='\0';
 		}