/* (c) Copyright 2012 - 2018 Anton Sviridenko https://picapica.im This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "openssltool.h" #include "../PICA_security.h" #include #include #include #include #define REGEXOLD "CN = [0-9]+\\#([^\\#\\$&\"\'=\\(\\)\\\\/\\|`!<>\\{\\}\\[\\]\\+\r\n]+)" #define REGEXNEW "CN = ([^\\#\\$&\"\'=\\(\\)\\\\/\\|`!<>\\{\\}\\[\\]\\+\r\n]+)" OpenSSLTool::OpenSSLTool() { } QString OpenSSLTool::NameFromCertFile(QString cert_file) { // QProcess openssl; openssl.start("openssl", QStringList() << "x509" << "-in" << cert_file << "-subject" << "-nameopt" << "oneline,-esc_msb,utf8" << "-noout"); if (!openssl.waitForStarted()) return QString(); if (!openssl.waitForFinished()) return QString(); QByteArray result = openssl.readAll(); QRegExp rxOld(REGEXOLD); QRegExp rx(REGEXNEW); QString name = QString::fromUtf8( result.constData()); if (name.contains(rxOld)) { name = rxOld.cap(1); } else if (name.contains(rx)) { name = rx.cap(1); } // return name; } QString OpenSSLTool::NameFromCertString(QString cert_pem) { QProcess openssl; openssl.start("openssl", QStringList() << "x509" << "-subject" << "-nameopt" << "oneline,-esc_msb,utf8" << "-noout"); if (!openssl.waitForStarted()) return QString(); openssl.write(cert_pem.toLatin1()); if (!openssl.waitForFinished()) return QString(); QByteArray result = openssl.readAll(); QRegExp rxOld(REGEXOLD); QRegExp rx(REGEXNEW); QString name = QString::fromUtf8( result.constData()); if (name.contains(rxOld)) { name = rxOld.cap(1); } else if (name.contains(rx)) { name = rx.cap(1); } // return name; } QString OpenSSLTool::CertTextFromString(QString cert_pem) { QProcess openssl; qint64 ret; char *data; QByteArray ba; openssl.start("openssl", QStringList() << "x509" << "-noout" << "-text" << "-nameopt" << "multiline,-esc_msb,utf8"); if (!openssl.waitForStarted()) return QString(); ba = cert_pem.toLatin1(); ret = openssl.write(data = (char*)ba.constData()); openssl.closeWriteChannel(); if (!openssl.waitForFinished()) return QString(); return QString::fromUtf8(openssl.readAllStandardOutput().constData()); } bool OpenSSLTool::GenRSAKeySignal(QString keyfile, bool setpassword, QString password, QString rand, QObject *receiver, const char *finished_slot) { QStringList args; quint32 numbits; unsigned char rndchar; args << "genrsa" << "-out" << keyfile; if (setpassword) args << "-passout" << "stdin" << PICA_PRIVKEYENCALGO; if (!rand.isEmpty()) args << "-rand" << rand; /* * Generate random-sized key with min size 4096 and multiply of 8. * Max size is limited to 4096 + 99*8. * See https://blog.josefsson.org/2016/11/03/why-i-dont-use-2048-or-4096-rsa-key-sizes/ * "Why I don’t Use 2048 or 4096 RSA Key Sizes" */ numbits = PICA_RSA_MINKEYSIZE; RAND_pseudo_bytes(&rndchar, 1); numbits += 8 * (rndchar % 100); args << QString::number(numbits); openssl_.start("openssl", args); if (!openssl_.waitForStarted()) return false; if (setpassword) { openssl_.write((password + "\n").toLatin1().constData()); } openssl_.disconnect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0); openssl_.connect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), receiver, finished_slot); return true; } bool OpenSSLTool::GenCertSignal(QString cert_file, QString keyfile, QString keypassword, QString subject, QObject *receiver, const char *finished_slot) { openssl_.start("openssl", QStringList() << "req" #ifdef WIN32 << "-config" << "openssl.cnf" #endif << "-out" << cert_file << "-key" << keyfile << "-subj" << "/CN=" + subject << "-new" << "-x509" << "-days" << "3680" << "-utf8" << "-batch" << PICA_CERTDIGESTALGO << "-passin" << "stdin"); if (!openssl_.waitForStarted()) return false; openssl_.write((keypassword + "\n").toLatin1().constData()); openssl_.disconnect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0); openssl_.connect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), receiver, finished_slot); return true; } QString OpenSSLTool::ReadStdErr() { return QString::fromUtf8(openssl_.readAllStandardError().constData()); } QString OpenSSLTool::ReadStdOut() { return QString::fromUtf8(openssl_.readAllStandardOutput().constData()); } bool OpenSSLTool::GenDHParamSignal(quint32 numbits, QString output_file, QObject *receiver, const char *finished_slot) { //openssl dhparam -5 4096 openssl_.start("openssl", QStringList() << "dhparam" << "-out" << output_file << "-5" << QString::number(numbits)); if (!openssl_.waitForStarted()) return false; openssl_.disconnect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0); openssl_.connect(&openssl_, SIGNAL(finished(int, QProcess::ExitStatus)), receiver, finished_slot); return true; }