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