bump product version to 4.1.6.2
[LibreOffice.git] / xmlsecurity / source / xmlsec / nss / x509certificate_nssimpl.cxx
blob72d4831cbf6a908c1448abd534eb164523acdadd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
21 #include "nspr.h"
22 #include "nss.h"
23 #include "secder.h"
25 #include "hasht.h"
26 #include "secoid.h"
27 #include "pk11func.h"
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() :
45 m_pCert( NULL )
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 ) ;
60 } else
61 return 0 ;
62 } else {
63 return -1 ;
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 ) ;
73 return serial ;
74 } else {
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) ;
82 } else {
83 return OUString() ;
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);
90 } else {
91 return OUString() ;
95 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_NssImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException) {
96 if( m_pCert != NULL ) {
97 SECStatus rv ;
98 PRTime notBefore ;
99 PRExplodedTime explTime ;
100 DateTime dateTime ;
102 rv = DER_DecodeTimeChoice( &notBefore, &m_pCert->validity.notBefore ) ;
103 if( rv ) {
104 return DateTime() ;
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 );
118 return dateTime ;
119 } else {
120 return DateTime() ;
124 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_NssImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException) {
125 if( m_pCert != NULL ) {
126 SECStatus rv ;
127 PRTime notAfter ;
128 PRExplodedTime explTime ;
129 DateTime dateTime ;
131 rv = DER_DecodeTimeChoice( &notAfter, &m_pCert->validity.notAfter ) ;
132 if( rv ) {
133 return DateTime() ;
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 );
147 return dateTime ;
148 } else {
149 return DateTime() ;
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 ) ;
159 return issuerUid ;
160 } else {
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 ) ;
171 return subjectUid ;
172 } else {
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 ;
181 sal_Bool crit ;
182 int len ;
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
192 OString objID;
193 OString oid("OID.");
194 if (oidString.match(oid))
195 objID = oidString.copy(oid.getLength());
196 else
197 objID = oidString;
199 if ( objID.equals("2.5.29.17") )
200 pExtn = (CertificateExtension_XmlSecImpl*) new SanExtensionImpl() ;
201 else
202 pExtn = new CertificateExtension_XmlSecImpl() ;
204 if( (*extns)->critical.data == NULL )
205 crit = sal_False ;
206 else
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 ;
213 return xExtns ;
214 } else {
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 ;
223 SECItem idItem ;
224 sal_Bool crit ;
226 idItem.data = ( unsigned char* )&oid[0] ;
227 idItem.len = oid.getLength() ;
229 pExtn = NULL ;
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() ;
236 else
237 pExtn = new CertificateExtension_XmlSecImpl() ;
238 if( (*extns)->critical.data == NULL )
239 crit = sal_False ;
240 else
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 ) ;
243 break;
247 return pExtn ;
248 } else {
249 return NULL ;
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 ) ;
261 return rawCert ;
262 } else {
263 return ::com::sun::star::uno::Sequence< sal_Int8 >();
267 //Helper methods
268 void X509Certificate_NssImpl :: setCert( CERTCertificate* cert ) {
269 if( m_pCert != NULL ) {
270 CERT_DestroyCertificate( m_pCert ) ;
271 m_pCert = NULL ;
274 if( cert != NULL ) {
275 m_pCert = CERT_DupCertificate( cert ) ;
279 const CERTCertificate* X509Certificate_NssImpl :: getNssCert() const {
280 if( m_pCert != NULL ) {
281 return m_pCert ;
282 } else {
283 return NULL ;
287 void X509Certificate_NssImpl :: setRawCert( Sequence< sal_Int8 > rawCert ) throw ( ::com::sun::star::uno::RuntimeException) {
288 CERTCertificate* cert ;
289 SECItem certItem ;
291 certItem.data = ( unsigned char* )&rawCert[0] ;
292 certItem.len = rawCert.getLength() ;
294 cert = CERT_DecodeDERCertificate( &certItem, PR_TRUE, NULL ) ;
295 if( cert == NULL )
296 throw RuntimeException() ;
298 if( m_pCert != NULL ) {
299 CERT_DestroyCertificate( m_pCert ) ;
300 m_pCert = NULL ;
303 m_pCert = cert ;
306 /* XUnoTunnel */
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));
311 return 0 ;
314 /* XUnoTunnel extension */
316 namespace
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)
327 SECOidTag tag;
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)
337 if( pCert != NULL )
339 SECStatus rv;
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);
345 if(rv == SECSuccess)
347 Sequence< sal_Int8 > thumbprint( length ) ;
348 for( int i = 0 ; i < length ; i ++ )
349 thumbprint[i] = fingerprint[i];
351 return thumbprint;
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));
364 else
366 return OUString() ;
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);
378 if ( spk.len>0)
380 Sequence< sal_Int8 > key( spk.len ) ;
381 for( unsigned int i = 0 ; i < spk.len ; i ++ )
383 key[i] = *( spk.data + i ) ;
386 return key ;
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));
400 else
402 return OUString() ;
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)
421 SECStatus rv;
422 SECItem tmpitem;
423 sal_Int32 usage;
425 rv = CERT_FindKeyUsageExtension(m_pCert, &tmpitem);
426 if ( rv == SECSuccess )
428 usage = tmpitem.data[0];
429 PORT_Free(tmpitem.data);
430 tmpitem.data = NULL;
432 else
434 usage = KU_ALL;
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;
448 return usage;
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */