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 #include <sal/config.h>
31 #include <rtl/uuid.h>
32 #include "x509certificate_mscryptimpl.hxx"
33 #include "certificateextension_xmlsecimpl.hxx"
34 #include "sanextension_mscryptimpl.hxx"
35 
36 //MM : added by MM
37 #include "oid.hxx"
38 //MM : end
39 
40 //CP : added by CP
41 #include <rtl/locale.h>
42 #include <osl/nlsupport.h>
43 #include <osl/process.h>
44 #include <utility>
45 
46 //CP : end
47 
48 using namespace ::com::sun::star::uno ;
49 using namespace ::com::sun::star::security ;
50 using ::rtl::OUString ;
51 
52 using ::com::sun::star::security::XCertificate ;
53 using ::com::sun::star::util::DateTime ;
54 
55 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
56 
57 /*Resturns the index withing rRawString where sTypeName starts and where it ends.
58     The starting index is pair.first. The ending index in pair.second points
59     one char after the last character of the type.
60     sTypeName can be
61     "S" or "CN" (without ""). Do not use spaces at the beginning of the type name.
62     If the type name is not found then pair.first and pair.second are -1.
63 */
64 std::pair< sal_Int32, sal_Int32 >
65 findTypeInDN(const OUString& rRawString, const OUString& sTypeName)
66 {
67     std::pair< sal_Int32, sal_Int32 > retVal;
68     bool bInEscape = false;
69     bool bInValue = false;
70     bool bFound = false;
71     sal_Int32 nTypeNameStart = 0;
72     sal_Int32 length = rRawString.getLength();
73 
74     for (sal_Int32 i = 0; i < length; i++)
75     {
76         sal_Unicode c = rRawString[i];
77 
78         if (c == '=')
79         {
80             if (! bInValue)
81             {
82                 OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
83                 sType = sType.trim();
84                 if (sType.equalsIgnoreAsciiCase(sTypeName))
85                 {
86                     bFound = true;
87                     break;
88                 }
89             }
90         }
91         else if (c == '"')
92         {
93             if (!bInEscape)
94             {
95                 //If this is the quote is the first of the couple which enclose the
96                 //whole value, because the value contains special characters
97                 //then we just drop it. That is, this character must be followed by
98                 //a character which is not '"'.
99                 if ( i + 1 < length && rRawString[i+1] == '"')
100                     bInEscape = true;
101                 else
102                     bInValue = !bInValue; //value is enclosed in " "
103             }
104             else
105             {
106                 //This quote is escaped by a preceding quote and therefore is
107                 //part of the value
108                 bInEscape = false;
109             }
110         }
111         else if (c == ',' || c == '+')
112         {
113             //The comma separate the attribute value pairs.
114             //If the comma is not part of a value (the value would then be enclosed in '"'),
115             //then we have reached the end of the value
116             if (!bInValue)
117             {
118                 //The next char is the start of the new type
119                 nTypeNameStart = i + 1;
120             }
121         }
122     }
123 
124     //Found the Type Name, but there can still be spaces after the last comma
125     //and the beginning of the type.
126     if (bFound)
127     {
128         while (true)
129         {
130             sal_Unicode c = rRawString[nTypeNameStart];
131             if (c != ' ' && c != '\t')
132                 //found
133                 break;
134             nTypeNameStart ++;
135         }
136         // search end (one after last letter)
137         sal_Int32 nTypeNameEnd = nTypeNameStart;
138         nTypeNameEnd++;
139         while (true)
140         {
141              sal_Unicode c = rRawString[nTypeNameEnd];
142              if (c == ' ' || c == '\t' || c == '=')
143                  break;
144              nTypeNameEnd++;
145         }
146         retVal = std::make_pair(nTypeNameStart, nTypeNameEnd);
147     }
148     else
149     {
150         retVal = std::make_pair(-1, -1);
151     }
152     return retVal;
153 }
154 
155 
156 /*
157   MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise
158   it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary
159   anymore, because we provide always the signers certificate when signing. So libmlsec can find
160   the private key based on the provided certificate (X509Certificate element) and does not need
161   the issuer name (X509IssuerName element). The issuer name in the xml signature has also no
162   effect for the signature nor the certificate validation.
163   In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain
164   strings for type names. Instead it uses OIDs.
165  */
166 
167 OUString replaceTagSWithTagST(OUString oldDN)
168 {
169     std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, OUSTR("S"));
170 
171     if (pairIndex.first != -1)
172     {
173         OUString newDN = oldDN.copy(0, pairIndex.first);
174         newDN += OUSTR("ST");
175         newDN += oldDN.copy(pairIndex.second);
176         return newDN;
177     }
178 	return oldDN;
179 }
180 /* end */
181 
182 X509Certificate_MSCryptImpl :: X509Certificate_MSCryptImpl() :
183 	m_pCertContext( NULL )
184 {
185 }
186 
187 X509Certificate_MSCryptImpl :: ~X509Certificate_MSCryptImpl() {
188 	if( m_pCertContext != NULL ) {
189 		CertFreeCertificateContext( m_pCertContext ) ;
190 	}
191 }
192 
193 //Methods from XCertificate
194 sal_Int16 SAL_CALL X509Certificate_MSCryptImpl :: getVersion() throw ( ::com::sun::star::uno::RuntimeException) {
195 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
196 		return ( char )m_pCertContext->pCertInfo->dwVersion ;
197 	} else {
198 		return -1 ;
199 	}
200 }
201 
202 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getSerialNumber() throw ( ::com::sun::star::uno::RuntimeException) {
203 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
204 		Sequence< sal_Int8 > serial( m_pCertContext->pCertInfo->SerialNumber.cbData ) ;
205 		for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ )
206 			serial[i] = *( m_pCertContext->pCertInfo->SerialNumber.pbData + m_pCertContext->pCertInfo->SerialNumber.cbData - i - 1 ) ;
207 
208 		return serial ;
209 	} else {
210 		return Sequence< sal_Int8 >();
211 	}
212 }
213 
214 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl :: getIssuerName() throw ( ::com::sun::star::uno::RuntimeException) {
215 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
216 		char* issuer ;
217 		DWORD cbIssuer ;
218 
219 		cbIssuer = CertNameToStr(
220 			X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
221 			&( m_pCertContext->pCertInfo->Issuer ),
222 			CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
223 			NULL, 0
224 		) ;
225 
226 		// Here the cbIssuer count the last 0x00 , take care.
227 		if( cbIssuer != 0 ) {
228 			issuer = new char[ cbIssuer ] ;
229 			if( issuer == NULL )
230 				throw RuntimeException() ;
231 
232 			cbIssuer = CertNameToStr(
233 				X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
234 				&( m_pCertContext->pCertInfo->Issuer ),
235 				CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
236 				issuer, cbIssuer
237 			) ;
238 
239 			if( cbIssuer <= 0 ) {
240 				delete [] issuer ;
241 				throw RuntimeException() ;
242 			}
243 
244 			// By CP , for correct encoding
245 			sal_uInt16 encoding ;
246 			rtl_Locale *pLocale = NULL ;
247 			osl_getProcessLocale( &pLocale ) ;
248 			encoding = osl_getTextEncodingFromLocale( pLocale ) ;
249 			// CP end
250 
251 			if(issuer[cbIssuer-1] == 0) cbIssuer--; //delimit the last 0x00;
252 			OUString xIssuer(issuer , cbIssuer ,encoding ) ; //By CP
253 			delete [] issuer ;
254 
255             return replaceTagSWithTagST(xIssuer);
256 		} else {
257 			return OUString() ;
258 		}
259 	} else {
260 		return OUString() ;
261 	}
262 }
263 
264 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl :: getSubjectName() throw ( ::com::sun::star::uno::RuntimeException)
265 {
266     if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
267     {
268         wchar_t* subject ;
269         DWORD cbSubject ;
270 
271         cbSubject = CertNameToStrW(
272             X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
273             &( m_pCertContext->pCertInfo->Subject ),
274             CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
275             NULL, 0
276         ) ;
277 
278         if( cbSubject != 0 )
279         {
280             subject = new wchar_t[ cbSubject ] ;
281             if( subject == NULL )
282                 throw RuntimeException() ;
283 
284             cbSubject = CertNameToStrW(
285                 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
286                 &( m_pCertContext->pCertInfo->Subject ),
287                 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
288                 subject, cbSubject
289             ) ;
290 
291             if( cbSubject <= 0 ) {
292                 delete [] subject ;
293                 throw RuntimeException() ;
294             }
295 
296             OUString xSubject(reinterpret_cast<const sal_Unicode*>(subject));
297             delete [] subject ;
298 
299             return replaceTagSWithTagST(xSubject);
300         } else
301         {
302             return OUString() ;
303         }
304     }
305     else
306     {
307         return OUString() ;
308     }
309 }
310 
311 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_MSCryptImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException ) {
312 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
313 		SYSTEMTIME explTime ;
314 		DateTime dateTime ;
315 		FILETIME localFileTime;
316 
317 		if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotBefore ), &localFileTime))
318 		{
319 			if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
320 				//Convert the time to readable local time
321 				dateTime.HundredthSeconds = explTime.wMilliseconds / 100 ;
322 				dateTime.Seconds = explTime.wSecond ;
323 				dateTime.Minutes = explTime.wMinute ;
324 				dateTime.Hours = explTime.wHour ;
325 				dateTime.Day = explTime.wDay ;
326 				dateTime.Month = explTime.wMonth ;
327 				dateTime.Year = explTime.wYear ;
328 			}
329 		}
330 
331 		return dateTime ;
332 	} else {
333 		return DateTime() ;
334 	}
335 }
336 
337 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_MSCryptImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException) {
338 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
339 		SYSTEMTIME explTime ;
340 		DateTime dateTime ;
341 		FILETIME localFileTime;
342 
343 		if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotAfter ), &localFileTime))
344 		{
345 			if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
346 				//Convert the time to readable local time
347 				dateTime.HundredthSeconds = explTime.wMilliseconds / 100 ;
348 				dateTime.Seconds = explTime.wSecond ;
349 				dateTime.Minutes = explTime.wMinute ;
350 				dateTime.Hours = explTime.wHour ;
351 				dateTime.Day = explTime.wDay ;
352 				dateTime.Month = explTime.wMonth ;
353 				dateTime.Year = explTime.wYear ;
354 			}
355 		}
356 
357 		return dateTime ;
358 	} else {
359 		return DateTime() ;
360 	}
361 }
362 
363 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getIssuerUniqueID() throw ( ::com::sun::star::uno::RuntimeException) {
364 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
365 		Sequence< sal_Int8 > issuerUid( m_pCertContext->pCertInfo->IssuerUniqueId.cbData ) ;
366 		for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ )
367 			issuerUid[i] = *( m_pCertContext->pCertInfo->IssuerUniqueId.pbData + i ) ;
368 
369 		return issuerUid ;
370 	} else {
371 		return Sequence< sal_Int8 >();
372 	}
373 }
374 
375 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getSubjectUniqueID() throw ( ::com::sun::star::uno::RuntimeException ) {
376 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
377 		Sequence< sal_Int8 > subjectUid( m_pCertContext->pCertInfo->SubjectUniqueId.cbData ) ;
378 		for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ )
379 			subjectUid[i] = *( m_pCertContext->pCertInfo->SubjectUniqueId.pbData + i ) ;
380 
381 		return subjectUid ;
382 	} else {
383 		return Sequence< sal_Int8 >();
384 	}
385 }
386 
387 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificateExtension > > SAL_CALL X509Certificate_MSCryptImpl :: getExtensions() throw ( ::com::sun::star::uno::RuntimeException ) {
388 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 ) {
389 		CertificateExtension_XmlSecImpl* xExtn ;
390 		CERT_EXTENSION* pExtn ;
391 		Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
392 
393 		for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
394 			pExtn = &(m_pCertContext->pCertInfo->rgExtension[i]) ;
395 
396 
397             ::rtl::OUString objId = ::rtl::OUString::createFromAscii( pExtn->pszObjId );
398 
399             if ( objId.equalsAscii("2.5.29.17") )
400                 xExtn = (CertificateExtension_XmlSecImpl*) new SanExtensionImpl() ;
401             else
402 			    xExtn = new CertificateExtension_XmlSecImpl() ;
403 			if( xExtn == NULL )
404 				throw RuntimeException() ;
405 
406 			xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, ( unsigned char* )pExtn->pszObjId, strlen( pExtn->pszObjId ), sal::static_int_cast<sal_Bool>(pExtn->fCritical) ) ;
407 
408 			xExtns[i] = xExtn ;
409 		}
410 
411 		return xExtns ;
412 	} else {
413 		return Sequence< Reference< XCertificateExtension > >();
414 	}
415 }
416 
417 ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificateExtension > SAL_CALL X509Certificate_MSCryptImpl :: findCertificateExtension( const ::com::sun::star::uno::Sequence< sal_Int8 >& /*oid*/ ) throw (::com::sun::star::uno::RuntimeException) {
418 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 ) {
419 		CertificateExtension_XmlSecImpl* xExtn ;
420 		CERT_EXTENSION* pExtn ;
421 		Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
422 
423 		xExtn = NULL ;
424 		for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
425 			pExtn = &( m_pCertContext->pCertInfo->rgExtension[i] ) ;
426 
427 			//TODO: Compare the oid
428 			if( 0 ) {
429 				xExtn = new CertificateExtension_XmlSecImpl() ;
430 				if( xExtn == NULL )
431 					throw RuntimeException() ;
432 
433 				xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, ( unsigned char* )pExtn->pszObjId, strlen( pExtn->pszObjId ), sal::static_int_cast<sal_Bool>(pExtn->fCritical) ) ;
434 			}
435 		}
436 
437 		return xExtn ;
438 	} else {
439 		return NULL ;
440 	}
441 }
442 
443 
444 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getEncoded() throw ( ::com::sun::star::uno::RuntimeException) {
445 	if( m_pCertContext != NULL && m_pCertContext->cbCertEncoded > 0 ) {
446 		Sequence< sal_Int8 > rawCert( m_pCertContext->cbCertEncoded ) ;
447 
448 		for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ )
449 			rawCert[i] = *( m_pCertContext->pbCertEncoded + i ) ;
450 
451 		return rawCert ;
452 	} else {
453 		return Sequence< sal_Int8 >();
454 	}
455 }
456 
457 //Helper methods
458 void X509Certificate_MSCryptImpl :: setMswcryCert( const CERT_CONTEXT* cert ) {
459 	if( m_pCertContext != NULL ) {
460 		CertFreeCertificateContext( m_pCertContext ) ;
461 		m_pCertContext = NULL ;
462 	}
463 
464 	if( cert != NULL ) {
465 		m_pCertContext = CertDuplicateCertificateContext( cert ) ;
466 	}
467 }
468 
469 const CERT_CONTEXT* X509Certificate_MSCryptImpl :: getMswcryCert() const {
470 	if( m_pCertContext != NULL ) {
471 		return m_pCertContext ;
472 	} else {
473 		return NULL ;
474 	}
475 }
476 
477 void X509Certificate_MSCryptImpl :: setRawCert( Sequence< sal_Int8 > rawCert ) throw ( ::com::sun::star::uno::RuntimeException) {
478 	if( m_pCertContext != NULL ) {
479 		CertFreeCertificateContext( m_pCertContext ) ;
480 		m_pCertContext = NULL ;
481 	}
482 
483 	if( rawCert.getLength() != 0 ) {
484 		m_pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING, ( const sal_uInt8* )&rawCert[0], rawCert.getLength() ) ;
485 	}
486 }
487 
488 /* XUnoTunnel */
489 sal_Int64 SAL_CALL X509Certificate_MSCryptImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw( RuntimeException ) {
490 	if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) {
491 		return ( sal_Int64 )this ;
492 	}
493 	return 0 ;
494 }
495 
496 /* XUnoTunnel extension */
497 const Sequence< sal_Int8>& X509Certificate_MSCryptImpl :: getUnoTunnelId() {
498 	static Sequence< sal_Int8 >* pSeq = 0 ;
499 	if( !pSeq ) {
500 		::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
501 		if( !pSeq ) {
502 			static Sequence< sal_Int8> aSeq( 16 ) ;
503 			rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ;
504 			pSeq = &aSeq ;
505 		}
506 	}
507 	return *pSeq ;
508 }
509 
510 /* XUnoTunnel extension */
511 X509Certificate_MSCryptImpl* X509Certificate_MSCryptImpl :: getImplementation( const Reference< XInterface > xObj ) {
512 	Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ;
513 	if( xUT.is() ) {
514 		return ( X509Certificate_MSCryptImpl* )xUT->getSomething( getUnoTunnelId() ) ;
515 	} else
516 		return NULL ;
517 }
518 
519 // MM : added by MM
520 ::rtl::OUString findOIDDescription(char *oid)
521 {
522 	OUString ouOID = OUString::createFromAscii( oid );
523 	for (int i=0; i<nOID; i++)
524 	{
525 		OUString item = OUString::createFromAscii( OIDs[i].oid );
526 		if (ouOID == item)
527 		{
528 			return OUString::createFromAscii( OIDs[i].desc );
529 		}
530 	}
531 
532 	return OUString() ;
533 }
534 
535 ::com::sun::star::uno::Sequence< sal_Int8 > getThumbprint(const CERT_CONTEXT* pCertContext, DWORD dwPropId)
536 {
537 	if( pCertContext != NULL )
538 	{
539 		DWORD cbData = 20;
540 		unsigned char fingerprint[20];
541 		if (CertGetCertificateContextProperty(pCertContext, dwPropId, (void*)fingerprint, &cbData))
542 		{
543 			Sequence< sal_Int8 > thumbprint( cbData ) ;
544 			for( unsigned int i = 0 ; i < cbData ; i ++ )
545 			{
546 				thumbprint[i] = fingerprint[i];
547 			}
548 
549 			return thumbprint;
550 		}
551 		else
552 		{
553 			DWORD e = GetLastError();
554 			cbData = e;
555 		}
556 	}
557 
558 	return Sequence< sal_Int8 >();
559 }
560 
561 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyAlgorithm()
562 	throw ( ::com::sun::star::uno::RuntimeException)
563 {
564 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
565 	{
566 		CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
567 		return findOIDDescription( algorithm.pszObjId ) ;
568 	}
569 	else
570 	{
571 		return OUString() ;
572 	}
573 }
574 
575 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyValue()
576 	throw ( ::com::sun::star::uno::RuntimeException)
577 {
578 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
579 	{
580 		CRYPT_BIT_BLOB publicKey = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;
581 
582 		Sequence< sal_Int8 > key( publicKey.cbData ) ;
583 		for( unsigned int i = 0 ; i < publicKey.cbData ; i++ )
584 		{
585 			key[i] = *(publicKey.pbData + i) ;
586 		}
587 
588 		return key;
589 	}
590 	else
591 	{
592 		return Sequence< sal_Int8 >();
593 	}
594 }
595 
596 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl::getSignatureAlgorithm()
597 	throw ( ::com::sun::star::uno::RuntimeException)
598 {
599 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
600 	{
601 		CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SignatureAlgorithm;
602 		return findOIDDescription( algorithm.pszObjId ) ;
603 	}
604 	else
605 	{
606 		return OUString() ;
607 	}
608 }
609 
610 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint()
611 	throw ( ::com::sun::star::uno::RuntimeException)
612 {
613 	return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID);
614 }
615 
616 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumbprint()
617 	throw ( ::com::sun::star::uno::RuntimeException)
618 {
619 	return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID);
620 }
621 
622 sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage(  )
623 	throw ( ::com::sun::star::uno::RuntimeException)
624 {
625 	sal_Int32 usage =
626 		CERT_DATA_ENCIPHERMENT_KEY_USAGE |
627 		CERT_DIGITAL_SIGNATURE_KEY_USAGE |
628 		CERT_KEY_AGREEMENT_KEY_USAGE |
629 		CERT_KEY_CERT_SIGN_KEY_USAGE |
630 		CERT_KEY_ENCIPHERMENT_KEY_USAGE |
631 		CERT_NON_REPUDIATION_KEY_USAGE |
632 		CERT_OFFLINE_CRL_SIGN_KEY_USAGE;
633 
634 	if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 )
635 	{
636 		CERT_EXTENSION* pExtn = CertFindExtension(
637 			szOID_KEY_USAGE,
638 			m_pCertContext->pCertInfo->cExtension,
639 			m_pCertContext->pCertInfo->rgExtension);
640 
641 		if (pExtn != NULL)
642 		{
643 			CERT_KEY_USAGE_RESTRICTION_INFO keyUsage;
644 			DWORD length = sizeof(CERT_KEY_USAGE_RESTRICTION_INFO);
645 
646 			bool rc = CryptDecodeObject(
647 				X509_ASN_ENCODING,
648 				X509_KEY_USAGE,
649 				pExtn->Value.pbData,
650 				pExtn->Value.cbData,
651 				CRYPT_DECODE_NOCOPY_FLAG,
652 				(void *)&keyUsage,
653 				&length);
654 
655 			if (rc && keyUsage.RestrictedKeyUsage.cbData!=0)
656 			{
657 				usage = (sal_Int32)keyUsage.RestrictedKeyUsage.pbData;
658 			}
659 		}
660 	}
661 
662 	return usage;
663 }
664 
665 // MM : end
666 
667