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