1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "CertificateImpl.hxx"
12 #include <comphelper/sequence.hxx>
13 #include <cppuhelper/supportsservice.hxx>
15 #include <com/sun/star/security/KeyUsage.hpp>
16 #include <officecfg/Office/Common.hxx>
17 #include <svl/sigstruct.hxx>
18 #include <svl/cryptosign.hxx>
24 using namespace css::uno
;
25 using namespace css::security
;
26 using namespace css::util
;
28 CertificateImpl::CertificateImpl()
32 CertificateImpl::~CertificateImpl()
36 //Methods from XCertificateImpl
37 sal_Int16 SAL_CALL
CertificateImpl::getVersion()
42 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSerialNumber()
44 // TODO: perhaps map to subkey's cardSerialNumber - if you have
46 return Sequence
< sal_Int8
>();
49 OUString SAL_CALL
CertificateImpl::getIssuerName()
51 const GpgME::UserID userId
= m_pKey
.userID(0);
55 return OStringToOUString(userId
.id(), RTL_TEXTENCODING_UTF8
);
58 OUString SAL_CALL
CertificateImpl::getSubjectName()
60 // Same as issuer name (user ID)
61 return getIssuerName();
65 DateTime
convertUnixTimeToDateTime(time_t time
)
68 struct tm
*timeStruct
= gmtime(&time
);
69 dateTime
.Year
= timeStruct
->tm_year
+ 1900;
70 dateTime
.Month
= timeStruct
->tm_mon
+ 1;
71 dateTime
.Day
= timeStruct
->tm_mday
;
72 dateTime
.Hours
= timeStruct
->tm_hour
;
73 dateTime
.Minutes
= timeStruct
->tm_min
;
74 dateTime
.Seconds
= timeStruct
->tm_sec
;
79 DateTime SAL_CALL
CertificateImpl::getNotValidBefore()
81 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
85 return convertUnixTimeToDateTime(m_pKey
.subkey(0).creationTime());
88 DateTime SAL_CALL
CertificateImpl::getNotValidAfter()
90 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
91 if (subkey
.isNull() || subkey
.neverExpires())
94 return convertUnixTimeToDateTime(m_pKey
.subkey(0).expirationTime());
97 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getIssuerUniqueID()
100 return Sequence
< sal_Int8
> ();
103 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSubjectUniqueID()
106 return Sequence
< sal_Int8
> ();
109 Sequence
< Reference
< XCertificateExtension
> > SAL_CALL
CertificateImpl::getExtensions()
112 return Sequence
< Reference
< XCertificateExtension
> > ();
115 Reference
< XCertificateExtension
> SAL_CALL
CertificateImpl::findCertificateExtension( const Sequence
< sal_Int8
>& /*oid*/ )
118 return Reference
< XCertificateExtension
> ();
121 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getEncoded()
123 if (m_aBits
.hasElements())
126 // lazy init: extract key data, store into m_aBits
127 GpgME::Data data_out
;
128 m_pContext
->setArmor(false); // caller will base64-encode anyway
129 GpgME::Error err
= m_pContext
->exportPublicKeys( // "exportPublicKeys" is slow!
130 m_pKey
.primaryFingerprint(),
132 officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get()
133 ? GpgME::Context::ExportMinimal
: 0
137 throw RuntimeException(u
"The GpgME library failed to retrieve the public key"_ustr
);
139 off_t result
= data_out
.seek(0,SEEK_SET
);
142 int len
=0, curr
=0; char buf
;
143 while( (curr
=data_out
.read(&buf
, 1)) )
146 // write bits to sequence of bytes
147 m_aBits
.realloc(len
);
148 result
= data_out
.seek(0,SEEK_SET
);
150 if( data_out
.read(m_aBits
.getArray(), len
) != len
)
151 throw RuntimeException(u
"The GpgME library failed to read the key"_ustr
);
153 // Export key to base64Empty for gpg
157 OUString SAL_CALL
CertificateImpl::getSubjectPublicKeyAlgorithm()
159 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
163 return OStringToOUString(subkey
.publicKeyAlgorithmAsString(), RTL_TEXTENCODING_UTF8
);
166 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSubjectPublicKeyValue()
168 return Sequence
< sal_Int8
> ();
171 OUString SAL_CALL
CertificateImpl::getSignatureAlgorithm()
173 const GpgME::UserID userId
= m_pKey
.userID(0);
177 const GpgME::UserID::Signature signature
= userId
.signature(0);
178 if (signature
.isNull())
181 return OStringToOUString(signature
.algorithmAsString(), RTL_TEXTENCODING_UTF8
);
184 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSHA1Thumbprint()
186 // This is mapped to the fingerprint for gpg
187 const char* keyId
= m_pKey
.primaryFingerprint();
189 // get hex fingerprint as byte array
190 return comphelper::containerToSequence
<sal_Int8
>(svl::crypto::DecodeHexString(keyId
));
193 Sequence
<sal_Int8
> CertificateImpl::getSHA256Thumbprint()
195 // This is mapped to the fingerprint for gpg (though that's only
197 const char* keyId
= m_pKey
.primaryFingerprint();
198 return comphelper::arrayToSequence
<sal_Int8
>(
199 keyId
, strlen(keyId
)+1);
202 svl::crypto::SignatureMethodAlgorithm
CertificateImpl::getSignatureMethodAlgorithm()
204 return svl::crypto::SignatureMethodAlgorithm::RSA
;
207 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getMD5Thumbprint()
209 // This is mapped to the shorter keyID for gpg
210 const char* keyId
= m_pKey
.keyID();
211 return comphelper::arrayToSequence
<sal_Int8
>(
212 keyId
, strlen(keyId
)+1);
215 CertificateKind SAL_CALL
CertificateImpl::getCertificateKind()
217 return CertificateKind_OPENPGP
;
220 sal_Int32 SAL_CALL
CertificateImpl::getCertificateUsage()
222 return KeyUsage::DIGITAL_SIGNATURE
| KeyUsage::NON_REPUDIATION
| KeyUsage::KEY_ENCIPHERMENT
| KeyUsage::DATA_ENCIPHERMENT
;
225 void CertificateImpl::setCertificate(const std::shared_ptr
<GpgME::Context
>& ctx
, const GpgME::Key
& key
)
231 const GpgME::Key
* CertificateImpl::getCertificate() const
237 OUString SAL_CALL
CertificateImpl::getImplementationName()
239 return u
"com.sun.star.xml.security.gpg.XCertificate_GpgImpl"_ustr
;
243 sal_Bool SAL_CALL
CertificateImpl::supportsService(const OUString
& serviceName
)
245 return cppu::supportsService(this, serviceName
);
249 Sequence
<OUString
> SAL_CALL
CertificateImpl::getSupportedServiceNames() { return { OUString() }; }
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */