File indexing completed on 2024-05-05 04:45:30

0001 /**
0002  * Copyright (C)  2006  Brad Hards <bradh@frogmouth.net>
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  *
0008  * 1. Redistributions of source code must retain the above copyright
0009  *   notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *   notice, this list of conditions and the following disclaimer in the
0012  *   documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0016  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0017  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0018  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0019  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0020  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0021  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0023  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 
0026 #include <QtCrypto>
0027 #include <QtTest/QtTest>
0028 
0029 #ifdef QT_STATICPLUGIN
0030 #include "import_plugins.h"
0031 #endif
0032 
0033 #include <openssl/opensslv.h>
0034 
0035 class CMSut : public QObject
0036 {
0037     Q_OBJECT
0038 
0039 private Q_SLOTS:
0040     void initTestCase();
0041     void cleanupTestCase();
0042     void xcrypt_data();
0043     void xcrypt();
0044     void signverify_data();
0045     void signverify();
0046     void signverify_message_data();
0047     void signverify_message();
0048     void signverify_message_invalid_data();
0049     void signverify_message_invalid();
0050 
0051 private:
0052     QCA::Initializer *m_init;
0053 };
0054 
0055 void CMSut::initTestCase()
0056 {
0057     m_init = new QCA::Initializer;
0058 }
0059 
0060 void CMSut::cleanupTestCase()
0061 {
0062     delete m_init;
0063 }
0064 
0065 void CMSut::xcrypt_data()
0066 {
0067     QTest::addColumn<QByteArray>("testText");
0068 
0069     QTest::newRow("empty") << QByteArray("");
0070     QTest::newRow("0") << QByteArray("0");
0071     QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01");
0072     QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()");
0073 }
0074 
0075 void CMSut::xcrypt()
0076 {
0077     QStringList providersToTest;
0078     providersToTest.append(QStringLiteral("qca-ossl"));
0079 
0080     foreach (const QString provider, providersToTest) {
0081         if (!QCA::isSupported("cert", provider))
0082             QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData());
0083         else if (!QCA::isSupported("cms", provider))
0084             QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData());
0085         else {
0086             QCA::Certificate pubCert =
0087                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), nullptr, provider);
0088             QCOMPARE(pubCert.isNull(), false);
0089 
0090             QCA::SecureMessageKey secMsgKey;
0091             QCA::CertificateChain chain;
0092             chain += pubCert;
0093             secMsgKey.setX509CertificateChain(chain);
0094 
0095             QCA::CMS           cms;
0096             QCA::SecureMessage msg(&cms);
0097             QCOMPARE(msg.canClearsign(), false);
0098             QCOMPARE(msg.canSignAndEncrypt(), false);
0099             QCOMPARE(msg.type(), QCA::SecureMessage::CMS);
0100 
0101             msg.setRecipient(secMsgKey);
0102 
0103             QFETCH(QByteArray, testText);
0104 
0105             msg.startEncrypt();
0106             msg.update(testText);
0107             msg.end();
0108 
0109             msg.waitForFinished(-1);
0110 
0111             QByteArray encryptedResult1 = msg.read();
0112             QCOMPARE(encryptedResult1.isEmpty(), false);
0113 
0114             msg.reset();
0115             msg.setRecipient(secMsgKey);
0116             msg.startEncrypt();
0117             msg.update(testText);
0118             msg.end();
0119 
0120             msg.waitForFinished(-1);
0121             QVERIFY(msg.success());
0122 
0123             QByteArray encryptedResult2 = msg.read();
0124             QCOMPARE(encryptedResult2.isEmpty(), false);
0125 
0126             QCA::ConvertResult res;
0127             QCA::SecureArray   passPhrase = "start";
0128             QCA::PrivateKey    privKey =
0129                 QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res);
0130             QCOMPARE(res, QCA::ConvertGood);
0131 
0132             secMsgKey.setX509PrivateKey(privKey);
0133             QCA::SecureMessageKeyList privKeyList;
0134             privKeyList += secMsgKey;
0135             QCA::CMS cms2;
0136             cms2.setPrivateKeys(privKeyList);
0137 
0138             QCA::SecureMessage msg2(&cms2);
0139 
0140             msg2.startDecrypt();
0141             msg2.update(encryptedResult1);
0142             msg2.end();
0143             msg2.waitForFinished(-1);
0144             QVERIFY(msg2.success());
0145             QByteArray decryptedResult1 = msg2.read();
0146             QCOMPARE(decryptedResult1, testText);
0147 
0148             msg2.reset();
0149             msg2.startDecrypt();
0150             msg2.update(encryptedResult1);
0151             msg2.end();
0152             msg2.waitForFinished(-1);
0153             QVERIFY(msg2.success());
0154             QByteArray decryptedResult2 = msg2.read();
0155 
0156             QCOMPARE(decryptedResult1, decryptedResult2);
0157 
0158             QCOMPARE(msg2.canClearsign(), false);
0159             QCOMPARE(msg2.canSignAndEncrypt(), false);
0160             QCOMPARE(msg2.type(), QCA::SecureMessage::CMS);
0161         }
0162     }
0163 }
0164 
0165 void CMSut::signverify_data()
0166 {
0167     QTest::addColumn<QByteArray>("testText");
0168 
0169     QTest::newRow("empty") << QByteArray("");
0170     QTest::newRow("0") << QByteArray("0");
0171     QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01");
0172     QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()");
0173 }
0174 
0175 // This one tests Detached format.
0176 void CMSut::signverify()
0177 {
0178     QStringList providersToTest;
0179     providersToTest.append(QStringLiteral("qca-ossl"));
0180 
0181     foreach (const QString provider, providersToTest) {
0182         if (!QCA::isSupported("cert", provider))
0183             QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData());
0184         else if (!QCA::isSupported("cms", provider))
0185             QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData());
0186         else {
0187             QCA::ConvertResult res;
0188             QCA::SecureArray   passPhrase = "start";
0189             QCA::PrivateKey    privKey =
0190                 QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider);
0191             QCOMPARE(res, QCA::ConvertGood);
0192 
0193             QCA::Certificate pubCert =
0194                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider);
0195             QCOMPARE(res, QCA::ConvertGood);
0196             QCOMPARE(pubCert.isNull(), false);
0197 
0198             QCA::CertificateChain chain;
0199             chain += pubCert;
0200             QCA::SecureMessageKey secMsgKey;
0201             secMsgKey.setX509CertificateChain(chain);
0202             secMsgKey.setX509PrivateKey(privKey);
0203 
0204             QCA::SecureMessageKeyList privKeyList;
0205             privKeyList += secMsgKey;
0206             QCA::CMS cms2;
0207             cms2.setPrivateKeys(privKeyList);
0208 
0209             QCA::SecureMessage msg2(&cms2);
0210             msg2.setSigners(privKeyList);
0211             QCOMPARE(msg2.canClearsign(), false);
0212             QCOMPARE(msg2.canSignAndEncrypt(), false);
0213             QCOMPARE(msg2.type(), QCA::SecureMessage::CMS);
0214 
0215             QFETCH(QByteArray, testText);
0216 
0217             msg2.startSign(QCA::SecureMessage::Detached);
0218             msg2.update(testText);
0219             msg2.end();
0220             msg2.waitForFinished(-1);
0221             QVERIFY(msg2.success());
0222             QByteArray signedResult1 = msg2.signature();
0223             QCOMPARE(signedResult1.isEmpty(), false);
0224 
0225             msg2.reset();
0226 
0227             msg2.setSigners(privKeyList);
0228             msg2.startSign(QCA::SecureMessage::Detached);
0229             msg2.update(testText);
0230             msg2.end();
0231             msg2.waitForFinished(-1);
0232             QVERIFY(msg2.success());
0233             QByteArray signedResult2 = msg2.signature();
0234 
0235             QCOMPARE(signedResult2.isEmpty(), false);
0236 
0237             QCA::CMS         cms;
0238             QCA::Certificate caCert =
0239                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider);
0240             QCOMPARE(res, QCA::ConvertGood);
0241             QCA::CertificateCollection caCertCollection;
0242             caCertCollection.addCertificate(caCert);
0243 
0244             cms.setTrustedCertificates(caCertCollection);
0245             QCA::SecureMessage msg(&cms);
0246             QCOMPARE(msg.canClearsign(), false);
0247             QCOMPARE(msg.canSignAndEncrypt(), false);
0248             QCOMPARE(msg.type(), QCA::SecureMessage::CMS);
0249 
0250             msg.startVerify(signedResult1);
0251             msg.update(testText);
0252             msg.end();
0253 
0254             msg.waitForFinished(-1);
0255             QVERIFY(msg.wasSigned());
0256             QVERIFY(msg.success());
0257 #if OPENSSL_VERSION_NUMBER < 0x1010109fL
0258             QEXPECT_FAIL("empty", "We don't seem to be able to verify signature of a zero length message", Continue);
0259 #endif
0260             QVERIFY(msg.verifySuccess());
0261 
0262             msg.reset();
0263 
0264             msg.startVerify(signedResult2);
0265             msg.update(testText);
0266             msg.end();
0267 
0268             msg.waitForFinished(-1);
0269             QVERIFY(msg.wasSigned());
0270             QVERIFY(msg.success());
0271 #if OPENSSL_VERSION_NUMBER < 0x1010109fL
0272             QEXPECT_FAIL("empty", "We don't seem to be able to verify signature of a zero length message", Continue);
0273 #endif
0274             QVERIFY(msg.verifySuccess());
0275 
0276             msg.reset();
0277 
0278             // This tests junk on the end of the signature - should fail
0279             msg.startVerify(signedResult2 + "junk");
0280             msg.update(testText);
0281             msg.end();
0282 
0283             msg.waitForFinished(-1);
0284             QVERIFY(msg.wasSigned());
0285             QVERIFY(msg.success());
0286 #if OPENSSL_VERSION_NUMBER >= 0x1010109fL
0287             QEXPECT_FAIL("empty", "On newer openssl verifaction of zero length message always succeeds", Continue);
0288 #endif
0289             QCOMPARE(msg.verifySuccess(), false);
0290 
0291             msg.reset();
0292 
0293             // This tests junk on the end of the message - should fail
0294             msg.startVerify(signedResult2);
0295             msg.update(testText + "junk");
0296             msg.end();
0297 
0298             msg.waitForFinished(-1);
0299             QVERIFY(msg.wasSigned());
0300             QVERIFY(msg.success());
0301             QCOMPARE(msg.verifySuccess(), false);
0302         }
0303     }
0304 }
0305 
0306 void CMSut::signverify_message_data()
0307 {
0308     QTest::addColumn<QByteArray>("testText");
0309 
0310     QTest::newRow("empty") << QByteArray("");
0311     QTest::newRow("0") << QByteArray("0");
0312     QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01");
0313     QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()");
0314 }
0315 
0316 // This one tests Message format
0317 void CMSut::signverify_message()
0318 {
0319     QStringList providersToTest;
0320     providersToTest.append(QStringLiteral("qca-ossl"));
0321 
0322     foreach (const QString provider, providersToTest) {
0323         if (!QCA::isSupported("cert", provider))
0324             QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData());
0325         else if (!QCA::isSupported("cms", provider))
0326             QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData());
0327         else {
0328             QCA::ConvertResult res;
0329             QCA::SecureArray   passPhrase = "start";
0330             QCA::PrivateKey    privKey =
0331                 QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider);
0332             QCOMPARE(res, QCA::ConvertGood);
0333 
0334             QCA::Certificate pubCert =
0335                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider);
0336             QCOMPARE(res, QCA::ConvertGood);
0337             QCOMPARE(pubCert.isNull(), false);
0338 
0339             QCA::CertificateChain chain;
0340             chain += pubCert;
0341             QCA::SecureMessageKey secMsgKey;
0342             secMsgKey.setX509CertificateChain(chain);
0343             secMsgKey.setX509PrivateKey(privKey);
0344 
0345             QCA::SecureMessageKeyList privKeyList;
0346             privKeyList += secMsgKey;
0347             QCA::CMS cms2;
0348             cms2.setPrivateKeys(privKeyList);
0349 
0350             QCA::SecureMessage msg2(&cms2);
0351             msg2.setSigners(privKeyList);
0352             QCOMPARE(msg2.canClearsign(), false);
0353             QCOMPARE(msg2.canSignAndEncrypt(), false);
0354             QCOMPARE(msg2.type(), QCA::SecureMessage::CMS);
0355 
0356             QFETCH(QByteArray, testText);
0357 
0358             msg2.startSign(QCA::SecureMessage::Message);
0359             msg2.update(testText);
0360             msg2.end();
0361             msg2.waitForFinished(-1);
0362             QVERIFY(msg2.success());
0363             QByteArray signedResult1 = msg2.read();
0364             QCOMPARE(signedResult1.isEmpty(), false);
0365 
0366             msg2.reset();
0367 
0368             msg2.setSigners(privKeyList);
0369             msg2.startSign(QCA::SecureMessage::Message);
0370             msg2.update(testText);
0371             msg2.end();
0372             msg2.waitForFinished(-1);
0373             QVERIFY(msg2.success());
0374             QByteArray signedResult2 = msg2.read();
0375 
0376             QCOMPARE(signedResult2.isEmpty(), false);
0377 
0378             QCA::CMS         cms;
0379             QCA::Certificate caCert =
0380                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider);
0381             QCOMPARE(res, QCA::ConvertGood);
0382 
0383             QCA::CertificateCollection caCertCollection;
0384             caCertCollection.addCertificate(caCert);
0385 
0386             cms.setTrustedCertificates(caCertCollection);
0387             QCA::SecureMessage msg(&cms);
0388             QCOMPARE(msg.canClearsign(), false);
0389             QCOMPARE(msg.canSignAndEncrypt(), false);
0390             QCOMPARE(msg.type(), QCA::SecureMessage::CMS);
0391 
0392             msg.startVerify();
0393             msg.update(signedResult1);
0394             msg.end();
0395 
0396             msg.waitForFinished(-1);
0397             QVERIFY(msg.wasSigned());
0398             QVERIFY(msg.success());
0399             QVERIFY(msg.verifySuccess());
0400 
0401             msg.reset();
0402 
0403             msg.startVerify();
0404             msg.update(signedResult2);
0405             msg.end();
0406 
0407             msg.waitForFinished(-1);
0408             QVERIFY(msg.wasSigned());
0409             QVERIFY(msg.success());
0410             QVERIFY(msg.verifySuccess());
0411 
0412             msg.reset();
0413 
0414             msg.startVerify();
0415             msg.update(signedResult2);
0416             msg.end();
0417 
0418             msg.waitForFinished(-1);
0419             QVERIFY(msg.wasSigned());
0420             QVERIFY(msg.success());
0421             QCOMPARE(msg.verifySuccess(), true);
0422         }
0423     }
0424 }
0425 
0426 void CMSut::signverify_message_invalid_data()
0427 {
0428     QTest::addColumn<QByteArray>("testText");
0429 
0430     QTest::newRow("empty") << QByteArray("");
0431     QTest::newRow("0") << QByteArray("0");
0432     QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01");
0433     QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()");
0434 }
0435 
0436 // This one tests Message format
0437 void CMSut::signverify_message_invalid()
0438 {
0439     QStringList providersToTest;
0440     providersToTest.append(QStringLiteral("qca-ossl"));
0441 
0442     foreach (const QString provider, providersToTest) {
0443         if (!QCA::isSupported("cert", provider))
0444             QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData());
0445         else if (!QCA::isSupported("cms", provider))
0446             QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData());
0447         else {
0448             QCA::ConvertResult res;
0449             QCA::SecureArray   passPhrase = "start";
0450             QCA::PrivateKey    privKey =
0451                 QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider);
0452             QCOMPARE(res, QCA::ConvertGood);
0453 
0454             QCA::Certificate pubCert =
0455                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider);
0456             QCOMPARE(res, QCA::ConvertGood);
0457             QCOMPARE(pubCert.isNull(), false);
0458 
0459             QCA::CertificateChain chain;
0460             chain += pubCert;
0461             QCA::SecureMessageKey secMsgKey;
0462             secMsgKey.setX509CertificateChain(chain);
0463             secMsgKey.setX509PrivateKey(privKey);
0464 
0465             QCA::SecureMessageKeyList privKeyList;
0466             privKeyList += secMsgKey;
0467             QCA::CMS cms2;
0468             cms2.setPrivateKeys(privKeyList);
0469 
0470             QCA::SecureMessage msg2(&cms2);
0471             msg2.setSigners(privKeyList);
0472             QCOMPARE(msg2.canClearsign(), false);
0473             QCOMPARE(msg2.canSignAndEncrypt(), false);
0474             QCOMPARE(msg2.type(), QCA::SecureMessage::CMS);
0475 
0476             QFETCH(QByteArray, testText);
0477 
0478             msg2.startSign(QCA::SecureMessage::Message);
0479             msg2.update(testText);
0480             msg2.end();
0481             msg2.waitForFinished(-1);
0482             QVERIFY(msg2.success());
0483             QByteArray signedResult1 = msg2.read();
0484             QCOMPARE(signedResult1.isEmpty(), false);
0485 
0486             QCA::CMS         cms;
0487             QCA::Certificate caCert =
0488                 QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider);
0489             QCOMPARE(res, QCA::ConvertGood);
0490 
0491             QCA::CertificateCollection caCertCollection;
0492             caCertCollection.addCertificate(caCert);
0493 
0494             cms.setTrustedCertificates(caCertCollection);
0495             QCA::SecureMessage msg(&cms);
0496             QCOMPARE(msg.canClearsign(), false);
0497             QCOMPARE(msg.canSignAndEncrypt(), false);
0498             QCOMPARE(msg.type(), QCA::SecureMessage::CMS);
0499 
0500             // This is just to break things
0501             // signedResult1[30] = signedResult1[30] + 1;
0502             if (signedResult1.at(signedResult1.size() - 2) != 0) {
0503                 signedResult1[signedResult1.size() - 2] = 0x00;
0504             } else {
0505                 signedResult1[signedResult1.size() - 2] = 0x01;
0506             }
0507 
0508             msg.startVerify();
0509             msg.update(signedResult1);
0510             msg.end();
0511 
0512             msg.waitForFinished(-1);
0513             QVERIFY(msg.wasSigned());
0514             QVERIFY(msg.success());
0515             QCOMPARE(msg.verifySuccess(), false);
0516         }
0517     }
0518 }
0519 
0520 QTEST_MAIN(CMSut)
0521 
0522 #include "cms.moc"