static X509 *pki_certificate(X509_NAME *issuer, EVP_PKEY *keyring, X509_REQ *cert_req, uint8_t is_cert_authority, uint32_t serial, uint32_t expiration_delay) { jlog(L_DEBUG, "pki_certificate"); X509 *certificate; X509_NAME *subject; X509V3_CTX ctx; X509_EXTENSION *ext; // create a new certificate certificate = X509_new(); // set certificate unique serial number ASN1_INTEGER_set(X509_get_serialNumber(certificate), serial); // set certificate 'Subject:' subject = X509_REQ_get_subject_name(cert_req); X509_set_subject_name(certificate, subject); // set certificate 'Issuer:' X509_set_issuer_name(certificate, issuer); // set X509v3 extension "basicConstraints" CA:TRUE/FALSE X509V3_set_ctx(&ctx, NULL, certificate, cert_req, NULL, 0); if (is_cert_authority == true) ext = X509V3_EXT_conf(NULL, &ctx, "basicConstraints", "CA:TRUE"); else ext = X509V3_EXT_conf(NULL, &ctx, "basicConstraints", "CA:FALSE"); X509_add_ext(certificate, ext, -1); X509_EXTENSION_free(ext); // set certificate version 3 X509_set_version(certificate, 0x2); // set certificate public key X509_set_pubkey(certificate, keyring); // set the 'notBefore' to yersterday X509_gmtime_adj(X509_get_notBefore(certificate), -(24*60*60)); // set certificate expiration delay X509_gmtime_adj(X509_get_notAfter(certificate), expiration_delay); return certificate; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_AddCustomExtension *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_AddCustomExtension( X509** a_ppCertificate, OpcUa_Crypto_Extension* a_pExtension, X509V3_CTX* a_pX509V3Context) { X509_EXTENSION* pExtension = OpcUa_Null; char* pName = OpcUa_Null; char* pValue = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_AddCustomExtension"); OpcUa_ReturnErrorIfArgumentNull(a_pX509V3Context); OpcUa_ReturnErrorIfArgumentNull(a_pExtension->key); OpcUa_ReturnErrorIfArgumentNull(a_pExtension->value); pName = (char*)a_pExtension->key; pValue = (char*)a_pExtension->value; /* create the extension. */ pExtension = X509V3_EXT_conf( OpcUa_Null, a_pX509V3Context, pName, pValue); if(pExtension == OpcUa_Null) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add it to the certificate. */ if(!X509_add_ext(*a_ppCertificate, pExtension, -1)) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* free the extension. */ X509_EXTENSION_free(pExtension); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pExtension != OpcUa_Null) { X509_EXTENSION_free(pExtension); } OpcUa_FinishErrorHandling; }
/* * Add a X509v3 extension to a certificate and handle errors. * Returns -1 on errors, 0 on success. */ int ssl_x509_v3ext_add(X509V3_CTX *ctx, X509 *crt, char *k, char *v) { X509_EXTENSION *ext; if (!(ext = X509V3_EXT_conf(NULL, ctx, k, v))) { return -1; } if (X509_add_ext(crt, ext, -1) != 1) { X509_EXTENSION_free(ext); return -1; } X509_EXTENSION_free(ext); return 0; }
int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl) { X509_EXTENSION *ext; STACK_OF(CONF_VALUE) *nval; CONF_VALUE *val; int i; if(!(nval = CONF_get_section(conf, section))) return 0; for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { val = sk_CONF_VALUE_value(nval, i); if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) return 0; if(crl) X509_CRL_add_ext(crl, ext, -1); X509_EXTENSION_free(ext); } return 1; }
int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req) { X509_EXTENSION *ext; STACK_OF(X509_EXTENSION) *extlist = NULL; STACK_OF(CONF_VALUE) *nval; CONF_VALUE *val; int i; if(!(nval = CONF_get_section(conf, section))) return 0; for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { val = sk_CONF_VALUE_value(nval, i); if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) return 0; if(!extlist) extlist = sk_X509_EXTENSION_new_null(); sk_X509_EXTENSION_push(extlist, ext); } if(req) i = X509_REQ_add_extensions(req, extlist); else i = 1; sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); return i; }
int gen_cert (X509 ** cert, EVP_PKEY ** key) { RSA *rsa; X509_NAME *subj; X509_EXTENSION *ext; X509V3_CTX ctx; const char *commonName = "localhost"; char dNSName[128]; int rc; *cert = NULL; *key = NULL; /* Generate a private key. */ *key = EVP_PKEY_new (); if (*key == NULL) { #ifdef DEBUG fprintf (stderr, "Error generating key.\n"); #endif exit (1); } do { rsa = RSA_generate_key (DEFAULT_KEY_BITS, RSA_F4, NULL, NULL); if (rsa == NULL) { #ifdef DEBUG fprintf (stderr, "Error generating RSA key.\n"); #endif exit (1); } rc = RSA_check_key (rsa); } while (rc == 0); if (rc == -1) { #ifdef DEBUG fprintf (stderr, "Error generating RSA key.\n"); #endif exit (1); } if (EVP_PKEY_assign_RSA (*key, rsa) == 0) { RSA_free (rsa); #ifdef DEBUG fprintf (stderr, "Error with EVP and PKEY.\n"); #endif exit (1); } /* Generate a certificate. */ *cert = X509_new (); if (*cert == NULL) { #ifdef DEBUG fprintf (stderr, "Couldn't generate 509 cert.\n"); #endif exit (1); } if (X509_set_version (*cert, 2) == 0) { /* Version 3. */ #ifdef DEBUG fprintf (stderr, "Couldn't set x509 version.\n"); #endif exit (1); } /* Set the commonName. */ subj = X509_get_subject_name (*cert); if (X509_NAME_add_entry_by_txt (subj, "commonName", MBSTRING_ASC, (unsigned char *) commonName, -1, -1, 0) == 0) { #ifdef DEBUG fprintf (stderr, "Couldn't set common name.\n"); #endif exit (1); } /* Set the dNSName. */ rc = snprintf (dNSName, sizeof (dNSName), "DNS:%s", commonName); if (rc < 0 || rc >= sizeof (dNSName)) { #ifdef DEBUG fprintf (stderr, "Unable to set dns name.\n"); #endif exit (1); } X509V3_set_ctx (&ctx, *cert, *cert, NULL, NULL, 0); ext = X509V3_EXT_conf (NULL, &ctx, "subjectAltName", dNSName); if (ext == NULL) { #ifdef DEBUG fprintf (stderr, "Unable to get subjectaltname.\n"); #endif exit (1); } if (X509_add_ext (*cert, ext, -1) == 0) { #ifdef DEBUG fprintf (stderr, "x509_add_ext error.\n"); #endif exit (1); } /* Set a comment. */ ext = X509V3_EXT_conf (NULL, &ctx, "nsComment", CERTIFICATE_COMMENT); if (ext == NULL) { #ifdef DEBUG fprintf (stderr, "x509v3_ext_conf error.\n"); #endif exit (1); } if (X509_add_ext (*cert, ext, -1) == 0) { #ifdef DEBUG fprintf (stderr, "x509_add_ext error.\n"); #endif exit (1); } X509_set_issuer_name (*cert, X509_get_subject_name (*cert)); X509_gmtime_adj (X509_get_notBefore (*cert), 0); X509_gmtime_adj (X509_get_notAfter (*cert), DEFAULT_CERT_DURATION); X509_set_pubkey (*cert, *key); /* Sign it. */ if (X509_sign (*cert, *key, EVP_sha1 ()) == 0) { #ifdef DEBUG fprintf (stderr, "x509_sign error.\n"); #endif exit (1); } return 1; }
PKI_X509_EXTENSION *PKI_X509_EXTENSION_value_new_profile ( PKI_X509_PROFILE *profile, PKI_CONFIG *oids, PKI_CONFIG_ELEMENT *extNode, PKI_TOKEN *tk ) { /* TODO: Implement the extended version of the extensions, this should allow better extensions management. That is, the value will be encoded as: extName=@section [ section ] extName=value otherVal=val otherVal=val ... The corresponding XML should be: <pki:extension name=".." critical=".." > <pki:value name="" type=".." tag=".."> .. </pki:value> <pki:value name="" type=".." tag=".."> .. </pki:value> </pki:extension> */ PKI_CONFIG_ELEMENT *valNode = NULL; PKI_X509_EXTENSION *ret = NULL; PKI_X509_EXTENSION_VALUE *ext = NULL; xmlChar *type_s = NULL; xmlChar *tag_s = NULL; xmlChar *oid_s = NULL; xmlChar *value_s = NULL; xmlChar *name_s = NULL; xmlChar *crit_s = NULL; PKI_OID *oid = NULL; X509V3_CTX v3_ctx; CONF *conf = NULL; char *envValString = NULL; char *valString = NULL; int crit = 0; if( !profile || !extNode ) { PKI_log_debug("ERROR, no profile or extNode provided in " "PKI_X509_EXTENSION_value_new_profile()"); return (NULL); } if((crit_s = xmlGetProp( extNode, BAD_CAST "critical" )) != NULL ) { if( strncmp_nocase( (char *) crit_s, "n", 1 ) == 0) { crit = 0; } else { crit = 1; } } if((name_s = xmlGetProp( extNode, BAD_CAST "name" )) == NULL ) { PKI_log_debug("ERROR, no name property in node %s", extNode->name); if( crit_s ) xmlFree ( crit_s ); return (NULL); } if ((oid = PKI_OID_get((char *) name_s)) == NULL) { if ((oid = PKI_CONFIG_OID_search(oids, (char *)name_s)) == NULL) { PKI_ERROR(PKI_ERR_OBJECT_CREATE, NULL); return NULL; } } else { PKI_OID_free ( oid ); } /* int nid = NID_undef; if((nid = OBJ_sn2nid( (char *) name_s )) == NID_undef ) { PKI_OID *oid = NULL; oid = PKI_CONFIG_OID_search ( oids, (char *) name_s ); if( !oid ) { PKI_log_debug( "ERROR, can not create object (%s)!", name_s ); return( NULL ); } } */ if ((valString = (char *) PKI_Malloc(BUFF_MAX_SIZE)) == NULL) { PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); if( name_s ) xmlFree ( name_s ); if( crit_s ) xmlFree (crit_s); return( NULL ); } memset( valString, 0, BUFF_MAX_SIZE ); if( crit == 1 ) snprintf( valString, BUFF_MAX_SIZE -1, "%s", "critical" ); for (valNode = extNode->children; valNode; valNode = valNode->next) { if ((valNode->type == XML_ELEMENT_NODE) && ((strncmp_nocase((char *)(valNode->name),"value",5)) == 0)) { char tmp[BUFF_MAX_SIZE]; type_s = xmlGetProp( valNode, BAD_CAST "type" ); tag_s = xmlGetProp( valNode, BAD_CAST "tag" ); oid_s = xmlGetProp( valNode, BAD_CAST "oid" ); value_s = xmlNodeListGetString( profile, valNode->xmlChildrenNode, 0); if( oid_s ) { /* Let's be sure the OID is created */ if((oid = PKI_CONFIG_OID_search(oids, (char *) value_s)) == NULL ) { PKI_log_debug ("WARNING, no oid " "created for %s!", oid_s ); } else { PKI_OID_free ( oid ); } } memset((unsigned char * )tmp, 0, BUFF_MAX_SIZE ); if( tag_s ) { snprintf( tmp, BUFF_MAX_SIZE - 1, "%s;", _ext_txt( tag_s ) ); } if( type_s == NULL ) { if( !oid_s ) { strncat( tmp, (char *) value_s, BUFF_MAX_SIZE - strlen( tmp )); } else { if( value_s && (strlen((char *) value_s) > 0) ) { strncat( tmp, (char *) oid_s, BUFF_MAX_SIZE - strlen( tmp ) ); strncat( tmp, ":", BUFF_MAX_SIZE - strlen ( tmp )); strncat( tmp, (char *) value_s, BUFF_MAX_SIZE - strlen (tmp )); } else { strncat( tmp, "OID:", BUFF_MAX_SIZE - strlen(tmp)); strncat( tmp, (char *) oid_s, BUFF_MAX_SIZE - strlen( tmp )); } } } else { strncat( tmp, (char *) _ext_txt(type_s), BUFF_MAX_SIZE - strlen( tmp )); if( value_s && (strlen((char*)value_s) > 0) ) { if(strcmp_nocase( (char*) type_s, "ia5org")) { strncat( tmp, ":", BUFF_MAX_SIZE - strlen( tmp )); } else { strncat( tmp, ",", BUFF_MAX_SIZE - strlen( tmp )); } strncat( tmp, (char *) value_s, BUFF_MAX_SIZE - strlen( tmp )); } } if( strlen( valString ) > 0 ) { strncat( valString, ",", BUFF_MAX_SIZE - 1); } strncat( valString, (char *) tmp, BUFF_MAX_SIZE - 1 ); if( type_s ) xmlFree ( type_s ); if( oid_s ) xmlFree ( oid_s ); if( tag_s ) xmlFree ( tag_s ); if( value_s ) xmlFree ( value_s ); } } //PKI_log_debug("INFO, Encoding %s=%s", name_s, valString); v3_ctx.db = NULL; v3_ctx.db_meth = NULL; v3_ctx.crl = NULL; v3_ctx.flags = 0; if ( tk ) { v3_ctx.issuer_cert = (X509 *) PKI_X509_get_value ( tk->cacert ); v3_ctx.subject_cert = (X509 *) PKI_X509_get_value ( tk->cert ); v3_ctx.subject_req = (X509_REQ *) PKI_X509_get_value ( tk->req ); } else { v3_ctx.issuer_cert = NULL; v3_ctx.subject_cert = NULL; v3_ctx.subject_req = NULL; } /* Sets the ctx.db and ctx.method */ conf = NCONF_new( NULL ); X509V3_set_nconf(&v3_ctx, conf); if((envValString = get_env_string( valString )) != NULL ) { PKI_log_debug("EXT STRING => %s=%s", name_s, envValString); ext = X509V3_EXT_conf(NULL, &v3_ctx, (char *) name_s, (char *) envValString); PKI_Free ( envValString ); } else { ext = X509V3_EXT_conf(NULL, &v3_ctx, (char *) name_s, (char *) valString); } if( !ext ) { PKI_log_debug("EXT::ERR::%s", ERR_error_string(ERR_get_error(), NULL )); return NULL; } if(( ret = PKI_X509_EXTENSION_new()) == NULL ) { PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); X509_EXTENSION_free ( ext ); return NULL; } ret->value = ext; ret->oid = ext->object; if( name_s ) xmlFree ( name_s ); if( crit_s ) xmlFree (crit_s ); if( valString ) PKI_Free ( valString ); if( conf ) NCONF_free ( conf ); return ( ret ); }