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; }
static X509 * GenerateX509Cert(X509_REQ *req, // IN CONF *config, // IN int days) // IN { X509 *cert; X509V3_CTX ctx; char *extensions; gboolean ret = FALSE; gchar *err = NULL; cert = X509_new(); if (!cert) { Error("Failed to allocate a X509 certificate: %s.\n", GetSSLError(&err)); goto exit; } if (!SetCertSerialNumber(cert)) { goto exit; } if (!X509_set_issuer_name(cert, X509_REQ_get_subject_name(req)) || !X509_gmtime_adj(X509_get_notBefore(cert), 0) || !X509_gmtime_adj(X509_get_notAfter(cert), (long)60*60*24*days) || !X509_set_subject_name(cert, X509_REQ_get_subject_name(req))) { Error("Failed to configure the X509 certificate: %s.\n", GetSSLError(&err)); goto exit; } X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); X509V3_set_nconf(&ctx, config); extensions = NCONF_get_string(config, "req", "x509_extensions"); if (extensions) { if (!X509_set_version(cert, 2)) { Error("Failed to set the certificate version: %s.\n", GetSSLError(&err)); goto exit; } if (!X509V3_EXT_add_nconf(config, &ctx, extensions, cert)) { Error("Error loading extension section %s: %s.\n", extensions, GetSSLError(&err)); goto exit; } } ret = TRUE; exit: if (!ret) { X509_free(cert); cert = NULL; } g_free(err); return cert; }
DWORD VMCAUpdateAuthorityKeyIdentifier( X509_CRL *pCrl, PVMCA_X509_CA pCA ) { DWORD dwError = 0; X509V3_CTX ctx; X509_EXTENSION *pExtension = NULL; if (!pCA || !pCA->pCertificate || !pCrl ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR (dwError); } X509V3_set_ctx_nodb (&ctx); X509V3_set_ctx( &ctx, pCA->pCertificate, NULL, NULL, pCrl, 0 ); pExtension = X509V3_EXT_conf_nid( NULL, &ctx, NID_authority_key_identifier, "keyid" ); if (!pExtension) { goto error; } X509_CRL_add_ext (pCrl, pExtension, -1); cleanup: if (pExtension) { X509_EXTENSION_free(pExtension); } return dwError; error: goto cleanup; }
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; }
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; }
/* * 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 ; }
// 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; }
X509 *make_server_cert(EC_GROUP *group, EVP_PKEY **pk, const char *cn) { X509 *cert = make_cert(group, pk); if (cert) { X509_NAME *name = X509_get_subject_name(cert); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *) cn, -1, -1, 0); X509_set_issuer_name(cert, name); X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); X509V3_add_ext(&ctx, cert, NID_basic_constraints, "critical,CA:TRUE"); X509V3_add_ext(&ctx, cert, NID_key_usage, "critical,keyCertSign,cRLSign,digitalSignature"); X509V3_add_ext(&ctx, cert, NID_ext_key_usage, "serverAuth"); } return cert; }
/** * 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; }
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); }
/* self sign */ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, CONF *conf, char *section) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(x); EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_save_parameters(pktmp,1); EVP_PKEY_free(pktmp); if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err; if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err; /* Lets just make it 12:00am GMT, Jan 1 1970 */ /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ /* 28 days to be certified */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto err; if (!X509_set_pubkey(x,pkey)) goto err; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err; } if (!X509_sign(x,pkey,digest)) goto err; return 1; err: ERR_print_errors(bio_err); return 0; }
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; }
NewX509::NewX509(QWidget *parent) :QDialog(parent) { int i; eku_nid = *MainWindow::eku_nid; dn_nid = *MainWindow::dn_nid; aia_nid = *MainWindow::aia_nid; attr_nid << NID_pkcs9_unstructuredName << NID_pkcs9_challengePassword; QStringList keys; setupUi(this); /* temporary storage for creating temporary X509V3_CTX */ ctx_cert = NULL; for (i=0; i < dn_nid.count(); i++) keys << QString(OBJ_nid2ln(dn_nid[i])); extDNlist->setKeys(keys); extDNlist->setInfoLabel(extDNinfo); connect(extDNlist->itemDelegateForColumn(1), SIGNAL(setupLineEdit(const QString &, QLineEdit *)), this, SLOT(setupExtDNwidget(const QString &, QLineEdit *))); setWindowTitle(XCA_TITLE); for (i=0; i<tabWidget->count(); i++) { tabnames << tabWidget->tabText(i); } nsImg->setPixmap(*MainWindow::nsImg); serialNr->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"), this)); QStringList strings; // are there any useable private keys ? newKeyDone(""); // any PKCS#10 requests to be used ? strings = MainWindow::reqs->getDesc(); if (strings.isEmpty()) { fromReqCB->setDisabled(true); fromReqCB->setChecked(false); } else { reqList->insertItems(0, strings); } on_fromReqCB_clicked(); // How about signing certificates ? strings = MainWindow::certs->getSignerDesc(); if (strings.isEmpty()) { foreignSignRB->setDisabled(true); } else { certList->insertItems(0, strings); } #ifdef WG_QA_SERIAL selfQASignRB = new QRadioButton(signerBox); setTabOrder(serialNr, selfQASignRB); setTabOrder(selfQASignRB, foreignSignRB); selfQASignRB->setText(tr( "Create a &self signed certificate with a MD5-hashed QA serial")); QBoxLayout *l = (QBoxLayout *)signerBox->layout(); l->insertWidget(1, selfQASignRB); #endif // set dates to now and now + 1 year validNumber->setText("1"); validRange->setCurrentIndex(2); on_applyTime_clicked(); // settings for the templates .... strings.clear(); strings = MainWindow::temps->getDescPredefs(); tempList->insertItems(0, strings); // setup Extended keyusage for (i=0; i < eku_nid.count(); i++) ekeyUsage->addItem(OBJ_nid2ln(eku_nid[i])); // setup Authority Info Access for (i=0; i < aia_nid.count(); i++) aiaOid->addItem(OBJ_nid2ln(aia_nid[i])); // init the X509 v3 context X509V3_set_ctx(&ext_ctx, NULL , NULL, NULL, NULL, 0); X509V3_set_ctx_nodb(&ext_ctx); QList<QLabel *> nameLabel; nameLabel << LcountryName << LstateOrProvinceName << LlocalityName << LorganisationName << LorganisationalUnitName << LcommonName << LemailAddress; for(int i=0; i<nameLabel.count(); i++) { nameLabel[i]->setText(OBJ_nid2ln(name_nid[i])); QString tt = nameLabel[i]->toolTip(); nameLabel[i]->setToolTip(QString("[%1] %2"). arg(OBJ_nid2sn(name_nid[i])).arg(tt)); name_ptr[i] = (QLineEdit *)nameLabel[i]->buddy(); setupLineEditByNid(name_nid[i], name_ptr[i]); } // Setup Request Attributes if (attrWidget->layout()) delete attrWidget->layout(); QGridLayout *attrLayout = new QGridLayout(attrWidget); attrLayout->setAlignment(Qt::AlignTop); attrLayout->setSpacing(6); attrLayout->setMargin(0); attr_edit.clear(); for (i=0; i < attr_nid.count(); i++) { QLabel *label; QLineEdit *edit; int nid = attr_nid[i]; label = new QLabel(this); label->setText(QString(OBJ_nid2ln(nid))); label->setToolTip(QString(OBJ_nid2sn(nid))); edit = new QLineEdit(this); attr_edit << edit; attrLayout->addWidget(label, i, 0); attrLayout->addWidget(edit, i, 1); setupLineEditByNid(nid, edit); } // last polish on_certList_currentIndexChanged(0); certList->setDisabled(true); tabWidget->setCurrentIndex(0); attrWidget->hide(); pt = none; notAfter->setEndDate(true); }
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; }
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; }
/* * Constructor for X509Extension, never called by Python code directly * * Arguments: type_name - ??? * critical - ??? * value - ??? * subject - An x509v3 certificate which is the subject for this extension. * issuer - An x509v3 certificate which is the issuer for this extension. * Returns: The newly created X509Extension object */ crypto_X509ExtensionObj * crypto_X509Extension_New(char *type_name, int critical, char *value, crypto_X509Obj *subject, crypto_X509Obj *issuer) { X509V3_CTX ctx; crypto_X509ExtensionObj *self; char* value_with_critical = NULL; /* * A context is necessary for any extension which uses the r2i conversion * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx. * Start off by initializing most of the fields to NULL. */ X509V3_set_ctx(&ctx, NULL, NULL, NULL, NULL, 0); /* * We have no configuration database - but perhaps we should (some * extensions may require it). */ X509V3_set_ctx_nodb(&ctx); /* * Initialize the subject and issuer, if appropriate. ctx is a local, and * as far as I can tell none of the X509V3_* APIs invoked here steal any * references, so no need to incref subject or issuer. */ if (subject) { ctx.subject_cert = subject->x509; } if (issuer) { ctx.issuer_cert = issuer->x509; } self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type); if (self == NULL) { goto error; } self->dealloc = 0; /* There are other OpenSSL APIs which would let us pass in critical * separately, but they're harder to use, and since value is already a pile * of crappy junk smuggling a ton of utterly important structured data, * what's the point of trying to avoid nasty stuff with strings? (However, * X509V3_EXT_i2d in particular seems like it would be a better API to * invoke. I do not know where to get the ext_struc it desires for its * last parameter, though.) */ value_with_critical = malloc(strlen("critical,") + strlen(value) + 1); if (!value_with_critical) { goto critical_malloc_error; } if (critical) { strcpy(value_with_critical, "critical,"); strcpy(value_with_critical + strlen("critical,"), value); } else { strcpy(value_with_critical, value); } self->x509_extension = X509V3_EXT_nconf( NULL, &ctx, type_name, value_with_critical); free(value_with_critical); if (!self->x509_extension) { goto nconf_error; } self->dealloc = 1; return self; nconf_error: exception_from_error_queue(crypto_Error); critical_malloc_error: Py_XDECREF(self); error: return NULL; }
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create, int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno) { int ret=0; ASN1_INTEGER *bs=NULL; X509_STORE_CTX xsc; EVP_PKEY *upkey; upkey = X509_get_pubkey(xca); EVP_PKEY_copy_parameters(upkey,pkey); EVP_PKEY_free(upkey); if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL)) { BIO_printf(bio_err,"Error initialising X509 store\n"); goto end; } if (sno) bs = sno; else if (!(bs = load_serial(CAfile, serialfile, create))) goto end; if (!X509_STORE_add_cert(ctx,x)) goto end; /* NOTE: this certificate can/should be self signed, unless it was * a certificate request in which case it is not. */ X509_STORE_CTX_set_cert(&xsc,x); if (!reqfile && !X509_verify_cert(&xsc)) goto end; if (!X509_check_private_key(xca,pkey)) { BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); goto end; } if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end; if (!X509_set_serialNumber(x,bs)) goto end; if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL) goto end; /* hardwired expired */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto end; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx2; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); X509V3_set_nconf(&ctx2, conf); if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end; } if (!X509_sign(x,pkey,digest)) goto end; ret=1; end: X509_STORE_CTX_cleanup(&xsc); if (!ret) ERR_print_errors(bio_err); if (!sno) ASN1_INTEGER_free(bs); return ret; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create( OpcUa_CryptoProvider* a_pProvider, OpcUa_Int32 a_serialNumber, OpcUa_UInt32 a_validToInSec, OpcUa_Crypto_NameEntry* a_pNameEntries, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_UInt a_nameEntriesCount, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_Key a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */ OpcUa_Crypto_Extension* a_pExtensions, OpcUa_UInt a_extensionsCount, OpcUa_UInt a_signatureHashAlgorithm, /* EVP_sha1(),... */ OpcUa_Key a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */ OpcUa_ByteString* a_pCertificate) { OpcUa_UInt i; X509_NAME* pSubj = OpcUa_Null; X509V3_CTX ctx; const EVP_MD* pDigest = OpcUa_Null; X509* pCert = OpcUa_Null; EVP_PKEY* pSubjectPublicKey = OpcUa_Null; EVP_PKEY* pIssuerPrivateKey = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries); OpcUa_ReturnErrorIfArgumentNull(a_pExtensions); OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length); if(pSubjectPublicKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length); if(pIssuerPrivateKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create new certificate object */ pCert = X509_new(); if(pCert == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set version of certificate (V3 since internal representation starts versioning from 0) */ if(X509_set_version(pCert, 2L) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* generate a unique number for a serial number if none provided. */ if(a_serialNumber == 0) { ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert); pSerialNumber->type = V_ASN1_INTEGER; pSerialNumber->data = OPENSSL_realloc(pSerialNumber->data, 16); pSerialNumber->length = 16; if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } } /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */ else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add key to the request */ if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); pSubjectPublicKey = OpcUa_Null; } /* assign the subject name */ pSubj = X509_NAME_new(); if(!pSubj) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create and add entries to subject name */ for(i=0; i<a_nameEntriesCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i); OpcUa_GotoErrorIfBad(uStatus); } /* set subject name in request */ if(X509_set_subject_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set name of issuer (CA) */ if(X509_set_issuer_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set ending time of the certificate */ if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add x509v3 extensions */ X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0); for(i=0; i<a_extensionsCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx); OpcUa_GotoErrorIfBad(uStatus); } /* sign certificate with the CA private key */ switch(a_signatureHashAlgorithm) { case OPCUA_P_SHA_160: pDigest = EVP_sha1(); break; case OPCUA_P_SHA_224: pDigest = EVP_sha224(); break; case OPCUA_P_SHA_256: pDigest = EVP_sha256(); break; case OPCUA_P_SHA_384: pDigest = EVP_sha384(); break; case OPCUA_P_SHA_512: pDigest = EVP_sha512(); break; default: uStatus = OpcUa_BadNotSupported; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(X509_verify(pCert, pIssuerPrivateKey) <= 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); pIssuerPrivateKey = OpcUa_Null; } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); pSubj = OpcUa_Null; } /* prepare container */ memset(a_pCertificate, 0, sizeof(OpcUa_ByteString)); /* get required length for conversion target buffer */ a_pCertificate->Length = i2d_X509(pCert, NULL); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } /* allocate conversion target buffer */ a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data); /* convert into DER */ a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data)); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } else { /* correct pointer incrementation by i2d_X509() */ a_pCertificate->Data -= a_pCertificate->Length; } X509_free(pCert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; X509_free(pCert); if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); } OpcUa_FinishErrorHandling; }
/* * 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; }