tests/auto/qsslkey/tst_qsslkey.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 #include <qsslkey.h>
       
    45 #include <qsslsocket.h>
       
    46 
       
    47 #include <QtNetwork/qhostaddress.h>
       
    48 #include <QtNetwork/qnetworkproxy.h>
       
    49 
       
    50 #ifdef Q_OS_SYMBIAN
       
    51 // In Symbian OS test data is located in applications private dir
       
    52 // Current path (C:\private\<UID>) contains only ascii chars
       
    53 #define SRCDIR QDir::currentPath().toAscii()
       
    54 #endif
       
    55 
       
    56 class tst_QSslKey : public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 
       
    60     struct KeyInfo {
       
    61         QFileInfo fileInfo;
       
    62         QSsl::KeyAlgorithm algorithm;
       
    63         QSsl::KeyType type;
       
    64         int length;
       
    65         QSsl::EncodingFormat format;
       
    66         KeyInfo(
       
    67             const QFileInfo &fileInfo, QSsl::KeyAlgorithm algorithm, QSsl::KeyType type,
       
    68             int length, QSsl::EncodingFormat format)
       
    69             : fileInfo(fileInfo), algorithm(algorithm), type(type), length(length)
       
    70             , format(format) {}
       
    71     };
       
    72 
       
    73     QList<KeyInfo> keyInfoList;
       
    74 
       
    75     void createPlainTestRows();
       
    76 
       
    77 public:
       
    78     tst_QSslKey();
       
    79     virtual ~tst_QSslKey();
       
    80 
       
    81 public slots:
       
    82     void initTestCase_data();
       
    83     void init();
       
    84     void cleanup();
       
    85 
       
    86 #ifndef QT_NO_OPENSSL
       
    87 
       
    88 private slots:
       
    89     void emptyConstructor();
       
    90     void constructor_data();
       
    91     void constructor();
       
    92     void copyAndAssign_data();
       
    93     void copyAndAssign();
       
    94     void equalsOperator();
       
    95     void length_data();
       
    96     void length();
       
    97     void toPemOrDer_data();
       
    98     void toPemOrDer();
       
    99     void toEncryptedPemOrDer_data();
       
   100     void toEncryptedPemOrDer();
       
   101 
       
   102 #endif
       
   103 };
       
   104 
       
   105 tst_QSslKey::tst_QSslKey()
       
   106 {
       
   107 #ifdef Q_WS_MAC
       
   108     // applicationDirPath() points to a path inside the app bundle on Mac.
       
   109     QDir dir(qApp->applicationDirPath() + QLatin1String("/../../../keys"));
       
   110 #elif defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN)
       
   111     QDir dir(SRCDIR + QLatin1String("/keys"));  // prefer this way to avoid ifdeffery and support shadow builds?
       
   112 #else
       
   113     QDir dir(qApp->applicationDirPath() + QLatin1String("/keys"));
       
   114 #endif
       
   115     QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
       
   116     QRegExp rx(QLatin1String("^(rsa|dsa)-(pub|pri)-(\\d+)\\.(pem|der)$"));
       
   117     foreach (QFileInfo fileInfo, fileInfoList) {
       
   118         if (rx.indexIn(fileInfo.fileName()) >= 0)
       
   119             keyInfoList << KeyInfo(
       
   120                 fileInfo,
       
   121                 rx.cap(1) == QLatin1String("rsa") ? QSsl::Rsa : QSsl::Dsa,
       
   122                 rx.cap(2) == QLatin1String("pub") ? QSsl::PublicKey : QSsl::PrivateKey,
       
   123                 rx.cap(3).toInt(),
       
   124                 rx.cap(4) == QLatin1String("pem") ? QSsl::Pem : QSsl::Der);
       
   125     }
       
   126 }
       
   127 
       
   128 tst_QSslKey::~tst_QSslKey()
       
   129 {
       
   130 }
       
   131 
       
   132 void tst_QSslKey::initTestCase_data()
       
   133 {
       
   134 }
       
   135 
       
   136 void tst_QSslKey::init()
       
   137 {
       
   138 }
       
   139 
       
   140 void tst_QSslKey::cleanup()
       
   141 {
       
   142 }
       
   143 
       
   144 static QByteArray readFile(const QString &absFilePath)
       
   145 {
       
   146     QFile file(absFilePath);
       
   147     if (!file.open(QIODevice::ReadOnly)) {
       
   148         QWARN("failed to open file");
       
   149         return QByteArray();
       
   150     }
       
   151     return file.readAll();
       
   152 }
       
   153 
       
   154 #ifndef QT_NO_OPENSSL
       
   155 
       
   156 void tst_QSslKey::emptyConstructor()
       
   157 {
       
   158     if (!QSslSocket::supportsSsl())
       
   159         return;
       
   160 
       
   161     QSslKey key;
       
   162     QVERIFY(key.isNull());
       
   163     QVERIFY(key.length() < 0);
       
   164 
       
   165     QSslKey key2;
       
   166     QCOMPARE(key, key2);
       
   167 }
       
   168 
       
   169 Q_DECLARE_METATYPE(QSsl::KeyAlgorithm);
       
   170 Q_DECLARE_METATYPE(QSsl::KeyType);
       
   171 Q_DECLARE_METATYPE(QSsl::EncodingFormat);
       
   172 
       
   173 void tst_QSslKey::createPlainTestRows()
       
   174 {
       
   175     QTest::addColumn<QString>("absFilePath");
       
   176     QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
       
   177     QTest::addColumn<QSsl::KeyType>("type");
       
   178     QTest::addColumn<int>("length");
       
   179     QTest::addColumn<QSsl::EncodingFormat>("format");
       
   180     foreach (KeyInfo keyInfo, keyInfoList) {
       
   181         QTest::newRow(keyInfo.fileInfo.fileName().toLatin1())
       
   182             << keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
       
   183             << keyInfo.length << keyInfo.format;
       
   184     }
       
   185 }
       
   186 
       
   187 void tst_QSslKey::constructor_data()
       
   188 {
       
   189     createPlainTestRows();
       
   190 }
       
   191 
       
   192 void tst_QSslKey::constructor()
       
   193 {
       
   194     if (!QSslSocket::supportsSsl())
       
   195         return;
       
   196 
       
   197     QFETCH(QString, absFilePath);
       
   198     QFETCH(QSsl::KeyAlgorithm, algorithm);
       
   199     QFETCH(QSsl::KeyType, type);
       
   200     QFETCH(QSsl::EncodingFormat, format);
       
   201 
       
   202     QByteArray encoded = readFile(absFilePath);
       
   203     QSslKey key(encoded, algorithm, format, type);
       
   204     QVERIFY(!key.isNull());
       
   205 }
       
   206 
       
   207 void tst_QSslKey::copyAndAssign_data()
       
   208 {
       
   209     createPlainTestRows();
       
   210 }
       
   211 
       
   212 void tst_QSslKey::copyAndAssign()
       
   213 {
       
   214     if (!QSslSocket::supportsSsl())
       
   215         return;
       
   216 
       
   217     QFETCH(QString, absFilePath);
       
   218     QFETCH(QSsl::KeyAlgorithm, algorithm);
       
   219     QFETCH(QSsl::KeyType, type);
       
   220     QFETCH(QSsl::EncodingFormat, format);
       
   221 
       
   222     QByteArray encoded = readFile(absFilePath);
       
   223     QSslKey key(encoded, algorithm, format, type);
       
   224 
       
   225     QSslKey copied(key);
       
   226     QCOMPARE(key, copied);
       
   227     QCOMPARE(key.algorithm(), copied.algorithm());
       
   228     QCOMPARE(key.type(), copied.type());
       
   229     QCOMPARE(key.length(), copied.length());
       
   230     QCOMPARE(key.toPem(), copied.toPem());
       
   231     QCOMPARE(key.toDer(), copied.toDer());
       
   232 
       
   233     QSslKey assigned = key;
       
   234     QCOMPARE(key, assigned);
       
   235     QCOMPARE(key.algorithm(), assigned.algorithm());
       
   236     QCOMPARE(key.type(), assigned.type());
       
   237     QCOMPARE(key.length(), assigned.length());
       
   238     QCOMPARE(key.toPem(), assigned.toPem());
       
   239     QCOMPARE(key.toDer(), assigned.toDer());
       
   240 }
       
   241 
       
   242 void tst_QSslKey::equalsOperator()
       
   243 {
       
   244     // ### unimplemented
       
   245 }
       
   246 
       
   247 void tst_QSslKey::length_data()
       
   248 {
       
   249     createPlainTestRows();
       
   250 }
       
   251 
       
   252 void tst_QSslKey::length()
       
   253 {
       
   254     if (!QSslSocket::supportsSsl())
       
   255         return;
       
   256 
       
   257     QFETCH(QString, absFilePath);
       
   258     QFETCH(QSsl::KeyAlgorithm, algorithm);
       
   259     QFETCH(QSsl::KeyType, type);
       
   260     QFETCH(int, length);
       
   261     QFETCH(QSsl::EncodingFormat, format);
       
   262 
       
   263     QByteArray encoded = readFile(absFilePath);
       
   264     QSslKey key(encoded, algorithm, format, type);
       
   265     QVERIFY(!key.isNull());
       
   266     QCOMPARE(key.length(), length);
       
   267 }
       
   268 
       
   269 void tst_QSslKey::toPemOrDer_data()
       
   270 {
       
   271     createPlainTestRows();
       
   272 }
       
   273 
       
   274 void tst_QSslKey::toPemOrDer()
       
   275 {
       
   276     if (!QSslSocket::supportsSsl())
       
   277         return;
       
   278 
       
   279     QFETCH(QString, absFilePath);
       
   280     QFETCH(QSsl::KeyAlgorithm, algorithm);
       
   281     QFETCH(QSsl::KeyType, type);
       
   282     QFETCH(QSsl::EncodingFormat, format);
       
   283 
       
   284     QByteArray encoded = readFile(absFilePath);
       
   285     QSslKey key(encoded, algorithm, format, type);
       
   286     QVERIFY(!key.isNull());
       
   287     if (format == QSsl::Pem)
       
   288         encoded.replace('\r', "");
       
   289     QCOMPARE(format == QSsl::Pem ? key.toPem() : key.toDer(), encoded);
       
   290 }
       
   291 
       
   292 void tst_QSslKey::toEncryptedPemOrDer_data()
       
   293 {
       
   294     QTest::addColumn<QString>("absFilePath");
       
   295     QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
       
   296     QTest::addColumn<QSsl::KeyType>("type");
       
   297     QTest::addColumn<QSsl::EncodingFormat>("format");
       
   298     QTest::addColumn<QString>("password");
       
   299 
       
   300     QStringList passwords;
       
   301     passwords << " " << "foobar" << "foo bar"
       
   302               << "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"; // ### add more (?)
       
   303     foreach (KeyInfo keyInfo, keyInfoList) {
       
   304         foreach (QString password, passwords) {
       
   305             QString testName = QString("%1-%2-%3-%4").arg(keyInfo.fileInfo.fileName())
       
   306                 .arg(keyInfo.algorithm == QSsl::Rsa ? "RSA" : "DSA")
       
   307                 .arg(keyInfo.type == QSsl::PrivateKey ? "PrivateKey" : "PublicKey")
       
   308                 .arg(keyInfo.format == QSsl::Pem ? "PEM" : "DER");
       
   309             QTest::newRow(testName.toLatin1())
       
   310                 << keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
       
   311                 << keyInfo.format << password;
       
   312         }
       
   313     }
       
   314 }
       
   315 
       
   316 void tst_QSslKey::toEncryptedPemOrDer()
       
   317 {
       
   318     if (!QSslSocket::supportsSsl())
       
   319         return;
       
   320 
       
   321     QFETCH(QString, absFilePath);
       
   322     QFETCH(QSsl::KeyAlgorithm, algorithm);
       
   323     QFETCH(QSsl::KeyType, type);
       
   324     QFETCH(QSsl::EncodingFormat, format);
       
   325     QFETCH(QString, password);
       
   326 
       
   327     QByteArray plain = readFile(absFilePath);
       
   328     QSslKey key(plain, algorithm, format, type);
       
   329     QVERIFY(!key.isNull());
       
   330 
       
   331     QByteArray pwBytes(password.toLatin1());
       
   332 
       
   333     if (type == QSsl::PrivateKey) {
       
   334         QByteArray encryptedPem = key.toPem(pwBytes);
       
   335         QVERIFY(!encryptedPem.isEmpty());
       
   336         QSslKey keyPem(encryptedPem, algorithm, QSsl::Pem, type, pwBytes);
       
   337         QVERIFY(!keyPem.isNull());
       
   338         QCOMPARE(keyPem, key);
       
   339         QCOMPARE(keyPem.toPem(), key.toPem());
       
   340     } else {
       
   341         // verify that public keys are never encrypted by toPem()
       
   342         QByteArray encryptedPem = key.toPem(pwBytes);
       
   343         QVERIFY(!encryptedPem.isEmpty());
       
   344         QByteArray plainPem = key.toPem();
       
   345         QVERIFY(!plainPem.isEmpty());
       
   346         QCOMPARE(encryptedPem, plainPem);
       
   347     }
       
   348 
       
   349     if (type == QSsl::PrivateKey) {
       
   350         QByteArray encryptedDer = key.toDer(pwBytes);
       
   351         // ### at this point, encryptedDer is invalid, hence the below QEXPECT_FAILs
       
   352         QVERIFY(!encryptedDer.isEmpty());
       
   353         QSslKey keyDer(encryptedDer, algorithm, QSsl::Der, type, pwBytes);
       
   354         if (type == QSsl::PrivateKey)
       
   355             QEXPECT_FAIL(
       
   356                 QTest::currentDataTag(), "We're not able to decrypt these yet...", Continue);
       
   357         QVERIFY(!keyDer.isNull());
       
   358         if (type == QSsl::PrivateKey)
       
   359             QEXPECT_FAIL(
       
   360                 QTest::currentDataTag(), "We're not able to decrypt these yet...", Continue);
       
   361         QCOMPARE(keyDer.toPem(), key.toPem());
       
   362     } else {
       
   363         // verify that public keys are never encrypted by toDer()
       
   364         QByteArray encryptedDer = key.toDer(pwBytes);
       
   365         QVERIFY(!encryptedDer.isEmpty());
       
   366         QByteArray plainDer = key.toDer();
       
   367         QVERIFY(!plainDer.isEmpty());
       
   368         QCOMPARE(encryptedDer, plainDer);
       
   369     }
       
   370 
       
   371     // ### add a test to verify that public keys are _decrypted_ correctly (by the ctor)
       
   372 }
       
   373 
       
   374 #endif
       
   375 
       
   376 QTEST_MAIN(tst_QSslKey)
       
   377 #include "tst_qsslkey.moc"