Skip to content

Commit

Permalink
Extend signature to LTA
Browse files Browse the repository at this point in the history
Signed-off-by: Raul Metsma <raul@metsma.ee>
  • Loading branch information
metsma committed Dec 10, 2024
1 parent c945e57 commit ab78e3f
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 114 deletions.
125 changes: 89 additions & 36 deletions client/DigiDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,12 @@ QDateTime DigiDocSignature::tsTime() const
return toTime(s->TimeStampTime());
}

QSslCertificate DigiDocSignature::tsaCert() const
QList<std::pair<QSslCertificate,QDateTime>> DigiDocSignature::archiveTimeStamps() const
{
return toCertificate(s->ArchiveTimeStampCertificate());
}

QDateTime DigiDocSignature::tsaTime() const
{
return toTime(s->ArchiveTimeStampTime());
QList<std::pair<QSslCertificate,QDateTime>> result;
for(const TSAInfo &i: s->ArchiveTimeStamps())
result.append({toCertificate(i.cert), toTime(i.time)});;
return result;
}

DigiDocSignature::SignatureStatus DigiDocSignature::validate(bool qscd)
Expand Down Expand Up @@ -448,6 +446,56 @@ DocumentModel* DigiDoc::documentModel() const
return m_documentModel.get();
}

bool DigiDoc::extend()
{
try {
auto *signer = qApp->signer();
signer->setUserAgent(QStringLiteral("%1/%2 (%3) Devices: %4").arg(
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion(),
Common::applicationOs(),
Common::drivers().join(',')).toUtf8().constData());
qApp->waitForTSL(fileName());
QWidget *parent = qobject_cast<QWidget *>(QObject::parent());
if(parent == nullptr)
parent = Application::activeWindow();
ServiceConfirmation cb(parent);
QString current = m_fileName;
if(waitFor([&] {
if(auto container = Container::extendContainerValidity(*b, signer))
{
load(std::move(container), cb);
return true;
}
return false;
}))
{
const QString asics = QCoreApplication::translate("MainWindow", "Documents (%1)").arg(QLatin1String("*.asics *.scs"));
QFileInfo f(current);
QString name = f.absolutePath() + '/' + f.completeBaseName() + QStringLiteral(".asics");
return save(FileDialog::getSaveFileName(Application::mainWindow(), QCoreApplication::translate("MainWindow", "Save file"), name, asics));
}
else
save();
}
catch(const Exception &e)
{
Exception::ExceptionCode code = Exception::General;
QStringList causes = parseException(e, code);
switch(code)
{
case Exception::NetworkError:
case Exception::HostNotFound:
WarningDialog::show(tr("Failed to sign container. Please check the access to signing services and network settings."), causes.join('\n')); break;
case Exception::InvalidUrl:
WarningDialog::show(tr("Failed to sign container. Signing service URL is incorrect."), causes.join('\n')); break;
default:
setLastError(tr("Failed to sign container."), e); break;
}
}
return false;
}

QString DigiDoc::fileName() const { return m_fileName; }

bool DigiDoc::isError(bool failure, const QString &msg) const
Expand Down Expand Up @@ -485,6 +533,39 @@ bool DigiDoc::isSupported() const
return b && b->mediaType() == "application/vnd.etsi.asic-e+zip" && !isCades();
}

void DigiDoc::load(std::unique_ptr<Container> &&doc, ServiceConfirmation &cb)
{
clear();
b = std::move(doc);
if(b && b->mediaType() == "application/vnd.etsi.asic-s+zip" &&
b->dataFiles().size() == 1 &&
b->signatures().size() == 1)
{
const DataFile *f = b->dataFiles().at(0);
if(from(f->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive))
{
const QString tmppath = FileDialog::tempPath(FileDialog::safeName(from(f->fileName())));
f->saveAs(to(tmppath));
if(QFileInfo::exists(tmppath))
{
m_tempFiles.append(tmppath);
try {
parentContainer = std::exchange(b, Container::openPtr(to(tmppath), &cb));
} catch(const Exception &) {}
}
}
}
bool isTimeStamped = parentContainer && parentContainer->signatures().at(0)->trustedSigningTime().compare("2018-07-01T00:00:00Z") < 0;
for(const Signature *signature: b->signatures())
m_signatures.append(DigiDocSignature(signature, this, isTimeStamped));
if(parentContainer)
{
for(const Signature *signature: parentContainer->signatures())
m_timestamps.append(DigiDocSignature(signature, this));
}
containerState = signatures().isEmpty() ? ContainerState::UnsignedSavedContainer : ContainerState::SignedContainer;
}

QString DigiDoc::mediaType() const
{ return b ? from( b->mediaType() ) : QString(); }

Expand Down Expand Up @@ -513,40 +594,12 @@ bool DigiDoc::open( const QString &file )
parent = Application::activeWindow();
ServiceConfirmation cb(parent);
qApp->waitForTSL( file );
clear();
try {
WaitDialogHolder waitDialog(parent, tr("Opening"), false);
return waitFor([&] {
b = Container::openPtr(to(file), &cb);
if(b && b->mediaType() == "application/vnd.etsi.asic-s+zip" &&
b->dataFiles().size() == 1 &&
b->signatures().size() == 1)
{
const DataFile *f = b->dataFiles().at(0);
if(from(f->fileName()).endsWith(QStringLiteral(".ddoc"), Qt::CaseInsensitive))
{
const QString tmppath = FileDialog::tempPath(FileDialog::safeName(from(f->fileName())));
f->saveAs(to(tmppath));
if(QFileInfo::exists(tmppath))
{
m_tempFiles.append(tmppath);
try {
parentContainer = std::exchange(b, Container::openPtr(to(tmppath), &cb));
} catch(const Exception &) {}
}
}
}
bool isTimeStamped = parentContainer && parentContainer->signatures().at(0)->trustedSigningTime().compare("2018-07-01T00:00:00Z") < 0;
for(const Signature *signature: b->signatures())
m_signatures.append(DigiDocSignature(signature, this, isTimeStamped));
if(parentContainer)
{
for(const Signature *signature: parentContainer->signatures())
m_timestamps.append(DigiDocSignature(signature, this));
}
load(Container::openPtr(to(file), &cb), cb);
Application::addRecent(file);
m_fileName = file;
containerState = signatures().isEmpty() ? ContainerState::UnsignedSavedContainer : ContainerState::SignedContainer;
return true;
});
} catch(const Exception &e) {
Expand Down
6 changes: 4 additions & 2 deletions client/DigiDoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ class DigiDocSignature
QDateTime trustedTime() const;
QSslCertificate tsCert() const;
QDateTime tsTime() const;
QSslCertificate tsaCert() const;
QDateTime tsaTime() const;
QList<std::pair<QSslCertificate,QDateTime>> archiveTimeStamps() const;
int warning() const;

private:
Expand Down Expand Up @@ -110,6 +109,7 @@ class SDocumentModel final: public DocumentModel
friend class DigiDoc;
};

struct ServiceConfirmation;

class DigiDoc: public QObject
{
Expand All @@ -122,6 +122,7 @@ class DigiDoc: public QObject
void create( const QString &file );
void clear();
DocumentModel *documentModel() const;
bool extend();
QString fileName() const;
bool isAsicS() const;
bool isCades() const;
Expand Down Expand Up @@ -149,6 +150,7 @@ class DigiDoc: public QObject

private:
bool isError(bool failure, const QString &msg = {}) const;
void load(std::unique_ptr<digidoc::Container> &&doc, ServiceConfirmation &cb);
static void setLastError( const QString &msg, const digidoc::Exception &e );

std::unique_ptr<digidoc::Container> b;
Expand Down
35 changes: 10 additions & 25 deletions client/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ MainWindow::MainWindow( QWidget *parent )
updateSelectorData(token);
updateMyEID(token);
ui->cryptoContainerPage->cardChanged(token.cert());
if(cryptoDoc)
ui->cryptoContainerPage->update(cryptoDoc, token.cert());
});
QPCSC::instance().start();

Expand All @@ -151,8 +149,6 @@ MainWindow::MainWindow( QWidget *parent )
connect(ui->cryptoContainerPage, &ContainerPage::action, this, &MainWindow::onCryptoAction);
connect(ui->cryptoContainerPage, &ContainerPage::addFiles, this, [this](const QStringList &files) { openFiles(files, true); } );
connect(ui->cryptoContainerPage, &ContainerPage::fileRemoved, this, &MainWindow::removeCryptoFile);
connect(ui->cryptoContainerPage, &ContainerPage::keysSelected, this, &MainWindow::updateKeys);
connect(ui->cryptoContainerPage, &ContainerPage::removed, this, &MainWindow::removeAddress);
connect(ui->cryptoContainerPage, &ContainerPage::warning, this, [this](WarningText warningText) {
ui->warnings->showWarning(warningText);
ui->crypto->warningIcon(true);
Expand Down Expand Up @@ -417,6 +413,16 @@ void MainWindow::onSignAction(int action, const QString &info1, const QString &i
digiDoc->sign(city, state, zip, country, role, &s);
});
break;
case SignatureExtend:
{
if(!digiDoc)
break;
WarningDialog *d = new WarningDialog(tr("All signatures are extended in container."), this);
d->addButton(tr("Extend"), QMessageBox::Yes);
if(d->exec() == QMessageBox::Yes && digiDoc->extend())
ui->signContainerPage->transition(digiDoc);
break;
}
case ClearSignatureWarning:
ui->signature->warningIcon(false);
ui->warnings->closeWarnings(SignDetails);
Expand Down Expand Up @@ -886,15 +892,6 @@ void MainWindow::sign(F &&sign)
adjustDrops();
}

void MainWindow::removeAddress(int index)
{
if(cryptoDoc)
{
cryptoDoc->removeKey(index);
ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert());
}
}

void MainWindow::removeCryptoFile(int index)
{
if(!cryptoDoc)
Expand Down Expand Up @@ -1077,18 +1074,6 @@ void MainWindow::updateSelectorData(TokenData data)
showCardMenu(false);
}

void MainWindow::updateKeys(const QList<CKey> &keys)
{
if(!cryptoDoc)
return;

for(auto i = cryptoDoc->keys().size() - 1; i >= 0; i--)
cryptoDoc->removeKey(i);
for(const auto &key: keys)
cryptoDoc->addKey(key);
ui->cryptoContainerPage->update(cryptoDoc, qApp->signer()->tokenauth().cert());
}

void MainWindow::containerSummary()
{
#ifdef Q_OS_WIN
Expand Down
2 changes: 0 additions & 2 deletions client/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ private Q_SLOTS:
void pinPukChange( QSmartCardData::PinType type );
void resetCryptoDoc(CryptoDoc *doc = nullptr);
void resetDigiDoc(DigiDoc *doc = nullptr, bool warnOnChange = true);
void removeAddress(int index);
void removeCryptoFile(int index);
bool removeFile(DocumentModel *model, int index);
void removeSignature(int index);
Expand All @@ -102,7 +101,6 @@ private Q_SLOTS:
void showPinBlockedWarning(const QSmartCardData& t);
void updateSelector();
void updateSelectorData(TokenData data);
void updateKeys(const QList<CKey> &keys);
void updateMyEID(const TokenData &t);
void updateMyEid(const QSmartCardData &data);
bool wrap(const QString& wrappedFile, bool enclose);
Expand Down
3 changes: 2 additions & 1 deletion client/common_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@ enum Actions {
EncryptContainer,
DecryptContainer,
DecryptToken,
ClearCryptoWarning,

SignatureAdd,
SignatureMobile,
SignatureSmartID,
SignatureToken,
SignatureExtend,
ClearSignatureWarning,
ClearCryptoWarning,
};

enum ItemType {
Expand Down
7 changes: 5 additions & 2 deletions client/dialogs/SignatureDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,18 @@ SignatureDialog::SignatureDialog(const DigiDocSignature &signature, QWidget *par
}
addItem(t, tr("Signed file count"), QString::number(s.container()->documentModel()->rowCount()));
addItem(t, QStringLiteral("SPUri"), QUrl(s.spuri()));
addTime(t, tr("Archive Timestamp"), s.tsaTime());
addCert(t, tr("Archive TS Certificate"), tr("Archive TS Certificate issuer"), s.tsaCert());
addTime(t, tr("Signature Timestamp"), s.tsTime());
addCert(t, tr("TS Certificate"), tr("TS Certificate issuer"), s.tsCert());
addItem(t, tr("Hash value of signature"), SslCertificate::toHex(s.messageImprint()));
addCert(t, tr("OCSP Certificate"), tr("OCSP Certificate issuer"), s.ocspCert());
addTime(t, tr("OCSP time"), s.ocspTime());
addItem(t, tr("Signing time (UTC)"), s.trustedTime());
addItem(t, tr("Claimed signing time (UTC)"), s.claimedTime());
for(const auto &[cert, time]: s.archiveTimeStamps())
{
addTime(t, tr("Archive Timestamp"), time);
addCert(t, tr("Archive TS Certificate"), tr("Archive TS Certificate issuer"), cert);
}

#ifdef Q_OS_MAC
t->setFont(Styles::font(Styles::Regular, 13));
Expand Down
12 changes: 12 additions & 0 deletions client/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,10 @@
<source>Sign</source>
<translation>Sign</translation>
</message>
<message>
<source>Extend signature(s)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CryptoDoc</name>
Expand Down Expand Up @@ -1621,6 +1625,14 @@ ID-CARD</translation>
<source>Crypto</source>
<translation>Crypto</translation>
</message>
<message>
<source>All signatures are extended in container.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Extend</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MobileDialog</name>
Expand Down
12 changes: 12 additions & 0 deletions client/translations/et.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,10 @@
<source>Sign</source>
<translation>Allkirjasta</translation>
</message>
<message>
<source>Extend signature(s)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CryptoDoc</name>
Expand Down Expand Up @@ -1621,6 +1625,14 @@ ID-KAARDIGA</translation>
<source>Crypto</source>
<translation>Krüpto</translation>
</message>
<message>
<source>All signatures are extended in container.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Extend</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MobileDialog</name>
Expand Down
12 changes: 12 additions & 0 deletions client/translations/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,10 @@
<source>Sign</source>
<translation>Подписать</translation>
</message>
<message>
<source>Extend signature(s)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CryptoDoc</name>
Expand Down Expand Up @@ -1622,6 +1626,14 @@ ID-КАРТОЙ</translation>
<source>Crypto</source>
<translation>Крипто</translation>
</message>
<message>
<source>All signatures are extended in container.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Extend</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MobileDialog</name>
Expand Down
Loading

0 comments on commit ab78e3f

Please sign in to comment.