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 63 X509Certificate_NssImpl :: X509Certificate_NssImpl() : 64 m_pCert( NULL ) 65 { 66 } 67 68 X509Certificate_NssImpl :: ~X509Certificate_NssImpl() { 69 if( m_pCert != NULL ) { 70 CERT_DestroyCertificate( m_pCert ) ; 71 } 72 } 73 74 //Methods from XCertificate 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 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 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 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 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( ¬Before, &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 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( ¬After, &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 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 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 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 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 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 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 297 const CERTCertificate* X509Certificate_NssImpl :: getNssCert() const { 298 if( m_pCert != NULL ) { 299 return m_pCert ; 300 } else { 301 return NULL ; 302 } 303 } 304 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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