Skip to content

Commit

Permalink
Merge PR #3076: Use RSA_generate_key_ex instead of RSA_generate_key f…
Browse files Browse the repository at this point in the history
…or generating Murmur's self-signed certificate.
  • Loading branch information
mkrautz committed May 8, 2017
2 parents b928c04 + 0d08ab3 commit c0c5ba7
Showing 1 changed file with 214 additions and 43 deletions.
257 changes: 214 additions & 43 deletions src/murmur/Cert.cpp
Expand Up @@ -11,19 +11,226 @@
#define SSL_STRING(x) QString::fromLatin1(x).toUtf8().data()

static int add_ext(X509 * crt, int nid, char *value) {
X509_EXTENSION *ex;
X509V3_CTX ctx;
X509V3_set_ctx_nodb(&ctx);
X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (!ex)

X509_EXTENSION *ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (ex == NULL) {
return 0;
}

if (X509_add_ext(crt, ex, -1) == 0) {
X509_EXTENSION_free(ex);
return 0;
}

X509_add_ext(crt, ex, -1);
X509_EXTENSION_free(ex);
return 1;
}

static bool selfSignedServerCert_SHA1_RSA_2048(QSslCertificate &qscCert, QSslKey &qskKey) {
bool ok = true;
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
BIGNUM *e = NULL;
X509_NAME *name = NULL;
ASN1_INTEGER *serialNumber = NULL;
ASN1_TIME *notBefore = NULL;
ASN1_TIME *notAfter = NULL;
unsigned char *commonName = NULL;

if (CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) == -1) {
ok = false;
goto out;
}

x509 = X509_new();
if (x509 == NULL) {
ok = false;
goto out;
}

pkey = EVP_PKEY_new();
if (pkey == NULL) {
ok = false;
goto out;
}

rsa = RSA_new();
if (rsa == NULL) {
ok = false;
goto out;
}

e = BN_new();
if (e == NULL) {
ok = false;
goto out;
}
if (BN_set_word(e, 65537) == 0) {
ok = false;
goto out;
}

if (RSA_generate_key_ex(rsa, 2048, e, NULL) == 0) {
ok = false;
goto out;
}

if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
ok = false;
goto out;
}

if (X509_set_version(x509, 2) == 0) {
ok = false;
goto out;
}

serialNumber = X509_get_serialNumber(x509);
if (serialNumber == NULL) {
ok = false;
goto out;
}
if (ASN1_INTEGER_set(serialNumber, 1) == 0) {
ok = false;
goto out;
}

notBefore = X509_get_notBefore(x509);
if (notBefore == NULL) {
ok = false;
goto out;
}
if (X509_gmtime_adj(notBefore, 0) == NULL) {
ok = false;
goto out;
}

notAfter = X509_get_notAfter(x509);
if (notAfter == NULL) {
ok = false;
goto out;
}
if (X509_gmtime_adj(notAfter, 60*60*24*365*20) == NULL) {
ok = false;
goto out;
}

if (X509_set_pubkey(x509, pkey) == 0) {
ok = false;
goto out;
}

name = X509_get_subject_name(x509);
if (name == NULL) {
ok = false;
goto out;
}

commonName = reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2"));
if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, commonName, -1, -1, 0) == 0) {
ok = false;
goto out;
}

if (X509_set_issuer_name(x509, name) == 0) {
ok = false;
goto out;
}

if (add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")) == 0) {
ok = false;
goto out;
}

if (add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")) == 0) {
ok = false;
goto out;
}

if (add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")) == 0) {
ok = false;
goto out;
}

if (add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")) == 0) {
ok = false;
goto out;
}

if (X509_sign(x509, pkey, EVP_sha1()) == 0) {
ok = false;
goto out;
}

{
QByteArray crt;
int len = i2d_X509(x509, NULL);
if (len <= 0) {
ok = false;
goto out;
}
crt.resize(len);

unsigned char *dptr = reinterpret_cast<unsigned char *>(crt.data());
if (i2d_X509(x509, &dptr) != len) {
ok = false;
goto out;
}

qscCert = QSslCertificate(crt, QSsl::Der);
if (qscCert.isNull()) {
ok = false;
}
}

{
QByteArray key;
int len = i2d_PrivateKey(pkey, NULL);
if (len <= 0) {
ok = false;
goto out;
}
key.resize(len);

unsigned char *dptr = reinterpret_cast<unsigned char *>(key.data());
if (i2d_PrivateKey(pkey, &dptr) != len) {
ok = false;
goto out;
}

qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
if (qskKey.isNull()) {
ok = false;
}
}

out:
if (e) {
BN_free(e);
}
// We only need to free the pkey pointer,
// not the RSA pointer. We have assigned
// our RSA key to pkey, and it will be freed
// once we free pkey.
if (pkey) {
EVP_PKEY_free(pkey);
}
if (x509) {
X509_free(x509);
}

if (!ok) {
qscCert = QSslCertificate();
qskKey = QSslKey();
}

return ok;
}

#if defined(USE_QSSLDIFFIEHELLMANPARAMETERS)
static BN_GENCB *mumble_BN_GENCB_new() {
#if OPENSSL_VERSION >= 0x10100000L
Expand Down Expand Up @@ -208,45 +415,9 @@ void Server::initializeCert() {
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");
if (!selfSignedServerCert_SHA1_RSA_2048(qscCert, qskKey)) {
log("Certificate or key generation failed");
}

setConf("certificate", qscCert.toPem());
setConf("key", qskKey.toPem());
Expand Down

0 comments on commit c0c5ba7

Please sign in to comment.