1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-16 19:14:06 +02:00

Import qt-certificate-addon

This commit is contained in:
Uwe L. Korn
2014-06-27 02:17:10 +01:00
parent 2c9fefebeb
commit 12bd51c3ef
48 changed files with 3515 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATE_H
#define CERTIFICATE_H
QT_BEGIN_NAMESPACE_CERTIFICATE
namespace Certificate {
enum EntryType {
EntryCountryName,
EntryOrganizationName,
EntryOrganizationalUnitName,
EntryCommonName,
EntryLocalityName,
EntryStateOrProvinceName,
EntryEmail
};
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATE_H

View File

@@ -0,0 +1,20 @@
QT += network
TEMPLATE = lib
TARGET = certificate
LIBS += -lgnutls
DEFINES += QT_CERTIFICATE_LIB
CONFIG += debug
# Input
SOURCES += certificatebuilder.cpp \
certificaterequestbuilder.cpp \
certificaterequest.cpp \
keybuilder.cpp \
utils.cpp \
randomgenerator.cpp

View File

@@ -0,0 +1,68 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATE_GLOBAL_H
#define CERTIFICATE_GLOBAL_H
#include "qglobal.h"
#if defined(QT_CERTIFICATE_LIB)
# define Q_CERTIFICATE_EXPORT Q_DECL_EXPORT
#else
# define Q_CERTIFICATE_EXPORT Q_DECL_IMPORT
#endif
#if defined(QT_NAMESPACE)
# define QT_BEGIN_NAMESPACE_CERTIFICATE namespace QT_NAMESPACE { namespace QtAddOn { namespace Certificate {
# define QT_END_NAMESPACE_CERTIFICATE } } }
# define QT_USE_NAMESPACE_CERTIFICATE using namespace QT_NAMESPACE::QtAddOn::Certificate;
# define QT_PREPEND_NAMESPACE_CERTIFICATE(name) ::QT_NAMESPACE::QtAddOn::Certificate::name
#else
# define QT_BEGIN_NAMESPACE_CERTIFICATE namespace QtAddOn { namespace Certificate {
# define QT_END_NAMESPACE_CERTIFICATE } }
# define QT_USE_NAMESPACE_CERTIFICATE using namespace QtAddOn::Certificate;
# define QT_PREPEND_NAMESPACE_CERTIFICATE(name) ::QtAddOn::Certificate::name
#endif
// a workaround for moc - if there is a header file that doesn't use certificate
// namespace, we still force moc to do "using namespace" but the namespace have to
// be defined, so let's define an empty namespace here
QT_BEGIN_NAMESPACE_CERTIFICATE
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATE_GLOBAL_H

View File

@@ -0,0 +1,379 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDateTime>
#include <QSslKey>
extern "C" {
#include <gnutls/abstract.h>
};
#include "certificaterequest_p.h"
#include "utils_p.h"
#include "certificatebuilder_p.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
/*!
\class CertificateBuilder
\brief The CertificateBuilder class is a tool for creating X.509 certificates.
*/
/*!
Creates a new CertificateBuilder.
*/
CertificateBuilder::CertificateBuilder()
: d(new CertificateBuilderPrivate)
{
ensure_gnutls_init();
d->errno = gnutls_x509_crt_init(&d->crt);
}
/*!
Cleans up a CertificateBuilder.
*/
CertificateBuilder::~CertificateBuilder()
{
gnutls_x509_crt_deinit(d->crt);
delete d;
}
/*!
Returns the last error that occurred when using this object. The values
used are those of gnutls. If there has not been an error then it is
guaranteed to be 0.
*/
int CertificateBuilder::error() const
{
return d->errno;
}
/*!
Returns a string describing the last error that occurred when using
this object.
*/
QString CertificateBuilder::errorString() const
{
return QString::fromUtf8(gnutls_strerror(d->errno));
}
/*!
Set the request that the certificate will be generated from.
*/
bool CertificateBuilder::setRequest(const CertificateRequest &crq)
{
d->errno = gnutls_x509_crt_set_crq(d->crt, crq.d->crq);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Set the version of the X.509 certificate. In general the version will be 3.
*/
bool CertificateBuilder::setVersion(int version)
{
d->errno = gnutls_x509_crt_set_version(d->crt, version);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Set the serial number of the certificate. This should be a random value
containing a large amount of entropy.
*/
bool CertificateBuilder::setSerial(const QByteArray &serial)
{
d->errno = gnutls_x509_crt_set_serial(d->crt, serial.constData(), serial.size());
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Set the time at which the certificate will become valid.
*/
bool CertificateBuilder::setActivationTime(const QDateTime &date)
{
d->errno = gnutls_x509_crt_set_activation_time(d->crt, date.toTime_t());
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Set the time after which the certificate is no longer valid.
*/
bool CertificateBuilder::setExpirationTime(const QDateTime &date)
{
d->errno = gnutls_x509_crt_set_expiration_time(d->crt, date.toTime_t());
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Copies the extensions from the request to the certificate being created. This
should only be done after checking that the request is safe, since otherwise
you could potentially copy extensions that grant the generated certificate
facilities you did not intend.
*/
bool CertificateBuilder::copyRequestExtensions(const CertificateRequest &crq)
{
d->errno = gnutls_x509_crt_set_crq_extensions(d->crt, crq.d->crq);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Add the basic constraints extension. This allows you to specify if the
certificate being created is a CA (ie. may sign certificates), and the
maximum length of the chain that is allowed if you grant it that
permission. By default the pathLength is unlimited.
*/
bool CertificateBuilder::setBasicConstraints(bool ca, int pathLength)
{
d->errno = gnutls_x509_crt_set_basic_constraints (d->crt, ca, pathLength);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Adds the specified purpose to the list of those this certificate may be
used for. This method may be called multiple times to add a series of
different purposes.
*/
bool CertificateBuilder::addKeyPurpose(KeyPurpose purpose, bool critical)
{
QByteArray ba;
switch(purpose) {
case PurposeWebServer:
ba = QByteArray(GNUTLS_KP_TLS_WWW_SERVER);
break;
case PurposeWebClient:
ba = QByteArray(GNUTLS_KP_TLS_WWW_CLIENT);
break;
case PurposeCodeSigning:
ba = QByteArray(GNUTLS_KP_CODE_SIGNING);
break;
case PurposeEmailProtection:
ba = QByteArray(GNUTLS_KP_EMAIL_PROTECTION);
break;
case PurposeTimeStamping:
ba = QByteArray(GNUTLS_KP_TIME_STAMPING);
break;
case PurposeOcspSigning:
ba = QByteArray(GNUTLS_KP_OCSP_SIGNING);
break;
case PurposeIpsecIke:
ba = QByteArray(GNUTLS_KP_IPSEC_IKE);
break;
case PurposeAny:
ba = QByteArray(GNUTLS_KP_ANY);
break;
default:
qWarning("Unknown Purpose %d", int(purpose));
return false;
}
return addKeyPurpose(ba, critical);
}
/*!
Adds the specified purpose to the list of those this certificate may be
used for. This method may be called multiple times to add a series of
different purposes. This method differs from the one above by allowing
arbitrary OIDs to be used, not just those for which there is built in
support.
*/
bool CertificateBuilder::addKeyPurpose(const QByteArray &oid, bool critical)
{
d->errno = gnutls_x509_crt_set_key_purpose_oid(d->crt, oid.constData(), critical);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Sets the key usage flags for the certificate. If you call this method more
than once then only the last value will be used by the created certificate.
*/
bool CertificateBuilder::setKeyUsage(KeyUsageFlags usages)
{
uint usage = 0;
if (usages & UsageEncipherOnly)
usage |= GNUTLS_KEY_ENCIPHER_ONLY;
if (usages & UsageCrlSign)
usage |= GNUTLS_KEY_CRL_SIGN;
if (usages & UsageKeyCertSign)
usage |= GNUTLS_KEY_KEY_CERT_SIGN;
if (usages & UsageKeyAgreement)
usage |= GNUTLS_KEY_KEY_AGREEMENT;
if (usages & UsageDataEncipherment)
usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
if (usages & UsageKeyEncipherment)
usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
if (usages & UsageNonRepudiation)
usage |= GNUTLS_KEY_NON_REPUDIATION;
if (usages & UsageDigitalSignature)
usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
if (usages & UsageDecipherOnly)
usage |= GNUTLS_KEY_DECIPHER_ONLY;
d->errno = gnutls_x509_crt_set_key_usage(d->crt, usage);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Adds the subject key identifier extension to the certificate. The key
is extracted automatically from the certificate being created.
*/
bool CertificateBuilder::addSubjectKeyIdentifier()
{
QByteArray ba(128, 0); // Normally 20 bytes (SHA1)
size_t size = ba.size();
d->errno = gnutls_x509_crt_get_key_id(d->crt, 0, reinterpret_cast<unsigned char *>(ba.data()), &size);
if (GNUTLS_E_SUCCESS != d->errno)
return false;
d->errno = gnutls_x509_crt_set_subject_key_id (d->crt, ba.constData(), size);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Adds the authority key identifier extension to the certificate. The key
is extracted the specified certificate which must be the one later used
to sign the certificate.
*/
bool CertificateBuilder::addAuthorityKeyIdentifier(const QSslCertificate &qcacert)
{
gnutls_x509_crt_t cacrt = qsslcert_to_crt(qcacert, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno)
return false;
QByteArray ba(128, 0); // Normally 20 bytes (SHA1)
size_t size = ba.size();
// Try using the subject keyid
d->errno = gnutls_x509_crt_get_subject_key_id(cacrt, reinterpret_cast<unsigned char *>(ba.data()), &size, NULL);
// Or fallback to creating it
if (GNUTLS_E_SUCCESS != d->errno) {
d->errno = gnutls_x509_crt_get_key_id(cacrt, 0, reinterpret_cast<unsigned char *>(ba.data()), &size);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_crt_deinit(cacrt);
return false;
}
}
gnutls_x509_crt_deinit(cacrt);
d->errno = gnutls_x509_crt_set_authority_key_id(d->crt, reinterpret_cast<const unsigned char *>(ba.constData()), size);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Creates a self-signed certificate by signing the certificate with the specified
key.
*/
QSslCertificate CertificateBuilder::signedCertificate(const QSslKey &qkey)
{
gnutls_x509_privkey_t key = qsslkey_to_key(qkey, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return QSslCertificate();
};
gnutls_privkey_t abstractKey;
d->errno = gnutls_privkey_init(&abstractKey);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return QSslCertificate();
}
gnutls_privkey_import_x509(abstractKey, key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
d->errno = gnutls_x509_crt_privkey_sign(d->crt, d->crt, abstractKey, GNUTLS_DIG_SHA1, 0);
gnutls_x509_privkey_deinit(key);
if (GNUTLS_E_SUCCESS != d->errno)
return QSslCertificate();
return crt_to_qsslcert(d->crt, &d->errno);
}
/*!
Creates a certificate signed by the specified CA certificate using the
CA key.
*/
QSslCertificate CertificateBuilder::signedCertificate(const QSslCertificate &qcacert, const QSslKey &qcakey)
{
//
// Extract the CA key
//
gnutls_x509_privkey_t key = qsslkey_to_key(qcakey, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return QSslCertificate();
};
gnutls_privkey_t abstractKey;
d->errno = gnutls_privkey_init(&abstractKey);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return QSslCertificate();
}
gnutls_privkey_import_x509(abstractKey, key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
//
// Extract the CA cert
//
gnutls_x509_crt_t cacrt = qsslcert_to_crt(qcacert, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return QSslCertificate();
}
//
// Sign the cert
//
d->errno = gnutls_x509_crt_privkey_sign(d->crt, cacrt, abstractKey, GNUTLS_DIG_SHA1, 0);
gnutls_x509_crt_deinit(cacrt);
gnutls_x509_privkey_deinit(key);
if (GNUTLS_E_SUCCESS != d->errno)
return QSslCertificate();
return crt_to_qsslcert(d->crt, &d->errno);
}
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEBUILDER_H
#define CERTIFICATEBUILDER_H
#include <QString>
#include <QFlags>
#include <QtNetwork/QSslCertificate>
#include "certificate_global.h"
class QDateTime;
QT_BEGIN_NAMESPACE_CERTIFICATE
class CertificateRequest;
class Q_CERTIFICATE_EXPORT CertificateBuilder
{
public:
enum KeyPurpose {
PurposeWebServer,
PurposeWebClient,
PurposeCodeSigning,
PurposeEmailProtection,
PurposeTimeStamping,
PurposeOcspSigning,
PurposeIpsecIke,
PurposeAny
};
enum KeyUsageFlag {
UsageEncipherOnly = 0x1,
UsageCrlSign = 0x2,
UsageKeyCertSign = 0x4,
UsageKeyAgreement = 0x8,
UsageDataEncipherment = 0x10,
UsageKeyEncipherment = 0x20,
UsageNonRepudiation = 0x40,
UsageDigitalSignature = 0x80,
UsageDecipherOnly = 0x100
};
Q_DECLARE_FLAGS(KeyUsageFlags, KeyUsageFlag)
CertificateBuilder();
~CertificateBuilder();
int error() const;
QString errorString() const;
bool setRequest(const CertificateRequest &crq);
bool setVersion(int version=3);
bool setSerial(const QByteArray &serial);
bool setActivationTime(const QDateTime &date);
bool setExpirationTime(const QDateTime &date);
// Extensions
bool copyRequestExtensions(const CertificateRequest &crq);
bool setBasicConstraints(bool ca=false, int pathLength=-1);
// Extended usage
bool addKeyPurpose(KeyPurpose purpose, bool critical=false);
bool addKeyPurpose(const QByteArray &oid, bool critical=false);
// Usage
bool setKeyUsage(KeyUsageFlags usage);
// Key identifiers
bool addSubjectKeyIdentifier();
bool addAuthorityKeyIdentifier(const QSslCertificate &cacert);
QSslCertificate signedCertificate(const QSslKey &key);
QSslCertificate signedCertificate(const QSslCertificate &cacert, const QSslKey &cakey);
private:
struct CertificateBuilderPrivate *d;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(CertificateBuilder::KeyUsageFlags)
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEBUILDER_H

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEBUILDER_P_H
#define CERTIFICATEBUILDER_P_H
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "certificatebuilder.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
struct CertificateBuilderPrivate
{
int errno;
gnutls_x509_crt_t crt;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEBUILDER_P_H

View File

@@ -0,0 +1,255 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QByteArray>
#include <QIODevice>
#include <QStringList>
#include <QDebug>
#include "utils_p.h"
#include "certificaterequest_p.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
/*!
\class CertificateRequest
\brief The CertificateRequest class provides a convenient interface for an X.509
certificate signing request.
*/
/*!
\internal
Convert a crq to a PEM or DER encoded QByteArray.
*/
static QByteArray request_to_bytearray(gnutls_x509_crq_t crq, gnutls_x509_crt_fmt_t format, int *errno)
{
QByteArray ba(4096, 0);
size_t size = ba.size();
*errno = gnutls_x509_crq_export(crq, format, ba.data(), &size);
if (GNUTLS_E_SUCCESS != *errno)
return QByteArray();
ba.resize(size); // size has now been updated
return ba;
}
CertificateRequestPrivate::CertificateRequestPrivate()
: null(true)
{
ensure_gnutls_init();
gnutls_x509_crq_init(&crq);
errno = GNUTLS_E_SUCCESS;
}
CertificateRequestPrivate::~CertificateRequestPrivate()
{
gnutls_x509_crq_deinit(crq);
}
/*!
Create a null CertificateRequest.
*/
CertificateRequest::CertificateRequest()
: d(new CertificateRequestPrivate)
{
}
/*!
Create a CertificateRequest that is a copy of other.
*/
CertificateRequest::CertificateRequest(const CertificateRequest &other)
: d(other.d)
{
}
/*!
Load a CertificateRequest from the specified QIODevice using the specified format.
*/
CertificateRequest::CertificateRequest(QIODevice *io, QSsl::EncodingFormat format)
: d(new CertificateRequestPrivate)
{
QByteArray buf = io->readAll();
// Setup a datum
gnutls_datum_t buffer;
buffer.data = (unsigned char *)(buf.data());
buffer.size = buf.size();
d->errno = gnutls_x509_crq_import(d->crq, &buffer, (QSsl::Pem == format) ? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
if (GNUTLS_E_SUCCESS == d->errno)
d->null = false;
}
/*!
Clean up.
*/
CertificateRequest::~CertificateRequest()
{
}
/*!
Returns true if this CertificateRequest is null (uninitialised).
*/
bool CertificateRequest::isNull() const
{
return d->null;
}
/*!
Returns the last error that occurred when using this object. The values
used are those of gnutls. If there has not been an error then it is
guaranteed to be 0.
*/
int CertificateRequest::error() const
{
return d->errno;
}
/*!
Returns a string describing the last error that occurred when using
this object.
*/
QString CertificateRequest::errorString() const
{
return QString::fromUtf8(gnutls_strerror(d->errno));
}
/*!
Returns the version of the certificate signing request.
*/
int CertificateRequest::version() const
{
return gnutls_x509_crq_get_version(d->crq);
}
/*!
Returns the list of attributes that are present in this requests
distinguished name. The attributes are returned as OIDs.
*/
QList<QByteArray> CertificateRequest::nameEntryAttributes()
{
QList<QByteArray> result;
int index = 0;
do {
QByteArray buffer(1024, 0);
size_t size = buffer.size();
d->errno = gnutls_x509_crq_get_dn_oid(d->crq, index, buffer.data(), &size);
if (GNUTLS_E_SUCCESS == d->errno) {
buffer.resize(size);
result << buffer;
}
index++;
} while(GNUTLS_E_SUCCESS == d->errno);
return result;
}
/*!
Returns the list of entries for the attribute specified.
*/
QStringList CertificateRequest::nameEntryInfo(Certificate::EntryType attribute)
{
return nameEntryInfo(entrytype_to_oid(attribute));
}
/*!
Returns the list of entries for the attribute specified by the oid.
*/
QStringList CertificateRequest::nameEntryInfo(const QByteArray &oid)
{
QStringList result;
if (oid.isNull())
return result;
int index = 0;
do {
QByteArray buffer(1024, 0);
size_t size = buffer.size();
d->errno = gnutls_x509_crq_get_dn_by_oid(d->crq, oid.constData(), index, false, buffer.data(), &size);
if (GNUTLS_E_SUCCESS == d->errno)
result << QString::fromUtf8(buffer);
index++;
} while(GNUTLS_E_SUCCESS == d->errno);
return result;
}
/*!
Returns a QByteArray containing this request encoded as PEM.
*/
QByteArray CertificateRequest::toPem()
{
return request_to_bytearray(d->crq, GNUTLS_X509_FMT_PEM, &d->errno);
}
/*!
Returns a QByteArray containing this request encoded as DER.
*/
QByteArray CertificateRequest::toDer()
{
return request_to_bytearray(d->crq, GNUTLS_X509_FMT_DER, &d->errno);
}
/*!
Returns a QString containing this request as a human readable string.
*/
QString CertificateRequest::toText()
{
gnutls_datum_t datum;
d->errno = gnutls_x509_crq_print(d->crq, GNUTLS_CRT_PRINT_FULL, &datum);
if (GNUTLS_E_SUCCESS != d->errno)
return QString();
QString result = QString::fromUtf8(reinterpret_cast<const char *>(datum.data), datum.size);
gnutls_free(datum.data);
return result;
}
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEREQUEST_H
#define CERTIFICATEREQUEST_H
#include <QtNetwork/QSsl>
#include <QtCore/qshareddata.h>
#include "certificate_global.h"
#include "certificate.h"
class QIODevice;
QT_BEGIN_NAMESPACE_CERTIFICATE
class CertificateRequestPrivate;
class CertificateRequestBuilder;
class Q_CERTIFICATE_EXPORT CertificateRequest
{
public:
CertificateRequest();
CertificateRequest(const CertificateRequest &other);
CertificateRequest(QIODevice *io, QSsl::EncodingFormat format=QSsl::Pem);
~CertificateRequest();
CertificateRequest &operator=(const CertificateRequest &other);
void swap(CertificateRequest &other) { qSwap(d, other.d); }
bool isNull() const;
int error() const;
QString errorString() const;
// TODO: Include accessors for the fields
int version() const;
QList<QByteArray> nameEntryAttributes();
// TODO: QList<QByteArray>?
QStringList nameEntryInfo(Certificate::EntryType attribute);
QStringList nameEntryInfo(const QByteArray &attribute);
QByteArray toPem();
QByteArray toDer();
QString toText();
private:
friend class CertificateRequestPrivate;
friend class CertificateRequestBuilder;
friend class CertificateBuilder;
QSharedDataPointer<CertificateRequestPrivate> d;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEREQUEST_H

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEREQUEST_P_H
#define CERTIFICATEREQUEST_P_H
#include "certificaterequest.h"
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
QT_BEGIN_NAMESPACE_CERTIFICATE
class CertificateRequestPrivate : public QSharedData
{
public:
CertificateRequestPrivate();
~CertificateRequestPrivate();
bool null;
int errno;
gnutls_x509_crq_t crq;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEREQUEST_P_H

View File

@@ -0,0 +1,265 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QIODevice>
#include "certificaterequest_p.h"
#include "utils_p.h"
#include "certificaterequestbuilder_p.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
/*!
\class CertificateRequestBuilder
\brief The CertificateRequestBuilder class is a tool for creating certificate
signing requests.
*/
/*!
Create a new CertificateRequestBuilder.
*/
CertificateRequestBuilder::CertificateRequestBuilder()
: d(new CertificateRequestBuilderPrivate)
{
ensure_gnutls_init();
gnutls_x509_crq_init(&d->crq);
d->errno = GNUTLS_E_SUCCESS;
}
/*!
Cleans up a CertificateRequestBuilder.
*/
CertificateRequestBuilder::~CertificateRequestBuilder()
{
gnutls_x509_crq_deinit(d->crq);
delete d;
}
/*!
Returns the last error that occurred when using this object. The values
used are those of gnutls. If there has not been an error then it is
guaranteed to be 0.
*/
int CertificateRequestBuilder::error() const
{
return d->errno;
}
/*!
Returns a string describing the last error that occurred when using
this object.
*/
QString CertificateRequestBuilder::errorString() const
{
return QString::fromUtf8(gnutls_strerror(d->errno));
}
/*!
Set the version of the certificate signing request. This should
generally be set to 1.
*/
bool CertificateRequestBuilder::setVersion(int version)
{
d->errno = gnutls_x509_crq_set_version(d->crq, version);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Returns the version of the certificate signing request.
*/
int CertificateRequestBuilder::version() const
{
int ver = gnutls_x509_crq_get_version(d->crq);
if (ver < 0)
d->errno = ver;
return ver;
}
/*!
Sets the key that will be used for the reqest.
*/
bool CertificateRequestBuilder::setKey(const QSslKey &qkey)
{
gnutls_x509_privkey_t key = qsslkey_to_key(qkey, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return false;
};
d->errno = gnutls_x509_crq_set_key(d->crq, key);
gnutls_x509_privkey_deinit(key);
return GNUTLS_E_SUCCESS == d->errno;
}
/*!
Returns the list of attributes that are present in this requests
distinguished name. The attributes are returned as OIDs.
*/
QList<QByteArray> CertificateRequestBuilder::nameEntryAttributes()
{
QList<QByteArray> result;
int index = 0;
do {
QByteArray buffer(1024, 0);
size_t size = buffer.size();
d->errno = gnutls_x509_crq_get_dn_oid(d->crq, index, buffer.data(), &size);
if (GNUTLS_E_SUCCESS == d->errno) {
buffer.resize(size);
result << buffer;
}
index++;
} while(GNUTLS_E_SUCCESS == d->errno);
return result;
}
/*!
Returns the list of entries for the attribute specified.
*/
QStringList CertificateRequestBuilder::nameEntryInfo(Certificate::EntryType attribute)
{
return nameEntryInfo(entrytype_to_oid(attribute));
}
/*!
Returns the list of entries for the attribute specified by the oid.
*/
QStringList CertificateRequestBuilder::nameEntryInfo(const QByteArray &oid)
{
QStringList result;
if (oid.isNull())
return result;
int index = 0;
do {
QByteArray buffer(1024, 0);
size_t size = buffer.size();
d->errno = gnutls_x509_crq_get_dn_by_oid(d->crq, oid.constData(), index, false, buffer.data(), &size);
if (GNUTLS_E_SUCCESS == d->errno)
result << QString::fromUtf8(buffer);
index++;
} while(GNUTLS_E_SUCCESS == d->errno);
return result;
}
/*!
Adds an entry to the distinguished name of the certificate signing request. The
\a type parameter specifies the field that will be added, and the \a value
parameter specifies the value. This method can be called multiple times with the
same \a type and will add additional entries.
*/
bool CertificateRequestBuilder::addNameEntry(Certificate::EntryType type, const QByteArray &value)
{
QByteArray oid = entrytype_to_oid(type);
if (oid.isNull())
return false;
return addNameEntry(oid, value);
}
/*!
Adds an entry to the distinguished name of the certificate signing request. The
\a oid parameter specifies the ASN.1 OID of the field that will be added, and
the \a value parameter specifies the value. If the \a raw flag is set to true
then OIDs not understood by GNUTLS may be added, and the value must be DER
encoded. This method can be called multiple times with the same \a type and
will add additional entries.
*/
bool CertificateRequestBuilder::addNameEntry(const QByteArray &oid, const QByteArray &value, bool raw)
{
d->errno = gnutls_x509_crq_set_dn_by_oid(d->crq, oid.constData(), raw,
value.constData(), qstrlen(value.constData()));
return GNUTLS_E_SUCCESS == d->errno;
}
#if QT_VERSION >= 0x050000
bool CertificateRequestBuilder::addSubjectAlternativeNameEntry(QSsl::AlternativeNameEntryType qtype, const QByteArray &value)
{
gnutls_x509_subject_alt_name_t type = qssl_altnameentrytype_to_altname(qtype);
d->errno = gnutls_x509_crq_set_subject_alt_name(d->crq, type, value.constData(), value.size(), GNUTLS_FSAN_APPEND);
return GNUTLS_E_SUCCESS == d->errno;
}
#else
bool CertificateRequestBuilder::addSubjectAlternativeNameEntry(QSsl::AlternateNameEntryType qtype, const QByteArray &value)
{
gnutls_x509_subject_alt_name_t type = qssl_altnameentrytype_to_altname(qtype);
d->errno = gnutls_x509_crq_set_subject_alt_name(d->crq, type, value.constData(), value.size(), GNUTLS_FSAN_APPEND);
return GNUTLS_E_SUCCESS == d->errno;
}
#endif
/*!
Signs the request with the specified key and returns the signed request.
*/
CertificateRequest CertificateRequestBuilder::signedRequest(const QSslKey &qkey)
{
CertificateRequest result;
gnutls_x509_privkey_t key = qsslkey_to_key(qkey, &d->errno);
if (GNUTLS_E_SUCCESS != d->errno) {
gnutls_x509_privkey_deinit(key);
return result;
};
d->errno = gnutls_x509_crq_sign2(d->crq, key, GNUTLS_DIG_SHA1, 0);
gnutls_x509_privkey_deinit(key);
if (GNUTLS_E_SUCCESS != d->errno)
return result;
gnutls_x509_crq_t crqsave = result.d->crq;
result.d->crq = d->crq;
d->crq = crqsave;
return result;
}
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEREQUESTBUILDER_H
#define CERTIFICATEREQUESTBUILDER_H
#include <QSslKey>
#include <QStringList>
#include "certificaterequest.h"
#include "certificate.h"
#include "certificate_global.h"
class QIODevice;
class QByteArray;
QT_BEGIN_NAMESPACE_CERTIFICATE
class Q_CERTIFICATE_EXPORT CertificateRequestBuilder
{
public:
CertificateRequestBuilder();
~CertificateRequestBuilder();
int error() const;
QString errorString() const;
bool setVersion(int version);
int version() const;
bool setKey(const QSslKey &key);
bool addNameEntry(Certificate::EntryType type, const QByteArray &value);
bool addNameEntry(const QByteArray &oid, const QByteArray &value, bool raw=false);
QList<QByteArray> nameEntryAttributes();
QStringList nameEntryInfo(Certificate::EntryType attribute);
QStringList nameEntryInfo(const QByteArray &attribute);
#if QT_VERSION >= 0x050000
bool addSubjectAlternativeNameEntry(QSsl::AlternativeNameEntryType type, const QByteArray &value);
#else
bool addSubjectAlternativeNameEntry(QSsl::AlternateNameEntryType type, const QByteArray &value);
#endif
CertificateRequest signedRequest(const QSslKey &key);
private:
struct CertificateRequestBuilderPrivate *d;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEREQUESTBUILDER_H

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CERTIFICATEREQUESTBUILDER_P_H
#define CERTIFICATEREQUESTBUILDER_P_H
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "certificaterequestbuilder.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
struct CertificateRequestBuilderPrivate
{
int errno;
gnutls_x509_crq_t crq;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // CERTIFICATEREQUESTBUILDER_P_H

View File

@@ -0,0 +1,108 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "utils_p.h"
#include "keybuilder.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
/*!
\class KeyBuilder
\brief The KeyBuilder class is a tool for creating QSslKeys.
The KeyBuilder class provides an easy way to generate a new private
key for an X.509 certificate.
*/
/*!
Generates a new key using the specified algorithm and strength. The algorithm
will generally be RSA. The various strengths allow you to specify the trade-off
between the security of the key and the time involved in creating it.
Note that this method can take a considerable length of time to execute, so in
gui applications it should be run in a worker thread.
*/
QSslKey KeyBuilder::generate( QSsl::KeyAlgorithm algo, KeyStrength strength )
{
ensure_gnutls_init();
gnutls_sec_param_t sec;
switch(strength) {
case StrengthLow:
sec = GNUTLS_SEC_PARAM_LOW;
break;
case StrengthNormal:
sec = GNUTLS_SEC_PARAM_NORMAL;
break;
case StrengthHigh:
sec = GNUTLS_SEC_PARAM_HIGH;
break;
case StrengthUltra:
sec = GNUTLS_SEC_PARAM_ULTRA;
break;
default:
qWarning("Unhandled strength %d passed to generate", uint(strength));
sec = GNUTLS_SEC_PARAM_NORMAL;
}
uint bits = gnutls_sec_param_to_pk_bits((algo == QSsl::Rsa) ? GNUTLS_PK_RSA : GNUTLS_PK_DSA, sec);
gnutls_x509_privkey_t key;
gnutls_x509_privkey_init(&key);
int errno = gnutls_x509_privkey_generate(key, (algo == QSsl::Rsa) ? GNUTLS_PK_RSA : GNUTLS_PK_DSA, bits, 0);
if (GNUTLS_E_SUCCESS != errno) {
qWarning("Failed to generate key %s", gnutls_strerror(errno));
gnutls_x509_privkey_deinit(key);
return QSslKey();
}
QSslKey qkey = key_to_qsslkey(key, algo, &errno);
if (GNUTLS_E_SUCCESS != errno) {
qWarning("Failed to convert key to bytearray %s", gnutls_strerror(errno));
gnutls_x509_privkey_deinit(key);
return QSslKey();
}
return qkey;
}
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef KEYBUILDER_H
#define KEYBUILDER_H
#include <QtNetwork/QSslKey>
#include <QtNetwork/QSsl>
#include "certificate_global.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
class Q_CERTIFICATE_EXPORT KeyBuilder
{
public:
enum KeyStrength {
StrengthLow,
StrengthNormal,
StrengthHigh,
StrengthUltra
};
static QSslKey generate( QSsl::KeyAlgorithm algo, KeyStrength strength );
private:
KeyBuilder() {}
~KeyBuilder() {}
private:
struct KeyBuilderPrivate *d;
};
QT_END_NAMESPACE_CERTIFICATE
#endif // KEYBUILDER_H

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include "randomgenerator.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
/*!
\class RandomGenerator
\brief The RandomGenerator class is a tool for creating hard random numbers.
The RandomGenerator class provides a source of secure random numbers using
the gnutls rnd API. The numbers are suitable for uses such as certificate
serial numbers.
*/
/*!
Generates a set of random bytes of the specified size. In order to allow
these to be conveniently used as serial numbers, this method ensures that
the value returned is positive (ie. that the first bit is 0). This means
that you get one less bit of entropy than requested, but avoids
interoperability issues.
Note that this method will either return the number of bytes requested,
or a null QByteArray. It will never return a smaller number.
*/
QByteArray RandomGenerator::getPositiveBytes(int size)
{
QByteArray result(size, 0);
int errno = gnutls_rnd(GNUTLS_RND_RANDOM, result.data(), size);
if (GNUTLS_E_SUCCESS != errno)
return QByteArray();
// Clear the top bit to ensure the number is positive
char *data = result.data();
*data = *data & 0x07f;
return result;
}
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef RANDOMGENERATOR_H
#define RANDOMGENERATOR_H
#include <QByteArray>
#include "certificate_global.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
class Q_CERTIFICATE_EXPORT RandomGenerator
{
public:
static QByteArray getPositiveBytes(int size);
private:
RandomGenerator() {}
~RandomGenerator() {}
};
QT_END_NAMESPACE_CERTIFICATE
#endif // RANDOMGENERATOR_H

View File

@@ -0,0 +1,186 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <gnutls/gnutls.h>
#include <QByteArray>
#include <QSslKey>
#include <QSslCertificate>
#include "utils_p.h"
QT_BEGIN_NAMESPACE_CERTIFICATE
using namespace Certificate;
void ensure_gnutls_init()
{
static bool done = false;
// TODO: protect with a mutex
if (!done) {
gnutls_global_init();
done = true;
}
}
QByteArray entrytype_to_oid(Certificate::EntryType type)
{
QByteArray oid;
// TODO: More common name entry types
switch(type) {
case EntryCountryName:
oid = QByteArray(GNUTLS_OID_X520_COUNTRY_NAME);
break;
case EntryOrganizationName:
oid = QByteArray(GNUTLS_OID_X520_ORGANIZATION_NAME);
break;
case EntryOrganizationalUnitName:
oid = QByteArray(GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME);
break;
case EntryCommonName:
oid = QByteArray(GNUTLS_OID_X520_COMMON_NAME);
break;
case EntryLocalityName:
oid = QByteArray(GNUTLS_OID_X520_LOCALITY_NAME);
break;
case EntryStateOrProvinceName:
oid = QByteArray(GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME);
break;
case EntryEmail:
oid = QByteArray(GNUTLS_OID_PKCS9_EMAIL);
break;
default:
qWarning("Unhandled name entry type %d", int(type));
}
return oid;
}
gnutls_x509_privkey_t qsslkey_to_key(const QSslKey &qkey, int *errno)
{
gnutls_x509_privkey_t key;
*errno = gnutls_x509_privkey_init(&key);
if (GNUTLS_E_SUCCESS != *errno)
return 0;
QByteArray buf(qkey.toPem());
// Setup a datum
gnutls_datum_t buffer;
buffer.data = (unsigned char *)(buf.data());
buffer.size = buf.size();
*errno = gnutls_x509_privkey_import(key, &buffer, GNUTLS_X509_FMT_PEM);
return key;
}
gnutls_x509_crt_t qsslcert_to_crt(const QSslCertificate &qcert, int *errno)
{
gnutls_x509_crt_t cert;
*errno = gnutls_x509_crt_init(&cert);
if (GNUTLS_E_SUCCESS != *errno)
return 0;
QByteArray buf(qcert.toPem());
// Setup a datum
gnutls_datum_t buffer;
buffer.data = (unsigned char *)(buf.data());
buffer.size = buf.size();
// Import the cert
*errno = gnutls_x509_crt_import(cert, &buffer, GNUTLS_X509_FMT_PEM);
return cert;
}
QSslCertificate crt_to_qsslcert(gnutls_x509_crt_t crt, int *errno)
{
QByteArray ba(4096, 0);
size_t size = ba.size();
*errno = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, ba.data(), &size);
if (GNUTLS_E_SUCCESS != *errno)
return QSslCertificate();
return QSslCertificate(ba);
}
QSslKey key_to_qsslkey(gnutls_x509_privkey_t key, QSsl::KeyAlgorithm algo, int *errno)
{
QByteArray ba(4096, 0);
size_t size = ba.size();
*errno = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, ba.data(), &size);
if (GNUTLS_E_SUCCESS != *errno)
return QSslKey();
return QSslKey(ba, algo);
}
#if QT_VERSION >= 0x050000
gnutls_x509_subject_alt_name_t qssl_altnameentrytype_to_altname(QSsl::AlternativeNameEntryType qtype)
{
switch(qtype) {
case QSsl::EmailEntry:
return GNUTLS_SAN_RFC822NAME;
case QSsl::DnsEntry:
return GNUTLS_SAN_DNSNAME;
default:
qWarning("Unknown alternative name type %d", int(qtype));
}
}
#else
gnutls_x509_subject_alt_name_t qssl_altnameentrytype_to_altname(QSsl::AlternateNameEntryType qtype)
{
switch(qtype) {
case QSsl::EmailEntry:
return GNUTLS_SAN_RFC822NAME;
case QSsl::DnsEntry:
return GNUTLS_SAN_DNSNAME;
default:
qWarning("Unknown alternative name type %d", int(qtype));
}
}
#endif
QT_END_NAMESPACE_CERTIFICATE

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2012-2013 Richard J. Moore <rich@kde.org>
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef UTILS_P_H
#define UTILS_P_H
#include <gnutls/x509.h>
#include <QtNetwork/QSsl>
#include <QtCore/QByteArray>
#include "certificate_global.h"
#include "certificate.h"
class QSslKey;
class QSslCertificate;
QT_BEGIN_NAMESPACE_CERTIFICATE
void ensure_gnutls_init();
QByteArray entrytype_to_oid(Certificate::EntryType type);
gnutls_x509_privkey_t qsslkey_to_key(const QSslKey &qkey, int *errno);
gnutls_x509_crt_t qsslcert_to_crt(const QSslCertificate &qcert, int *errno);
QSslCertificate crt_to_qsslcert(gnutls_x509_crt_t crt, int *errno);
QSslKey key_to_qsslkey(gnutls_x509_privkey_t key, QSsl::KeyAlgorithm algo, int *errno);
#if QT_VERSION >= 0x050000
gnutls_x509_subject_alt_name_t qssl_altnameentrytype_to_altname(QSsl::AlternativeNameEntryType qtype);
#else
gnutls_x509_subject_alt_name_t qssl_altnameentrytype_to_altname(QSsl::AlternateNameEntryType qtype);
#endif
QT_END_NAMESPACE_CERTIFICATE
#endif // UTILS_P_H