I had a string CN=myserver,O=test,C=us in a certificate, which has been encoded
Offset : EBCDIC ASCII
00000000 : 302F310B 30090603 55040613 02757331 ................ 0/1.0...U....us1
00000010 : 0D300B06 0355040A 13047465 73743111 ................ .0...U....test1.
00000020 : 300F0603 55040313 086D7973 65727665 ........._`..... 0...U....myserve
00000030 : 72 . r
where you can see the encoded string in ASCII on the right. How do I extract the string CN=myserver,O=test,C=us from this?
This format is used for Subjects and Issuers (and other types).
The hex string has an ASN.1 encoding. It usually starts with a 0x30. See here for a good introduction to ASN.1 encoding.
- 30 means this is a sequence
- 2f is the length of the data following
- etc
On z/OS you can use system ssl to decode this back to a printable string. You need two steps.
- Convert to internal format,
- Create the printable EBCDIC string from the internal format.
Step1 create internal format of the data
#pragma runopts(POSIX(ON))
#include <gskcms.h>
#include <gskssl.h>
void x509_to_string(char * pData, // pointer to the data
int lData) // length of the data
{
x509_name X509; // internal format.
int rc;
gsk_buffer cert; // intermediate format
if (lData == 0)
{
printf("no data");
return;
}
cert.length= lData;
cert.data = pData ;
// convert from 0x302F310B 30090603 to internal
rc = gsk_decode_name(
& cert,
& X509);
if ( rc != 0)
{
//use gsk_strerror(rc) to return a string.
printf("\nInternal error:gsk_decode_name %s\n",
gsk_strerror(rc));
return;
}
Convert from internal format to an EBCDIC string.
char * pName ; // output value
// convert from internal to CN=COLIN,C=GB
rc = gsk_name_to_dn(
&X509,
&pName);
// free the intermediate value regardless of rc
gsk_free_name(&X509);
if ( rc != 0)
{
printf("\nInternal error:gsk_name_dn %s\n",
gsk_strerror(rc));
return;
}
printf("%s.",pName);
//free the string
gsk_free_string(pName);
}
Convert from EBCDIC string to intermediate or certificate format.
There are the reverse functions.
- gsk_dn_to_name( pName, &X509);
- rc = gsk_encode_name( &X509, & cert);
Both C=GB,CN=colin and c=GB,cn=colin produce
00000000 : 301D310E 300C0603 55040313 05636F6C …………..?% 0.1.0…U….col 00000010 : 696E310B 30090603 55040613 024742 .>…………. in1.0…U….GB
JCL
I needed binder input options.
INCLUDE GSK(GSKCMS31) INCLUDE GSK(GSKSSL)
and JCL
//COMPILE EXEC PROC=EDCCB, // LIBPRFX=&LIBPRFX, // CPARM='OPTFILE(DD:SYSOPTF)', // BPARM='SIZE=(900K,124K),RENT,LIST,RMODE=ANY,AMODE=31,AC=1' //COMPILE.SYSLIB DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H // DD DISP=SHR,DSN=&LIBPRFX..SCEEH.H // DD DISP=SHR,DSN=SYS1.SIEAHDR.H ... //COMPILE.SYSIN DD DSN=&SOURCE(&PROG),DISP=SHR //COMPILE.SYS DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H //COMPILE.SYSOPTF DD DISP=SHR,DSN=&SOURCE(CCOPTS) //* //* Bind the module //* //BIND.SYSLMOD DD DISP=SHR,DSN=&LOADLIB(&PROG) //BIND.SYSLIB DD DISP=SHR,DSN=&LIBPRFX..SCEELKED // DD DISP=SHR,DSN=SYS1.SIEALNKE //BIND.GSK DD DISP=SHR,DSN=SYS1.SIEALNKE ... //BIND.SYSIN DD DISP=SHR,DSN=&SOURCE(&BINDOPTS)
Where the gskcms.h and gskssl.h are in DSN=SYS1.SIEAHDR.H or /usr/include/, and the binder stubs are in DSN=SYS1.SIEALNKE.