1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: x509certificate_nssimpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmlsecurity.hxx"
49 #include <sal/config.h>
51 #include "x509certificate_nssimpl.hxx"
53 #ifndef _CERTIFICATEEXTENSION_NSSIMPL_HXX_
54 #include "certificateextension_xmlsecimpl.hxx"
58 using namespace ::com::sun::star::uno
;
59 using namespace ::com::sun::star::security
;
60 using ::rtl::OUString
;
62 using ::com::sun::star::security::XCertificate
;
63 using ::com::sun::star::util::DateTime
;
65 X509Certificate_NssImpl :: X509Certificate_NssImpl() :
70 X509Certificate_NssImpl :: ~X509Certificate_NssImpl() {
71 if( m_pCert
!= NULL
) {
72 CERT_DestroyCertificate( m_pCert
) ;
76 //Methods from XCertificate
77 sal_Int16 SAL_CALL
X509Certificate_NssImpl :: getVersion() throw ( ::com::sun::star::uno::RuntimeException
) {
78 if( m_pCert
!= NULL
) {
79 if( m_pCert
->version
.len
> 0 ) {
80 return ( char )*( m_pCert
->version
.data
) ;
88 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getSerialNumber() throw ( ::com::sun::star::uno::RuntimeException
) {
89 if( m_pCert
!= NULL
&& m_pCert
->serialNumber
.len
> 0 ) {
90 Sequence
< sal_Int8
> serial( m_pCert
->serialNumber
.len
) ;
91 for( unsigned int i
= 0 ; i
< m_pCert
->serialNumber
.len
; i
++ )
92 serial
[i
] = *( m_pCert
->serialNumber
.data
+ i
) ;
96 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
100 ::rtl::OUString SAL_CALL
X509Certificate_NssImpl :: getIssuerName() throw ( ::com::sun::star::uno::RuntimeException
) {
101 if( m_pCert
!= NULL
) {
102 return OUString(m_pCert
->issuerName
, PL_strlen(m_pCert
->issuerName
) , RTL_TEXTENCODING_UTF8
) ;
108 ::rtl::OUString SAL_CALL
X509Certificate_NssImpl :: getSubjectName() throw ( ::com::sun::star::uno::RuntimeException
) {
109 if( m_pCert
!= NULL
) {
110 return OUString(m_pCert
->subjectName
, PL_strlen(m_pCert
->subjectName
) , RTL_TEXTENCODING_UTF8
);
116 ::com::sun::star::util::DateTime SAL_CALL
X509Certificate_NssImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException
) {
117 if( m_pCert
!= NULL
) {
120 PRExplodedTime explTime
;
123 rv
= DER_DecodeTimeChoice( ¬Before
, &m_pCert
->validity
.notBefore
) ;
128 //Convert the time to readable local time
129 PR_ExplodeTime( notBefore
, PR_LocalTimeParameters
, &explTime
) ;
131 dateTime
.HundredthSeconds
= explTime
.tm_usec
/ 1000 ;
132 dateTime
.Seconds
= explTime
.tm_sec
;
133 dateTime
.Minutes
= explTime
.tm_min
;
134 dateTime
.Hours
= explTime
.tm_hour
;
135 dateTime
.Day
= explTime
.tm_mday
;
136 dateTime
.Month
= explTime
.tm_month
+1 ;
137 dateTime
.Year
= explTime
.tm_year
;
145 ::com::sun::star::util::DateTime SAL_CALL
X509Certificate_NssImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException
) {
146 if( m_pCert
!= NULL
) {
149 PRExplodedTime explTime
;
152 rv
= DER_DecodeTimeChoice( ¬After
, &m_pCert
->validity
.notAfter
) ;
157 //Convert the time to readable local time
158 PR_ExplodeTime( notAfter
, PR_LocalTimeParameters
, &explTime
) ;
160 dateTime
.HundredthSeconds
= explTime
.tm_usec
/ 1000 ;
161 dateTime
.Seconds
= explTime
.tm_sec
;
162 dateTime
.Minutes
= explTime
.tm_min
;
163 dateTime
.Hours
= explTime
.tm_hour
;
164 dateTime
.Day
= explTime
.tm_mday
;
165 dateTime
.Month
= explTime
.tm_month
+1 ;
166 dateTime
.Year
= explTime
.tm_year
;
174 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getIssuerUniqueID() throw ( ::com::sun::star::uno::RuntimeException
) {
175 if( m_pCert
!= NULL
&& m_pCert
->issuerID
.len
> 0 ) {
176 Sequence
< sal_Int8
> issuerUid( m_pCert
->issuerID
.len
) ;
177 for( unsigned int i
= 0 ; i
< m_pCert
->issuerID
.len
; i
++ )
178 issuerUid
[i
] = *( m_pCert
->issuerID
.data
+ i
) ;
182 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
186 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl :: getSubjectUniqueID() throw ( ::com::sun::star::uno::RuntimeException
) {
187 if( m_pCert
!= NULL
&& m_pCert
->subjectID
.len
> 0 ) {
188 Sequence
< sal_Int8
> subjectUid( m_pCert
->subjectID
.len
) ;
189 for( unsigned int i
= 0 ; i
< m_pCert
->subjectID
.len
; i
++ )
190 subjectUid
[i
] = *( m_pCert
->subjectID
.data
+ i
) ;
194 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
198 ::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
) {
199 if( m_pCert
!= NULL
&& m_pCert
->extensions
!= NULL
) {
200 CERTCertExtension
** extns
;
201 CertificateExtension_XmlSecImpl
* pExtn
;
205 for( len
= 0, extns
= m_pCert
->extensions
; *extns
!= NULL
; len
++, extns
++ ) ;
206 Sequence
< Reference
< XCertificateExtension
> > xExtns( len
) ;
208 for( extns
= m_pCert
->extensions
, len
= 0; *extns
!= NULL
; extns
++, len
++ ) {
209 pExtn
= new CertificateExtension_XmlSecImpl() ;
210 if( (*extns
)->critical
.data
== NULL
)
213 crit
= ( (*extns
)->critical
.data
[0] == 0xFF ) ? sal_True
: sal_False
;
214 pExtn
->setCertExtn( (*extns
)->value
.data
, (*extns
)->value
.len
, (*extns
)->id
.data
, (*extns
)->id
.len
, crit
) ;
216 xExtns
[len
] = pExtn
;
221 return ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::security::XCertificateExtension
> > ();
225 ::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
) {
226 if( m_pCert
!= NULL
&& m_pCert
->extensions
!= NULL
) {
227 CertificateExtension_XmlSecImpl
* pExtn
;
228 CERTCertExtension
** extns
;
232 idItem
.data
= ( unsigned char* )&oid
[0] ;
233 idItem
.len
= oid
.getLength() ;
236 for( extns
= m_pCert
->extensions
; *extns
!= NULL
; extns
++ ) {
237 if( SECITEM_CompareItem( &idItem
, &(*extns
)->id
) == SECEqual
) {
238 pExtn
= new CertificateExtension_XmlSecImpl() ;
239 if( (*extns
)->critical
.data
== NULL
)
242 crit
= ( (*extns
)->critical
.data
[0] == 0xFF ) ? sal_True
: sal_False
;
243 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 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier
.getConstArray(), 16 ) ) {
309 return sal::static_int_cast
<sal_Int64
>(reinterpret_cast<sal_uIntPtr
>(this));
314 /* XUnoTunnel extension */
315 const Sequence
< sal_Int8
>& X509Certificate_NssImpl :: getUnoTunnelId() {
316 static Sequence
< sal_Int8
>* pSeq
= 0 ;
318 ::osl::Guard
< ::osl::Mutex
> aGuard( ::osl::Mutex::getGlobalMutex() ) ;
320 static Sequence
< sal_Int8
> aSeq( 16 ) ;
321 rtl_createUuid( ( sal_uInt8
* )aSeq
.getArray() , 0 , sal_True
) ;
328 /* XUnoTunnel extension */
329 X509Certificate_NssImpl
* X509Certificate_NssImpl :: getImplementation( const Reference
< XInterface
> xObj
) {
330 Reference
< XUnoTunnel
> xUT( xObj
, UNO_QUERY
) ;
332 return reinterpret_cast<X509Certificate_NssImpl
*>(
333 sal::static_int_cast
<sal_uIntPtr
>(xUT
->getSomething( getUnoTunnelId() )));
339 ::rtl::OUString
getAlgorithmDescription(SECAlgorithmID
*aid
)
342 tag
= SECOID_GetAlgorithmTag(aid
);
344 const char *pDesc
= SECOID_FindOIDTagDescription(tag
);
346 return rtl::OUString::createFromAscii( pDesc
) ;
349 ::com::sun::star::uno::Sequence
< sal_Int8
> getThumbprint(CERTCertificate
*pCert
, SECOidTag id
)
353 unsigned char fingerprint
[20];
354 //char *fpStr = NULL;
356 int length
= ((id
== SEC_OID_MD5
)?MD5_LENGTH
:SHA1_LENGTH
);
358 memset(fingerprint
, 0, sizeof fingerprint
);
359 PK11_HashBuf(id
, fingerprint
, pCert
->derCert
.data
, pCert
->derCert
.len
);
360 fpItem
.data
= fingerprint
;
362 //fpStr = CERT_Hexify(&fpItem, 1);
364 Sequence
< sal_Int8
> thumbprint( length
) ;
365 for( int i
= 0 ; i
< length
; i
++ )
367 thumbprint
[i
] = fingerprint
[i
];
375 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
379 ::rtl::OUString SAL_CALL
X509Certificate_NssImpl::getSubjectPublicKeyAlgorithm()
380 throw ( ::com::sun::star::uno::RuntimeException
)
382 if( m_pCert
!= NULL
)
384 return getAlgorithmDescription(&(m_pCert
->subjectPublicKeyInfo
.algorithm
));
392 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getSubjectPublicKeyValue()
393 throw ( ::com::sun::star::uno::RuntimeException
)
395 if( m_pCert
!= NULL
)
397 SECItem spk
= m_pCert
->subjectPublicKeyInfo
.subjectPublicKey
;
398 DER_ConvertBitString(&spk
);
402 Sequence
< sal_Int8
> key( spk
.len
) ;
403 for( unsigned int i
= 0 ; i
< spk
.len
; i
++ )
405 key
[i
] = *( spk
.data
+ i
) ;
412 return ::com::sun::star::uno::Sequence
< sal_Int8
>();
415 ::rtl::OUString SAL_CALL
X509Certificate_NssImpl::getSignatureAlgorithm()
416 throw ( ::com::sun::star::uno::RuntimeException
)
418 if( m_pCert
!= NULL
)
420 return getAlgorithmDescription(&(m_pCert
->signature
));
428 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getSHA1Thumbprint()
429 throw ( ::com::sun::star::uno::RuntimeException
)
431 return getThumbprint(m_pCert
, SEC_OID_SHA1
);
434 ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
X509Certificate_NssImpl::getMD5Thumbprint()
435 throw ( ::com::sun::star::uno::RuntimeException
)
437 return getThumbprint(m_pCert
, SEC_OID_MD5
);
440 sal_Int32 SAL_CALL
X509Certificate_NssImpl::getCertificateUsage( )
441 throw ( ::com::sun::star::uno::RuntimeException
)
447 rv
= CERT_FindKeyUsageExtension(m_pCert
, &tmpitem
);
448 if ( rv
== SECSuccess
)
450 usage
= tmpitem
.data
[0];
451 PORT_Free(tmpitem
.data
);
460 * to make the nss implementation compatible with MSCrypto,
461 * the following usage is ignored
464 if ( CERT_GovtApprovedBitSet(m_pCert) )
466 usage |= KU_NS_GOVT_APPROVED;