27#include <osl/diagnose.h>
34#include <rtl/ustrbuf.hxx>
38#include <com/sun/star/task/InteractionHandler.hpp>
41#include <osl/thread.h>
50#include <com/sun/star/security/NoPasswordException.hpp>
51#include <com/sun/star/security/CertificateCharacters.hpp>
52#include <com/sun/star/security/CertificateValidity.hpp>
54namespace csss = ::com::sun::star::security;
60using ::com::sun::star::security::XCertificate ;
64template <>
struct default_delete<PRArenaPool>
66 void operator()(PRArenaPool* ptr) { PORT_FreeArena(ptr, PR_FALSE); }
75struct UsageDescription
77 SECCertificateUsage usage;
78 char const* description;
81 : usage( certificateUsageCheckAllUsages )
82 , description( nullptr )
85 UsageDescription( SECCertificateUsage i_usage,
char const* i_description )
87 , description( i_description )
95 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
96 uno::Reference < task::XInteractionHandler2 > xInteractionHandler(
97 task::InteractionHandler::createWithParent(xContext,
nullptr) );
99 task::PasswordRequestMode
eMode = bRetry ? task::PasswordRequestMode_PASSWORD_REENTER : task::PasswordRequestMode_PASSWORD_ENTER;
103 xInteractionHandler->handle( pPasswordRequest );
105 if ( pPasswordRequest->isPassword() )
108 pPasswordRequest->getPassword(),
109 osl_getThreadTextEncoding()));
110 sal_Int32 nLen = aPassword.getLength();
111 char* pPassword =
static_cast<char*
>(PORT_Alloc( nLen+1 ) );
113 memcpy( pPassword, aPassword.getStr(), nLen );
120m_pHandler( nullptr ) {
126 PK11_SetPasswordFunc(
nullptr ) ;
134 PK11_FreeSymKey( symKey ) ;
139 return "com.sun.star.xml.crypto.SecurityEnvironment";
149 Sequence<OUString> seqServiceNames{
"com.sun.star.xml.crypto.SecurityEnvironment" };
150 return seqServiceNames;
158 buff.appendAscii(PK11_GetTokenName(slot));
161 return buff.makeStringAndClear();
166 PK11_ReferenceSlot(aSlot);
176 if( aSymKey ==
nullptr )
return;
183 PK11SymKey* symkey = PK11_ReferenceSymKey( aSymKey ) ;
184 if( symkey ==
nullptr )
190 PK11_FreeSymKey( symkey ) ;
197 std::scoped_lock guard(
m_mutex);
202 PK11SlotList * slotList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE,
nullptr ) ;
203 if( slotList ==
nullptr )
206 for (PK11SlotListElement* slotEle = slotList->head ; slotEle !=
nullptr; slotEle = slotEle->next)
208 PK11SlotInfo * pSlot = slotEle->slot ;
213 "xmlsecurity.xmlsec",
214 "Found a slot: SlotName=" << PK11_GetSlotName(pSlot)
215 <<
", TokenName=" << PK11_GetTokenName(pSlot));
227 PK11SymKey * pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC,
nullptr, 128,
nullptr ) ;
236 if (pSymKey !=
nullptr)
239 PK11_FreeSymKey( pSymKey ) ;
246 PK11_FreeSlotList(slotList);
249Sequence< Reference < XCertificate > >
252 std::vector< rtl::Reference<X509Certificate_NssImpl> > certsList ;
258 SECKEYPrivateKeyList* priKeyList ;
260 if( PK11_NeedLogin(slot ) ) {
261 SECStatus nRet = PK11_Authenticate(slot, PR_TRUE,
nullptr);
265 if( nRet != SECSuccess && PORT_GetError() != SEC_ERROR_IO) {
266 throw NoPasswordException();
270 priKeyList = PK11_ListPrivateKeysInSlot(slot) ;
271 if( priKeyList !=
nullptr )
273 for (SECKEYPrivateKeyListNode* curPri = PRIVKEY_LIST_HEAD(priKeyList);
274 !PRIVKEY_LIST_END( curPri, priKeyList ) && curPri !=
nullptr;
275 curPri = PRIVKEY_LIST_NEXT(curPri))
278 if( xcert !=
nullptr )
279 certsList.push_back( xcert ) ;
281 SECKEY_DestroyPrivateKeyList( priKeyList ) ;
287 if( certsList.size() != 0 ) {
288 return comphelper::containerToSequence<Reference< XCertificate >>(certsList) ;
291 return Sequence< Reference < XCertificate > > ();
300 CERTIssuerAndSN issuerAndSN ;
301 CERTCertificate* cert ;
305 std::unique_ptr<PRArenaPool> arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
306 if( arena ==
nullptr )
311 chIssuer = PL_strndup( ostr.getStr(),
static_cast<int>(ostr.getLength()) ) ;
312 nmIssuer = CERT_AsciiToName( chIssuer ) ;
313 if( nmIssuer ==
nullptr ) {
314 PL_strfree( chIssuer ) ;
318 derIssuer = SEC_ASN1EncodeItem( arena.get(),
nullptr,
static_cast<void*
>(nmIssuer), SEC_ASN1_GET( CERT_NameTemplate ) ) ;
319 if( derIssuer ==
nullptr ) {
320 PL_strfree( chIssuer ) ;
321 CERT_DestroyName( nmIssuer ) ;
325 memset( &issuerAndSN, 0,
sizeof( issuerAndSN ) ) ;
327 issuerAndSN.derIssuer.data = derIssuer->data ;
328 issuerAndSN.derIssuer.len = derIssuer->len ;
330 issuerAndSN.serialNumber.data =
reinterpret_cast<unsigned char *
>(
const_cast<sal_Int8 *
>(serialNumber.getConstArray()));
331 issuerAndSN.serialNumber.len = serialNumber.getLength() ;
333 cert = CERT_FindCertByIssuerAndSN(
m_pHandler, &issuerAndSN ) ;
334 if( cert !=
nullptr ) {
338 PL_strfree( chIssuer ) ;
339 CERT_DestroyName( nmIssuer ) ;
341 CERT_DestroyCertificate( cert ) ;
351 if( xcert ==
nullptr ) {
355 const CERTCertificate* cert = xcert->
getNssCert() ;
360 int64 timeboundary = PR_Now() ;
361 CERTCertList* certChain = CERT_GetCertChainFromCert(
const_cast<CERTCertificate*
>(cert), timeboundary, certUsageAnyCA ) ;
366 std::vector<uno::Reference<security::XCertificate>> aCertChain;
368 for (CERTCertListNode* node = CERT_LIST_HEAD(certChain); !CERT_LIST_END(node, certChain); node = CERT_LIST_NEXT(node)) {
370 if( pCert ==
nullptr ) {
371 CERT_DestroyCertList( certChain ) ;
375 pCert->setCert( node->cert ) ;
377 aCertChain.push_back(pCert);
380 CERT_DestroyCertList( certChain ) ;
386 const css::uno::Sequence<sal_Int8>& raDERCertificate,
387 std::u16string_view raString)
389 auto pCertificateBytes =
reinterpret_cast<char *
>(
const_cast<sal_Int8 *
>(raDERCertificate.getConstArray()));
390 CERTCertificate* pCERTCertificate = CERT_DecodeCertFromPackage(pCertificateBytes, raDERCertificate.getLength());
392 if (!pCERTCertificate)
398 CERTCertTrust aTrust;
400 aStatus = CERT_DecodeTrustString(&aTrust, aTrustString.getStr());
402 if (aStatus != SECSuccess)
404 PRIntn
err = PR_GetError();
409 PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
414 aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE,
nullptr, PR_FALSE);
416 if (aStatus != SECSuccess)
418 PRIntn
err = PR_GetError();
423 aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust);
425 if (aStatus != SECSuccess)
427 PRIntn
err = PR_GetError();
432 PK11_FreeSlot(pSlot);
435 pX509Certificate->setCert(pCERTCertificate);
436 return pX509Certificate;
443 if (aDerCertificate.hasElements())
446 if (pX509Certificate ==
nullptr)
448 pX509Certificate->setRawCert(aDerCertificate);
450 return pX509Certificate;
460 OString oscert =
OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
461 xmlChar* chCert = xmlStrndup(
reinterpret_cast<const xmlChar*
>(oscert.getStr()),
static_cast<int>(oscert.getLength()) ) ;
463 int nRet = xmlSecBase64Decode_ex( chCert,
reinterpret_cast<xmlSecByte*
>(chCert), xmlStrlen( chCert ), &certSize ) ;
464 if (nRet < 0 || certSize == 0)
479 const Sequence< Reference< csss::XCertificate > >& intermediateCerts )
481 sal_Int32 validity = csss::CertificateValidity::INVALID;
482 const CERTCertificate* cert ;
484 SAL_INFO(
"xmlsecurity.xmlsec",
"Start verification of certificate: " << aCert->getSubjectName());
487 if( xcert ==
nullptr ) {
494 OSL_ASSERT(
m_pHandler == CERT_GetDefaultCertDB());
498 return css::security::CertificateValidity::INVALID;
501 ::std::vector<CERTCertificate*> vecTmpNSSCertificates;
504 for (
const auto& rIntermediateCert : intermediateCerts)
506 Sequence<sal_Int8> der = rIntermediateCert->getEncoded();
508 item.type = siBuffer;
509 item.data =
reinterpret_cast<unsigned char*
>(der.getArray());
510 item.len = der.getLength();
518 SAL_INFO(
"xmlsecurity.xmlsec",
"Failed to add a temporary certificate: " << rIntermediateCert->getIssuerName());
523 SAL_INFO(
"xmlsecurity.xmlsec",
"Added temporary certificate: " <<
524 (certTmp->subjectName ? certTmp->subjectName :
""));
525 vecTmpNSSCertificates.push_back(certTmp);
533 log.arena = PORT_NewArena(512);
534 log.head =
log.tail =
nullptr;
537 CERT_EnableOCSPChecking(certDb);
538 CERT_DisableOCSPDefaultResponder(certDb);
539 CERTValOutParam cvout[5];
540 CERTValInParam cvin[3];
543#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 0 )
544 cvin[ncvinCount].type = cert_pi_useAIACertFetch;
545 cvin[ncvinCount].value.scalar.b = PR_TRUE;
549 PRUint64 revFlagsLeaf[2];
550 PRUint64 revFlagsChain[2];
551 CERTRevocationFlags rev;
552 rev.leafTests.number_of_defined_methods = 2;
553 rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf;
567 rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
568 CERT_REV_M_TEST_USING_THIS_METHOD
569 | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
570 rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
571 CERT_REV_M_TEST_USING_THIS_METHOD
572 | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
573 rev.leafTests.number_of_preferred_methods = 0;
574 rev.leafTests.preferred_methods =
nullptr;
575 rev.leafTests.cert_rev_method_independent_flags =
576 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
578 rev.chainTests.number_of_defined_methods = 2;
579 rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
580 rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
581 CERT_REV_M_TEST_USING_THIS_METHOD
582 | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
583 rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
584 CERT_REV_M_TEST_USING_THIS_METHOD
585 | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
586 rev.chainTests.number_of_preferred_methods = 0;
587 rev.chainTests.preferred_methods =
nullptr;
588 rev.chainTests.cert_rev_method_independent_flags =
589 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
592 cvin[ncvinCount].type = cert_pi_revocationFlags;
593 cvin[ncvinCount].value.pointer.revocation = &rev;
599 cvin[ncvinCount].type = cert_pi_end;
601 cvout[0].type = cert_po_trustAnchor;
602 cvout[0].value.pointer.cert =
nullptr;
603 cvout[1].type = cert_po_errorLog;
604 cvout[1].value.pointer.log = &
log;
605 cvout[2].type = cert_po_end;
621 UsageDescription arUsages[5];
622 arUsages[0] = UsageDescription( certificateUsageSSLClient,
"certificateUsageSSLClient" );
623 arUsages[1] = UsageDescription( certificateUsageSSLServer,
"certificateUsageSSLServer" );
624 arUsages[2] = UsageDescription( certificateUsageSSLCA,
"certificateUsageSSLCA" );
625 arUsages[3] = UsageDescription( certificateUsageEmailSigner,
"certificateUsageEmailSigner" );
626 arUsages[4] = UsageDescription( certificateUsageEmailRecipient,
"certificateUsageEmailRecipient" );
628 int numUsages = std::size(arUsages);
629 for (
int i = 0;
i < numUsages;
i++)
631 SAL_INFO(
"xmlsecurity.xmlsec",
"Testing usage " <<
i+1 <<
632 " of " << numUsages <<
": " <<
633 arUsages[
i].description <<
634 " (0x" << std::hex <<
static_cast<int>(arUsages[
i].usage) <<
")" << std::dec);
636 status = CERT_PKIXVerifyCert(
const_cast<CERTCertificate *
>(cert), arUsages[
i].usage,
637 cvin, cvout,
nullptr);
638 if( status == SECSuccess )
640 SAL_INFO(
"xmlsecurity.xmlsec",
"CERT_PKIXVerifyCert returned SECSuccess.");
650 validity = csss::CertificateValidity::VALID;
651 SAL_INFO(
"xmlsecurity.xmlsec",
"Certificate is valid.");
652 CERTCertificate * issuerCert = cvout[0].value.pointer.cert;
655 SAL_INFO(
"xmlsecurity.xmlsec",
"Root certificate: " << issuerCert->subjectName);
656 CERT_DestroyCertificate(issuerCert);
663 PRIntn
err = PR_GetError();
669 CERTVerifyLogNode *node =
nullptr;
672 for (node =
log.head; node; node = node->next) {
674 CERT_DestroyCertificate(node->cert);
676 log.head =
log.tail =
nullptr;
679 SAL_INFO(
"xmlsecurity.xmlsec",
"Certificate is invalid.");
684 for (
auto& tmpCert : vecTmpNSSCertificates)
686 SAL_INFO(
"xmlsecurity.xmlsec",
"Destroying temporary certificate");
687 CERT_DestroyCertificate(tmpCert);
689 PORT_FreeArena(
log.arena,
true);
694 const css::uno::Reference< css::security::XCertificate >& aCert ) {
695 sal_Int32 characters ;
696 const CERTCertificate* cert ;
699 if( xcert ==
nullptr ) {
705 characters = 0x00000000 ;
708 if( SECITEM_CompareItem( &(cert->derIssuer), &(cert->derSubject) ) == SECEqual ) {
709 characters |= css::security::CertificateCharacters::SELF_SIGNED ;
711 characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ;
721 SECKEYPrivateKey* priKey =
nullptr;
723 if (cert->slot !=
nullptr)
725 priKey = PK11_FindPrivateKeyFromCert( cert->slot,
const_cast<CERTCertificate*
>(cert),
nullptr ) ;
727 if(priKey ==
nullptr)
731 priKey = PK11_FindPrivateKeyFromCert(slot,
const_cast<CERTCertificate*
>(cert),
nullptr);
736 if( priKey !=
nullptr ) {
737 characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
739 SECKEY_DestroyPrivateKey( priKey ) ;
741 characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
749 if( cert !=
nullptr ) {
751 xcert->setCert( cert ) ;
760 if( priKey !=
nullptr ) {
762 CERTCertificate* cert = PK11_GetCertFromPrivateKey( priKey ) ;
764 if( cert !=
nullptr ) {
768 CERT_DestroyCertificate( cert ) ;
782 std::unique_ptr<PK11SlotInfo*[]> sarSlots(
new PK11SlotInfo*[cSlots]);
783 PK11SlotInfo** slots = sarSlots.get();
785 for (
const auto& slot :
m_Slots)
791 xmlSecKeysMngrPtr pKeysMngr = xmlSecKeysMngrCreate();
795 if (xmlSecNssAppDefaultKeysMngrInit(pKeysMngr) < 0)
799 if (
auto pCertificate
802 SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->getPrivateKey());
805 xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey,
nullptr);
806 xmlSecKeyPtr pKey = xmlSecKeyCreate();
807 xmlSecKeySetValue(pKey, pKeyData);
808 xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey);
812 SAL_WARN(
"xmlsecurity.xmlsec",
"Can't get the private key from the certificate.");
820 if( pKeysMngr !=
nullptr ) {
821 xmlSecKeysMngrDestroy( pKeysMngr ) ;
827 PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
832 SECItem aDerPrivateKeyInfo;
833 aDerPrivateKeyInfo.data =
reinterpret_cast<unsigned char *
>(
const_cast<sal_Int8 *
>(raPrivateKey.getConstArray()));
834 aDerPrivateKeyInfo.len = raPrivateKey.getLength();
836 const unsigned int aKeyUsage = KU_ALL;
837 SECKEYPrivateKey* pPrivateKey =
nullptr;
839 bool bPermanent = PR_FALSE;
840 bool bPrivate = PR_TRUE;
842 SECStatus nStatus = PK11_ImportDERPrivateKeyInfoAndReturnKey(
843 pSlot, &aDerPrivateKeyInfo,
nullptr,
nullptr, bPermanent, bPrivate,
844 aKeyUsage, &pPrivateKey,
nullptr);
846 if (nStatus != SECSuccess)
849 PK11_FreeSlot(pSlot);
855 Sequence<sal_Int8>
const & raDERCertificate, Sequence<sal_Int8>
const & raPrivateKey)
860 return uno::Reference<security::XCertificate>();
866 uno::Sequence<sal_Int8>
const & raDERCertificate, OUString
const & raTrustString)
871extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
873 uno::XComponentContext* , uno::Sequence<uno::Any>
const& )
css::uno::Reference< css::security::XCertificate > SAL_CALL addDERCertificateToTheDatabase(css::uno::Sequence< sal_Int8 > const &raDERCertificate, OUString const &raTrustString) override
css::uno::Reference< css::security::XCertificate > SAL_CALL createDERCertificateWithPrivateKey(css::uno::Sequence< sal_Int8 > const &raDERCertificate, css::uno::Sequence< sal_Int8 > const &raPrivateKey) override
virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override
virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii(const OUString &asciiCertificate) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath(const css::uno::Reference< css::security::XCertificate > &beginCert) override
static rtl::Reference< X509Certificate_NssImpl > createX509CertificateFromDER(const css::uno::Sequence< sal_Int8 > &raDerCertificate)
static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr)
static rtl::Reference< X509Certificate_NssImpl > createAndAddCertificateFromPackage(const css::uno::Sequence< sal_Int8 > &raDerCertificate, std::u16string_view raString)
static SECKEYPrivateKey * insertPrivateKey(css::uno::Sequence< sal_Int8 > const &raPrivateKey)
void adoptSymKey(PK11SymKey *aSymKey)
virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw(const css::uno::Sequence< sal_Int8 > &rawCertificate) override
css::uno::Reference< css::security::XCertificate > m_xSigningCertificate
The last used certificate which has the private key for signing.
virtual ::sal_Int32 SAL_CALL verifyCertificate(const css::uno::Reference< css::security::XCertificate > &xCert, const css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > &intermediateCerts) override
std::vector< PK11SymKey * > m_tSymKeyList
virtual OUString SAL_CALL getImplementationName() override
SecurityEnvironment_NssImpl()
virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate(const OUString &issuerName, const css::uno::Sequence< sal_Int8 > &serialNumber) override
virtual ~SecurityEnvironment_NssImpl() override
std::vector< PK11SlotInfo * > m_Slots
void setCertDb(CERTCertDBHandle *aCertDb)
CERTCertDBHandle * m_pHandler
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
void addCryptoSlot(PK11SlotInfo *aSlot)
xmlSecKeysMngrPtr createKeysManager()
virtual ::sal_Int32 SAL_CALL getCertificateCharacters(const css::uno::Reference< css::security::XCertificate > &xCert) override
virtual OUString SAL_CALL getSecurityEnvironmentInformation() override
const CERTCertificate * getNssCert() const
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
enumrange< T >::Iterator begin(enumrange< T >)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define CERT_NewTempCertificate
const char * getCertError(PRErrorCode errNum)
void printChainFailure(CERTVerifyLog *log)
static rtl::Reference< X509Certificate_NssImpl > NssCertToXCert(CERTCertificate *cert)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_xml_crypto_SecurityEnvironment_get_implementation(uno::XComponentContext *, uno::Sequence< uno::Any > const &)
static char * GetPasswordFunction(PK11SlotInfo *pSlot, PRBool bRetry, void *)
static rtl::Reference< X509Certificate_NssImpl > NssPrivKeyToXCert(SECKEYPrivateKey *)
void operator()(PRArenaPool *ptr)