The structure containing information about a certificate has a very deep nesting of structures and arrays. Fortunately for the most common information, gskit provides an interface.
There is a standards document giving the layout of the certificate, and what the fields mean.
- First steps in using system ssl give some introductions to gskit.
- Compiling a gsk program
- Example of system ssl to display keyring information
- Example of using system ssl to sign some data.
The structures are in /usr/include/gskcms.h. Some of the data types are in /usr/include/gsktypes.h .
The certificate structure
- The structure pkcs_certificate>s has an array of pkcs_certificate and a count of the elements.
- The structure pkcs_certificate has a certificate type and an x509_certificate.
- The structure x509_certificate has
- a tbsCertificate
- signature algorithm
- The x509_tbs_certificate structure (tbs from To Be Signed) has
- the certificate version
- the certificate serial number
- the signature algorithm of the certificate
- the issuer
- the validity period
- the subject.
The fields
- The certificate serial number. This a hexadecimal value. The definition has a pointer to the data, and a length of the data. The length is at least one.
- The signature algorithm of the certificate. This includes
- The signature type. This is a C enum, such as x509_alg_sha256WithRsaEncryption = 25
- The issuer is a complex nest of structure. Fortunately gskit provide a function gsk_name_to_dn(structure,name). The output “name” is a printable EBCDIC string like CN=DocZosCA,OU=CA,O=COLIN
- The validity period. This structure contains two time-value fields, not before, and not after.
- You can format a time value field using
- char dest[18];
- strftime(dest,18,”%y/%m/%d %H:%M:%S”,timeval);
- You can format a time value field using
- The subject is like the issuer. Use the function gsk_name_to_dn to convert it to printable EBCDIC. For example CN=10.1.1.2,OU=SSS,O=NISTECC521
Printing the structures
I have some functions like
void print_certs(pkcs_certificates * pcs){ // pkcs_certificate has a count and array of certs // iterate over them all int i; pkcs_certificate * pc = & pcs-> certificates[0]; for (i = 1; i <= pcs-> count;i++) { printf("Certificate %i\n",i); printf("==========\n"); print_cert(pc); pc ++; printf(" \n"); } }
which invokes
void print_cert(pkcs_certificate * pc ){ print_x509_algorithm_type(pc ->u.certificate. signatureAlgorithm .type,0); // Serial number char output[60]; // into here // hexof is written by Colin Paice printf("Serial number Hex :%s\n",hexof( pc ->u.certificate.tbsCertificate.serialNumber.data, pc ->u.certificate.tbsCertificate.serialNumber.length, &output[0]) ); // get the subject and issuer names gsk_status gskrc; char * pName; // returned here - must free it pName = "Unknown"; gskrc = gsk_name_to_dn( & pc ->u.certificate.tbsCertificate.subject, &pName); if (gskrc != 0) printf("Subject gsk_name_to_dn %s\n", gsk_strerror(gskrc)); printf("Subject name :%s\n",pName); gsk_free_string(pName); // extract the issuer, pName = "Unknown"; gskrc = gsk_name_to_dn ( & pc ->u.certificate.tbsCertificate.issuer, &pName); if (gskrc != 0) printf("Issuer gsk_name_to_dn %s\n, gsk_strerror(gskrc)); printf("Issuers name :%s\n",pName); gsk_free_string(pName); // extract the valid times. char buffer[18]; printf("Not Before :%s\n", ccpformattime ( & pc ->u.certificate.tbsCertificate.validity.notBefore, &buffer[0] ) ); printf("Not After :%s\n", ccpformattime ( & pc ->u.certificate.tbsCertificate.validity.notAfter, &buffer[0] )); print_x509_extensions(&pc -> u.certificate.tbsCertificate.extensions);}
Process DER ASN.1
Some data is encoded in ASN.1 format.
This is of format
- 1 byte of type
- 1 or more bytes of length
- Value, where value can be
- Integer data
- ASCII string data
- …
- A sequence of things ..
For example
16304765 6E657261… is
- Type 16 is an ASCII string
- of length 0x30
- with value 0x4765… which translates to EBCDIC Genera…
30068704 0A010102
- Type 30 is a sequence (it happens to be a sequence of one element)
- Of length 6
- The value is a dotted decimal IP address of length 4
- with value 0A010102 – which is 10.1.1.2.
Certificate 2
==========
Certificate algorithm :x509_alg_sha256WithRsaEncryption
Serial number Hex :68
Subject name :CN=10.1.1.2,OU=SSS,O=NISTEC256
Issuers name :CN=DocZosCA,OU=CA,O=COLIN
Not Before :26/04/05 00:00:00
Not After :27/04/05 23:59:59
Extension 1
============
Extension type:x509_ext_unknown
DER IA5String: Generated by the Security Server for z/OS (RACF)
Extension 2
============
Extension type:x509_ext_subjectAltName
DER Dotted address: 0x0A010102
Extension 3
============
Extension type:x509_ext_keyUsage
DER BitString: 0x0780
Sample output
Extension 4
============
Extension type:x509_ext_subjectKeyIdentifier
DER Octet: 0xF421DD55 F00BEE6E E81B97D2 1D5556AB A671EC59
Extension 5
============
Extension type:x509_ext_authorityKeyIdentifier
DER Context: 0xCAD12CE6 AACB598C 6E9595CD D812C90A C9C4C289