xref: /trunk/main/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 
31 
32 
33 #include "nssrenam.h"
34 #include "nspr.h"
35 #include "nss.h"
36 #include "secder.h"
37 
38 //MM : added by MM
39 #include "hasht.h"
40 #include "secoid.h"
41 #include "pk11func.h"
42 //MM : end
43 
44 
45 
46 #include <sal/config.h>
47 #include <rtl/uuid.h>
48 #include "x509certificate_nssimpl.hxx"
49 
50 #ifndef _CERTIFICATEEXTENSION_NSSIMPL_HXX_
51 #include "certificateextension_xmlsecimpl.hxx"
52 #endif
53 
54 #ifndef _SANEXTENSION_NSSIMPL_HXX_
55 #include "sanextension_nssimpl.hxx"
56 #endif
57 
58 using namespace ::com::sun::star::uno ;
59 using namespace ::com::sun::star::security ;
60 using ::rtl::OUString ;
61 
62 using ::com::sun::star::security::XCertificate ;
63 using ::com::sun::star::util::DateTime ;
64 
65 X509Certificate_NssImpl :: X509Certificate_NssImpl() :
66     m_pCert( NULL )
67 {
68 }
69 
70 X509Certificate_NssImpl :: ~X509Certificate_NssImpl() {
71     if( m_pCert != NULL ) {
72         CERT_DestroyCertificate( m_pCert ) ;
73     }
74 }
75 
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 ) ;
81         } else
82             return 0 ;
83     } else {
84         return -1 ;
85     }
86 }
87 
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 ) ;
93 
94         return serial ;
95     } else {
96         return ::com::sun::star::uno::Sequence< sal_Int8 >();
97     }
98 }
99 
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) ;
103     } else {
104         return OUString() ;
105     }
106 }
107 
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);
111     } else {
112         return OUString() ;
113     }
114 }
115 
116 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_NssImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException) {
117     if( m_pCert != NULL ) {
118         SECStatus rv ;
119         PRTime notBefore ;
120         PRExplodedTime explTime ;
121         DateTime dateTime ;
122 
123         rv = DER_DecodeTimeChoice( &notBefore, &m_pCert->validity.notBefore ) ;
124         if( rv ) {
125             return DateTime() ;
126         }
127 
128         //Convert the time to readable local time
129         PR_ExplodeTime( notBefore, PR_LocalTimeParameters, &explTime ) ;
130 
131         dateTime.HundredthSeconds = static_cast< sal_Int16 >( explTime.tm_usec / 1000  );
132         dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec  );
133         dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min  );
134         dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour  );
135         dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday  );
136         dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1  );
137         dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year  );
138 
139         return dateTime ;
140     } else {
141         return DateTime() ;
142     }
143 }
144 
145 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_NssImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException) {
146     if( m_pCert != NULL ) {
147         SECStatus rv ;
148         PRTime notAfter ;
149         PRExplodedTime explTime ;
150         DateTime dateTime ;
151 
152         rv = DER_DecodeTimeChoice( &notAfter, &m_pCert->validity.notAfter ) ;
153         if( rv ) {
154             return DateTime() ;
155         }
156 
157         //Convert the time to readable local time
158         PR_ExplodeTime( notAfter, PR_LocalTimeParameters, &explTime ) ;
159 
160         dateTime.HundredthSeconds = static_cast< sal_Int16 >( explTime.tm_usec / 1000  );
161         dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec  );
162         dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min  );
163         dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour  );
164         dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday  );
165         dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1  );
166         dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year  );
167 
168         return dateTime ;
169     } else {
170         return DateTime() ;
171     }
172 }
173 
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 ) ;
179 
180         return issuerUid ;
181     } else {
182         return ::com::sun::star::uno::Sequence< sal_Int8 >();
183     }
184 }
185 
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 ) ;
191 
192         return subjectUid ;
193     } else {
194         return ::com::sun::star::uno::Sequence< sal_Int8 >();
195     }
196 }
197 
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 ;
202         sal_Bool crit ;
203         int len ;
204 
205         for( len = 0, extns = m_pCert->extensions; *extns != NULL; len ++, extns ++ ) ;
206         Sequence< Reference< XCertificateExtension > > xExtns( len ) ;
207 
208         for( extns = m_pCert->extensions, len = 0; *extns != NULL; extns ++, len ++ ) {
209             const SECItem id = (*extns)->id;
210             ::rtl::OString oidString(CERT_GetOidString(&id));
211 
212             // remove "OID." prefix if existing
213             ::rtl::OString objID;
214             ::rtl::OString oid("OID.");
215             if (oidString.match(oid))
216                 objID = oidString.copy(oid.getLength());
217             else
218                 objID = oidString;
219 
220             if ( objID.equals("2.5.29.17") )
221                 pExtn = (CertificateExtension_XmlSecImpl*) new SanExtensionImpl() ;
222             else
223                 pExtn = new CertificateExtension_XmlSecImpl() ;
224 
225             if( (*extns)->critical.data == NULL )
226                 crit = sal_False ;
227             else
228                 crit = ( (*extns)->critical.data[0] == 0xFF ) ? sal_True : sal_False ;
229             pExtn->setCertExtn( (*extns)->value.data, (*extns)->value.len, (unsigned char*)objID.getStr(), objID.getLength(), crit ) ;
230 
231             xExtns[len] = pExtn ;
232         }
233 
234         return xExtns ;
235     } else {
236         return ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificateExtension > > ();
237     }
238 }
239 
240 ::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) {
241     if( m_pCert != NULL && m_pCert->extensions != NULL ) {
242         CertificateExtension_XmlSecImpl* pExtn ;
243         CERTCertExtension** extns ;
244         SECItem idItem ;
245         sal_Bool crit ;
246 
247         idItem.data = ( unsigned char* )&oid[0] ;
248         idItem.len = oid.getLength() ;
249 
250         pExtn = NULL ;
251         for( extns = m_pCert->extensions; *extns != NULL; extns ++ ) {
252             if( SECITEM_CompareItem( &idItem, &(*extns)->id ) == SECEqual ) {
253                 const SECItem id = (*extns)->id;
254                 ::rtl::OString objId(CERT_GetOidString(&id));
255                 if ( objId.equals("OID.2.5.29.17") )
256                     pExtn = (CertificateExtension_XmlSecImpl*) new SanExtensionImpl() ;
257                 else
258                     pExtn = new CertificateExtension_XmlSecImpl() ;
259                 if( (*extns)->critical.data == NULL )
260                     crit = sal_False ;
261                 else
262                     crit = ( (*extns)->critical.data[0] == 0xFF ) ? sal_True : sal_False ;
263                 pExtn->setCertExtn( (*extns)->value.data, (*extns)->value.len, (*extns)->id.data, (*extns)->id.len, crit ) ;
264             }
265         }
266 
267         return pExtn ;
268     } else {
269         return NULL ;
270     }
271 }
272 
273 
274 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl :: getEncoded() throw ( ::com::sun::star::uno::RuntimeException) {
275     if( m_pCert != NULL && m_pCert->derCert.len > 0 ) {
276         Sequence< sal_Int8 > rawCert( m_pCert->derCert.len ) ;
277 
278         for( unsigned int i = 0 ; i < m_pCert->derCert.len ; i ++ )
279             rawCert[i] = *( m_pCert->derCert.data + i ) ;
280 
281         return rawCert ;
282     } else {
283         return ::com::sun::star::uno::Sequence< sal_Int8 >();
284     }
285 }
286 
287 //Helper methods
288 void X509Certificate_NssImpl :: setCert( CERTCertificate* cert ) {
289     if( m_pCert != NULL ) {
290         CERT_DestroyCertificate( m_pCert ) ;
291         m_pCert = NULL ;
292     }
293 
294     if( cert != NULL ) {
295         m_pCert = CERT_DupCertificate( cert ) ;
296     }
297 }
298 
299 const CERTCertificate* X509Certificate_NssImpl :: getNssCert() const {
300     if( m_pCert != NULL ) {
301         return m_pCert ;
302     } else {
303         return NULL ;
304     }
305 }
306 
307 void X509Certificate_NssImpl :: setRawCert( Sequence< sal_Int8 > rawCert ) throw ( ::com::sun::star::uno::RuntimeException) {
308     CERTCertificate* cert ;
309     SECItem certItem ;
310 
311     certItem.data = ( unsigned char* )&rawCert[0] ;
312     certItem.len = rawCert.getLength() ;
313 
314     cert = CERT_DecodeDERCertificate( &certItem, PR_TRUE, NULL ) ;
315     if( cert == NULL )
316         throw RuntimeException() ;
317 
318     if( m_pCert != NULL ) {
319         CERT_DestroyCertificate( m_pCert ) ;
320         m_pCert = NULL ;
321     }
322 
323     m_pCert = cert ;
324 }
325 
326 /* XUnoTunnel */
327 sal_Int64 SAL_CALL X509Certificate_NssImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw( RuntimeException ) {
328     if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) {
329         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this));
330     }
331     return 0 ;
332 }
333 
334 /* XUnoTunnel extension */
335 const Sequence< sal_Int8>& X509Certificate_NssImpl :: getUnoTunnelId() {
336     static Sequence< sal_Int8 >* pSeq = 0 ;
337     if( !pSeq ) {
338         ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
339         if( !pSeq ) {
340             static Sequence< sal_Int8> aSeq( 16 ) ;
341             rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ;
342             pSeq = &aSeq ;
343         }
344     }
345     return *pSeq ;
346 }
347 
348 /* XUnoTunnel extension */
349 X509Certificate_NssImpl* X509Certificate_NssImpl :: getImplementation( const Reference< XInterface > xObj ) {
350     Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ;
351     if( xUT.is() ) {
352         return reinterpret_cast<X509Certificate_NssImpl*>(
353             sal::static_int_cast<sal_uIntPtr>(xUT->getSomething( getUnoTunnelId() )));
354     } else
355         return NULL ;
356 }
357 
358 // MM : added by MM
359 ::rtl::OUString getAlgorithmDescription(SECAlgorithmID *aid)
360 {
361     SECOidTag tag;
362     tag = SECOID_GetAlgorithmTag(aid);
363 
364     const char *pDesc = SECOID_FindOIDTagDescription(tag);
365 
366     return rtl::OUString::createFromAscii( pDesc ) ;
367 }
368 
369 ::com::sun::star::uno::Sequence< sal_Int8 > getThumbprint(CERTCertificate *pCert, SECOidTag id)
370 {
371     if( pCert != NULL )
372     {
373         unsigned char fingerprint[20];
374         //char *fpStr = NULL;
375         SECItem fpItem;
376         int length = ((id == SEC_OID_MD5)?MD5_LENGTH:SHA1_LENGTH);
377 
378         memset(fingerprint, 0, sizeof fingerprint);
379         PK11_HashBuf(id, fingerprint, pCert->derCert.data, pCert->derCert.len);
380         fpItem.data = fingerprint;
381         fpItem.len = length;
382         //fpStr = CERT_Hexify(&fpItem, 1);
383 
384         Sequence< sal_Int8 > thumbprint( length ) ;
385         for( int i = 0 ; i < length ; i ++ )
386         {
387             thumbprint[i] = fingerprint[i];
388         }
389 
390         //PORT_Free(fpStr);
391         return thumbprint;
392     }
393     else
394     {
395         return ::com::sun::star::uno::Sequence< sal_Int8 >();
396     }
397 }
398 
399 ::rtl::OUString SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyAlgorithm()
400     throw ( ::com::sun::star::uno::RuntimeException)
401 {
402     if( m_pCert != NULL )
403     {
404         return getAlgorithmDescription(&(m_pCert->subjectPublicKeyInfo.algorithm));
405     }
406     else
407     {
408         return OUString() ;
409     }
410 }
411 
412 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyValue()
413     throw ( ::com::sun::star::uno::RuntimeException)
414 {
415     if( m_pCert != NULL )
416     {
417         SECItem spk = m_pCert->subjectPublicKeyInfo.subjectPublicKey;
418         DER_ConvertBitString(&spk);
419 
420         if ( spk.len>0)
421         {
422             Sequence< sal_Int8 > key( spk.len ) ;
423             for( unsigned int i = 0 ; i < spk.len ; i ++ )
424             {
425                 key[i] = *( spk.data + i ) ;
426             }
427 
428             return key ;
429         }
430     }
431 
432     return ::com::sun::star::uno::Sequence< sal_Int8 >();
433 }
434 
435 ::rtl::OUString SAL_CALL X509Certificate_NssImpl::getSignatureAlgorithm()
436     throw ( ::com::sun::star::uno::RuntimeException)
437 {
438     if( m_pCert != NULL )
439     {
440         return getAlgorithmDescription(&(m_pCert->signature));
441     }
442     else
443     {
444         return OUString() ;
445     }
446 }
447 
448 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSHA1Thumbprint()
449     throw ( ::com::sun::star::uno::RuntimeException)
450 {
451     return getThumbprint(m_pCert, SEC_OID_SHA1);
452 }
453 
454 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getMD5Thumbprint()
455     throw ( ::com::sun::star::uno::RuntimeException)
456 {
457     return getThumbprint(m_pCert, SEC_OID_MD5);
458 }
459 
460 sal_Int32 SAL_CALL X509Certificate_NssImpl::getCertificateUsage(  )
461     throw ( ::com::sun::star::uno::RuntimeException)
462 {
463     SECStatus rv;
464     SECItem tmpitem;
465     sal_Int32 usage;
466 
467     rv = CERT_FindKeyUsageExtension(m_pCert, &tmpitem);
468     if ( rv == SECSuccess )
469     {
470         usage = tmpitem.data[0];
471         PORT_Free(tmpitem.data);
472         tmpitem.data = NULL;
473     }
474     else
475     {
476         usage = KU_ALL;
477     }
478 
479     /*
480      * to make the nss implementation compatible with MSCrypto,
481      * the following usage is ignored
482      *
483      *
484     if ( CERT_GovtApprovedBitSet(m_pCert) )
485     {
486         usage |= KU_NS_GOVT_APPROVED;
487     }
488     */
489 
490     return usage;
491 }
492 
493 // MM : end
494 
495