int signRequest(char* pemRequest, int days, char* pemCAKey, char* pemCaCert, int certType, char *url, char* result) { BIO* bioReq = BIO_new_mem_buf(pemRequest, -1); BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1); BIO* bioCert = BIO_new_mem_buf(pemCaCert, -1); X509* caCert = PEM_read_bio_X509(bioCert, NULL, NULL, NULL); int err = 0; X509_REQ *req=NULL; if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return ERR_peek_error(); } EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL); if (!caKey) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return ERR_peek_error(); } X509* cert = X509_new(); EVP_PKEY* reqPub; if(!(err = X509_set_version(cert, 2))) { BIO_free(bioReq); BIO_free(bioCAKey); return ERR_peek_error(); } //redo all the certificate details, because OpenSSL wants us to work hard X509_set_issuer_name(cert, X509_get_subject_name(caCert)); ASN1_UTCTIME *s=ASN1_UTCTIME_new(); // Jira-issue: WP-37 // This is temp solution for putting pzp validity 5 minutes before current time // If there is a small clock difference between machines, it results in cert_not_yet_valid // It does set GMT time but is relevant to machine time. // A better solution would be to have ntp server contacted to get a proper time. if(certType == 2) { X509_gmtime_adj(s, long(0-300)); } else { X509_gmtime_adj(s, long(0)); } // End of WP-37 X509_set_notBefore(cert, s); X509_gmtime_adj(s, (long)60*60*24*days); X509_set_notAfter(cert, s); ASN1_UTCTIME_free(s); X509_set_subject_name(cert, X509_REQ_get_subject_name(req)); reqPub = X509_REQ_get_pubkey(req); X509_set_pubkey(cert,reqPub); EVP_PKEY_free(reqPub); //create a serial number at random ASN1_INTEGER* serial = getRandomSN(); X509_set_serialNumber(cert, serial); X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); char *str = (char*)malloc(strlen("caIssuers;") + strlen(url) + 1); if (str == NULL) { return -10; } strcpy(str, "caIssuers;"); strcat(str, url); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_info_access, (char*)str))) { free(str); return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } free(str); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_issuer_alt_name, (char*)"issuer:copy"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if( certType == 1) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } else if( certType == 2) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } if (!(err = X509_sign(cert,caKey,EVP_sha1()))) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return err; } BIO *mem = BIO_new(BIO_s_mem()); PEM_write_bio_X509(mem,cert); BUF_MEM *bptr; BIO_get_mem_ptr(mem, &bptr); BIO_read(mem, result, bptr->length); BIO_free(mem); BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return 0; }
int selfSignRequest(char* pemRequest, int days, char* pemCAKey, int certType, char *url, char* result) { BIO* bioReq = BIO_new_mem_buf(pemRequest, -1); BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1); int err = 0; X509_REQ *req=NULL; if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) { BIO_free(bioReq); BIO_free(bioCAKey); return -5; } EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL); if (!caKey) { BIO_free(bioReq); BIO_free(bioCAKey); return -6; } X509* cert = X509_new(); EVP_PKEY* reqPub; //redo all the certificate details, because OpenSSL wants us to work hard if(!(err = X509_set_version(cert, 2))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } if(!(err = X509_set_issuer_name(cert, X509_REQ_get_subject_name(req)))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } ASN1_UTCTIME *s=ASN1_UTCTIME_new(); // Jira-issue: WP-37 // This is temp solution for putting pzp validity 5 minutes before current time // If there is a small clock difference between machines, it results in cert_not_yet_valid // It does set GMT time but is relevant to machine time. // A better solution would be to have ntp server contacted to get proper time. if(certType == 2) { X509_gmtime_adj(s, long(0-300)); } else { X509_gmtime_adj(s, long(0)); } // End of WP-37 X509_set_notBefore(cert, s); X509_gmtime_adj(s, (long)60*60*24*days); X509_set_notAfter(cert, s); ASN1_UTCTIME_free(s); if(!(err = X509_set_subject_name(cert, X509_REQ_get_subject_name(req)))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } if (!(reqPub = X509_REQ_get_pubkey(req))) { BIO_free(bioReq); BIO_free(bioCAKey); return -7; } err = X509_set_pubkey(cert,reqPub); EVP_PKEY_free(reqPub); if (!err) { return err; // an error occurred, this is terrible style. } //create a serial number at random ASN1_INTEGER* serial = getRandomSN(); X509_set_serialNumber(cert, serial); // V3 extensions X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if( certType == 0) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:TRUE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_key_usage, (char*)"critical, keyCertSign, digitalSignature, cRLSign"))) { /* critical, keyCertSign,cRLSign, nonRepudiation,*/ return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_inhibit_any_policy, (char*)"0"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_crl_distribution_points, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } if (!(err = X509_sign(cert,caKey,EVP_sha1()))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } BIO *mem = BIO_new(BIO_s_mem()); PEM_write_bio_X509(mem,cert); BUF_MEM *bptr; BIO_get_mem_ptr(mem, &bptr); BIO_read(mem, result, bptr->length); BIO_free(mem); BIO_free(bioReq); BIO_free(bioCAKey); return 0; }
/* Adds X509v3 extensions to a certificate. */ int add_ext(X509 *cacert, X509 *usrcert) { X509_EXTENSION *ext = NULL; X509V3_CTX ctx; int i = 0; if (cacert == NULL || usrcert == NULL) return OPENSSLCA_ERR_ARGS; /* Set extension context */ X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cacert, usrcert, NULL, NULL, 0); /* Add all specified extensions */ while (ext_entries[i].nid) { if ((ext = X509V3_EXT_conf_nid(NULL, &ctx, ext_entries[i].nid, ext_entries[i].value)) == NULL) return OPENSSLCA_ERR_EXT_MAKE; if (!X509_add_ext(usrcert, ext, -1)) return OPENSSLCA_ERR_EXT_ADD; X509_EXTENSION_free(ext); i++; } return OPENSSLCA_NO_ERR; }
sqbind::SQINT COsslCert::SetExtension( const sqbind::stdString &sField, const sqbind::stdString &sValue ) { _STT(); if ( !m_pX509 ) return 0; if ( !sField.length() ) return 0; // Find this extension by short name const ASN1_OBJECT* pObj = COSSLCERT_SnToObj( oexStrToMb( sqbind::std2oex( sField ) ).Ptr() ); if ( !pObj ) return 0; // Create extension X509_EXTENSION *ex = X509V3_EXT_conf_nid( oexNULL, oexNULL, pObj->nid, (char*)oexStrToMb( sqbind::std2oex( sValue ) ).Ptr() ); if ( !ex ) return 0; // Add to cert X509_add_ext( m_pX509, ex, -1 ); X509_EXTENSION_free( ex ); return 1; }
/** * Returns true on success, false on failure * * Example: * @code * <#example#> * @endcode */ static bool _addCertificateExtension(X509 *cert, int nid, char *value) { X509_EXTENSION *extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value); if (extension == NULL) { return false; } X509_add_ext(cert, extension, -1); X509_EXTENSION_free(extension); return true; }
int PKI_X509_CERT_add_extension(PKI_X509_CERT *x, PKI_X509_EXTENSION *ext) { PKI_X509_CERT_VALUE *val = NULL; if( !x || !x->value || !ext || !ext->value ) return (PKI_ERR); val = x->value; if (!X509_add_ext(val, ext->value, -1)) return (PKI_ERR); return (PKI_OK); }
int add_ext(X509 *cert, int nid, char *value) { X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ex) return 0; X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); return 1; }
int SDMMD__add_ext(X509 *cert, int flag, char *name) { int result = 0; X509V3_CTX ctx; X509V3_set_ctx(&ctx, cert, cert, 0, 0, 0); X509_EXTENSION *ex = X509V3_EXT_conf_nid(0, &ctx, flag, name); if (ex) { result = X509_add_ext(cert, ex, -1); X509_EXTENSION_free(ex); } return result; }
/* * Set one extension in a given certificate */ static int set_extension(X509 * issuer, X509 * cert, int nid, char * value) { X509_EXTENSION * ext ; X509V3_CTX ctx ; X509V3_set_ctx(&ctx, issuer, cert, NULL, NULL, 0); ext = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ext) return -1; X509_add_ext(cert, ext, -1); X509_EXTENSION_free(ext); return 0 ; }
/*============================================================================ * 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; }
// Add extension using V3 code: we can set the config file as NULL because we wont reference any other sections. int __fastcall util_add_ext(X509 *cert, int nid, char *value) { X509_EXTENSION *ex; X509V3_CTX ctx; // This sets the 'context' of the extensions. No configuration database X509V3_set_ctx_nodb(&ctx); // Issuer and subject certs: both the target since it is self signed, no request and no CRL X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ex) return 0; X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); return 1; }
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; }
void add_ext(X509 *cert, int nid, const char *value) { X509_EXTENSION *ex = NULL; X509V3_CTX ctx; /* This sets the 'context' of the extensions. */ /* No configuration database */ X509V3_set_ctx_nodb(&ctx); /* Issuer and subject certs: both the target since it is self signed, * no request and no CRL */ X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); MORDOR_VERIFY(X509V3_EXT_conf_nid(NULL, &ctx, nid, (char*) value)); X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); }
/* * Copy a X509v3 extension from one certificate to another. * If the extension is not present in the original certificate, * the extension will not be added to the destination certificate. * Returns 1 if ext was copied, 0 if not present in origcrt, -1 on error. */ int ssl_x509_v3ext_copy_by_nid(X509 *crt, X509 *origcrt, int nid) { X509_EXTENSION *ext; int pos; pos = X509_get_ext_by_NID(origcrt, nid, -1); if (pos == -1) return 0; ext = X509_get_ext(origcrt, pos); if (!ext) return -1; if (X509_add_ext(crt, ext, -1) != 1) return -1; return 1; }
/** * Returns true on success, false on failure * * Example: * @code * <#example#> * @endcode */ static bool _addCertificateExtensionWithContext(X509 *cert, int nid, char *value) { X509_EXTENSION *extension; X509V3_CTX context; X509V3_set_ctx_nodb(&context); X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0); extension = X509V3_EXT_conf_nid(NULL, &context, nid, value); if (extension == NULL) { return false; } X509_add_ext(cert, extension, -1); X509_EXTENSION_free(extension); return true; }
int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert) { 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(cert) X509_add_ext(cert, ext, -1); X509_EXTENSION_free(ext); } return 1; }
int PKI_X509_CERT_add_extension_stack(PKI_X509_CERT *x, const PKI_X509_EXTENSION_STACK *ext) { int i = 0; PKI_X509_EXTENSION *ossl_ext = NULL; if( !x || !x->value || !ext ) return (PKI_ERR); for( i = 0; i < PKI_STACK_X509_EXTENSION_elements(ext); i++ ) { ossl_ext = PKI_STACK_X509_EXTENSION_get_num( ext, i); if( !ossl_ext ) continue; if(!X509_add_ext ((X509 *) x->value, ossl_ext->value, -1 )) { PKI_log_err ( "Adding Extensions::%s", ERR_error_string( ERR_get_error(), NULL ) ); return ( PKI_ERR ); }; } return (PKI_OK); }
int add_ext( X509 *issuer, X509 *subj, int nid, const char* value ) { X509V3_CTX ctx; X509V3_set_ctx( &ctx, issuer, subj, NULL, NULL, 0 ); X509_EXTENSION *ex = X509V3_EXT_conf_nid( NULL, &ctx, nid, (char *) value ); if( !ex ) { return 0; } // removing old extensions of the same type int loc = -1; while( ( loc = X509_get_ext_by_NID(subj, nid, loc) ) != -1 ){ printf("Removing old extension number %d\n", loc); X509_EXTENSION *old = X509_delete_ext(subj, loc); X509_EXTENSION_free(old); } // adding the new extension X509_add_ext( subj, ex, -1 ); X509_EXTENSION_free( ex ); return 1; }
/* * Create a fake X509v3 certificate, signed by the provided CA, * based on the original certificate retrieved from the real server. * The returned certificate is created using X509_new() and thus must * be freed by the caller using X509_free(). * The optional argument extraname is added to subjectAltNames if provided. */ X509 * ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt, const char *extraname, EVP_PKEY *key) { X509_NAME *subject, *issuer; GENERAL_NAMES *names; GENERAL_NAME *gn; X509 *crt; subject = X509_get_subject_name(origcrt); issuer = X509_get_subject_name(cacrt); if (!subject || !issuer) return NULL; crt = X509_new(); if (!crt) return NULL; if (!X509_set_version(crt, 0x02) || !X509_set_subject_name(crt, subject) || !X509_set_issuer_name(crt, issuer) || ssl_x509_serial_copyrand(crt, origcrt) == -1 || !X509_gmtime_adj(X509_get_notBefore(crt), (long)-60*60*24) || !X509_gmtime_adj(X509_get_notAfter(crt), (long)60*60*24*364) || !X509_set_pubkey(crt, key)) goto errout; /* add standard v3 extensions; cf. RFC 2459 */ X509V3_CTX ctx; X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0); if (ssl_x509_v3ext_add(&ctx, crt, "basicConstraints", "CA:FALSE") == -1 || ssl_x509_v3ext_add(&ctx, crt, "keyUsage", "digitalSignature," "keyEncipherment") == -1 || ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage", "serverAuth") == -1 || ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier", "hash") == -1 || ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier", "keyid,issuer:always") == -1) goto errout; if (!extraname) { /* no extraname provided: copy original subjectAltName ext */ if (ssl_x509_v3ext_copy_by_nid(crt, origcrt, NID_subject_alt_name) == -1) goto errout; } else { names = X509_get_ext_d2i(origcrt, NID_subject_alt_name, 0, 0); if (!names) { /* no subjectAltName present: add new one */ char *cfval; if (asprintf(&cfval, "DNS:%s", extraname) < 0) goto errout; if (ssl_x509_v3ext_add(&ctx, crt, "subjectAltName", cfval) == -1) { free(cfval); goto errout; } free(cfval); } else { /* add extraname to original subjectAltName * and add it to the new certificate */ gn = GENERAL_NAME_new(); if (!gn) goto errout2; gn->type = GEN_DNS; gn->d.dNSName = M_ASN1_IA5STRING_new(); if (!gn->d.dNSName) goto errout3; ASN1_STRING_set(gn->d.dNSName, (unsigned char *)extraname, strlen(extraname)); sk_GENERAL_NAME_push(names, gn); X509_EXTENSION *ext = X509V3_EXT_i2d( NID_subject_alt_name, 0, names); if (!X509_add_ext(crt, ext, -1)) { if (ext) { X509_EXTENSION_free(ext); } goto errout3; } X509_EXTENSION_free(ext); sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } } #ifdef DEBUG_CERTIFICATE ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PNAME); #endif /* DEBUG_CERTIFICATE */ const EVP_MD *md; switch (EVP_PKEY_type(cakey->type)) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: md = EVP_sha1(); break; #endif /* !OPENSSL_NO_RSA */ #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: md = EVP_dss1(); break; #endif /* !OPENSSL_NO_DSA */ #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: md = EVP_ecdsa(); break; #endif /* !OPENSSL_NO_ECDSA */ default: goto errout; } if (!X509_sign(crt, cakey, md)) goto errout; return crt; errout3: GENERAL_NAME_free(gn); errout2: sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); errout: X509_free(crt); return NULL; }
// Creates a X509 certificate, if rootcert is NULL this creates a root (self-signed) certificate. // Is the name parameter is NULL, the hex value of the hash of the public key will be the subject name. int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert) { X509 *x = NULL; X509_EXTENSION *ex = NULL; EVP_PKEY *pk = NULL; RSA *rsa = NULL; X509_NAME *cname=NULL; X509 **x509p = NULL; EVP_PKEY **pkeyp = NULL; char hash[UTIL_HASHSIZE]; char serial[8]; char nameStr[(UTIL_HASHSIZE * 2) + 2]; BIGNUM *oBigNbr; CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); if (initialcert != NULL) { pk = X509_get_pubkey(initialcert->x509); rsa = EVP_PKEY_get1_RSA(initialcert->pkey); if ((x=X509_new()) == NULL) goto err; } else { if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) return 0; } else pk = *pkeyp; if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x = *x509p; oBigNbr = BN_new(); rsa = RSA_new(); BN_set_word(oBigNbr, RSA_F4); if (RSA_generate_key_ex(rsa, bits, oBigNbr, NULL) == -1) { RSA_free(rsa); BN_free(oBigNbr); abort(); goto err; } BN_free(oBigNbr); } if (!EVP_PKEY_assign_RSA(pk, rsa)) { RSA_free(rsa); abort(); goto err; } rsa = NULL; util_randomtext(8, serial); X509_set_version(x, 2); ASN1_STRING_set(X509_get_serialNumber(x), serial, 8); X509_gmtime_adj(X509_get_notBefore(x),(long)60*60*24*-2); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x, pk); // Set the subject name cname = X509_get_subject_name(x); if (name == NULL) { // Computer the hash of the public key util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); util_tohex(hash, UTIL_HASHSIZE, nameStr); X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0); } else { // This function creates and adds the entry, working out the correct string type and performing checks on its length. Normally we'd check the return value for errors... X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)name, -1, -1, 0); } if (rootcert == NULL) { // Its self signed so set the issuer name to be the same as the subject. X509_set_issuer_name(x,cname); // Add various extensions: standard extensions util_add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); util_add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); util_add_ext(x, NID_subject_key_identifier, "hash"); //util_add_ext(x, NID_netscape_cert_type, "sslCA"); //util_add_ext(x, NID_netscape_comment, "example comment extension"); if (!X509_sign(x, pk, EVP_sha256())) goto err; } else { // This is a sub-certificate cname=X509_get_subject_name(rootcert->x509); X509_set_issuer_name(x, cname); // Add usual cert stuff ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "digitalSignature, keyEncipherment, keyAgreement"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); // Add usages: TLS server, TLS client, Intel(R) AMT Console //ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication, TLS Web Client Authentication, 2.16.840.1.113741.1.2.1, 2.16.840.1.113741.1.2.2"); if (certtype == CERTIFICATE_TLS_SERVER) { // TLS server ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } else if (certtype == CERTIFICATE_TLS_CLIENT) { // TLS client ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Client Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } if (!X509_sign(x, rootcert->pkey, EVP_sha256())) goto err; } cert->x509 = x; cert->pkey = pk; return(1); err: return(0); }
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; }
void X509V3_add_ext(X509V3_CTX *ctx, X509 *cert, int nid, char *value) { X509_EXTENSION *ex = X509V3_EXT_conf_nid(NULL, ctx, nid, value); X509_add_ext(cert, ex, -1); X509_EXTENSION_free(ex); }
static int autoca_gencert( Operation *op, genargs *args ) { X509_NAME *subj_name, *issuer_name; X509 *subj_cert; struct berval derdn; unsigned char *pp; EVP_PKEY *evpk = NULL; int rc; if ((subj_cert = X509_new()) == NULL) return -1; autoca_dnbv2der( op, args->subjectDN, &derdn ); pp = (unsigned char *)derdn.bv_val; subj_name = d2i_X509_NAME( NULL, (const unsigned char **)&pp, derdn.bv_len ); op->o_tmpfree( derdn.bv_val, op->o_tmpmemctx ); if ( subj_name == NULL ) { fail1: X509_free( subj_cert ); return -1; } rc = autoca_genpkey( args->keybits, &evpk ); if ( rc <= 0 ) { fail2: if ( subj_name ) X509_NAME_free( subj_name ); goto fail1; } /* encode DER in PKCS#8 */ { PKCS8_PRIV_KEY_INFO *p8inf; if (( p8inf = EVP_PKEY2PKCS8( evpk )) == NULL ) goto fail2; args->derpkey.bv_len = i2d_PKCS8_PRIV_KEY_INFO( p8inf, NULL ); args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->derpkey.bv_val; i2d_PKCS8_PRIV_KEY_INFO( p8inf, &pp ); PKCS8_PRIV_KEY_INFO_free( p8inf ); } args->newpkey = evpk; /* set random serial */ { BIGNUM *bn = BN_new(); if ( bn == NULL ) { fail3: EVP_PKEY_free( evpk ); goto fail2; } if (!BN_pseudo_rand(bn, SERIAL_BITS, 0, 0)) { BN_free( bn ); goto fail3; } if (!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(subj_cert))) { BN_free( bn ); goto fail3; } BN_free(bn); } if (args->issuer_cert) { issuer_name = X509_get_subject_name(args->issuer_cert); } else { issuer_name = subj_name; args->issuer_cert = subj_cert; args->issuer_pkey = evpk; } if (!X509_set_version(subj_cert, 2) || /* set version to V3 */ !X509_set_issuer_name(subj_cert, issuer_name) || !X509_set_subject_name(subj_cert, subj_name) || !X509_gmtime_adj(X509_get_notBefore(subj_cert), 0) || !X509_time_adj_ex(X509_get_notAfter(subj_cert), args->days, 0, NULL) || !X509_set_pubkey(subj_cert, evpk)) { goto fail3; } X509_NAME_free(subj_name); subj_name = NULL; /* set cert extensions */ { X509V3_CTX ctx; X509_EXTENSION *ext; int i; X509V3_set_ctx(&ctx, args->issuer_cert, subj_cert, NULL, NULL, 0); for (i=0; args->cert_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->cert_exts[i].name, args->cert_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } if (args->more_exts) { for (i=0; args->more_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->more_exts[i].name, args->more_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } } } rc = autoca_signcert( subj_cert, args->issuer_pkey ); if ( rc < 0 ) goto fail3; args->dercert.bv_len = i2d_X509( subj_cert, NULL ); args->dercert.bv_val = op->o_tmpalloc( args->dercert.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->dercert.bv_val; i2d_X509( subj_cert, &pp ); args->newcert = subj_cert; return 0; }
static TokenError saveKeys(const CertReq *reqs, const char *hostname, const char *password, FILE *file) { TokenError error = TokenError_Unknown; PKCS12 *p12 = NULL; // Add PKCS7 safes with the keys STACK_OF(PKCS7) *authsafes = NULL; uint32_t localKeyId = 0; size_t error_count = 0; while (reqs) { STACK_OF(PKCS12_SAFEBAG) *bags = NULL; X509 *cert = NULL; ASN1_OBJECT *objOwningHost = NULL; uint32_t keyid = htonl(localKeyId++); bool success = false; // Add private key PKCS12_SAFEBAG *bag = PKCS12_add_key(&bags, reqs->privkey, opensslKeyUsages[reqs->pkcs10->keyUsage], ENC_ITER, ENC_NID, (char*)password); if (!bag) goto loop_end; // Add name and localKeyId to the key bag // TODO extract name from subject DN char *name = "names are not implemented yet"; if (!X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, MBSTRING_UTF8, (unsigned char*)name, strlen(name)) || !PKCS12_add_localkeyid(bag, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; // Add a certificate so we can find the key by the subject name cert = X509_REQ_to_X509(reqs->x509, 3650, reqs->privkey); if (!cert || !X509_keyid_set1(cert, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; if (!X509_add_ext(cert, makeKeyUsageExt(reqs->pkcs10->keyUsage), -1)) goto loop_end; if (!PKCS12_add_cert(&bags, cert)) goto loop_end; // Add hostname (FriBID extension) so we can do same-origin checks // TODO maybe we should use document.domain instead of document.location.hostname? objOwningHost = OBJ_txt2obj(OID_OWNING_HOST, 1); if (!objOwningHost) goto loop_end; bag = sk_PKCS12_SAFEBAG_value(bags, sk_PKCS12_SAFEBAG_num(bags)-1); if (!X509at_add1_attr_by_OBJ(&bag->attrib, objOwningHost, MBSTRING_UTF8, (unsigned char*)hostname, strlen(hostname))) goto loop_end; // Add a new authsafe if (!PKCS12_add_safe(&authsafes, bags, -1, 0, NULL)) goto loop_end; // Success! success = true; loop_end: if (!success) { error_count--; certutil_updateErrorString(); } ASN1_OBJECT_free(objOwningHost); X509_free(cert); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); reqs = reqs->next; } if (error_count != 0) goto end; // Create the PKCS12 wrapper p12 = PKCS12_add_safes(authsafes, 0); if (!p12) { certutil_updateErrorString(); goto end; } PKCS12_set_mac(p12, (char*)password, -1, NULL, 0, MAC_ITER, NULL); // Save file if (i2d_PKCS12_fp(file, p12)) { error = TokenError_Success; } end: sk_PKCS7_pop_free(authsafes, PKCS7_free); PKCS12_free(p12); return error; }
int main() { EVP_PKEY *pKey; RSA *rsa; X509 *x509; X509_NAME *name; X509_EXTENSION *ex; FILE *fp; int KEY_SIZE = 2048; int days = 365; pKey = EVP_PKEY_new(); // Create a private key rsa = RSA_generate_key( KEY_SIZE, // Key length (bits) RSA_F4, // Exponent NULL, // Callback NULL // Callback argument ); EVP_PKEY_assign_RSA(pKey, rsa); x509 = X509_new(); X509_set_version(x509, 3); ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); X509_gmtime_adj(X509_get_notBefore(x509), 0); X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * days); X509_set_pubkey(x509, pKey); name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, "Wnmp", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "Wnmp", -1, -1, 0); X509_set_issuer_name(x509, name); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_cert_type, "server"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_comment, "Wnmp by Kurt Cancemi"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_ssl_server_name, "localhost"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); X509_sign(x509, pKey, EVP_sha1()); if (!(fp = fopen(KEY_PUB, "w"))) { printf("Error writing to public key file"); return -1; } if (PEM_write_X509(fp, x509) != 1) printf("Error while writing public key"); fclose(fp); if (!(fp = fopen(KEY_PRV, "w"))) { printf("Error writing to private key file"); return -1; } if (PEM_write_PrivateKey(fp, pKey, NULL, NULL, 0, NULL, NULL) != 1) printf("Error while writing private key"); fclose(fp); X509_free(x509); EVP_PKEY_free(pKey); return 0; }