Reputation: 63
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;
}
Upvotes: 3
Views: 2652
Reputation: 7704
I am doing virtually the same as I can see (see below). The only delta I see is the use of V_ASN1_IA5STRING or a V_ASN1_UTF8STRING if needed.
Dw.
+(X509_NAME_ENTRY *) x509nameEntryFromDict:(NSDictionary *)entry {
X509_NAME_ENTRY * nameEntry = NULL;
int nid = [self nidFromDict:entry];
if (nid == NID_undef) {
NSLog(@"x509nameFromDictArray: Unknown entry - ignored: %@", entry);
return NULL;
}
NSString * val = [entry objectForKey:kOpenSSLNameValueKey];
const char * buff;
int valType;
if ([val dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO]) {
valType = V_ASN1_IA5STRING;
buff = [val cStringUsingEncoding:NSASCIIStringEncoding];
} else {
valType = V_ASN1_UTF8STRING;
buff = [val cStringUsingEncoding:NSUTF8StringEncoding];
}
int len = strlen(buff);
return X509_NAME_ENTRY_create_by_NID(&nameEntry, nid, valType, (unsigned char*)buff, len);
}
Upvotes: 2