I have been using openssl API to create my own certificate utility. I am currently facing an issue when adding a distinguished name in the subject alternative name extension. Although the extension is successfully created, the value of the extension is wrongly encoded when viewing the certificate, e.g with the windows certificate utility:
Basic Constraints Subject Type=CA, Path...
Subject Alternative Name
74 53 19 00 00 00 38 27 tS....8'
ac 0b 88 ae ac 0b 00 00 ........
00 00 00 00 00 00 6f 72 ......or
20 53 21 00 00 00 02 00 S!.....
00 00 13 00 00 00 d0 d7 ........
ac 0b 00 00 00 00 0a 00 ........
00 00 00 00 00 00 20 00 ...... .
00 00 19 00 00 00 b8 5d .......]
a4 0b
Thumbprint algorithm sha1
Below is a snippet of the relevant source code focusing on the points of interest (there might be some syntax errors):
GENERAL_NAME * genn = NULL;
STACK_OF(GENERAL_NAME) * sk_genn;
ASN1_OCTET_STRING *asn1OctetStr=NULL;
X509_EXTENSION* tmpEXT;
X509_NAME* tmpDIRNAME;
char* extSAN_str=(char *) "C=CR, O=OU, D=DR";
/*..*/
case DISTINGUISHED_NAME:
// Initialization of ASN.1 structures
genn = GENERAL_NAME_new();
asn1OctetStr = M_ASN1_OCTET_STRING_new();
sk_genn = GENERAL_NAMES_new();
// Create the X509 extension
tmpDIRNAME=CharToX509_NAME(extSAN_str);
// This GeneralName is an directoryName
genn->type=GEN_DIRNAME;
genn->d.directoryName=tmpDIRNAME;
// Using the stack to create a sequence
sk_GENERAL_NAME_push(sk_genn,genn);
ext_len = i2d_GENERAL_NAMES(sk_genn, NULL);
ext_der = OPENSSL_malloc(ext_len); /* allocate that much memory */
i2d_GENERAL_NAMES(sk_genn, &ext_der);
asn1OctetStr->data = ext_der;
/* fill in the value of the SubjectAltName extension */
asn1OctetStr->length = ext_len;
sanNID = OBJ_txt2nid("subjAltName");
if (!(tmpEXT = X509_EXTENSION_create_by_NID(NULL, sanNID, 0, asn1OctetStr)))
{
ERR_error_string(ERR_get_error(), NULL), ERR_get_error());
}
// Adding the certificate to the X509 structure
if(!X509_add_ext(tmpCert, tmpEXT, -1))
{
ERR_error_string(ERR_get_error(), NULL), ERR_get_error());
}
/*..*/
X509_NAME* CharToX509_NAME(char* SubjectName)
{
X509_NAME *tempSubjectName=NULL;
char name[128];
char value[128];
char* equal;
char* comma;
char* field;
memset(name, 0, 128);
memset(value, 0, 128);
if(!(tempSubjectName = X509_NAME_new()))
{
return 0;
}
if (NULL != SubjectName)
{
field = SubjectName;
do
{
equal=strchr(field, '=');
comma=strchr(field, ',');
if(comma == 0)
comma = field + strlen(field);
strncpy(name, field, (unsigned)(equal-field));
name[equal-field]=0;
strncpy(value, equal+1, (unsigned)(comma-equal-1));
value[comma-equal-1]=0;
field=comma+1;
if(!X509_NAME_add_entry_by_txt(tempSubjectName,name, MBSTRING_ASC, value, -1, -1, 0))
return 0;
}while(*comma != 0);
}
return tempSubjectName;
}