/** * Copyright (C) 2006 Brad Hards * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #ifdef QT_STATICPLUGIN #include "import_plugins.h" #endif #include class CMSut : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void xcrypt_data(); void xcrypt(); void signverify_data(); void signverify(); void signverify_message_data(); void signverify_message(); void signverify_message_invalid_data(); void signverify_message_invalid(); private: QCA::Initializer *m_init; }; void CMSut::initTestCase() { m_init = new QCA::Initializer; } void CMSut::cleanupTestCase() { delete m_init; } void CMSut::xcrypt_data() { QTest::addColumn("testText"); QTest::newRow("empty") << QByteArray(""); QTest::newRow("0") << QByteArray("0"); QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01"); QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()"); } void CMSut::xcrypt() { QStringList providersToTest; providersToTest.append(QStringLiteral("qca-ossl")); foreach (const QString provider, providersToTest) { if (!QCA::isSupported("cert", provider)) QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData()); else if (!QCA::isSupported("cms", provider)) QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData()); else { QCA::Certificate pubCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), nullptr, provider); QCOMPARE(pubCert.isNull(), false); QCA::SecureMessageKey secMsgKey; QCA::CertificateChain chain; chain += pubCert; secMsgKey.setX509CertificateChain(chain); QCA::CMS cms; QCA::SecureMessage msg(&cms); QCOMPARE(msg.canClearsign(), false); QCOMPARE(msg.canSignAndEncrypt(), false); QCOMPARE(msg.type(), QCA::SecureMessage::CMS); msg.setRecipient(secMsgKey); QFETCH(QByteArray, testText); msg.startEncrypt(); msg.update(testText); msg.end(); msg.waitForFinished(-1); QByteArray encryptedResult1 = msg.read(); QCOMPARE(encryptedResult1.isEmpty(), false); msg.reset(); msg.setRecipient(secMsgKey); msg.startEncrypt(); msg.update(testText); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.success()); QByteArray encryptedResult2 = msg.read(); QCOMPARE(encryptedResult2.isEmpty(), false); QCA::ConvertResult res; QCA::SecureArray passPhrase = "start"; QCA::PrivateKey privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res); QCOMPARE(res, QCA::ConvertGood); secMsgKey.setX509PrivateKey(privKey); QCA::SecureMessageKeyList privKeyList; privKeyList += secMsgKey; QCA::CMS cms2; cms2.setPrivateKeys(privKeyList); QCA::SecureMessage msg2(&cms2); msg2.startDecrypt(); msg2.update(encryptedResult1); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray decryptedResult1 = msg2.read(); QCOMPARE(decryptedResult1, testText); msg2.reset(); msg2.startDecrypt(); msg2.update(encryptedResult1); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray decryptedResult2 = msg2.read(); QCOMPARE(decryptedResult1, decryptedResult2); QCOMPARE(msg2.canClearsign(), false); QCOMPARE(msg2.canSignAndEncrypt(), false); QCOMPARE(msg2.type(), QCA::SecureMessage::CMS); } } } void CMSut::signverify_data() { QTest::addColumn("testText"); QTest::newRow("empty") << QByteArray(""); QTest::newRow("0") << QByteArray("0"); QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01"); QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()"); } // This one tests Detached format. void CMSut::signverify() { QStringList providersToTest; providersToTest.append(QStringLiteral("qca-ossl")); foreach (const QString provider, providersToTest) { if (!QCA::isSupported("cert", provider)) QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData()); else if (!QCA::isSupported("cms", provider)) QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData()); else { QCA::ConvertResult res; QCA::SecureArray passPhrase = "start"; QCA::PrivateKey privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::Certificate pubCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCOMPARE(pubCert.isNull(), false); QCA::CertificateChain chain; chain += pubCert; QCA::SecureMessageKey secMsgKey; secMsgKey.setX509CertificateChain(chain); secMsgKey.setX509PrivateKey(privKey); QCA::SecureMessageKeyList privKeyList; privKeyList += secMsgKey; QCA::CMS cms2; cms2.setPrivateKeys(privKeyList); QCA::SecureMessage msg2(&cms2); msg2.setSigners(privKeyList); QCOMPARE(msg2.canClearsign(), false); QCOMPARE(msg2.canSignAndEncrypt(), false); QCOMPARE(msg2.type(), QCA::SecureMessage::CMS); QFETCH(QByteArray, testText); msg2.startSign(QCA::SecureMessage::Detached); msg2.update(testText); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray signedResult1 = msg2.signature(); QCOMPARE(signedResult1.isEmpty(), false); msg2.reset(); msg2.setSigners(privKeyList); msg2.startSign(QCA::SecureMessage::Detached); msg2.update(testText); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray signedResult2 = msg2.signature(); QCOMPARE(signedResult2.isEmpty(), false); QCA::CMS cms; QCA::Certificate caCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::CertificateCollection caCertCollection; caCertCollection.addCertificate(caCert); cms.setTrustedCertificates(caCertCollection); QCA::SecureMessage msg(&cms); QCOMPARE(msg.canClearsign(), false); QCOMPARE(msg.canSignAndEncrypt(), false); QCOMPARE(msg.type(), QCA::SecureMessage::CMS); msg.startVerify(signedResult1); msg.update(testText); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); #if OPENSSL_VERSION_NUMBER < 0x1010109fL QEXPECT_FAIL("empty", "We don't seem to be able to verify signature of a zero length message", Continue); #endif QVERIFY(msg.verifySuccess()); msg.reset(); msg.startVerify(signedResult2); msg.update(testText); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); #if OPENSSL_VERSION_NUMBER < 0x1010109fL QEXPECT_FAIL("empty", "We don't seem to be able to verify signature of a zero length message", Continue); #endif QVERIFY(msg.verifySuccess()); msg.reset(); // This tests junk on the end of the signature - should fail msg.startVerify(signedResult2 + "junk"); msg.update(testText); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); #if OPENSSL_VERSION_NUMBER >= 0x1010109fL QEXPECT_FAIL("empty", "On newer openssl verifaction of zero length message always succeeds", Continue); #endif QCOMPARE(msg.verifySuccess(), false); msg.reset(); // This tests junk on the end of the message - should fail msg.startVerify(signedResult2); msg.update(testText + "junk"); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); QCOMPARE(msg.verifySuccess(), false); } } } void CMSut::signverify_message_data() { QTest::addColumn("testText"); QTest::newRow("empty") << QByteArray(""); QTest::newRow("0") << QByteArray("0"); QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01"); QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()"); } // This one tests Message format void CMSut::signverify_message() { QStringList providersToTest; providersToTest.append(QStringLiteral("qca-ossl")); foreach (const QString provider, providersToTest) { if (!QCA::isSupported("cert", provider)) QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData()); else if (!QCA::isSupported("cms", provider)) QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData()); else { QCA::ConvertResult res; QCA::SecureArray passPhrase = "start"; QCA::PrivateKey privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::Certificate pubCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCOMPARE(pubCert.isNull(), false); QCA::CertificateChain chain; chain += pubCert; QCA::SecureMessageKey secMsgKey; secMsgKey.setX509CertificateChain(chain); secMsgKey.setX509PrivateKey(privKey); QCA::SecureMessageKeyList privKeyList; privKeyList += secMsgKey; QCA::CMS cms2; cms2.setPrivateKeys(privKeyList); QCA::SecureMessage msg2(&cms2); msg2.setSigners(privKeyList); QCOMPARE(msg2.canClearsign(), false); QCOMPARE(msg2.canSignAndEncrypt(), false); QCOMPARE(msg2.type(), QCA::SecureMessage::CMS); QFETCH(QByteArray, testText); msg2.startSign(QCA::SecureMessage::Message); msg2.update(testText); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray signedResult1 = msg2.read(); QCOMPARE(signedResult1.isEmpty(), false); msg2.reset(); msg2.setSigners(privKeyList); msg2.startSign(QCA::SecureMessage::Message); msg2.update(testText); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray signedResult2 = msg2.read(); QCOMPARE(signedResult2.isEmpty(), false); QCA::CMS cms; QCA::Certificate caCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::CertificateCollection caCertCollection; caCertCollection.addCertificate(caCert); cms.setTrustedCertificates(caCertCollection); QCA::SecureMessage msg(&cms); QCOMPARE(msg.canClearsign(), false); QCOMPARE(msg.canSignAndEncrypt(), false); QCOMPARE(msg.type(), QCA::SecureMessage::CMS); msg.startVerify(); msg.update(signedResult1); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); QVERIFY(msg.verifySuccess()); msg.reset(); msg.startVerify(); msg.update(signedResult2); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); QVERIFY(msg.verifySuccess()); msg.reset(); msg.startVerify(); msg.update(signedResult2); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); QCOMPARE(msg.verifySuccess(), true); } } } void CMSut::signverify_message_invalid_data() { QTest::addColumn("testText"); QTest::newRow("empty") << QByteArray(""); QTest::newRow("0") << QByteArray("0"); QTest::newRow("07") << QByteArray("07899847jkjjfasjaJKJLJkljklj&kjlj;/**-+.01"); QTest::newRow("dubious") << QByteArray("~!#**$#&&%^@#^&()"); } // This one tests Message format void CMSut::signverify_message_invalid() { QStringList providersToTest; providersToTest.append(QStringLiteral("qca-ossl")); foreach (const QString provider, providersToTest) { if (!QCA::isSupported("cert", provider)) QWARN((QStringLiteral("Certificate not supported for ") + provider).toLocal8Bit().constData()); else if (!QCA::isSupported("cms", provider)) QWARN((QStringLiteral("CMS not supported for ") + provider).toLocal8Bit().constData()); else { QCA::ConvertResult res; QCA::SecureArray passPhrase = "start"; QCA::PrivateKey privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("QcaTestClientKey.pem"), passPhrase, &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::Certificate pubCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestClientCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCOMPARE(pubCert.isNull(), false); QCA::CertificateChain chain; chain += pubCert; QCA::SecureMessageKey secMsgKey; secMsgKey.setX509CertificateChain(chain); secMsgKey.setX509PrivateKey(privKey); QCA::SecureMessageKeyList privKeyList; privKeyList += secMsgKey; QCA::CMS cms2; cms2.setPrivateKeys(privKeyList); QCA::SecureMessage msg2(&cms2); msg2.setSigners(privKeyList); QCOMPARE(msg2.canClearsign(), false); QCOMPARE(msg2.canSignAndEncrypt(), false); QCOMPARE(msg2.type(), QCA::SecureMessage::CMS); QFETCH(QByteArray, testText); msg2.startSign(QCA::SecureMessage::Message); msg2.update(testText); msg2.end(); msg2.waitForFinished(-1); QVERIFY(msg2.success()); QByteArray signedResult1 = msg2.read(); QCOMPARE(signedResult1.isEmpty(), false); QCA::CMS cms; QCA::Certificate caCert = QCA::Certificate::fromPEMFile(QStringLiteral("QcaTestRootCert.pem"), &res, provider); QCOMPARE(res, QCA::ConvertGood); QCA::CertificateCollection caCertCollection; caCertCollection.addCertificate(caCert); cms.setTrustedCertificates(caCertCollection); QCA::SecureMessage msg(&cms); QCOMPARE(msg.canClearsign(), false); QCOMPARE(msg.canSignAndEncrypt(), false); QCOMPARE(msg.type(), QCA::SecureMessage::CMS); // This is just to break things // signedResult1[30] = signedResult1[30] + 1; signedResult1[signedResult1.size() - 2] = 0x00; msg.startVerify(); msg.update(signedResult1); msg.end(); msg.waitForFinished(-1); QVERIFY(msg.wasSigned()); QVERIFY(msg.success()); QCOMPARE(msg.verifySuccess(), false); } } } QTEST_MAIN(CMSut) #include "cms.moc"