xref: /trunk/main/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.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 #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