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 <config_gpgme.h>
12 #include "CertificateImpl.hxx"
14 #include <comphelper/servicehelper.hxx>
15 #include <comphelper/sequence.hxx>
16 #include <cppuhelper/supportsservice.hxx>
18 #include <com/sun/star/security/KeyUsage.hpp>
19 #include <officecfg/Office/Common.hxx>
20 #include <svl/sigstruct.hxx>
26 using namespace css::uno
;
27 using namespace css::security
;
28 using namespace css::util
;
30 CertificateImpl::CertificateImpl()
34 CertificateImpl::~CertificateImpl()
38 //Methods from XCertificateImpl
39 sal_Int16 SAL_CALL
CertificateImpl::getVersion()
44 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSerialNumber()
46 // TODO: perhaps map to subkey's cardSerialNumber - if you have
48 return Sequence
< sal_Int8
>();
51 OUString SAL_CALL
CertificateImpl::getIssuerName()
53 const GpgME::UserID userId
= m_pKey
.userID(0);
57 return OStringToOUString(userId
.id(), RTL_TEXTENCODING_UTF8
);
60 OUString SAL_CALL
CertificateImpl::getSubjectName()
62 // Same as issuer name (user ID)
63 return getIssuerName();
67 DateTime
convertUnixTimeToDateTime(time_t time
)
70 struct tm
*timeStruct
= gmtime(&time
);
71 dateTime
.Year
= timeStruct
->tm_year
+ 1900;
72 dateTime
.Month
= timeStruct
->tm_mon
+ 1;
73 dateTime
.Day
= timeStruct
->tm_mday
;
74 dateTime
.Hours
= timeStruct
->tm_hour
;
75 dateTime
.Minutes
= timeStruct
->tm_min
;
76 dateTime
.Seconds
= timeStruct
->tm_sec
;
81 DateTime SAL_CALL
CertificateImpl::getNotValidBefore()
83 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
87 return convertUnixTimeToDateTime(m_pKey
.subkey(0).creationTime());
90 DateTime SAL_CALL
CertificateImpl::getNotValidAfter()
92 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
93 if (subkey
.isNull() || subkey
.neverExpires())
96 return convertUnixTimeToDateTime(m_pKey
.subkey(0).expirationTime());
99 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getIssuerUniqueID()
102 return Sequence
< sal_Int8
> ();
105 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSubjectUniqueID()
108 return Sequence
< sal_Int8
> ();
111 Sequence
< Reference
< XCertificateExtension
> > SAL_CALL
CertificateImpl::getExtensions()
114 return Sequence
< Reference
< XCertificateExtension
> > ();
117 Reference
< XCertificateExtension
> SAL_CALL
CertificateImpl::findCertificateExtension( const Sequence
< sal_Int8
>& /*oid*/ )
120 return Reference
< XCertificateExtension
> ();
123 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getEncoded()
125 // Export key to base64Empty for gpg
129 OUString SAL_CALL
CertificateImpl::getSubjectPublicKeyAlgorithm()
131 const GpgME::Subkey subkey
= m_pKey
.subkey(0);
135 return OStringToOUString(subkey
.publicKeyAlgorithmAsString(), RTL_TEXTENCODING_UTF8
);
138 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSubjectPublicKeyValue()
140 return Sequence
< sal_Int8
> ();
143 OUString SAL_CALL
CertificateImpl::getSignatureAlgorithm()
145 const GpgME::UserID userId
= m_pKey
.userID(0);
149 const GpgME::UserID::Signature signature
= userId
.signature(0);
150 if (signature
.isNull())
153 return OStringToOUString(signature
.algorithmAsString(), RTL_TEXTENCODING_UTF8
);
156 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getSHA1Thumbprint()
158 // This is mapped to the fingerprint for gpg
159 const char* keyId
= m_pKey
.primaryFingerprint();
160 return comphelper::arrayToSequence
<sal_Int8
>(
161 keyId
, strlen(keyId
)+1);
164 Sequence
<sal_Int8
> CertificateImpl::getSHA256Thumbprint()
166 // This is mapped to the fingerprint for gpg (though that's only
168 const char* keyId
= m_pKey
.primaryFingerprint();
169 return comphelper::arrayToSequence
<sal_Int8
>(
170 keyId
, strlen(keyId
)+1);
173 svl::crypto::SignatureMethodAlgorithm
CertificateImpl::getSignatureMethodAlgorithm()
175 return svl::crypto::SignatureMethodAlgorithm::RSA
;
178 Sequence
< sal_Int8
> SAL_CALL
CertificateImpl::getMD5Thumbprint()
180 // This is mapped to the shorter keyID for gpg
181 const char* keyId
= m_pKey
.keyID();
182 return comphelper::arrayToSequence
<sal_Int8
>(
183 keyId
, strlen(keyId
)+1);
186 CertificateKind SAL_CALL
CertificateImpl::getCertificateKind()
188 return CertificateKind_OPENPGP
;
191 sal_Int32 SAL_CALL
CertificateImpl::getCertificateUsage()
193 return KeyUsage::DIGITAL_SIGNATURE
| KeyUsage::NON_REPUDIATION
| KeyUsage::KEY_ENCIPHERMENT
| KeyUsage::DATA_ENCIPHERMENT
;
196 void CertificateImpl::setCertificate(GpgME::Context
* ctx
, const GpgME::Key
& key
)
200 // extract key data, store into m_aBits
201 GpgME::Data data_out
;
202 ctx
->setArmor(false); // caller will base64-encode anyway
203 GpgME::Error err
= ctx
->exportPublicKeys(
204 key
.primaryFingerprint(),
206 officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get()
207 ? GpgME::Context::ExportMinimal
: 0
211 throw RuntimeException("The GpgME library failed to retrieve the public key");
213 off_t result
= data_out
.seek(0,SEEK_SET
);
216 int len
=0, curr
=0; char buf
;
217 while( (curr
=data_out
.read(&buf
, 1)) )
220 // write bits to sequence of bytes
221 m_aBits
.realloc(len
);
222 result
= data_out
.seek(0,SEEK_SET
);
224 if( data_out
.read(m_aBits
.getArray(), len
) != len
)
225 throw RuntimeException("The GpgME library failed to read the key");
228 const GpgME::Key
* CertificateImpl::getCertificate() const
234 OUString SAL_CALL
CertificateImpl::getImplementationName()
236 return "com.sun.star.xml.security.gpg.XCertificate_GpgImpl";
240 sal_Bool SAL_CALL
CertificateImpl::supportsService(const OUString
& serviceName
)
242 return cppu::supportsService(this, serviceName
);
246 Sequence
<OUString
> SAL_CALL
CertificateImpl::getSupportedServiceNames() { return { OUString() }; }
248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */