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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "nssrenam.h" // rename problematic symbols
29 #include <sal/config.h>
30 #include <comphelper/servicehelper.hxx>
31 #include "x509certificate_nssimpl.hxx"
33 #include "certificateextension_xmlsecimpl.hxx"
35 #include "sanextension_nssimpl.hxx"
36 #include <tools/time.hxx>
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::security
;
41 using ::com::sun::star::security::XCertificate
;
42 using ::com::sun::star::util::DateTime
;
44 X509Certificate_NssImpl :: X509Certificate_NssImpl() :
49 X509Certificate_NssImpl :: ~X509Certificate_NssImpl() {
50 if( m_pCert
!= NULL
) {
51 CERT_DestroyCertificate( m_pCert
) ;
55 //Methods from XCertificate
56 sal_Int16 SAL_CALL
X509Certificate_NssImpl :: getVersion() throw ( ::com::sun::star::uno::RuntimeException
) {
57 if( m_pCert
!= NULL
) {
58 if( m_pCert
->version
.len
> 0 ) {
59 return ( char )*( m_pCert
->version
.data
) ;
67 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getSerialNumber() throw ( ::com::sun::star::uno::RuntimeException
) {
68 if( m_pCert
!= NULL
&& m_pCert
->serialNumber
.len
> 0 ) {
69 Sequence
< sal_Int8
> serial( m_pCert
->serialNumber
.len
) ;
70 for( unsigned int i
= 0 ; i
< m_pCert
->serialNumber
.len
; i
++ )
71 serial
[i
] = *( m_pCert
->serialNumber
.data
+ i
) ;
75 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
79 OUString SAL_CALL
X509Certificate_NssImpl :: getIssuerName() throw ( ::com::sun::star::uno::RuntimeException
) {
80 if( m_pCert
!= NULL
) {
81 return OUString(m_pCert
->issuerName
, PL_strlen(m_pCert
->issuerName
) , RTL_TEXTENCODING_UTF8
) ;
87 OUString SAL_CALL
X509Certificate_NssImpl :: getSubjectName() throw ( ::com::sun::star::uno::RuntimeException
) {
88 if( m_pCert
!= NULL
) {
89 return OUString(m_pCert
->subjectName
, PL_strlen(m_pCert
->subjectName
) , RTL_TEXTENCODING_UTF8
);
95 ::com::sun::star::util::DateTime SAL_CALL
X509Certificate_NssImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException
) {
96 if( m_pCert
!= NULL
) {
99 PRExplodedTime explTime
;
102 rv
= DER_DecodeTimeChoice( ¬Before
, &m_pCert
->validity
.notBefore
) ;
107 //Convert the time to readable local time
108 PR_ExplodeTime( notBefore
, PR_LocalTimeParameters
, &explTime
) ;
110 dateTime
.NanoSeconds
= static_cast< sal_Int32
>( explTime
.tm_usec
* ::Time::nanoPerMicro
);
111 dateTime
.Seconds
= static_cast< sal_Int16
>( explTime
.tm_sec
);
112 dateTime
.Minutes
= static_cast< sal_Int16
>( explTime
.tm_min
);
113 dateTime
.Hours
= static_cast< sal_Int16
>( explTime
.tm_hour
);
114 dateTime
.Day
= static_cast< sal_Int16
>( explTime
.tm_mday
);
115 dateTime
.Month
= static_cast< sal_Int16
>( explTime
.tm_month
+1 );
116 dateTime
.Year
= static_cast< sal_Int16
>( explTime
.tm_year
);
124 ::com::sun::star::util::DateTime SAL_CALL
X509Certificate_NssImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException
) {
125 if( m_pCert
!= NULL
) {
128 PRExplodedTime explTime
;
131 rv
= DER_DecodeTimeChoice( ¬After
, &m_pCert
->validity
.notAfter
) ;
136 //Convert the time to readable local time
137 PR_ExplodeTime( notAfter
, PR_LocalTimeParameters
, &explTime
) ;
139 dateTime
.NanoSeconds
= static_cast< sal_Int16
>( explTime
.tm_usec
* ::Time::nanoPerMicro
);
140 dateTime
.Seconds
= static_cast< sal_Int16
>( explTime
.tm_sec
);
141 dateTime
.Minutes
= static_cast< sal_Int16
>( explTime
.tm_min
);
142 dateTime
.Hours
= static_cast< sal_Int16
>( explTime
.tm_hour
);
143 dateTime
.Day
= static_cast< sal_Int16
>( explTime
.tm_mday
);
144 dateTime
.Month
= static_cast< sal_Int16
>( explTime
.tm_month
+1 );
145 dateTime
.Year
= static_cast< sal_Int16
>( explTime
.tm_year
);
153 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getIssuerUniqueID() throw ( ::com::sun::star::uno::RuntimeException
) {
154 if( m_pCert
!= NULL
&& m_pCert
->issuerID
.len
> 0 ) {
155 Sequence
< sal_Int8
> issuerUid( m_pCert
->issuerID
.len
) ;
156 for( unsigned int i
= 0 ; i
< m_pCert
->issuerID
.len
; i
++ )
157 issuerUid
[i
] = *( m_pCert
->issuerID
.data
+ i
) ;
161 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
165 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getSubjectUniqueID() throw ( ::com::sun::star::uno::RuntimeException
) {
166 if( m_pCert
!= NULL
&& m_pCert
->subjectID
.len
> 0 ) {
167 Sequence
< sal_Int8
> subjectUid( m_pCert
->subjectID
.len
) ;
168 for( unsigned int i
= 0 ; i
< m_pCert
->subjectID
.len
; i
++ )
169 subjectUid
[i
] = *( m_pCert
->subjectID
.data
+ i
) ;
173 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
177 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::security::XCertificateExtension
> > SAL_CALL
X509Certificate_NssImpl :: getExtensions() throw ( ::com::sun::star::uno::RuntimeException
) {
178 if( m_pCert
!= NULL
&& m_pCert
->extensions
!= NULL
) {
179 CERTCertExtension
** extns
;
180 CertificateExtension_XmlSecImpl
* pExtn
;
184 for( len
= 0, extns
= m_pCert
->extensions
; *extns
!= NULL
; len
++, extns
++ ) ;
185 Sequence
< Reference
< XCertificateExtension
> > xExtns( len
) ;
187 for( extns
= m_pCert
->extensions
, len
= 0; *extns
!= NULL
; extns
++, len
++ ) {
188 const SECItem id
= (*extns
)->id
;
189 OString
oidString(CERT_GetOidString(&id
));
191 // remove "OID." prefix if existing
194 if (oidString
.match(oid
))
195 objID
= oidString
.copy(oid
.getLength());
199 if ( objID
.equals("2.5.29.17") )
200 pExtn
= (CertificateExtension_XmlSecImpl
*) new SanExtensionImpl() ;
202 pExtn
= new CertificateExtension_XmlSecImpl() ;
204 if( (*extns
)->critical
.data
== NULL
)
207 crit
= ( (*extns
)->critical
.data
[0] == 0xFF ) ? sal_True
: sal_False
;
208 pExtn
->setCertExtn( (*extns
)->value
.data
, (*extns
)->value
.len
, (unsigned char*)objID
.getStr(), objID
.getLength(), crit
) ;
210 xExtns
[len
] = pExtn
;
215 return ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::security::XCertificateExtension
> > ();
219 ::com::sun::star::uno::Reference
< ::com::sun::star::security::XCertificateExtension
> SAL_CALL
X509Certificate_NssImpl :: findCertificateExtension( const ::com::sun::star::uno::Sequence
< sal_Int8
>& oid
) throw (::com::sun::star::uno::RuntimeException
) {
220 if( m_pCert
!= NULL
&& m_pCert
->extensions
!= NULL
) {
221 CertificateExtension_XmlSecImpl
* pExtn
;
222 CERTCertExtension
** extns
;
226 idItem
.data
= ( unsigned char* )&oid
[0] ;
227 idItem
.len
= oid
.getLength() ;
230 for( extns
= m_pCert
->extensions
; *extns
!= NULL
; extns
++ ) {
231 if( SECITEM_CompareItem( &idItem
, &(*extns
)->id
) == SECEqual
) {
232 const SECItem id
= (*extns
)->id
;
233 OString
objId(CERT_GetOidString(&id
));
234 if ( objId
.equals("OID.2.5.29.17") )
235 pExtn
= (CertificateExtension_XmlSecImpl
*) new SanExtensionImpl() ;
237 pExtn
= new CertificateExtension_XmlSecImpl() ;
238 if( (*extns
)->critical
.data
== NULL
)
241 crit
= ( (*extns
)->critical
.data
[0] == 0xFF ) ? sal_True
: sal_False
;
242 pExtn
->setCertExtn( (*extns
)->value
.data
, (*extns
)->value
.len
, (*extns
)->id
.data
, (*extns
)->id
.len
, crit
) ;
254 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getEncoded() throw ( ::com::sun::star::uno::RuntimeException
) {
255 if( m_pCert
!= NULL
&& m_pCert
->derCert
.len
> 0 ) {
256 Sequence
< sal_Int8
> rawCert( m_pCert
->derCert
.len
) ;
258 for( unsigned int i
= 0 ; i
< m_pCert
->derCert
.len
; i
++ )
259 rawCert
[i
] = *( m_pCert
->derCert
.data
+ i
) ;
263 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
268 void X509Certificate_NssImpl :: setCert( CERTCertificate
* cert
) {
269 if( m_pCert
!= NULL
) {
270 CERT_DestroyCertificate( m_pCert
) ;
275 m_pCert
= CERT_DupCertificate( cert
) ;
279 const CERTCertificate
* X509Certificate_NssImpl :: getNssCert() const {
280 if( m_pCert
!= NULL
) {
287 void X509Certificate_NssImpl :: setRawCert( Sequence
< sal_Int8
> rawCert
) throw ( ::com::sun::star::uno::RuntimeException
) {
288 CERTCertificate
* cert
;
291 certItem
.data
= ( unsigned char* )&rawCert
[0] ;
292 certItem
.len
= rawCert
.getLength() ;
294 cert
= CERT_DecodeDERCertificate( &certItem
, PR_TRUE
, NULL
) ;
296 throw RuntimeException() ;
298 if( m_pCert
!= NULL
) {
299 CERT_DestroyCertificate( m_pCert
) ;
307 sal_Int64 SAL_CALL
X509Certificate_NssImpl :: getSomething( const Sequence
< sal_Int8
>& aIdentifier
) throw( RuntimeException
) {
308 if( aIdentifier
.getLength() == 16 && 0 == memcmp( getUnoTunnelId().getConstArray(), aIdentifier
.getConstArray(), 16 ) ) {
309 return sal::static_int_cast
<sal_Int64
>(reinterpret_cast<sal_uIntPtr
>(this));
314 /* XUnoTunnel extension */
318 class theX509Certificate_NssImplUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theX509Certificate_NssImplUnoTunnelId
> {};
321 const Sequence
< sal_Int8
>& X509Certificate_NssImpl :: getUnoTunnelId() {
322 return theX509Certificate_NssImplUnoTunnelId::get().getSeq();
325 OUString
getAlgorithmDescription(SECAlgorithmID
*aid
)
328 tag
= SECOID_GetAlgorithmTag(aid
);
330 const char *pDesc
= SECOID_FindOIDTagDescription(tag
);
332 return OUString::createFromAscii( pDesc
) ;
335 ::com::sun::star::uno::Sequence
< sal_Int8
> getThumbprint(CERTCertificate
*pCert
, SECOidTag id
)
340 unsigned char fingerprint
[20];
341 int length
= ((id
== SEC_OID_MD5
)?MD5_LENGTH
:SHA1_LENGTH
);
343 memset(fingerprint
, 0, sizeof fingerprint
);
344 rv
= PK11_HashBuf(id
, fingerprint
, pCert
->derCert
.data
, pCert
->derCert
.len
);
347 Sequence
< sal_Int8
> thumbprint( length
) ;
348 for( int i
= 0 ; i
< length
; i
++ )
349 thumbprint
[i
] = fingerprint
[i
];
354 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
357 OUString SAL_CALL
X509Certificate_NssImpl::getSubjectPublicKeyAlgorithm()
358 throw ( ::com::sun::star::uno::RuntimeException
)
360 if( m_pCert
!= NULL
)
362 return getAlgorithmDescription(&(m_pCert
->subjectPublicKeyInfo
.algorithm
));
370 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getSubjectPublicKeyValue()
371 throw ( ::com::sun::star::uno::RuntimeException
)
373 if( m_pCert
!= NULL
)
375 SECItem spk
= m_pCert
->subjectPublicKeyInfo
.subjectPublicKey
;
376 DER_ConvertBitString(&spk
);
380 Sequence
< sal_Int8
> key( spk
.len
) ;
381 for( unsigned int i
= 0 ; i
< spk
.len
; i
++ )
383 key
[i
] = *( spk
.data
+ i
) ;
390 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
393 OUString SAL_CALL
X509Certificate_NssImpl::getSignatureAlgorithm()
394 throw ( ::com::sun::star::uno::RuntimeException
)
396 if( m_pCert
!= NULL
)
398 return getAlgorithmDescription(&(m_pCert
->signature
));
406 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getSHA1Thumbprint()
407 throw ( ::com::sun::star::uno::RuntimeException
)
409 return getThumbprint(m_pCert
, SEC_OID_SHA1
);
412 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getMD5Thumbprint()
413 throw ( ::com::sun::star::uno::RuntimeException
)
415 return getThumbprint(m_pCert
, SEC_OID_MD5
);
418 sal_Int32 SAL_CALL
X509Certificate_NssImpl::getCertificateUsage( )
419 throw ( ::com::sun::star::uno::RuntimeException
)
425 rv
= CERT_FindKeyUsageExtension(m_pCert
, &tmpitem
);
426 if ( rv
== SECSuccess
)
428 usage
= tmpitem
.data
[0];
429 PORT_Free(tmpitem
.data
);
438 * to make the nss implementation compatible with MSCrypto,
439 * the following usage is ignored
442 if ( CERT_GovtApprovedBitSet(m_pCert) )
444 usage |= KU_NS_GOVT_APPROVED;
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */