merged tag ooo/OOO330_m14
[LibreOffice.git] / xmlsecurity / source / xmlsec / mscrypt / x509certificate_mscryptimpl.cxx
blobd5928b027075fcd7722301338a0a3e47d5f460da
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
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"
35 //MM : added by MM
36 #include "oid.hxx"
37 //MM : end
39 //CP : added by CP
40 #include <rtl/locale.h>
41 #include <osl/nlsupport.h>
42 #include <osl/process.h>
43 #include <utility>
45 //CP : end
47 using namespace ::com::sun::star::uno ;
48 using namespace ::com::sun::star::security ;
49 using ::rtl::OUString ;
51 using ::com::sun::star::security::XCertificate ;
52 using ::com::sun::star::util::DateTime ;
54 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
56 /*Resturns the index withing rRawString where sTypeName starts and where it ends.
57 The starting index is pair.first. The ending index in pair.second points
58 one char after the last character of the type.
59 sTypeName can be
60 "S" or "CN" (without ""). Do not use spaces at the beginning of the type name.
61 If the type name is not found then pair.first and pair.second are -1.
63 std::pair< sal_Int32, sal_Int32 >
64 findTypeInDN(const OUString& rRawString, const OUString& sTypeName)
66 std::pair< sal_Int32, sal_Int32 > retVal;
67 bool bInEscape = false;
68 bool bInValue = false;
69 bool bFound = false;
70 sal_Int32 nTypeNameStart = 0;
71 sal_Int32 length = rRawString.getLength();
73 for (sal_Int32 i = 0; i < length; i++)
75 sal_Unicode c = rRawString[i];
77 if (c == '=')
79 if (! bInValue)
81 OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
82 sType = sType.trim();
83 if (sType.equalsIgnoreAsciiCase(sTypeName))
85 bFound = true;
86 break;
90 else if (c == '"')
92 if (!bInEscape)
94 //If this is the quote is the first of the couple which enclose the
95 //whole value, because the value contains special characters
96 //then we just drop it. That is, this character must be followed by
97 //a character which is not '"'.
98 if ( i + 1 < length && rRawString[i+1] == '"')
99 bInEscape = true;
100 else
101 bInValue = !bInValue; //value is enclosed in " "
103 else
105 //This quote is escaped by a preceding quote and therefore is
106 //part of the value
107 bInEscape = false;
110 else if (c == ',' || c == '+')
112 //The comma separate the attribute value pairs.
113 //If the comma is not part of a value (the value would then be enclosed in '"'),
114 //then we have reached the end of the value
115 if (!bInValue)
117 //The next char is the start of the new type
118 nTypeNameStart = i + 1;
123 //Found the Type Name, but there can still be spaces after the last comma
124 //and the beginning of the type.
125 if (bFound)
127 while (true)
129 sal_Unicode c = rRawString[nTypeNameStart];
130 if (c != ' ' && c != '\t')
131 //found
132 break;
133 nTypeNameStart ++;
135 // search end (one after last letter)
136 sal_Int32 nTypeNameEnd = nTypeNameStart;
137 nTypeNameEnd++;
138 while (true)
140 sal_Unicode c = rRawString[nTypeNameEnd];
141 if (c == ' ' || c == '\t' || c == '=')
142 break;
143 nTypeNameEnd++;
145 retVal = std::make_pair(nTypeNameStart, nTypeNameEnd);
147 else
149 retVal = std::make_pair(-1, -1);
151 return retVal;
156 MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise
157 it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary
158 anymore, because we provide always the signers certificate when signing. So libmlsec can find
159 the private key based on the provided certificate (X509Certificate element) and does not need
160 the issuer name (X509IssuerName element). The issuer name in the xml signature has also no
161 effect for the signature nor the certificate validation.
162 In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain
163 strings for type names. Instead it uses OIDs.
166 OUString replaceTagSWithTagST(OUString oldDN)
168 std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, OUSTR("S"));
170 if (pairIndex.first != -1)
172 OUString newDN = oldDN.copy(0, pairIndex.first);
173 newDN += OUSTR("ST");
174 newDN += oldDN.copy(pairIndex.second);
175 return newDN;
177 return oldDN;
179 /* end */
181 X509Certificate_MSCryptImpl :: X509Certificate_MSCryptImpl() :
182 m_pCertContext( NULL )
186 X509Certificate_MSCryptImpl :: ~X509Certificate_MSCryptImpl() {
187 if( m_pCertContext != NULL ) {
188 CertFreeCertificateContext( m_pCertContext ) ;
192 //Methods from XCertificate
193 sal_Int16 SAL_CALL X509Certificate_MSCryptImpl :: getVersion() throw ( ::com::sun::star::uno::RuntimeException) {
194 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
195 return ( char )m_pCertContext->pCertInfo->dwVersion ;
196 } else {
197 return -1 ;
201 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getSerialNumber() throw ( ::com::sun::star::uno::RuntimeException) {
202 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
203 Sequence< sal_Int8 > serial( m_pCertContext->pCertInfo->SerialNumber.cbData ) ;
204 for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ )
205 serial[i] = *( m_pCertContext->pCertInfo->SerialNumber.pbData + m_pCertContext->pCertInfo->SerialNumber.cbData - i - 1 ) ;
207 return serial ;
208 } else {
209 return NULL ;
213 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl :: getIssuerName() throw ( ::com::sun::star::uno::RuntimeException) {
214 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
215 char* issuer ;
216 DWORD cbIssuer ;
218 cbIssuer = CertNameToStr(
219 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
220 &( m_pCertContext->pCertInfo->Issuer ),
221 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
222 NULL, 0
225 // Here the cbIssuer count the last 0x00 , take care.
226 if( cbIssuer != 0 ) {
227 issuer = new char[ cbIssuer ] ;
228 if( issuer == NULL )
229 throw RuntimeException() ;
231 cbIssuer = CertNameToStr(
232 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
233 &( m_pCertContext->pCertInfo->Issuer ),
234 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
235 issuer, cbIssuer
238 if( cbIssuer <= 0 ) {
239 delete [] issuer ;
240 throw RuntimeException() ;
243 // By CP , for correct encoding
244 sal_uInt16 encoding ;
245 rtl_Locale *pLocale = NULL ;
246 osl_getProcessLocale( &pLocale ) ;
247 encoding = osl_getTextEncodingFromLocale( pLocale ) ;
248 // CP end
250 if(issuer[cbIssuer-1] == 0) cbIssuer--; //delimit the last 0x00;
251 OUString xIssuer(issuer , cbIssuer ,encoding ) ; //By CP
252 delete [] issuer ;
254 return replaceTagSWithTagST(xIssuer);
255 } else {
256 return OUString() ;
258 } else {
259 return OUString() ;
263 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl :: getSubjectName() throw ( ::com::sun::star::uno::RuntimeException)
265 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
267 wchar_t* subject ;
268 DWORD cbSubject ;
270 cbSubject = CertNameToStrW(
271 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
272 &( m_pCertContext->pCertInfo->Subject ),
273 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
274 NULL, 0
277 if( cbSubject != 0 )
279 subject = new wchar_t[ cbSubject ] ;
280 if( subject == NULL )
281 throw RuntimeException() ;
283 cbSubject = CertNameToStrW(
284 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
285 &( m_pCertContext->pCertInfo->Subject ),
286 CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
287 subject, cbSubject
290 if( cbSubject <= 0 ) {
291 delete [] subject ;
292 throw RuntimeException() ;
295 OUString xSubject(reinterpret_cast<const sal_Unicode*>(subject));
296 delete [] subject ;
298 return replaceTagSWithTagST(xSubject);
299 } else
301 return OUString() ;
304 else
306 return OUString() ;
310 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_MSCryptImpl :: getNotValidBefore() throw ( ::com::sun::star::uno::RuntimeException ) {
311 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
312 SYSTEMTIME explTime ;
313 DateTime dateTime ;
314 FILETIME localFileTime;
316 if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotBefore ), &localFileTime))
318 if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
319 //Convert the time to readable local time
320 dateTime.HundredthSeconds = explTime.wMilliseconds / 100 ;
321 dateTime.Seconds = explTime.wSecond ;
322 dateTime.Minutes = explTime.wMinute ;
323 dateTime.Hours = explTime.wHour ;
324 dateTime.Day = explTime.wDay ;
325 dateTime.Month = explTime.wMonth ;
326 dateTime.Year = explTime.wYear ;
330 return dateTime ;
331 } else {
332 return DateTime() ;
336 ::com::sun::star::util::DateTime SAL_CALL X509Certificate_MSCryptImpl :: getNotValidAfter() throw ( ::com::sun::star::uno::RuntimeException) {
337 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
338 SYSTEMTIME explTime ;
339 DateTime dateTime ;
340 FILETIME localFileTime;
342 if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotAfter ), &localFileTime))
344 if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
345 //Convert the time to readable local time
346 dateTime.HundredthSeconds = explTime.wMilliseconds / 100 ;
347 dateTime.Seconds = explTime.wSecond ;
348 dateTime.Minutes = explTime.wMinute ;
349 dateTime.Hours = explTime.wHour ;
350 dateTime.Day = explTime.wDay ;
351 dateTime.Month = explTime.wMonth ;
352 dateTime.Year = explTime.wYear ;
356 return dateTime ;
357 } else {
358 return DateTime() ;
362 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getIssuerUniqueID() throw ( ::com::sun::star::uno::RuntimeException) {
363 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
364 Sequence< sal_Int8 > issuerUid( m_pCertContext->pCertInfo->IssuerUniqueId.cbData ) ;
365 for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ )
366 issuerUid[i] = *( m_pCertContext->pCertInfo->IssuerUniqueId.pbData + i ) ;
368 return issuerUid ;
369 } else {
370 return NULL ;
374 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getSubjectUniqueID() throw ( ::com::sun::star::uno::RuntimeException ) {
375 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL ) {
376 Sequence< sal_Int8 > subjectUid( m_pCertContext->pCertInfo->SubjectUniqueId.cbData ) ;
377 for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ )
378 subjectUid[i] = *( m_pCertContext->pCertInfo->SubjectUniqueId.pbData + i ) ;
380 return subjectUid ;
381 } else {
382 return NULL ;
386 ::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 ) {
387 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 ) {
388 CertificateExtension_XmlSecImpl* xExtn ;
389 CERT_EXTENSION* pExtn ;
390 Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
392 for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
393 pExtn = &(m_pCertContext->pCertInfo->rgExtension[i]) ;
395 xExtn = new CertificateExtension_XmlSecImpl() ;
396 if( xExtn == NULL )
397 throw RuntimeException() ;
399 xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, ( unsigned char* )pExtn->pszObjId, strlen( pExtn->pszObjId ), sal::static_int_cast<sal_Bool>(pExtn->fCritical) ) ;
401 xExtns[i] = xExtn ;
404 return xExtns ;
405 } else {
406 return NULL ;
410 ::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) {
411 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 ) {
412 CertificateExtension_XmlSecImpl* xExtn ;
413 CERT_EXTENSION* pExtn ;
414 Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
416 xExtn = NULL ;
417 for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
418 pExtn = &( m_pCertContext->pCertInfo->rgExtension[i] ) ;
420 //TODO: Compare the oid
421 if( 0 ) {
422 xExtn = new CertificateExtension_XmlSecImpl() ;
423 if( xExtn == NULL )
424 throw RuntimeException() ;
426 xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, ( unsigned char* )pExtn->pszObjId, strlen( pExtn->pszObjId ), sal::static_int_cast<sal_Bool>(pExtn->fCritical) ) ;
430 return xExtn ;
431 } else {
432 return NULL ;
437 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl :: getEncoded() throw ( ::com::sun::star::uno::RuntimeException) {
438 if( m_pCertContext != NULL && m_pCertContext->cbCertEncoded > 0 ) {
439 Sequence< sal_Int8 > rawCert( m_pCertContext->cbCertEncoded ) ;
441 for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ )
442 rawCert[i] = *( m_pCertContext->pbCertEncoded + i ) ;
444 return rawCert ;
445 } else {
446 return NULL ;
450 //Helper methods
451 void X509Certificate_MSCryptImpl :: setMswcryCert( const CERT_CONTEXT* cert ) {
452 if( m_pCertContext != NULL ) {
453 CertFreeCertificateContext( m_pCertContext ) ;
454 m_pCertContext = NULL ;
457 if( cert != NULL ) {
458 m_pCertContext = CertDuplicateCertificateContext( cert ) ;
462 const CERT_CONTEXT* X509Certificate_MSCryptImpl :: getMswcryCert() const {
463 if( m_pCertContext != NULL ) {
464 return m_pCertContext ;
465 } else {
466 return NULL ;
470 void X509Certificate_MSCryptImpl :: setRawCert( Sequence< sal_Int8 > rawCert ) throw ( ::com::sun::star::uno::RuntimeException) {
471 if( m_pCertContext != NULL ) {
472 CertFreeCertificateContext( m_pCertContext ) ;
473 m_pCertContext = NULL ;
476 if( rawCert.getLength() != 0 ) {
477 m_pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING, ( const BYTE* )&rawCert[0], rawCert.getLength() ) ;
481 /* XUnoTunnel */
482 sal_Int64 SAL_CALL X509Certificate_MSCryptImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw( RuntimeException ) {
483 if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) {
484 return ( sal_Int64 )this ;
486 return 0 ;
489 /* XUnoTunnel extension */
490 const Sequence< sal_Int8>& X509Certificate_MSCryptImpl :: getUnoTunnelId() {
491 static Sequence< sal_Int8 >* pSeq = 0 ;
492 if( !pSeq ) {
493 ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
494 if( !pSeq ) {
495 static Sequence< sal_Int8> aSeq( 16 ) ;
496 rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ;
497 pSeq = &aSeq ;
500 return *pSeq ;
503 /* XUnoTunnel extension */
504 X509Certificate_MSCryptImpl* X509Certificate_MSCryptImpl :: getImplementation( const Reference< XInterface > xObj ) {
505 Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ;
506 if( xUT.is() ) {
507 return ( X509Certificate_MSCryptImpl* )xUT->getSomething( getUnoTunnelId() ) ;
508 } else
509 return NULL ;
512 // MM : added by MM
513 ::rtl::OUString findOIDDescription(char *oid)
515 OUString ouOID = OUString::createFromAscii( oid );
516 for (int i=0; i<nOID; i++)
518 OUString item = OUString::createFromAscii( OIDs[i].oid );
519 if (ouOID == item)
521 return OUString::createFromAscii( OIDs[i].desc );
525 return OUString() ;
528 ::com::sun::star::uno::Sequence< sal_Int8 > getThumbprint(const CERT_CONTEXT* pCertContext, DWORD dwPropId)
530 if( pCertContext != NULL )
532 DWORD cbData = 20;
533 unsigned char fingerprint[20];
534 if (CertGetCertificateContextProperty(pCertContext, dwPropId, (void*)fingerprint, &cbData))
536 Sequence< sal_Int8 > thumbprint( cbData ) ;
537 for( unsigned int i = 0 ; i < cbData ; i ++ )
539 thumbprint[i] = fingerprint[i];
542 return thumbprint;
544 else
546 DWORD e = GetLastError();
547 cbData = e;
551 return NULL;
554 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyAlgorithm()
555 throw ( ::com::sun::star::uno::RuntimeException)
557 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
559 CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
560 return findOIDDescription( algorithm.pszObjId ) ;
562 else
564 return OUString() ;
568 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyValue()
569 throw ( ::com::sun::star::uno::RuntimeException)
571 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
573 CRYPT_BIT_BLOB publicKey = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;
575 Sequence< sal_Int8 > key( publicKey.cbData ) ;
576 for( unsigned int i = 0 ; i < publicKey.cbData ; i++ )
578 key[i] = *(publicKey.pbData + i) ;
581 return key;
583 else
585 return NULL ;
589 ::rtl::OUString SAL_CALL X509Certificate_MSCryptImpl::getSignatureAlgorithm()
590 throw ( ::com::sun::star::uno::RuntimeException)
592 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL )
594 CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SignatureAlgorithm;
595 return findOIDDescription( algorithm.pszObjId ) ;
597 else
599 return OUString() ;
603 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint()
604 throw ( ::com::sun::star::uno::RuntimeException)
606 return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID);
609 ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumbprint()
610 throw ( ::com::sun::star::uno::RuntimeException)
612 return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID);
615 sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage( )
616 throw ( ::com::sun::star::uno::RuntimeException)
618 sal_Int32 usage =
619 CERT_DATA_ENCIPHERMENT_KEY_USAGE |
620 CERT_DIGITAL_SIGNATURE_KEY_USAGE |
621 CERT_KEY_AGREEMENT_KEY_USAGE |
622 CERT_KEY_CERT_SIGN_KEY_USAGE |
623 CERT_KEY_ENCIPHERMENT_KEY_USAGE |
624 CERT_NON_REPUDIATION_KEY_USAGE |
625 CERT_OFFLINE_CRL_SIGN_KEY_USAGE;
627 if( m_pCertContext != NULL && m_pCertContext->pCertInfo != NULL && m_pCertContext->pCertInfo->cExtension != 0 )
629 CERT_EXTENSION* pExtn = CertFindExtension(
630 szOID_KEY_USAGE,
631 m_pCertContext->pCertInfo->cExtension,
632 m_pCertContext->pCertInfo->rgExtension);
634 if (pExtn != NULL)
636 CERT_KEY_USAGE_RESTRICTION_INFO keyUsage;
637 DWORD length = sizeof(CERT_KEY_USAGE_RESTRICTION_INFO);
639 bool rc = CryptDecodeObject(
640 X509_ASN_ENCODING,
641 X509_KEY_USAGE,
642 pExtn->Value.pbData,
643 pExtn->Value.cbData,
644 CRYPT_DECODE_NOCOPY_FLAG,
645 (void *)&keyUsage,
646 &length);
648 if (rc && keyUsage.RestrictedKeyUsage.cbData!=0)
650 usage = (sal_Int32)keyUsage.RestrictedKeyUsage.pbData;
655 return usage;
658 // MM : end