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