Esempio n. 1
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;
}
ConnectionInitiator::ConnectionInitiator(QObject *parent) :
    QObject(parent)
{
    this->qSql = DatabaseHandler::getInstance();

    // generate self-signed certificate
    // this bit is inspired by http://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl
    EVP_PKEY* pkey;
    pkey = EVP_PKEY_new();

    RSA* rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
        qWarning() << "Unable to generate 2048-bit RSA key";
        UnixSignalHandler::termSignalHandler(0);
    }

    X509* x509 = X509_new();
    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
    X509_gmtime_adj(X509_get_notBefore(x509), -2000);
    X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

    X509_set_pubkey(x509, pkey);

    X509_NAME * name = X509_get_subject_name(x509);
    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                               (unsigned char *)"BE", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                               (unsigned char *)"FriendsVPN", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                               (unsigned char *)"facebookApp", -1, -1, 0);
    X509_set_issuer_name(x509, name);

    if (!X509_sign(x509, pkey, EVP_sha1())) {
        qWarning() << "Error signing certificate";
        UnixSignalHandler::termSignalHandler(0);
    }

    // get the PEM string for cert and key

    // cert
    BIO* bio = BIO_new(BIO_s_mem());
    PEM_write_bio_X509(bio, x509);
    BUF_MEM *bptr;
    BIO_get_mem_ptr(bio, &bptr);
    int length = bptr->length;
    char certBuf[length + 1];
    BIO_read(bio, certBuf, length);
    certBuf[length] = '\0';
    BIO_free(bio);

    // key
    bio = BIO_new(BIO_s_mem());
    PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL);
    BIO_get_mem_ptr(bio, &bptr);
    length = bptr->length;

    char keyBuf[length + 1];
    BIO_read(bio, keyBuf, length);
    keyBuf[length] = '\0';
    BIO_free(bio);

    qDebug() << "Printing local key and certificate";
    qDebug() << keyBuf;
    qDebug() << certBuf;

    key = QSslKey(keyBuf, QSsl::Rsa, QSsl::Pem);
    cert = QSslCertificate(certBuf, QSsl::Pem);
    qSql->pushCert(cert);
}
Esempio n. 3
0
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;

        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, "UK", -1, -1, 0);
        X509_NAME_add_entry_by_txt(name,"CN",
                                MBSTRING_ASC, "OpenSSL 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");

        /* 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_md5()))
                goto err;

        *x509p=x;
        *pkeyp=pk;
        return(1);
err:
        return(0);
        }
void LFNetConfigLoader::retrieveConfig()
{
    this->notifyStatus("Loading OpenSSL stuff ...");
    OpenSSL_add_all_algorithms();
    ERR_load_BIO_strings();
    ERR_load_crypto_strings();

    this->notifyStatus("Generating private key ...");

    BIGNUM* e = BN_new();
    BN_set_word(e, RSA_F4);

    RSA* key = RSA_new();
    RSA_generate_key_ex(key, 4096, e, NULL);

    this->notifyStatus("Saving private key ...");

    BIO* privateKey = BIO_new_file((_configLocation + "/private.key").toLocal8Bit().data(), "w");
    PEM_write_bio_RSAPrivateKey(privateKey, key, NULL, NULL, 0, NULL, NULL);
    BIO_free(privateKey);

    this->notifyStatus("Generating csr ...");

    EVP_PKEY* pkey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey, key);

    X509_NAME* name = X509_NAME_new();
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_UTF8, (unsigned char*)"LF-Net", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_UTF8, (unsigned char*)"VPN", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8, (unsigned char*)(_username.toUpper() + "_" + _computerName.toUpper()).toUtf8().data(), -1, -1, 0);

    X509_REQ* req = X509_REQ_new();
    X509_REQ_set_pubkey(req, pkey);
    X509_REQ_set_subject_name(req, name);
    X509_REQ_set_version(req, 1);
    X509_REQ_sign(req, pkey, EVP_sha512());

    BIO* request = BIO_new(BIO_s_mem());
    PEM_write_bio_X509_REQ(request, req);

    BUF_MEM* requestData;
    BIO_get_mem_ptr(request, &requestData);

    this->notifyStatus("Request certificate using generated csr ...");

    QNetworkAccessManager *mgr = new QNetworkAccessManager(this);
    connect(mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(certificateRequestFinished(QNetworkReply*)));
    connect(mgr, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));

    QNetworkRequest netRequest(QUrl("https://mokoscha.lf-net.org/request_certificate"));
    netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");

    mgr->post(netRequest, QByteArray(requestData->data, requestData->length));

    this->notifyStatus("Cleaning up temporary data ...");
    BIO_free(request);
    X509_REQ_free(req);
    X509_NAME_free(name);
    EVP_PKEY_free(pkey);
    BN_free(e);

    this->notifyStatus("Waiting for certificate ...");
}
Esempio n. 5
0
int mkit(X509 **x509p,EVP_PKEY **pkeyp, int bits, int serial, int days)
{
    X509 *x;
    EVP_PKEY *pk;
    RSA *rsa;
    X509_NAME *name=NULL;
    X509_NAME_ENTRY *ne=NULL;
    X509_EXTENSION *ex=NULL;
    char hostname[HOST_NAME_MAX];

    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;

    rsa=RSA_generate_key(bits,RSA_F4,NULL,NULL);
    if (!EVP_PKEY_assign_RSA(pk,rsa))
    {
        abort();
        goto err;
    }
    rsa=NULL;

    X509_set_version(x,3);
    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, "UK", -1, -1, 0);

    get_local_host_name(hostname, sizeof(hostname));
    X509_NAME_add_entry_by_txt(name,"CN",
                               MBSTRING_ASC, hostname, -1, -1, 0);

    X509_set_issuer_name(x,name);

    if (!X509_sign(x,pk,EVP_md5()))
        goto err;

    *x509p=x;
    *pkeyp=pk;
    return(1);
err:
    return(0);
}
Esempio n. 6
0
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, char* common_name, 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;

	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);

	unsigned char* response = (unsigned char*) calloc(1,512);
	printf("Enter Country: "); scanf("%s",response);
	X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, response, -1, -1, 0);
	printf("Enter State: "); memset(response, 0, 512); scanf("%s",response);
	X509_NAME_add_entry_by_txt(name,"ST", MBSTRING_ASC, response, -1, -1, 0);
	printf("Enter City: "); memset(response, 0, 512); scanf("%s",response);
	X509_NAME_add_entry_by_txt(name,"L", MBSTRING_ASC, response, -1, -1, 0);
	printf("Enter Organization: "); memset(response, 0, 512); scanf("%s",response);
	X509_NAME_add_entry_by_txt(name,"O", MBSTRING_ASC, response, -1, -1, 0);

	X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (unsigned char*)common_name, -1, -1, 0);

	X509_set_issuer_name(x,name);

	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");
	
	if (!X509_sign(x,pk,EVP_sha1())) goto err;

	*x509p=x;
	*pkeyp=pk;
	return 1;
err:
	return 0;
}
int createCertificateRequest(char* result, char* keyToCertify, char * country, char* state, char* loc, char* organisation, char *organisationUnit, char* cname, char* email)
{
  BIO *mem = BIO_new(BIO_s_mem());
  X509_REQ *req=X509_REQ_new();
  X509_NAME *nm = X509_NAME_new();
  int err=0;

  //fill in details
  if (strlen(country) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"C",
      MBSTRING_UTF8, (unsigned char*)country, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(state) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"ST",
      MBSTRING_UTF8, (unsigned char*)state, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(loc) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"L",
      MBSTRING_UTF8, (unsigned char*)loc, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(organisation) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"O",
      MBSTRING_UTF8, (unsigned char*)organisation, -1, -1, 0))) {
      return err;
    }
  }

  if (strlen(organisationUnit) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"OU",
      MBSTRING_UTF8, (unsigned char*)organisationUnit, -1, -1, 0))) {
      return err;
    }
  }

   // This is mandatory to have, rest are optional
  if(!(err = X509_NAME_add_entry_by_txt(nm,"CN", MBSTRING_UTF8, (unsigned char*) cname, -1, -1, 0))) {
    return err;
  }

  if (strlen(email) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"emailAddress",MBSTRING_UTF8, (unsigned char*)email, -1, -1, 0))) {
      return err;
    }
  }

  if(!(err = X509_REQ_set_subject_name(req, nm))) {
    return err;
  }

    //Set the public key
  //...convert PEM private key into a BIO

  BIO* bmem = BIO_new_mem_buf(keyToCertify, -1);
  if (!bmem) {
    BIO_free(bmem);
    return -3;
  }

  // read the private key into an EVP_PKEY structure
  EVP_PKEY* privkey = PEM_read_bio_PrivateKey(bmem, NULL, NULL, NULL);
  if (!privkey) {
    BIO_free(bmem);
    return -4;
  }


  if(!(err = X509_REQ_set_pubkey(req, privkey)))
  {
    BIO_free(bmem);
    return err;
  }

  if(!(err = X509_REQ_set_version(req,3)))
  {
    BIO_free(bmem);
    return err;
  }

  //write it to PEM format
  if (!(err = PEM_write_bio_X509_REQ(mem, req))) {
    BIO_free(mem);
    BIO_free(bmem);
    return err;
  }


  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(bmem);
  BIO_free(mem);
  return 0;
}
Esempio n. 8
0
void ssl_client_init()
{
    /*
     * This is twisted. We can generate the required keys by calling RSA_generate_key,
     * however we cannot put the private part and the public part in the two containers.
     * For that we need to save each part to a file and then load each part from
     * the respective file.
     */
    RSA *key = NULL;
    key = RSA_generate_key(1024, 17, NULL, NULL);
    if (!key)
    {
        correctly_initialized = false;
        return;
    }
    char name_template_private[] = "/tmp/tls_test/mnopqrXXXXXX";
    char name_template_public[] = "/tmp/tls_test/stuvwxXXXXXX";
    int private_key_file = 0;
    FILE *private_key_stream = NULL;
    int ret = 0;

    private_key_file = mkstemp(name_template_private);
    if (private_key_file < 0)
    {
        correctly_initialized = false;
        return;
    }
    private_key_stream = fdopen(private_key_file, "w+");
    if (!private_key_stream)
    {
        correctly_initialized = false;
        return;
    }
    ret = PEM_write_RSAPrivateKey(private_key_stream, key, NULL, NULL, 0, 0, NULL);
    if (ret == 0)
    {
        correctly_initialized = false;
        return;
    }
    fseek(private_key_stream, 0L, SEEK_SET);
    PRIVKEY = PEM_read_RSAPrivateKey(private_key_stream, (RSA **)NULL, NULL, NULL);
    if (!PRIVKEY)
    {
        correctly_initialized = false;
        return;
    }
    fclose(private_key_stream);

    int public_key_file = 0;
    FILE *public_key_stream = NULL;
    public_key_file = mkstemp(name_template_public);
    if (public_key_file < 0)
    {
        correctly_initialized = false;
        return;
    }
    public_key_stream = fdopen(public_key_file, "w+");
    if (!public_key_stream)
    {
        correctly_initialized = false;
        return;
    }
    ret = PEM_write_RSAPublicKey(public_key_stream, key);
    if (ret == 0)
    {
        correctly_initialized = false;
        return;
    }
    fseek(public_key_stream, 0L, SEEK_SET);
    PUBKEY = PEM_read_RSAPublicKey(public_key_stream, (RSA **)NULL, NULL, NULL);
    if (!PUBKEY)
    {
        correctly_initialized = false;
        return;
    }
    fclose(public_key_stream);
    RSA_free(key);

    SSLCLIENTCONTEXT = SSL_CTX_new(SSLv23_client_method());
    if (SSLCLIENTCONTEXT == NULL)
    {
        Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err1;
    }

    /* Use only TLS v1 or later.
       TODO option for SSL_OP_NO_TLSv{1,1_1} */
    SSL_CTX_set_options(SSLCLIENTCONTEXT,
                        SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

    /* Never bother with retransmissions, SSL_write() should
     * always either write the whole amount or fail. */
    SSL_CTX_set_mode(SSLCLIENTCONTEXT, SSL_MODE_AUTO_RETRY);

    /*
     * Create cert into memory and load it into SSL context.
     */

    if (PRIVKEY == NULL || PUBKEY == NULL)
    {
        correctly_initialized = false;
        return;
    }

    /* Generate self-signed cert valid from now to 50 years later. */
    {
        X509 *x509 = X509_new();
        X509_gmtime_adj(X509_get_notBefore(x509), 0);
        X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL);
        EVP_PKEY *pkey = EVP_PKEY_new();
        EVP_PKEY_set1_RSA(pkey, PRIVKEY);
        X509_NAME *name = X509_get_subject_name(x509);
        X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                                   (const char *) "",
                                   -1, -1, 0);
        X509_set_issuer_name(x509, name);
        X509_set_pubkey(x509, pkey);

        const EVP_MD *md = EVP_get_digestbyname("sha384");
        if (md == NULL)
        {
            correctly_initialized = false;
            return;
        }
        ret = X509_sign(x509, pkey, md);

        EVP_PKEY_free(pkey);
        SSLCLIENTCERT = x509;

        if (ret <= 0)
        {
            Log(LOG_LEVEL_ERR,
                "Couldn't sign the public key for the TLS handshake: %s",
                ERR_reason_error_string(ERR_get_error()));
            goto err3;
        }
    }
    /* Log(LOG_LEVEL_ERR, "generate cert from priv key: %s", */
    /*     ERR_reason_error_string(ERR_get_error())); */

    SSL_CTX_use_certificate(SSLCLIENTCONTEXT, SSLCLIENTCERT);

    ret = SSL_CTX_use_RSAPrivateKey(SSLCLIENTCONTEXT, PRIVKEY);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Verify cert consistency. */
    ret = SSL_CTX_check_private_key(SSLCLIENTCONTEXT);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Set options to always request a certificate from the peer, either we
     * are client or server. */
    SSL_CTX_set_verify(SSLCLIENTCONTEXT, SSL_VERIFY_PEER, NULL);
    /* Always accept that certificate, we do proper checking after TLS
     * connection is established since OpenSSL can't pass a connection
     * specific pointer to the callback (so we would have to lock).  */
    SSL_CTX_set_cert_verify_callback(SSLCLIENTCONTEXT, TLSVerifyCallback, NULL);

    correctly_initialized = true;
    return;

  err3:
    X509_free(SSLCLIENTCERT);
    SSLCLIENTCERT = NULL;
    SSL_CTX_free(SSLCLIENTCONTEXT);
    SSLCLIENTCONTEXT = NULL;
  err1:
    correctly_initialized = false;
    return;
}
Esempio n. 9
0
void Server::initializeCert() {
	QByteArray crt, key, pass, dhparams;

	crt = getConf("certificate", QString()).toByteArray();
	key = getConf("key", QString()).toByteArray();
	pass = getConf("passphrase", QByteArray()).toByteArray();
	dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray();

	QList<QSslCertificate> ql;

	// Attempt to load key as an RSA key or a DSA key
	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 we still can't load the key, try loading any keys from the certificate
	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 have a key, walk the list of certs, find the one for our key,
	// remove any certs for our key from the list, what's left is part of
	// the CA certificate chain.
	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;
	}

#if defined(USE_QSSLDIFFIEHELLMANPARAMETERS)
	if (! dhparams.isEmpty()) {
		QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters(dhparams);
		if (qdhp.isValid()) {
			qsdhpDHParams = qdhp;
		} else {
			log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString()));
		}
	}
#else
	if (! dhparams.isEmpty()) {
		log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters.");
	}
#endif

	QString issuer;
#if QT_VERSION >= 0x050000
	QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName);
	if (! issuerNames.isEmpty()) {
		issuer = issuerNames.first();
	}
#else
	issuer = qscCert.issuerInfo(QSslCertificate::CommonName);
#endif

	// Really old certs/keys are no good, throw them away so we can
	// generate a new one below.
	if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) {
		log("Old autogenerated certificate is unusable for registration, invalidating it");
		qscCert = QSslCertificate();
		qskKey = QSslKey();
	}

	// If we have a cert, and it's a self-signed one, but we're binding to
	// all the same addresses as the Meta server is, use it's cert instead.
	// This allows a self-signed certificate generated by Murmur to be
	// replaced by a CA-signed certificate in the .ini file.
	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 we still don't have a certificate by now, try to load the one from Meta
	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 loading from Meta doesn't work, build+sign a new one
		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());
		}
	}

#if defined(USE_QSSLDIFFIEHELLMANPARAMETERS)
	if (qsdhpDHParams.isEmpty()) {
		log("Generating new server 2048-bit Diffie-Hellman parameters. This could take a while...");

		DH *dh = DH_new();
		if (dh == NULL) {
			qFatal("DH_new failed: unable to generate Diffie-Hellman parameters for virtual server");
		}

		// Generate DH params.
		// We register a status callback in order to update the UI
		// for Murmur on Windows. We don't show the actual status,
		// but we do it to keep Murmur on Windows responsive while
		// generating the parameters.
		BN_GENCB cb;
		memset(&cb, 0, sizeof(BN_GENCB));
		BN_GENCB_set(&cb, dh_progress, NULL);
		if (DH_generate_parameters_ex(dh, 2048, 2, &cb) == 0) {
			qFatal("DH_generate_parameters_ex failed: unable to generate Diffie-Hellman parameters for virtual server");
		}

		BIO *mem = BIO_new(BIO_s_mem());
		if (PEM_write_bio_DHparams(mem, dh) == 0) {
			qFatal("PEM_write_bio_DHparams failed: unable to write generated Diffie-Hellman parameters to memory");
		}

		char *pem = NULL;
		long len = BIO_get_mem_data(mem, &pem);
		if (len <= 0) {
			qFatal("BIO_get_mem_data returned an empty or invalid buffer");
		}

		QByteArray pemdh(pem, len);
		QSslDiffieHellmanParameters qdhp(pemdh);
		if (!qdhp.isValid()) {
			qFatal("QSslDiffieHellmanParameters: unable to import generated Diffie-HellmanParameters: %s", qdhp.errorString().toStdString().c_str());
		}

		qsdhpDHParams = qdhp;
		setConf("sslDHParams", pemdh);

		BIO_free(mem);
		DH_free(dh);
	}
#endif

	// Drain OpenSSL's per-thread error queue
	// to ensure that errors from the operations
	// we've done in here do not leak out into
	// Qt's SSL module.
	//
	// If an error leaks, it can break all connections
	// to the server because each invocation of Qt's SSL
	// read callback checks OpenSSL's per-thread error
	// queue (albeit indirectly, via SSL_get_error()).
	// Qt expects any errors returned from SSL_get_error()
	// to be related to the QSslSocket it is currently
	// processing -- which is the obvious thing to expect:
	// SSL_get_error() takes a pointer to an SSL object
	// and the return code of the failed operation.
	// However, it is also documented as:
	//
	//  "In addition to ssl and ret, SSL_get_error()
	//   inspects the current thread's OpenSSL error
	//   queue."
	//
	// So, if any OpenSSL operation on the main thread
	// forgets to clear the error queue, those errors
	// *will* leak into other things that *do* error
	// checking. In our case, into Qt's SSL read callback,
	// resulting in all clients being disconnected.
	ERR_clear_error();
}
Esempio n. 10
0
/**
 * @warning Make sure you've called CryptoInitialize() first!
 */
bool ServerTLSInitialize()
{
    int ret;

    /* OpenSSL is needed for our new protocol over TLS. */
    SSL_library_init();
    SSL_load_error_strings();

    assert(SSLSERVERCONTEXT == NULL);
    SSLSERVERCONTEXT = SSL_CTX_new(SSLv23_server_method());
    if (SSLSERVERCONTEXT == NULL)
    {
        Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err1;
    }

    /* Use only TLS v1 or later.
       TODO option for SSL_OP_NO_TLSv{1,1_1} */
    SSL_CTX_set_options(SSLSERVERCONTEXT,
                        SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

    /*
     * CFEngine is not a web server so we don't need many ciphers. We only
     * allow a safe but very common subset by default, extensible via
     * "allowciphers" in body server control. By default allow:
     *     AES256-GCM-SHA384: most high-grade RSA-based cipher from TLSv1.2
     *     AES256-SHA: most backwards compatible but high-grade, from SSLv3
     */
    const char *cipher_list = SV.allowciphers;
    if (cipher_list == NULL)
        cipher_list ="AES256-GCM-SHA384:AES256-SHA";
    ret = SSL_CTX_set_cipher_list(SSLSERVERCONTEXT, cipher_list);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR,
            "No valid ciphers in cipher list: %s",
            cipher_list);
    }

    /* Never bother with retransmissions, SSL_write() should
     * always either write the whole amount or fail. */
    SSL_CTX_set_mode(SSLSERVERCONTEXT, SSL_MODE_AUTO_RETRY);

    /*
     * Create cert into memory and load it into SSL context.
     */

    if (PRIVKEY == NULL || PUBKEY == NULL)
    {
        Log(LOG_LEVEL_ERR,
            "No public/private key pair is loaded, create one with cf-key");
        goto err2;
    }
    assert(SSLSERVERCERT == NULL);
    /* Generate self-signed cert valid from now to 50 years later. */
    {
        X509 *x509 = X509_new();
        X509_gmtime_adj(X509_get_notBefore(x509), 0);
        X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL);
        EVP_PKEY *pkey = EVP_PKEY_new();
        EVP_PKEY_set1_RSA(pkey, PRIVKEY);
        X509_NAME *name = X509_get_subject_name(x509);
        X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                                   (const char *) "",
                                   -1, -1, 0);
        X509_set_issuer_name(x509, name);
        X509_set_pubkey(x509, pkey);

        const EVP_MD *md = EVP_get_digestbyname("sha384");
        if (md == NULL)
        {
            Log(LOG_LEVEL_ERR, "Uknown digest algorithm %s",
                "sha384");
            return false;
        }
        ret = X509_sign(x509, pkey, md);

        EVP_PKEY_free(pkey);
        SSLSERVERCERT = x509;

        if (ret <= 0)
        {
            Log(LOG_LEVEL_ERR,
                "Couldn't sign the public key for the TLS handshake: %s",
                ERR_reason_error_string(ERR_get_error()));
            goto err3;
        }
    }

    SSL_CTX_use_certificate(SSLSERVERCONTEXT, SSLSERVERCERT);

    ret = SSL_CTX_use_RSAPrivateKey(SSLSERVERCONTEXT, PRIVKEY);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Verify cert consistency. */
    ret = SSL_CTX_check_private_key(SSLSERVERCONTEXT);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Set options to always request a certificate from the peer, either we
     * are client or server. */
    SSL_CTX_set_verify(SSLSERVERCONTEXT, SSL_VERIFY_PEER, NULL);
    /* Always accept that certificate, we do proper checking after TLS
     * connection is established since OpenSSL can't pass a connection
     * specific pointer to the callback (so we would have to lock).  */
    SSL_CTX_set_cert_verify_callback(SSLSERVERCONTEXT, TLSVerifyCallback, NULL);

    return true;

  err3:
    X509_free(SSLSERVERCERT);
    SSLSERVERCERT = NULL;
  err2:
    SSL_CTX_free(SSLSERVERCONTEXT);
    SSLSERVERCONTEXT = NULL;
  err1:
    return false;
}
Esempio n. 11
0
/*
 * Parse an X509 subject name where 'subject' is in the format
 *    /type0=value0/type1=value1/type2=...
 * where characters may be escaped by '\'.
 * See lib/libssl/src/apps/apps.c:parse_name()
 */
void *
ca_x509_name_parse(char *subject)
{
	char		*cp, *value = NULL, *type = NULL;
	size_t		 maxlen;
	X509_NAME	*name = NULL;

	if (*subject != '/') {
		log_warnx("%s: leading '/' missing in '%s'", __func__, subject);
		goto err;
	}

	/* length of subject is upper bound for unescaped type/value */
	maxlen = strlen(subject) + 1;

	if ((type = calloc(1, maxlen)) == NULL ||
	    (value = calloc(1, maxlen)) == NULL ||
	    (name = X509_NAME_new()) == NULL)
		goto err;

	cp = subject + 1;
	while (*cp) {
		/* unescape type, terminated by '=' */
		cp = ca_x509_name_unescape(cp, type, '=');
		if (cp == NULL) {
			log_warnx("%s: could not parse type", __func__);
			goto err;
		}
		if (!*cp) {
			log_warnx("%s: missing value", __func__);
			goto err;
		}
		/* unescape value, terminated by '/' */
		cp = ca_x509_name_unescape(cp, value, '/');
		if (cp == NULL) {
			log_warnx("%s: could not parse value", __func__);
			goto err;
		}
		if (!*type || !*value) {
			log_warnx("%s: empty type or value", __func__);
			goto err;
		}
		log_debug("%s: setting '%s' to '%s'", __func__, type, value);
		if (!X509_NAME_add_entry_by_txt(name, type, MBSTRING_ASC,
		    value, -1, -1, 0)) {
			log_warnx("%s: setting '%s' to '%s' failed", __func__,
			    type, value);
			ca_sslerror(__func__);
			goto err;
		}
	}
	free(type);
	free(value);
	return (name);

err:
	X509_NAME_free(name);
	free(type);
	free(value);
	return (NULL);
}
Esempio n. 12
0
File: 2cca.c Progetto: randunel/2cca
/*
 * Create identity
 */
int build_identity(void)
{
    EVP_PKEY * pkey ;
    RSA * rsa ;
    EC_KEY * ecc ;
    X509 * cert ;
    X509_NAME * name ;
    identity ca ;
    char filename[FIELD_SZ+5];
    FILE * pem ;

    /* Check before overwriting */
    sprintf(filename, "%s.crt", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }
    sprintf(filename, "%s.key", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }

    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        strcpy(certinfo.ou, "Root");
        break;

        case PROFILE_SUB_CA:
        strcpy(certinfo.ou, "Sub");
        break;

        case PROFILE_SERVER:
        strcpy(certinfo.ou, "Server");
        break;
        
        case PROFILE_CLIENT:
        strcpy(certinfo.ou, "Client");
        break;

        case PROFILE_WWW:
        strcpy(certinfo.ou, "Server");
        break;

        default:
        fprintf(stderr, "Unknown profile: aborting\n");
        return -1 ;
    }

    if (certinfo.ec_name[0] && certinfo.profile!=PROFILE_CLIENT) {
        fprintf(stderr, "ECC keys are only supported for clients\n");
        return -1 ;
    }

    if (certinfo.profile != PROFILE_ROOT_CA) {
        /* Need to load signing CA */
        if (load_ca(certinfo.signing_ca, &ca)!=0) {
            fprintf(stderr, "Cannot find CA key or certificate\n");
            return -1 ;
        }
        /* Organization is the same as root */
        X509_NAME_get_text_by_NID(X509_get_subject_name(ca.cert),
                                  NID_organizationName,
                                  certinfo.o,
                                  FIELD_SZ);
    }

    /* Generate key pair */
    if (certinfo.ec_name[0]) {
        printf("Generating EC key [%s]\n", certinfo.ec_name);
        ecc = EC_KEY_new_by_curve_name(OBJ_txt2nid(certinfo.ec_name));
        if (!ecc) {
            fprintf(stderr, "Unknown curve: [%s]\n", certinfo.ec_name);
            return -1 ;
        }
        EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
        EC_KEY_generate_key(ecc);
        pkey = EVP_PKEY_new();
        EVP_PKEY_assign_EC_KEY(pkey, ecc);
    } else {
        printf("Generating RSA-%d key\n", certinfo.rsa_keysz);
        pkey = EVP_PKEY_new();
        rsa = RSA_generate_key(certinfo.rsa_keysz, RSA_F4, progress, 0);
        EVP_PKEY_assign_RSA(pkey, rsa);
    }

    /* Assign all certificate fields */
    cert = X509_new();
    X509_set_version(cert, 2);
    set_serial128(cert);
    X509_gmtime_adj(X509_get_notBefore(cert), 0);
    X509_gmtime_adj(X509_get_notAfter(cert), certinfo.days * 24*60*60);
    X509_set_pubkey(cert, pkey);

    name = X509_get_subject_name(cert);
    if (certinfo.c[0]) {
        X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)certinfo.c, -1, -1, 0);
    }
    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)certinfo.o, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)certinfo.cn, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char*)certinfo.ou, -1, -1, 0);
    if (certinfo.l[0]) {
        X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)certinfo.l, -1, -1, 0);
    }
    if (certinfo.st[0]) {
        X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (unsigned char *)certinfo.st, -1, -1, 0);
    }

    /* Set extensions according to profile */
    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(cert, cert, NID_subject_key_identifier, "hash");
        set_extension(cert, cert, NID_authority_key_identifier, "keyid:always");
        break ;

        case PROFILE_SUB_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(ca.cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(ca.cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "keyid:always");
        break;

        case PROFILE_CLIENT:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_SERVER:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_WWW:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth,clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break;

        case PROFILE_UNKNOWN:
        default:
        break ;
    }
    /* Set issuer */
    if (certinfo.profile==PROFILE_ROOT_CA) {
        /* Self-signed */
        X509_set_issuer_name(cert, name);
        X509_sign(cert, pkey, EVP_sha256());
    } else {
        /* Signed by parent CA */
        X509_set_issuer_name(cert, X509_get_subject_name(ca.cert));
        X509_sign(cert, ca.key, EVP_sha256());
    }

    printf("Saving results to %s.[crt|key]\n", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_PrivateKey(pem, pkey, NULL, NULL, 0, NULL, NULL);
    fclose(pem);
    sprintf(filename, "%s.crt", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_X509(pem, cert);
    fclose(pem);
    X509_free(cert);
    EVP_PKEY_free(pkey);

    if (certinfo.profile!=PROFILE_ROOT_CA) {
        X509_free(ca.cert);
        EVP_PKEY_free(ca.key);
    }
    printf("done\n");

    return 0;
}
Esempio n. 13
0
static int janus_dtls_generate_keys(X509 **certificate, EVP_PKEY **private_key) {
	static const int num_bits = 2048;
	BIGNUM *bne = NULL;
	RSA *rsa_key = NULL;
	X509_NAME *cert_name = NULL;

	JANUS_LOG(LOG_VERB, "Generating DTLS key / cert\n");

	/* Create a big number object. */
	bne = BN_new();
	if(!bne) {
		JANUS_LOG(LOG_FATAL, "BN_new() failed\n");
		goto error;
	}

	if(!BN_set_word(bne, RSA_F4)) {  /* RSA_F4 == 65537 */
		JANUS_LOG(LOG_FATAL, "BN_set_word() failed\n");
		goto error;
	}

	/* Generate a RSA key. */
	rsa_key = RSA_new();
	if(!rsa_key) {
		JANUS_LOG(LOG_FATAL, "RSA_new() failed\n");
		goto error;
	}

	/* This takes some time. */
	if(!RSA_generate_key_ex(rsa_key, num_bits, bne, NULL)) {
		JANUS_LOG(LOG_FATAL, "RSA_generate_key_ex() failed\n");
		goto error;
	}

	/* Create a private key object (needed to hold the RSA key). */
	*private_key = EVP_PKEY_new();
	if(!*private_key) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_new() failed\n");
		goto error;
	}

	if(!EVP_PKEY_assign_RSA(*private_key, rsa_key)) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_assign_RSA() failed\n");
		goto error;
	}
	/* The RSA key now belongs to the private key, so don't clean it up separately. */
	rsa_key = NULL;

	/* Create the X509 certificate. */
	*certificate = X509_new();
	if(!*certificate) {
		JANUS_LOG(LOG_FATAL, "X509_new() failed\n");
		goto error;
	}

	/* Set version 3 (note that 0 means version 1). */
	X509_set_version(*certificate, 2);

	/* Set serial number. */
	ASN1_INTEGER_set(X509_get_serialNumber(*certificate), (long)g_random_int());

	/* Set valid period. */
	X509_gmtime_adj(X509_get_notBefore(*certificate), -1 * DTLS_AUTOCERT_DURATION);  /* -1 year */
	X509_gmtime_adj(X509_get_notAfter(*certificate), DTLS_AUTOCERT_DURATION);  /* 1 year */

	/* Set the public key for the certificate using the key. */
	if(!X509_set_pubkey(*certificate, *private_key)) {
		JANUS_LOG(LOG_FATAL, "X509_set_pubkey() failed\n");
		goto error;
	}

	/* Set certificate fields. */
	cert_name = X509_get_subject_name(*certificate);
	if(!cert_name) {
		JANUS_LOG(LOG_FATAL, "X509_get_subject_name() failed\n");
		goto error;
	}
	X509_NAME_add_entry_by_txt(cert_name, "O", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);
	X509_NAME_add_entry_by_txt(cert_name, "CN", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);

	/* It is self-signed so set the issuer name to be the same as the subject. */
	if(!X509_set_issuer_name(*certificate, cert_name)) {
		JANUS_LOG(LOG_FATAL, "X509_set_issuer_name() failed\n");
		goto error;
	}

	/* Sign the certificate with the private key. */
	if(!X509_sign(*certificate, *private_key, EVP_sha1())) {
		JANUS_LOG(LOG_FATAL, "X509_sign() failed\n");
		goto error;
	}

	/* Free stuff and resurn. */
	BN_free(bne);
	return 0;

error:
	if(bne)
		BN_free(bne);
	if(rsa_key && !*private_key)
		RSA_free(rsa_key);
	if(*private_key)
		EVP_PKEY_free(*private_key);  /* This also frees the RSA key. */
	if(*certificate)
		X509_free(*certificate);
	return -1;
}
Esempio n. 14
0
int main()
{
    EVP_PKEY *pKey;
    RSA *rsa;
    X509 *x509;
    X509_NAME *name;
    X509_EXTENSION *ex;
    FILE *fp;
    int KEY_SIZE = 2048;
    int days = 365;

    pKey = EVP_PKEY_new(); // Create a private key

    rsa = RSA_generate_key(
        KEY_SIZE, // Key length (bits)
        RSA_F4,   // Exponent
        NULL,     // Callback
        NULL      // Callback argument
        );

    EVP_PKEY_assign_RSA(pKey, rsa);

    x509 = X509_new();

    X509_set_version(x509, 3);
    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
    X509_gmtime_adj(X509_get_notBefore(x509), 0);
    X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * days);
    X509_set_pubkey(x509, pKey);

    name = X509_get_subject_name(x509);

    X509_NAME_add_entry_by_txt(name, "C",
        MBSTRING_ASC, "Wnmp", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN",
        MBSTRING_ASC, "Wnmp", -1, -1, 0);

    X509_set_issuer_name(x509, name);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_cert_type, "server");
    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_comment,
        "Wnmp by Kurt Cancemi");
    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_ssl_server_name,
        "localhost");

    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    X509_sign(x509, pKey, EVP_sha1());

    if (!(fp = fopen(KEY_PUB, "w"))) {
        printf("Error writing to public key file");
        return -1;
    }
    if (PEM_write_X509(fp, x509) != 1)
        printf("Error while writing public key");
    fclose(fp);

    if (!(fp = fopen(KEY_PRV, "w"))) {
        printf("Error writing to private key file");
        return -1;
    }
    if (PEM_write_PrivateKey(fp, pKey, NULL, NULL, 0, NULL, NULL) != 1)
        printf("Error while writing private key");
    fclose(fp);

    X509_free(x509);
    EVP_PKEY_free(pKey);

    return 0;
}
Esempio n. 15
0
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() == nullptr) {
      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 == nullptr) {
    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) == nullptr ||
      X509_gmtime_adj(X509_get_notAfter(x509),
                      60L * 60L * 24L * days) == nullptr) {
    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 == nullptr) {
    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;
}
Esempio n. 16
0
X509_NAME* subject_to_x509_name(const char *subject, int *nentries)
{
    X509_NAME* in_subject;
    const char *p;
    char *key, *val, *k, *v = NULL;
    int escape;
    enum {
        KEY,
        VALUE
    } state;

    key = (char*)alloca(strlen(subject));
    val = (char*)alloca(strlen(subject));
    in_subject = X509_NAME_new();

    if (!in_subject || !key || !val) {
        SPICE_DEBUG("failed to allocate");
        return NULL;
    }

    *nentries = 0;

    k = key;
    state = KEY;
    for (p = subject;; ++p) {
        escape = 0;
        if (*p == '\\') {
            ++p;
            if (*p != '\\' && *p != ',') {
                SPICE_DEBUG("Invalid character after \\");
                goto fail;
            }
            escape = 1;
        }

        switch (state) {
        case KEY:
            if (*p == 0) {
                if (k == key) /* empty key */
                    goto success;
                goto fail;
            } else if (*p == '=' && !escape) {
                state = VALUE;
                *k = 0;
                v = val;
            } else
                *k++ = *p;
            break;
        case VALUE:
            if (*p == 0 || (*p == ',' && !escape)) {
                if (v == val) /* empty value */
                    goto fail;

                *v = 0;

                if (!X509_NAME_add_entry_by_txt(in_subject, key,
                                                MBSTRING_UTF8,
                                                (const unsigned char*)val,
                                                strlen(val), -1, 0)) {
                    SPICE_DEBUG("warning: failed to add entry %s=%s to X509_NAME",
                                key, val);
                    goto fail;
                }
                *nentries += 1;

                if (*p == 0)
                    goto success;

                state = KEY;
                k = key;
            } else
                *v++ = *p;
        }
    }

success:
    return in_subject;

fail:
    if (in_subject)
        X509_NAME_free(in_subject);

    return NULL;
}