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; }
void AuthorityCertificateManager::getCertificateForTarget(boost::asio::ip::tcp::endpoint &endpoint, bool wildcardOK, X509 *serverCertificate, Certificate **cert, std::list<Certificate*> **chainList) { X509_NAME *serverName = X509_get_subject_name(serverCertificate); X509_NAME *issuerName = X509_get_subject_name(authority->getCert()); X509 *request = X509_new(); X509_set_version(request, 3); X509_set_subject_name(request, serverName); X509_set_issuer_name(request, issuerName); ASN1_INTEGER_set(X509_get_serialNumber(request), generateRandomSerial()); X509_gmtime_adj(X509_get_notBefore(request), -365); X509_gmtime_adj(X509_get_notAfter(request), (long)60*60*24*365); X509_set_pubkey(request, this->leafPair); X509_sign(request, authority->getKey(), EVP_sha1()); Certificate *leaf = new Certificate(); leaf->setCert(request); leaf->setKey(this->leafPair); *cert = leaf; *chainList = &(this->chainList); // *chain = this->authority; }
X509 *make_cert(EC_GROUP *group, EVP_PKEY **pk) { EC_KEY *key = EC_KEY_new(); X509 *cert = X509_new(); *pk = EVP_PKEY_new(); if (!key || !cert || !*pk) goto error; if (!EC_KEY_set_group(key, group)) goto error; if (!EC_KEY_generate_key(key)) goto error; EVP_PKEY_assign_EC_KEY(*pk, key); unsigned long serial; RAND_bytes((unsigned char *) &serial, sizeof(serial)); ASN1_INTEGER_set(X509_get_serialNumber(cert), serial >> 1); X509_set_version(cert, 2); X509_gmtime_adj(X509_get_notBefore(cert), 0); X509_gmtime_adj(X509_get_notAfter(cert), 60 * 60 * 24 * 3650L); X509_set_pubkey(cert, *pk); return cert; error: if (key) EC_KEY_free(key); if (cert) X509_free(cert); if (*pk) EVP_PKEY_free(*pk); *pk = NULL; return NULL; }
/* creates a self-signed certificate for a key */ X509 * ship_create_selfsigned_cert(char *subject, int ttl, RSA* signer_key) { X509 *x = 0, *ret = 0; X509_NAME *tmp = 0; EVP_PKEY *pr_key = 0; ASSERT_TRUE(x = X509_new(), err); ASSERT_TRUE(pr_key = EVP_PKEY_new(), err); ASSERT_TRUE(EVP_PKEY_set1_RSA(pr_key, signer_key), err); ASSERT_TRUE(X509_set_version(x, 2), err); /* version 3 certificate */ ASN1_INTEGER_set(X509_get_serialNumber(x), 0); ASSERT_TRUE(X509_gmtime_adj(X509_get_notBefore(x), 0), err); ASSERT_TRUE(X509_gmtime_adj(X509_get_notAfter(x), (long)ttl), err); ASSERT_TRUE(tmp = X509_get_subject_name(x), err); ASSERT_TRUE(X509_NAME_add_entry_by_txt(tmp, "CN", MBSTRING_ASC, (unsigned char*)subject, -1, -1, 0), err); ASSERT_TRUE(X509_set_subject_name(x, tmp), err); ASSERT_TRUE(X509_set_pubkey(x, pr_key), err); ASSERT_TRUE(X509_sign(x, pr_key, EVP_sha1()), err); ret = x; x = NULL; err: if (x) X509_free(x); if (pr_key) EVP_PKEY_free(pr_key); return ret; }
sqbind::SQINT COsslCert::Create( COsslKey *x_pKey, sqbind::SQINT x_nSerialNumber, sqbind::SQINT x_nSecondsValid ) {_STT(); // Lose old cert Destroy(); if ( !x_pKey || ! x_pKey->getPublicKeyPtr() ) return 0; m_pX509 = X509_new(); if ( !m_pX509 ) return 0; // Set certificate version X509_set_version( m_pX509, 2 ); ASN1_INTEGER_set( X509_get_serialNumber( m_pX509 ), x_nSerialNumber ); X509_gmtime_adj( X509_get_notBefore( m_pX509 ), 0 ); X509_gmtime_adj( X509_get_notAfter( m_pX509 ), x_nSecondsValid ); X509_set_pubkey( m_pX509, x_pKey->getPublicKeyPtr() ); return 1; }
Certificate::Certificate(const string& _subject, const string& _issuer, const string& _validity, const Node::Id_t _owner, RSA *_rsaPubKey) : #ifdef DEBUG_LEAKS LeakMonitor(LEAK_TYPE_CERTIFICATE), #endif stored(false), verified(false), hasSignature(false), x(NULL), subject(_subject), issuer(_issuer), validity(_validity), pubKey(NULL), rsaPubKey(NULL), x509_PEM_str(NULL) { memcpy(owner, _owner, sizeof(Node::Id_t)); x = X509_new(); if (!x) { HAGGLE_ERR("Could not allocate X509 certificate struct\n"); return; } X509_set_version(x, 2); pubKey = EVP_PKEY_new(); if (!pubKey) { X509_free(x); HAGGLE_ERR("Could not allocate X509 EVP_PKEY\n"); return; } EVP_PKEY_assign_RSA(pubKey, RSAPublicKey_dup(_rsaPubKey)); X509_set_pubkey(x, pubKey); rsaPubKey = EVP_PKEY_get1_RSA(pubKey); /* Set validity. FIXME: currently hardcoded */ int days = 30; X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_NAME *subject_name = X509_get_subject_name(x); /* Set subject */ //X509_NAME_add_entry_by_txt(subname,"C", MBSTRING_ASC, "SE", -1, -1, 0); X509_NAME_add_entry_by_txt(subject_name, "CN", MBSTRING_ASC, (const unsigned char *)subject.c_str(), -1, -1, 0); X509_NAME_add_entry_by_txt(subject_name, "O", MBSTRING_ASC, (const unsigned char *)"Haggle", -1, -1, 0); X509_set_subject_name(x, subject_name); /* Set issuer */ X509_NAME *issuer_name = X509_get_issuer_name(x); X509_NAME_add_entry_by_txt(issuer_name, "CN", MBSTRING_ASC, (const unsigned char *)issuer.c_str(), -1, -1, 0); X509_NAME_add_entry_by_txt(issuer_name, "O", MBSTRING_ASC, (const unsigned char *)"Haggle", -1, -1, 0); X509_set_issuer_name(x, issuer_name); //HAGGLE_DBG("Subject=\'%s\' issuer=\'%s\'\n", subject.c_str(), issuer.c_str()); certificate_set_serial(x); }
// Generate a self-signed certificate, with the public key from the // given key pair. Caller is responsible for freeing the returned object. static X509* MakeCertificate(EVP_PKEY* pkey, const char* common_name) { LOG(LS_INFO) << "Making certificate for " << common_name; X509* x509 = NULL; BIGNUM* serial_number = NULL; X509_NAME* name = NULL; if ((x509=X509_new()) == NULL) goto error; if (!X509_set_pubkey(x509, pkey)) goto error; // serial number // temporary reference to serial number inside x509 struct ASN1_INTEGER* asn1_serial_number; if (!(serial_number = BN_new()) || !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) || !(asn1_serial_number = X509_get_serialNumber(x509)) || !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) goto error; if (!X509_set_version(x509, 0L)) // version 1 goto error; // There are a lot of possible components for the name entries. In // our P2P SSL mode however, the certificates are pre-exchanged // (through the secure XMPP channel), and so the certificate // identification is arbitrary. It can't be empty, so we set some // arbitrary common_name. Note that this certificate goes out in // clear during SSL negotiation, so there may be a privacy issue in // putting anything recognizable here. if (!(name = X509_NAME_new()) || !X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, (unsigned char*)common_name, -1, -1, 0) || !X509_set_subject_name(x509, name) || !X509_set_issuer_name(x509, name)) goto error; if (!X509_gmtime_adj(X509_get_notBefore(x509), 0) || !X509_gmtime_adj(X509_get_notAfter(x509), CERTIFICATE_LIFETIME)) goto error; if (!X509_sign(x509, pkey, EVP_sha1())) goto error; BN_free(serial_number); X509_NAME_free(name); LOG(LS_INFO) << "Returning certificate"; return x509; error: BN_free(serial_number); X509_NAME_free(name); X509_free(x509); return NULL; }
static void mkcert(std::shared_ptr<X509> &cert, std::shared_ptr<EVP_PKEY> &pkey, int bits, int serial, int days) { RSA *rsa; X509_NAME *name=NULL; pkey.reset(EVP_PKEY_new(), &EVP_PKEY_free); if (!pkey) throw std::bad_alloc(); cert.reset(X509_new(), &X509_free); if (!cert) throw std::bad_alloc(); rsa = RSA_generate_key(bits,RSA_F4,NULL,NULL); MORDOR_VERIFY(EVP_PKEY_assign_RSA(pkey.get(),rsa)); X509_set_version(cert.get(),2); ASN1_INTEGER_set(X509_get_serialNumber(cert.get()),serial); X509_gmtime_adj(X509_get_notBefore(cert.get()),0); X509_gmtime_adj(X509_get_notAfter(cert.get()),(long)60*60*24*days); X509_set_pubkey(cert.get(),pkey.get()); name=X509_get_subject_name(cert.get()); /* 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(name,"C", MBSTRING_ASC, (const unsigned char *)"United States", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char *)"Mordor Default Self-signed Certificate", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(cert.get(),name); /* Add various extensions: standard extensions */ add_ext(cert.get(), NID_basic_constraints, "critical,CA:TRUE"); add_ext(cert.get(), NID_key_usage, "critical,keyCertSign,cRLSign"); add_ext(cert.get(), NID_subject_key_identifier, "hash"); /* Some Netscape specific extensions */ add_ext(cert.get(), NID_netscape_cert_type, "sslCA"); MORDOR_VERIFY(X509_sign(cert.get(),pkey.get(),EVP_md5())); }
static X509 *make_cert() { X509 *crt = NULL; if (!TEST_ptr(crt = X509_new())) return NULL; if (!TEST_true(X509_set_version(crt, 2))) { X509_free(crt); return NULL; } return crt; }
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; }
Settings::KeyPair CertWizard::generateNewCert(QString qsname, const QString &qsemail) { CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); if (qsname.isEmpty()) qsname = tr("Mumble User"); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(qsname.toUtf8().data()), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated by Mumble")); add_ext(x509, NID_subject_alt_name, QString::fromLatin1("email:%1").arg(qsemail).toUtf8().data()); X509_sign(x509, pkey, EVP_sha1()); QByteArray crt, key; crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); QSslCertificate qscCert = QSslCertificate(crt, QSsl::Der); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); QSslKey qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); QList<QSslCertificate> qlCert; qlCert << qscCert; return Settings::KeyPair(qlCert, qskKey); }
static X509 *make_cert() { X509 *ret = NULL; X509 *crt = NULL; X509_NAME *issuer = NULL; crt = X509_new(); if (crt == NULL) goto out; if (!X509_set_version(crt, 3)) goto out; ret = crt; crt = NULL; out: X509_NAME_free(issuer); return ret; }
static X509 * gen_cert(EVP_PKEY* pkey, const char *common, int days) { X509 *x509 = NULL; BIGNUM *serial_number = NULL; X509_NAME *name = NULL; if ((x509 = X509_new()) == NULL) return NULL; if (!X509_set_pubkey(x509, pkey)) return NULL; ASN1_INTEGER* asn1_serial_number; if ((serial_number = BN_new()) == NULL || !BN_pseudo_rand(serial_number, 64, 0, 0) || (asn1_serial_number = X509_get_serialNumber(x509)) == NULL || !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) goto cert_err; if (!X509_set_version(x509, 0L)) // version 1 goto cert_err; if ((name = X509_NAME_new()) == NULL || !X509_NAME_add_entry_by_NID( name, NID_commonName, MBSTRING_UTF8, (unsigned char*)common, -1, -1, 0) || !X509_set_subject_name(x509, name) || !X509_set_issuer_name(x509, name)) goto cert_err; if (!X509_gmtime_adj(X509_get_notBefore(x509), 0) || !X509_gmtime_adj(X509_get_notAfter(x509), days * 24 * 3600)) goto cert_err; if (!X509_sign(x509, pkey, EVP_sha1())) goto cert_err; if (0) { cert_err: X509_free(x509); x509 = NULL; } BN_free(serial_number); X509_NAME_free(name); return x509; }
bool parcSelfSignedCertificate_CreateRSACertificate(const char *subjectname, unsigned keylength, unsigned validityDays, X509 *cert, RSA *rsa, EVP_PKEY *private_key) { int res; bool return_value = false; BIGNUM *pub_exp; pub_exp = BN_new(); BN_set_word(pub_exp, RSA_F4); res = 1; if (RSA_generate_key_ex(rsa, keylength, pub_exp, NULL)) { if (EVP_PKEY_set1_RSA(private_key, rsa)) { if (X509_set_version(cert, 2)) { // 2 => X509v3 return_value = true; } } } if (return_value) { // add serial number if (_addRandomSerial(cert) == true) { if (_addValidityPeriod(cert, validityDays) == true) { if (X509_set_pubkey(cert, private_key) == 1) { if (_addSubjectName(cert, subjectname) == true) { if (_addExtensions(cert) == true) { if (_addKeyIdentifier(cert) == true) { // The certificate is complete, sign it. if (X509_sign(cert, private_key, EVP_sha256())) { return_value = true; } else { printf("error: (%d) %s\n", res, ERR_lib_error_string(res)); } } } } } } } } ERR_print_errors_fp(stdout); BN_free(pub_exp); return return_value; }
RSA* Rsa::ssl_generateKeys (int size) { Rsa::size = size; RSA* key_pair = RSA_generate_key(size, 3, NULL, NULL); /*PEM_write_bio_RSAPublicKey(pub, keypair); pub_len = BIO_pending(pub); pub_key = (char*) malloc(pub_len + 1); BIO_read(pub, pub_key, pub_len); pub_key[pub_len] = '\0';*/ EVP_PKEY_set1_RSA(evp_pkey, key_pair); X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),0); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*365); X509_set_pubkey(x,evp_pkey); //X509_NAME* name = X509_get_subject_name(x); /* 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(name,"C", MBSTRING_ASC, (unsigned char*) "BE", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"Falior", MBSTRING_ASC, (unsigned char*) "Falior Group", -1, -1, 0);*/ /* Its self signed so set the issuer name to be the same as the * subject. */ //X509_set_issuer_name(x,name); /* Add various extensions: standard extensions */ /*add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); add_ext(x, NID_subject_key_identifier, "hash"); add_ext(x, NID_netscape_cert_type, "sslCA"); add_ext(x, NID_netscape_comment, "example comment extension");*/ X509_sign(x,evp_pkey,EVP_sha1()); return key_pair; }
void mkcert(X509_REQ* req, const char* rootkey, const char* rootcert, const char* passwd) { RSA* rsa_key = EVP_PKEY_get1_RSA(X509_PUBKEY_get(req->req_info->pubkey)); int key_length = RSA_size(rsa_key); if (key_len != 128) { fprintf(stderr, "CA::key length of req is %d, not long enough\n"); return NULL; } X509* cacert = X509_new(); assert(cacert != NULL); load_cacert(&cacert, rootcert); EVP_PKEY* cakey = EVP_PKEY_new(); load_cakey(&cakey, rootkey, passwd); PEM_write_PrivateKey(stdout, cakey, NULL, NULL, 0, NULL, NULL); PEM_write_PUBKEY(stdout, cakey); X509* x = X509_new(); X509_set_version(x, 3); ASN1_INTEGER_set(X509_get_serialNumber(x), 1024); X509_gmtime_adj(X509_get_notBefore(x), 0); X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * 365); X509_set_pubkey(x, X509_PUBKEY_get(req->req_info->pubkey)); X509_set_subject_name(x, X509_REQ_get_subject_name(req)); X509_set_issuer_name(x, X509_get_subject_name(cacert)); assert(X509_sign(x, cakey, EVP_sha1()) > 0); FILE* f = fopen("usercert.pem", "wb"); PEM_write_X509(f, x); fclose(f); X509_print_fp(stdout, x); PEM_write_X509(stdout, x); X509_free(cacert); EVP_PKEY_free(cakey); }
static X509 * getcert(void) { /* Dummy code to make a quick-and-dirty valid certificate with OpenSSL. Don't copy this code into your own program! It does a number of things in a stupid and insecure way. */ X509 *x509 = NULL; X509_NAME *name = NULL; EVP_PKEY *key = getkey(); int nid; time_t now = time(NULL); tt_assert(key); x509 = X509_new(); tt_assert(x509); tt_assert(0 != X509_set_version(x509, 2)); tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)now)); name = X509_NAME_new(); tt_assert(name); nid = OBJ_txt2nid("commonName"); tt_assert(NID_undef != nid); tt_assert(0 != X509_NAME_add_entry_by_NID( name, nid, MBSTRING_ASC, (unsigned char*)"example.com", -1, -1, 0)); X509_set_subject_name(x509, name); X509_set_issuer_name(x509, name); X509_time_adj(X509_get_notBefore(x509), 0, &now); now += 3600; X509_time_adj(X509_get_notAfter(x509), 0, &now); X509_set_pubkey(x509, key); tt_assert(0 != X509_sign(x509, key, EVP_sha1())); return x509; end: X509_free(x509); return NULL; }
/* 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; }
static int cert_init() { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; BIGNUM *exponent = NULL, *serial_number = NULL; RSA *rsa = NULL; ASN1_INTEGER *asn1_serial_number; X509_NAME *name; struct dtls_cert *new_cert; ilog(LOG_INFO, "Generating new DTLS certificate"); /* objects */ pkey = EVP_PKEY_new(); exponent = BN_new(); rsa = RSA_new(); serial_number = BN_new(); name = X509_NAME_new(); x509 = X509_new(); if (!exponent || !pkey || !rsa || !serial_number || !name || !x509) goto err; /* key */ if (!BN_set_word(exponent, 0x10001)) goto err; if (!RSA_generate_key_ex(rsa, 1024, exponent, NULL)) goto err; if (!EVP_PKEY_assign_RSA(pkey, rsa)) goto err; /* x509 cert */ if (!X509_set_pubkey(x509, pkey)) goto err; /* serial */ if (!BN_pseudo_rand(serial_number, 64, 0, 0)) goto err; asn1_serial_number = X509_get_serialNumber(x509); if (!asn1_serial_number) goto err; if (!BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) goto err; /* version 1 */ if (!X509_set_version(x509, 0L)) goto err; /* common name */ if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, (unsigned char *) "rtpengine", -1, -1, 0)) goto err; if (!X509_set_subject_name(x509, name)) goto err; if (!X509_set_issuer_name(x509, name)) goto err; /* cert lifetime */ if (!X509_gmtime_adj(X509_get_notBefore(x509), -60*60*24)) goto err; if (!X509_gmtime_adj(X509_get_notAfter(x509), CERT_EXPIRY_TIME)) goto err; /* sign it */ if (!X509_sign(x509, pkey, EVP_sha1())) goto err; /* digest */ new_cert = obj_alloc0("dtls_cert", sizeof(*new_cert), cert_free); new_cert->fingerprint.hash_func = &hash_funcs[0]; dtls_fingerprint_hash(&new_cert->fingerprint, x509); new_cert->x509 = x509; new_cert->pkey = pkey; new_cert->expires = time(NULL) + CERT_EXPIRY_TIME; dump_cert(new_cert); /* swap out certs */ rwlock_lock_w(&__dtls_cert_lock); if (__dtls_cert) obj_put(__dtls_cert); __dtls_cert = new_cert; rwlock_unlock_w(&__dtls_cert_lock); /* cleanup */ BN_free(exponent); BN_free(serial_number); X509_NAME_free(name); return 0; err: ilog(LOG_ERROR, "Failed to generate DTLS certificate"); if (pkey) EVP_PKEY_free(pkey); if (exponent) BN_free(exponent); if (rsa) RSA_free(rsa); if (x509) X509_free(x509); if (serial_number) BN_free(serial_number); return -1; }
DVT_STATUS CERTIFICATE_CLASS::generateFiles(LOG_CLASS* logger_ptr, const char* signerCredentialsFile_ptr, const char* credentialsPassword_ptr, const char* keyPassword_ptr, const char* keyFile_ptr, const char* certificateFile_ptr) // DESCRIPTION : Generate a certificate and key files from this class. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : If signerCredentialsFile_ptr is NULL, a self signed // : certificate will be generated. // : // : Returns: MSG_OK, MSG_LIB_NOT_EXIST, MSG_FILE_NOT_EXIST, // : MSG_ERROR, MSG_INVALID_PASSWORD //<<=========================================================================== { DVT_STATUS ret = MSG_ERROR; unsigned long err; OPENSSL_CLASS* openSsl_ptr; BIO* caBio_ptr = NULL; EVP_PKEY* caPrivateKey_ptr = NULL; X509* caCertificate_ptr = NULL; EVP_PKEY* key_ptr = NULL; X509* cert_ptr = NULL; X509_NAME* name_ptr; time_t effectiveTime; time_t expirationTime; EVP_PKEY* tmpKey_ptr; const EVP_MD *digest_ptr; BIO* pkBio_ptr = NULL; const EVP_CIPHER *cipher_ptr; BIO* certBio_ptr = NULL; // check for the existence of the OpenSSL DLLs openSsl_ptr = OPENSSL_CLASS::getInstance(); if (openSsl_ptr == NULL) { return MSG_LIB_NOT_EXIST; } // clear the error queue ERR_clear_error(); if (signerCredentialsFile_ptr != NULL) { // open the credentials file caBio_ptr = BIO_new(BIO_s_file_internal()); if (caBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to read CA credentials file"); goto end; } if (BIO_read_filename(caBio_ptr, signerCredentialsFile_ptr) <= 0) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_SYS) && (ERR_GET_REASON(err) == ERROR_FILE_NOT_FOUND)) { // file does not exist ERR_clear_error(); // eat any errors ret = MSG_FILE_NOT_EXIST; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening CA credentials file for reading"); } goto end; } // read the certificate authority's private key caPrivateKey_ptr = PEM_read_bio_PrivateKey(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caPrivateKey_ptr == NULL) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_EVP) && (ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT)) { // bad password ERR_clear_error(); // eat any errors ret = MSG_INVALID_PASSWORD; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading private key from CA credentials file"); } goto end; } // read the certificate authority's certificate caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caCertificate_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading CA certificate from CA credentials file"); goto end; } } // generate the new private/public key pair if (signatureAlgorithmM.compare("RSA") == 0) { // RSA key RSA* rsa_key; rsa_key = RSA_generate_key(signatureKeyLengthM, RSA_3, NULL, 0); if (rsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating RSA key"); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating RSA key"); RSA_free(rsa_key); goto end; } EVP_PKEY_assign_RSA(key_ptr, rsa_key); } else { // DSA key DSA* dsa_key; dsa_key = DSA_generate_parameters(signatureKeyLengthM, NULL, 0, NULL, NULL, NULL, 0); if (dsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA parameters"); goto end; } if (DSA_generate_key(dsa_key) == 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA key"); DSA_free(dsa_key); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating DSA key"); DSA_free(dsa_key); goto end; } EVP_PKEY_assign_DSA(key_ptr, dsa_key); } // create the certificate cert_ptr = X509_new(); if (cert_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating certificate object"); goto end; } // version if (X509_set_version(cert_ptr, (versionM - 1)) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting certificate version"); goto end; } // subject name_ptr = openSsl_ptr->onelineName2Name(subjectM.c_str()); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "parsing owner name"); goto end; } if (X509_set_subject_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting owner name in certificate"); goto end; } // issuer if (signerCredentialsFile_ptr != NULL) { // CA signed name_ptr = X509_get_subject_name(caCertificate_ptr); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "getting name from CA certificate"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } else { // self signed name_ptr = X509_NAME_dup(name_ptr); // duplicate the name so it can be used again if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "duplicating owner name"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } // public key if (X509_set_pubkey(cert_ptr, key_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting public key in certificate"); goto end; } // valid dates effectiveTime = mktime(&effectiveDateM); expirationTime = mktime(&expirationDateM); if ((X509_time_adj(X509_get_notBefore(cert_ptr), 0, &effectiveTime) == NULL) || (X509_time_adj(X509_get_notAfter(cert_ptr), 0, &expirationTime) == NULL)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting valid dates in certificate"); goto end; } // serial number, use the current time_t ASN1_INTEGER_set(X509_get_serialNumber(cert_ptr), (unsigned)time(NULL)); // sign the certificate if (signerCredentialsFile_ptr != NULL) { // CA signed tmpKey_ptr = caPrivateKey_ptr; } else { // self signed tmpKey_ptr = key_ptr; } if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_RSA) { digest_ptr = EVP_sha1(); } else if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_DSA) { digest_ptr = EVP_dss1(); } else { if (logger_ptr) { logger_ptr->text(LOG_ERROR, 1, "Unsupported key type in CA private key"); } goto end; } if (!X509_sign(cert_ptr, tmpKey_ptr, digest_ptr)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "signing certificate"); goto end; } // write out the private key // open the private key file pkBio_ptr = BIO_new(BIO_s_file_internal()); if (pkBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write private key file"); goto end; } if (BIO_write_filename(pkBio_ptr, (void *)keyFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write private key file"); goto end; } if ((keyPassword_ptr != NULL) && (strlen(keyPassword_ptr) > 0)) { // we have a password, use 3DES to encrypt the key cipher_ptr = EVP_des_ede3_cbc(); } else { // there is no password, don't encrypt the key cipher_ptr = NULL; } // write out the private key if (PEM_write_bio_PKCS8PrivateKey(pkBio_ptr, key_ptr, cipher_ptr, NULL, 0, NULL, (void *)keyPassword_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing private key"); goto end; } // write the certificate file // open the certificate file certBio_ptr = BIO_new(BIO_s_file_internal()); if (certBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write certificate file"); goto end; } if (BIO_write_filename(certBio_ptr, (void *)certificateFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write certificate file"); goto end; } // write the new certificate if (PEM_write_bio_X509(certBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } // write the new certificate into the credential file if (PEM_write_bio_X509(pkBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } if (signerCredentialsFile_ptr != NULL) { // write the CA certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing CA certificate"); goto end; } // loop reading certificates from the CA credentials file and writing them to the certificate file X509_free(caCertificate_ptr); while ((caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr)) != NULL) { // write the certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate chain"); goto end; } X509_free(caCertificate_ptr); } // check the error err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_PEM) && (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { // end of data - this is normal ERR_clear_error(); } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading certificates from CA credentials file"); goto end; } } ret = MSG_OK; end: if (certBio_ptr != NULL) BIO_free(certBio_ptr); if (pkBio_ptr != NULL) BIO_free(pkBio_ptr); if (cert_ptr != NULL) X509_free(cert_ptr); if (key_ptr != NULL) EVP_PKEY_free(key_ptr); if (caCertificate_ptr != NULL) X509_free(caCertificate_ptr); if (caPrivateKey_ptr != NULL) EVP_PKEY_free(caPrivateKey_ptr); if (caBio_ptr != NULL) BIO_free(caBio_ptr); return ret; }
static ERL_NIF_TERM x509_make_cert_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int expiry, serial; ASN1_INTEGER *asn1serial = NULL; BIGNUM *bn_rsa_genkey=NULL; BIO *bio_signing_private=NULL, *bio_issuer_cert = NULL, *bio_newcert_public = NULL; BIO *bio_x509=NULL; char *issuer_cert_pem=NULL; X509 *pX509 = NULL; X509 *pIssuerX509 = NULL; X509_NAME *pX509Name = NULL; X509_NAME *pIssuerName = NULL; x509_subject_entry *subject_entries; int num_subject_entries; int iret = 0; RSA *rsa=NULL; unsigned long f4=RSA_F4; unsigned args_len=-1; char *signing_keys[2], *cert_keys[2]; ERL_NIF_TERM tail, *arg_terms=NULL; int idx; ERL_NIF_TERM ret, x509term; int x509len; unsigned char *x509data; EVP_PKEY *evp_signing_private = EVP_PKEY_new(); EVP_PKEY *evp_newcert_public_key = EVP_PKEY_new(); /* set RSA key gen type */ bn_rsa_genkey = BN_new(); BN_set_word(bn_rsa_genkey, f4); // // 1. stick subject of CA cert into NewCert // 2. stick public key of NewKeypair into NewCert // 3. sign NewCert with CA keypair /* Should be 6 elements in the list of X509 parameters. We'll check each */ if(!enif_get_list_length(env, argv[0], &args_len) || args_len != 6 || NULL == (arg_terms = (ERL_NIF_TERM*)malloc(args_len * sizeof(ERL_NIF_TERM)))) return enif_make_badarg(env); enif_get_list_cell(env, argv[0], &arg_terms[0], &tail); for(idx=1; idx<args_len; idx++){ if(!enif_get_list_cell(env, tail, &arg_terms[idx], &tail)){ free(arg_terms); return enif_make_badarg(env); } } idx=0; /* get the signing private key */ x509_parse_keypair(env, "signing_key", arg_terms[idx++], signing_keys); /* get the issuer cert */ x509_parse_issuer_cert(env, arg_terms[idx++], &issuer_cert_pem); /* get the soon-to-be cert's public key */ x509_parse_keypair(env, "newcert_public_key", arg_terms[idx++], cert_keys); /* get the subject */ x509_parse_subject(env, arg_terms[idx++], &num_subject_entries, &subject_entries); /* get the serial number */ x509_parse_int_tuple(env, arg_terms[idx++], "serial", &serial); /* get the expiry */ x509_parse_int_tuple(env, arg_terms[idx++], "expiry", &expiry); /* work the OpenSSL cert creation magic */ if ((bio_signing_private = BIO_new_mem_buf(signing_keys[1], -1)) && (rsa = PEM_read_bio_RSAPrivateKey(bio_signing_private, NULL, NULL, NULL)) && (iret = EVP_PKEY_assign_RSA(evp_signing_private, rsa)) && (bio_newcert_public = BIO_new_mem_buf(cert_keys[0], -1)) && (evp_newcert_public_key = PEM_read_bio_PUBKEY(bio_newcert_public, NULL, NULL, NULL)) && (bio_issuer_cert = BIO_new_mem_buf(issuer_cert_pem, -1)) && (pIssuerX509 = PEM_read_bio_X509(bio_issuer_cert, NULL, NULL, NULL)) && (pX509 = X509_new())) { /* if we've managed to generate a key and allocate structure memory, set X509 fields */ asn1serial = ASN1_INTEGER_new(); X509_set_version(pX509, 2); /* cert_helper uses '3' here */ ASN1_INTEGER_set(asn1serial, serial); X509_set_serialNumber(pX509, asn1serial); X509_gmtime_adj(X509_get_notBefore(pX509),0); X509_gmtime_adj(X509_get_notAfter(pX509),(long)60*60*24*expiry); X509_set_pubkey(pX509, evp_newcert_public_key); pX509Name = X509_get_subject_name(pX509); while(--num_subject_entries >= 0){ X509_NAME_add_entry_by_txt(pX509Name, (subject_entries[num_subject_entries]).name, MBSTRING_ASC, (unsigned char*)(subject_entries[num_subject_entries]).value, -1, -1, 0); } pIssuerName = X509_get_issuer_name(pIssuerX509); X509_set_issuer_name(pX509, pIssuerName); X509_sign(pX509, evp_signing_private, digest); bio_x509 = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio_x509, pX509); x509len = BIO_get_mem_data(bio_x509, &x509data); memcpy(enif_make_new_binary(env, x509len, &x509term), x509data, x509len); ret = enif_make_tuple2(env, atom_x509_cert, x509term); } done: if(arg_terms) free(arg_terms); free_keys(signing_keys); free_keys(cert_keys); free_subject_entries(num_subject_entries, subject_entries); if(pX509) X509_free(pX509); if(pIssuerX509) X509_free(pIssuerX509); if(issuer_cert_pem) free(issuer_cert_pem); if(bio_issuer_cert) { BIO_set_close(bio_issuer_cert, BIO_NOCLOSE); BIO_free_all(bio_issuer_cert); } if(bio_signing_private) { BIO_set_close(bio_signing_private, BIO_NOCLOSE); BIO_free_all(bio_signing_private); } if(bio_newcert_public) { BIO_set_close(bio_newcert_public, BIO_NOCLOSE); BIO_free_all(bio_newcert_public); } if(bio_x509) BIO_free_all(bio_x509); if(asn1serial) ASN1_INTEGER_free(asn1serial); if(bn_rsa_genkey) BN_free(bn_rsa_genkey); if(rsa) RSA_free(rsa); return ret; }
static std::string generateCertificate (EVP_PKEY *private_key) { std::shared_ptr <X509> x509; std::shared_ptr <BIO> bio; X509_NAME *name = nullptr; int rc = 0; unsigned long err = 0; BUF_MEM *mem; std::string pem; x509 = std::shared_ptr<X509> (X509_new (), [] (X509 * obj) { X509_free (obj); }); if (x509 == nullptr) { GST_ERROR ("X509 not created"); return pem; } X509_set_version (x509.get(), 2L); ASN1_INTEGER_set (X509_get_serialNumber (x509.get() ), 0); X509_gmtime_adj (X509_get_notBefore (x509.get() ), 0); X509_gmtime_adj (X509_get_notAfter (x509.get() ), 31536000L); /* A year */ X509_set_pubkey (x509.get(), private_key); name = X509_get_subject_name (x509.get() ); X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *) "SE", -1, -1, 0); X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *) "Kurento", -1, -1, 0); X509_set_issuer_name (x509.get(), name); name = nullptr; if (!X509_sign (x509.get(), private_key, EVP_sha256 () ) ) { GST_ERROR ("Failed to sign certificate"); return pem; } bio = std::shared_ptr<BIO> (BIO_new (BIO_s_mem () ), [] (BIO * obj) { BIO_free_all (obj); }); if (bio == nullptr) { GST_ERROR ("BIO not created"); return pem; } rc = PEM_write_bio_X509 (bio.get(), x509.get() ); if (rc != 1) { err = ERR_get_error(); GST_ERROR ("PEM_write_bio_X509 failed, error %ld", err); return pem; } BIO_get_mem_ptr (bio.get(), &mem); if (!mem || !mem->data || !mem->length) { err = ERR_get_error(); GST_ERROR ("BIO_get_mem_ptr failed, error %ld", err); return pem; } pem = std::string (mem->data, mem->length); return pem; }
Try<X509*> generate_x509( EVP_PKEY* subject_key, EVP_PKEY* sign_key, const Option<X509*>& parent_certificate, int serial, int days, Option<std::string> hostname) { Option<X509_NAME*> issuer_name = None(); if (parent_certificate.isNone()) { // If there is no parent certificate, then the subject and // signing key must be the same. if (subject_key != sign_key) { return Error("Subject vs signing key mismatch"); } } else { // If there is a parent certificate, then set the issuer name to // be that of the parent. issuer_name = X509_get_subject_name(parent_certificate.get()); if (issuer_name.get() == NULL) { return Error("Failed to get subject name of parent certificate: " "X509_get_subject_name"); } } // Allocate the in-memory structure for the certificate. X509* x509 = X509_new(); if (x509 == NULL) { return Error("Failed to allocate certification: X509_new"); } // Set the version to V3. if (X509_set_version(x509, 2) != 1) { X509_free(x509); return Error("Failed to set version: X509_set_version"); } // Set the serial number. if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) { X509_free(x509); return Error("Failed to set serial number: ASN1_INTEGER_set"); } // Make this certificate valid for 'days' number of days from now. if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL || X509_gmtime_adj(X509_get_notAfter(x509), 60L * 60L * 24L * days) == NULL) { X509_free(x509); return Error("Failed to set valid days of certificate: X509_gmtime_adj"); } // Set the public key for our certificate based on the subject key. if (X509_set_pubkey(x509, subject_key) != 1) { X509_free(x509); return Error("Failed to set public key: X509_set_pubkey"); } // Figure out our hostname if one was not provided. if (hostname.isNone()) { const Try<std::string> _hostname = net::hostname(); if (_hostname.isError()) { X509_free(x509); return Error("Failed to determine hostname"); } hostname = _hostname.get(); } // Grab the subject name of the new certificate. X509_NAME* name = X509_get_subject_name(x509); if (name == NULL) { X509_free(x509); return Error("Failed to get subject name: X509_get_subject_name"); } // Set the country code, organization, and common name. if (X509_NAME_add_entry_by_txt( name, "C", MBSTRING_ASC, reinterpret_cast<const unsigned char*>("US"), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set country code: X509_NAME_add_entry_by_txt"); } if (X509_NAME_add_entry_by_txt( name, "O", MBSTRING_ASC, reinterpret_cast<const unsigned char*>("Test"), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set organization name: X509_NAME_add_entry_by_txt"); } if (X509_NAME_add_entry_by_txt( name, "CN", MBSTRING_ASC, reinterpret_cast<const unsigned char*>(hostname.get().c_str()), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set common name: X509_NAME_add_entry_by_txt"); } // Set the issuer name to be the same as the subject if it is not // already set (this is a self-signed certificate). if (issuer_name.isNone()) { issuer_name = name; } CHECK_SOME(issuer_name); if (X509_set_issuer_name(x509, issuer_name.get()) != 1) { X509_free(x509); return Error("Failed to set issuer name: X509_set_issuer_name"); } // Sign the certificate with the sign key. if (X509_sign(x509, sign_key, EVP_sha1()) == 0) { X509_free(x509); return Error("Failed to sign certificate: X509_sign"); } return x509; }
int PKI_X509_CERT_set_data(PKI_X509_CERT *x, int type, void *data) { long *aLong = NULL; PKI_TIME *aTime = NULL; PKI_INTEGER *aInt = NULL; PKI_X509_NAME *aName = NULL; PKI_X509_KEYPAIR_VALUE *aKey = NULL; int ret = 0; LIBPKI_X509_CERT *xVal = NULL; LIBPKI_X509_ALGOR *alg = NULL; // PKI_X509_CERT_VALUE *xVal = NULL; if ( !x || !x->value || !data || x->type != PKI_DATATYPE_X509_CERT) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (PKI_ERR); } // xVal = PKI_X509_get_value( x ); xVal = x->value; switch( type ) { case PKI_X509_DATA_VERSION: aLong = (long *) data; ret = X509_set_version( xVal, *aLong ); break; case PKI_X509_DATA_SERIAL: aInt = (PKI_INTEGER *) data; ret = X509_set_serialNumber( xVal, aInt); break; case PKI_X509_DATA_SUBJECT: aName = (PKI_X509_NAME *) data; ret = X509_set_subject_name( xVal, aName ); break; case PKI_X509_DATA_ISSUER: aName = (PKI_X509_NAME *) data; ret = X509_set_issuer_name( xVal, aName ); break; case PKI_X509_DATA_NOTBEFORE: aTime = (PKI_TIME *) data; ret = X509_set_notBefore( xVal, aTime ); break; case PKI_X509_DATA_NOTAFTER: aTime = (PKI_TIME *) data; ret = X509_set_notAfter( xVal, aTime ); break; case PKI_X509_DATA_KEYPAIR_VALUE: aKey = data; ret = X509_set_pubkey( xVal, aKey); break; case PKI_X509_DATA_ALGORITHM: case PKI_X509_DATA_SIGNATURE_ALG1: alg = data; #if OPENSSL_VERSION_NUMBER < 0x1010000fL if (xVal->cert_info != NULL) xVal->cert_info->signature = alg; #else // Transfer Ownership xVal->cert_info.signature.algorithm = alg->algorithm; xVal->cert_info.signature.parameter = alg->parameter; // Remove the transfered data alg->algorithm = NULL; alg->parameter = NULL; // Free memory X509_ALGOR_free((X509_ALGOR *)data); data = NULL; #endif // Ok ret = 1; break; case PKI_X509_DATA_SIGNATURE_ALG2: // if (xVal->sig_alg != NULL ) X509_ALGOR_free(xVal->sig_alg); alg = data; #if OPENSSL_VERSION_NUMBER < 0x1010000fL xVal->sig_alg = alg; #else // Transfer Ownership xVal->sig_alg.algorithm = alg->algorithm; xVal->sig_alg.parameter = alg->parameter; // Remove the transfered data alg->algorithm = NULL; alg->parameter = NULL; // Free memory X509_ALGOR_free((X509_ALGOR *)alg); data = NULL; // Ok ret = 1; #endif break; default: /* Not Recognized/Supported DATATYPE */ ret = 0; break; } if (!ret) return PKI_ERR; return PKI_OK; }
PKI_X509_CERT * PKI_X509_CERT_new (const PKI_X509_CERT * ca_cert, const PKI_X509_KEYPAIR * kPair, const PKI_X509_REQ * req, const char * subj_s, const char * serial_s, uint64_t validity, const PKI_X509_PROFILE * conf, const PKI_ALGOR * algor, const PKI_CONFIG * oids, HSM *hsm ) { PKI_X509_CERT *ret = NULL; PKI_X509_CERT_VALUE *val = NULL; PKI_X509_NAME *subj = NULL; PKI_X509_NAME *issuer = NULL; PKI_DIGEST_ALG *digest = NULL; PKI_X509_KEYPAIR_VALUE *signingKey = NULL; PKI_TOKEN *tk = NULL; PKI_X509_KEYPAIR_VALUE *certPubKeyVal = NULL; int rv = 0; int ver = 2; int64_t notBeforeVal = 0; ASN1_INTEGER *serial = NULL; char *ver_s = NULL; /* Check if the REQUIRED PKEY has been passed */ if (!kPair || !kPair->value) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (NULL); }; signingKey = kPair->value; /* TODO: This has to be fixed, to work on every option */ if ( subj_s ) { subj = PKI_X509_NAME_new ( subj_s ); } else if (conf || req) { char *tmp_s = NULL; // Let's use the configuration option first if (conf) { // Get the value of the DN, if present if ((tmp_s = PKI_CONFIG_get_value( conf, "/profile/subject/dn")) != NULL ) { // Builds from the DN in the config subj = PKI_X509_NAME_new(tmp_s); PKI_Free ( tmp_s ); } } // If we still do not have a name, let's check // the request for one if (req && !subj) { const PKI_X509_NAME * req_subj = NULL; // Copy the name from the request if ((req_subj = PKI_X509_REQ_get_data(req, PKI_X509_DATA_SUBJECT)) != NULL) { subj = PKI_X509_NAME_dup(req_subj); } } // If no name is provided, let's use an empty one // TODO: Shall we remove this and fail instead ? if (!subj) subj = PKI_X509_NAME_new( "" ); } else { struct utsname myself; char tmp_name[1024]; if (uname(&myself) < 0) { subj = PKI_X509_NAME_new( "" ); } else { sprintf( tmp_name, "CN=%s", myself.nodename ); subj = PKI_X509_NAME_new( tmp_name ); } } if (!subj) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SUBJECT, subj_s ); goto err; } if( ca_cert ) { const PKI_X509_NAME *ca_subject = NULL; /* Let's get the ca_cert subject and dup that data */ // ca_subject = (PKI_X509_NAME *) // X509_get_subject_name( (X509 *) ca_cert ); ca_subject = PKI_X509_CERT_get_data( ca_cert, PKI_X509_DATA_SUBJECT ); if( ca_subject ) { issuer = (PKI_X509_NAME *) X509_NAME_dup((X509_NAME *)ca_subject); } else { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } } else { issuer = (PKI_X509_NAME *) X509_NAME_dup((X509_NAME *) subj); } if( !issuer ) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } if(( ret = PKI_X509_CERT_new_null()) == NULL ) { PKI_ERROR(PKI_ERR_OBJECT_CREATE, NULL); goto err; } /* Alloc memory structure for the Certificate */ if((ret->value = ret->cb->create()) == NULL ) { PKI_ERROR(PKI_ERR_OBJECT_CREATE, NULL); return (NULL); } val = ret->value; if(( ver_s = PKI_CONFIG_get_value( conf, "/profile/version")) != NULL ) { ver = atoi( ver_s ) - 1; if ( ver < 0 ) ver = 0; PKI_Free ( ver_s ); } else { ver = 2; }; if (!X509_set_version(val,ver)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_VERSION, NULL); goto err; } if (serial_s) { char * tmp_s = (char *) serial_s; serial = s2i_ASN1_INTEGER(NULL, tmp_s); } else { // If cacert we assume it is a normal cert - let's create a // random serial number, otherwise - it's a self-signed, use // the usual 'fake' 0 if ( ca_cert ) { unsigned char bytes[11]; RAND_bytes(bytes, sizeof(bytes)); bytes[0] = 0; serial = PKI_INTEGER_new_bin(bytes, sizeof(bytes)); } else { serial = s2i_ASN1_INTEGER( NULL, "0"); }; }; if(!X509_set_serialNumber( val, serial )) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SERIAL, serial_s); goto err; } /* Set the issuer Name */ // rv = X509_set_issuer_name((X509 *) ret, (X509_NAME *) issuer); if(!X509_set_issuer_name( val, (X509_NAME *) issuer)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } /* Set the subject Name */ if(!X509_set_subject_name(val, (X509_NAME *) subj)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SUBJECT, NULL); goto err; } /* Set the start date (notBefore) */ if (conf) { int years = 0; int days = 0; int hours = 0; int mins = 0; int secs = 0; char *tmp_s = NULL; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/years")) != NULL ) { years = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/days")) != NULL ) { days = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/hours")) != NULL ) { hours = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/minutes")) != NULL ) { mins = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/seconds")) != NULL ) { secs = atoi( tmp_s ); PKI_Free ( tmp_s ); }; notBeforeVal = secs + ( mins * 60 ) + ( hours * 3600 ) + ( days * 3600 * 24 ) + ( years * 3600 * 24 * 365 ); }; /* Set the validity (notAfter) */ if( conf && validity == 0 ) { long long years = 0; long long days = 0; long long hours = 0; long long mins = 0; long long secs = 0; char *tmp_s = NULL; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/years")) != NULL ) { years = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/days")) != NULL ) { days = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/hours")) != NULL ) { hours = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/minutes")) != NULL ) { mins = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/minutes")) != NULL ) { secs = atoll( tmp_s ); PKI_Free ( tmp_s ); }; validity = (unsigned long long) secs + (unsigned long long) ( mins * 60 ) + (unsigned long long) ( hours * 3600 ) + (unsigned long long) ( days * 3600 * 24 ) + (unsigned long long) ( years * 3600 * 24 * 365 ); }; if (validity <= 0) validity = 30 * 3600 * 24; #if ( LIBPKI_OS_BITS == LIBPKI_OS32 ) long notBeforeVal32 = (long) notBeforeVal; if (X509_gmtime_adj(X509_get_notBefore(val), notBeforeVal32 ) == NULL) { #else if (X509_gmtime_adj(X509_get_notBefore(val), notBeforeVal ) == NULL) { #endif PKI_ERROR(PKI_ERR_X509_CERT_CREATE_NOTBEFORE, NULL); goto err; } /* Set the end date in a year */ if (X509_gmtime_adj(X509_get_notAfter(val),(long int) validity) == NULL) { PKI_DEBUG("ERROR: can not set notAfter field!"); goto err; } /* Copy the PKEY if it is in the request, otherwise use the public part of the PKI_X509_CERT */ if (req) { certPubKeyVal = (PKI_X509_KEYPAIR_VALUE *) PKI_X509_REQ_get_data(req, PKI_X509_DATA_KEYPAIR_VALUE); if( !certPubKeyVal ) { PKI_DEBUG("ERROR, can not get pubkey from req!"); goto err; } } else { /* Self Signed -- Same Public Key! */ certPubKeyVal = signingKey; } if (!ca_cert && conf) { char *tmp_s = NULL; if(( tmp_s = PKI_X509_PROFILE_get_value( conf, "/profile/keyParams/algorithm")) != NULL ) { PKI_ALGOR *myAlg = NULL; PKI_DIGEST_ALG *dgst = NULL; if((myAlg = PKI_ALGOR_get_by_name( tmp_s )) != NULL ) { if(!algor) algor = myAlg; if((dgst = PKI_ALGOR_get_digest( myAlg )) != NULL ) { PKI_DEBUG("Got Signing Algorithm: %s, %s", PKI_DIGEST_ALG_get_parsed(dgst), PKI_ALGOR_get_parsed(myAlg)); digest = dgst; } else { PKI_DEBUG("Can not parse digest algorithm from %s", tmp_s); } } else { PKI_DEBUG("Can not parse key algorithm from %s", tmp_s); } PKI_Free ( tmp_s ); } } if (conf) { PKI_KEYPARAMS *kParams = NULL; PKI_SCHEME_ID scheme; scheme = PKI_ALGOR_get_scheme( algor ); kParams = PKI_KEYPARAMS_new(scheme, conf); if (kParams) { /* Sets the point compression */ switch ( kParams->scheme ) { #ifdef ENABLE_ECDSA case PKI_SCHEME_ECDSA: if ( (int) kParams->ec.form > 0 ) { # if OPENSSL_VERSION_NUMBER < 0x1010000fL EC_KEY_set_conv_form(certPubKeyVal->pkey.ec, (point_conversion_form_t) kParams->ec.form); # else EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY(certPubKeyVal), (point_conversion_form_t) kParams->ec.form); # endif } if ( kParams->ec.asn1flags > -1 ) { # if OPENSSL_VERSION_NUMBER < 0x1010000fL EC_KEY_set_asn1_flag(certPubKeyVal->pkey.ec, kParams->ec.asn1flags ); # else EC_KEY_set_asn1_flag(EVP_PKEY_get0_EC_KEY(certPubKeyVal), kParams->ec.asn1flags ); # endif } break; #endif case PKI_SCHEME_RSA: case PKI_SCHEME_DSA: break; default: // Nothing to do PKI_ERROR(PKI_ERR_GENERAL, "Signing Scheme Uknown %d!", kParams->scheme); break; } } } if (!X509_set_pubkey(val, certPubKeyVal)) { PKI_DEBUG("ERROR, can not set pubkey in cert!"); goto err; } if (conf) { if((tk = PKI_TOKEN_new_null()) == NULL ) { PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); goto err; } PKI_TOKEN_set_cert(tk, ret); if (ca_cert) { PKI_TOKEN_set_cacert(tk, (PKI_X509_CERT *)ca_cert); } else { PKI_TOKEN_set_cacert(tk, (PKI_X509_CERT *)ret); } if (req) PKI_TOKEN_set_req(tk, (PKI_X509_REQ *)req ); if (kPair) PKI_TOKEN_set_keypair ( tk, (PKI_X509_KEYPAIR *)kPair ); rv = PKI_X509_EXTENSIONS_cert_add_profile(conf, oids, ret, tk); if (rv != PKI_OK) { PKI_DEBUG( "ERROR, can not set extensions!"); tk->cert = NULL; tk->cacert = NULL; tk->req = NULL; tk->keypair = NULL; PKI_TOKEN_free ( tk ); goto err; } // Cleanup for the token (used only to add extensions) tk->cert = NULL; tk->cacert = NULL; tk->req = NULL; tk->keypair = NULL; PKI_TOKEN_free ( tk ); } if (!digest) { if (!algor) { PKI_log_debug("Getting the Digest Algorithm from the CA cert"); // Let's get the Digest Algorithm from the CA Cert if (ca_cert) { if((algor = PKI_X509_CERT_get_data(ca_cert, PKI_X509_DATA_ALGORITHM )) == NULL) { PKI_log_err("Can not retrieve DATA algorithm from CA cert"); } } } // If we have an Algor from either the passed argument or // the CA Certificate, extract the digest from it. Otherwise // get the digest from the signing key if (algor) { if((digest = PKI_ALGOR_get_digest(algor)) == NULL ) { PKI_log_err("Can not get digest from algor"); } } // Check, if still no digest, let's try from the signing Key if (digest == NULL) { if ((digest = PKI_DIGEST_ALG_get_by_key( kPair )) == NULL) { PKI_log_err("Can not infer digest algor from the key pair"); } } } // No Digest Here ? We failed... if (digest == NULL) { PKI_log_err("PKI_X509_CERT_new()::Can not get the digest!"); return( NULL ); } // Sign the data if (PKI_X509_sign(ret, digest, kPair) == PKI_ERR) { PKI_log_err ("Can not sign certificate [%s]", ERR_error_string(ERR_get_error(), NULL )); PKI_X509_CERT_free ( ret ); return NULL; } #if ( OPENSSL_VERSION_NUMBER >= 0x0090900f ) # if OPENSSL_VERSION_NUMBER < 0x1010000fL PKI_X509_CERT_VALUE *cVal = (PKI_X509_CERT_VALUE *) ret->value; if (cVal && cVal->cert_info) { PKI_log_debug("Signature = %s", PKI_ALGOR_get_parsed(cVal->cert_info->signature)); } # endif // PKI_X509_CINF_FULL *cFull = NULL; // cFull = (PKI_X509_CINF_FULL *) cVal->cert_info; // cFull->enc.modified = 1; #endif return ret; err: if (ret) PKI_X509_CERT_free(ret); if (subj) PKI_X509_NAME_free(subj); if (issuer) PKI_X509_NAME_free(issuer); return NULL; } /*! * \brief Signs a PKI_X509_CERT */ int PKI_X509_CERT_sign(PKI_X509_CERT *cert, PKI_X509_KEYPAIR *kp, PKI_DIGEST_ALG *digest) { const PKI_ALGOR *alg = NULL; if( !cert || !cert->value || !kp || !kp->value ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return PKI_ERR; } if(!digest) { if((alg = PKI_X509_CERT_get_data(cert, PKI_X509_DATA_ALGORITHM))!=NULL) { digest = PKI_ALGOR_get_digest ( alg ); } } if(!digest) { if((digest = PKI_DIGEST_ALG_get_by_key(kp)) == NULL) { PKI_log_err("PKI_X509_CERT_new()::Can not get digest algor " "from key"); return PKI_ERR; } } if( PKI_X509_sign(cert, digest, kp) == PKI_ERR) { PKI_log_err ("PKI_X509_CERT_new()::Can not sign certificate [%s]", ERR_error_string(ERR_get_error(), NULL )); return PKI_ERR; } return PKI_OK; }; /*! * \brief Signs a PKI_X509_CERT by using a configured PKI_TOKEN */ int PKI_X509_CERT_sign_tk ( PKI_X509_CERT *cert, PKI_TOKEN *tk, PKI_DIGEST_ALG *digest) { PKI_X509_KEYPAIR *kp = NULL; if( !cert || !cert->value || !tk ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return PKI_ERR; }; if( PKI_TOKEN_login( tk ) == PKI_ERR ) { PKI_ERROR(PKI_ERR_HSM_LOGIN, NULL); return PKI_ERR; }; if((kp = PKI_TOKEN_get_keypair( tk )) == NULL ) { return PKI_ERR; }; return PKI_X509_CERT_sign ( cert, kp, digest ); };
/* cr_make_cert generates a server public/private keys * cert : X509 instance * pkey : private key instance * bits : RSA key length * serial : serial number * days : how many days the certificate is valid */ int cr_make_cert(X509 **cert,EVP_PKEY **pkey,int bits,int serial,int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name = NULL; if((pkey == NULL) || (*pkey == NULL)) { pk = EVP_PKEY_new(); if(pk == NULL) { perrx("EVP_PKEY_new() failed\n"); return -1; } } else pk = *pkey; if((cert == NULL) || (*cert == NULL)) { x = X509_new(); if ((x == NULL)) { perrx("X509_new() failed\n"); return -1; } }else x= *cert; /* generate RSA key */ rsa = RSA_generate_key(bits,RSA_F4,NULL,NULL); if(!EVP_PKEY_assign_RSA(pk, rsa)) { perrx("X509_new() failed\n"); return -1; } rsa = NULL; X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),serial); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x,pk); name=X509_get_subject_name(x); X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *)"UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char*)"VPNPivot", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x, name); if(!X509_sign(x, pk, EVP_md5())) // secured more with sha1? md5/sha1? sha256? abort(); *cert = x; *pkey = pk; return 1; }
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name=NULL; if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk=EVP_PKEY_new()) == NULL) { abort(); return(0); } } else pk= *pkeyp; if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x= *x509p; if (bits != 0){ rsa=RSA_generate_key(bits,RSA_F4,callback,NULL); if (!EVP_PKEY_assign_RSA(pk,rsa)) { abort(); goto err; } rsa=NULL; } X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),serial); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x,pk); name=X509_get_subject_name(x); /* 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(name,"C", MBSTRING_ASC,(const unsigned char *) "UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char *) _cert_cn, -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x,name); /* Add various extensions: standard extensions */ add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); add_ext(x, NID_subject_key_identifier, "hash"); /* Some Netscape specific extensions */ add_ext(x, NID_netscape_cert_type, "sslCA"); add_ext(x, NID_netscape_comment, "example comment extension"); #ifdef CUSTOM_EXT /* Maybe even add our own extension based on existing */ { int nid; nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension"); X509V3_EXT_add_alias(nid, NID_netscape_comment); add_ext(x, nid, "example comment alias"); } #endif if (!X509_sign(x,pk,EVP_sha1())) goto err; *x509p=x; *pkeyp=pk; return(1); err: return(0); }
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; }
void DtlsTransport::GenerateCertificateAndPrivateKey() { MS_TRACE(); int ret = 0; BIGNUM* bne = nullptr; RSA* rsa_key = nullptr; int num_bits = 1024; X509_NAME* cert_name = nullptr; // Create a big number object. bne = BN_new(); if (!bne) { LOG_OPENSSL_ERROR("BN_new() failed"); goto error; } ret = BN_set_word(bne, RSA_F4); // RSA_F4 == 65537. if (ret == 0) { LOG_OPENSSL_ERROR("BN_set_word() failed"); goto error; } // Generate a RSA key. rsa_key = RSA_new(); if (!rsa_key) { LOG_OPENSSL_ERROR("RSA_new() failed"); goto error; } // This takes some time. ret = RSA_generate_key_ex(rsa_key, num_bits, bne, nullptr); if (ret == 0) { LOG_OPENSSL_ERROR("RSA_generate_key_ex() failed"); goto error; } // Create a private key object (needed to hold the RSA key). DtlsTransport::privateKey = EVP_PKEY_new(); if (!DtlsTransport::privateKey) { LOG_OPENSSL_ERROR("EVP_PKEY_new() failed"); goto error; } ret = EVP_PKEY_assign_RSA(DtlsTransport::privateKey, rsa_key); if (ret == 0) { LOG_OPENSSL_ERROR("EVP_PKEY_assign_RSA() failed"); goto error; } // The RSA key now belongs to the private key, so don't clean it up separately. rsa_key = nullptr; // Create the X509 certificate. DtlsTransport::certificate = X509_new(); if (!DtlsTransport::certificate) { LOG_OPENSSL_ERROR("X509_new() failed"); goto error; } // Set version 3 (note that 0 means version 1). X509_set_version(DtlsTransport::certificate, 2); // Set serial number (avoid default 0). ASN1_INTEGER_set(X509_get_serialNumber(DtlsTransport::certificate), (long)Utils::Crypto::GetRandomUInt(1000000, 9999999)); // Set valid period. X509_gmtime_adj(X509_get_notBefore(DtlsTransport::certificate), -1*60*60*24*365*10); // - 10 years. X509_gmtime_adj(X509_get_notAfter(DtlsTransport::certificate), 60*60*24*365*10); // 10 years. // Set the public key for the certificate using the key. ret = X509_set_pubkey(DtlsTransport::certificate, DtlsTransport::privateKey); if (ret == 0) { LOG_OPENSSL_ERROR("X509_set_pubkey() failed"); goto error; } // Set certificate fields. cert_name = X509_get_subject_name(DtlsTransport::certificate); if (!cert_name) { LOG_OPENSSL_ERROR("X509_get_subject_name() failed"); goto error; } X509_NAME_add_entry_by_txt(cert_name, "O", MBSTRING_ASC, (uint8_t*)MS_APP_NAME, -1, -1, 0); X509_NAME_add_entry_by_txt(cert_name, "CN", MBSTRING_ASC, (uint8_t*)MS_APP_NAME, -1, -1, 0); // It is self-signed so set the issuer name to be the same as the subject. ret = X509_set_issuer_name(DtlsTransport::certificate, cert_name); if (ret == 0) { LOG_OPENSSL_ERROR("X509_set_issuer_name() failed"); goto error; } // Sign the certificate with its own private key. ret = X509_sign(DtlsTransport::certificate, DtlsTransport::privateKey, EVP_sha1()); if (ret == 0) { LOG_OPENSSL_ERROR("X509_sign() failed"); goto error; } // Free stuff and return. BN_free(bne); return; error: if (bne) BN_free(bne); if (rsa_key && !DtlsTransport::privateKey) RSA_free(rsa_key); if (DtlsTransport::privateKey) EVP_PKEY_free(DtlsTransport::privateKey); // NOTE: This also frees the RSA key. if (DtlsTransport::certificate) X509_free(DtlsTransport::certificate); MS_THROW_ERROR("DTLS certificate and private key generation failed"); }
void Server::initializeCert() { QByteArray crt, key, pass; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); QList<QSslCertificate> ql; if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } QString issuer; #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } }