CryptoProvider.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Base / System / Security / RightsManagement / CryptoProvider.cs / 1 / CryptoProvider.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description:  Crypto provider class which is a wrapper around unmanaged DRM SDK Bound License handle 
//   provides ability to Encryt/Decrypt protected content, and enumerate granted rights. 
//
// History: 
//  06/01/2005: IgorBel :   Initial Implementation
//
//-----------------------------------------------------------------------------
 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Security;
using System.Security.Permissions;
using System.Windows;
using System.Collections.ObjectModel; 
using MS.Internal.Security.RightsManagement;
using MS.Internal; 
using SecurityHelper=MS.Internal.WindowsBase.SecurityHelper; 

namespace System.Security.RightsManagement 
{
    /// 
    /// CryptoProvider class is built as a result of UseLicense.Bind call. This class represents a successful RightsManagement
    /// Initialization, and as a result provides Encryption/Decryption services, and exposes list of Bound Grants, which are rights 
    /// that have been given by the publisher to the user, and were properly validated (expiration checks, secure environment, and so on)
    ///  
    ///  
    ///     Critical:    This class expose access to methods that eventually do one or more of the the following
    ///             1. call into unmanaged code 
    ///             2. affects state/data that will eventually cross over unmanaged code boundary
    ///             3. Return some RM related information which is considered private
    ///
    ///     TreatAsSafe: This attrbiute automatically applied to all public entry points. All the public entry points have 
    ///     Demands for RightsManagementPermission at entry to counter the possible attacks that do
    ///     not lead to the unamanged code directly(which is protected by another Demand there) but rather leave 
    ///     some status/data behind which eventually might cross the unamanaged boundary. 
    /// 
    [SecurityCritical(SecurityCriticalScope.Everything)] 
    public class CryptoProvider : IDisposable
    {
        //-----------------------------------------------------
        // 
        //  Public Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// This method is responsible for tearing down crypto provider that was built as a result of UseLicense.Bind call.
        /// 
        ~CryptoProvider()
        { 
            Dispose(false);
        } 
 
        /// 
        /// This method is responsible for tearing down crypto provider that was built as a result of UseLicense.Bind call. 
        /// 
        public void Dispose()
        {
            SecurityHelper.DemandRightsManagementPermission(); 
            Dispose(true);
            GC.SuppressFinalize(this); 
        } 

         ///  
        /// This function encrypts clear text content.
        /// An application is expected to create a padding scheme based on the value returned from
        /// BlockSize property. BlockSize property should be used to determine the amount of extra
        /// padding to be added to the clear text. The length, in bytes, of the buffer holding content to 
        /// be encrypted should be a multiple of the block cipher block size.
        /// RMS system currently uses AES block cipher. All blocks are encrypted independently, so that 2 blocks 
        /// of identical clear text will produce identical results after encryption.  An application 
        /// is encouraged to either compress data prior to encryption or create some other scheme to mitigate
        /// threats potentially arising from independent block encryption. 
        /// 
        public byte[] Encrypt(byte[] clearText)
        {
            SecurityHelper.DemandRightsManagementPermission(); 
            CheckDisposed();
 
            if (clearText == null) 
            {
                throw new ArgumentNullException("clearText"); 
            }

            // validation of the proper size of the clearText is done by the unmanaged libraries
 
            if (!CanEncrypt)
            { 
                throw new RightsManagementException(RightsManagementFailureCode.EncryptionNotPermitted); 
            }
 
            // first get the size
            uint outputBufferSize=0;
            byte[] outputBuffer = null;
            int hr; 

#if DEBUG 
            hr= SafeNativeMethods.DRMEncrypt( 
                            EncryptorHandle,
                            0, 
                            (uint)clearText.Length,
                            clearText,
                            ref outputBufferSize,
                            null); 

            Errors.ThrowOnErrorCode(hr); 
 
            // We do not expect Decryption to change the size of the buffer; otherwise it will break
            // basic assumptions behind the encrypted compound file envelope format 
            Invariant.Assert(outputBufferSize == clearText.Length);
#else
            outputBufferSize = (uint)clearText.Length;
#endif 

            outputBuffer = new byte[outputBufferSize]; 
 
            // This will decrypt content
            hr = SafeNativeMethods.DRMEncrypt( 
                            EncryptorHandle,
                            0,
                            (uint)clearText.Length,
                            clearText, 
                            ref outputBufferSize,
                            outputBuffer); 
            Errors.ThrowOnErrorCode(hr); 

            return outputBuffer; 
        }

        /// 
        /// This function decrypts cipher text content. 
        /// The length, in bytes, of the buffer holding content to be encrypted should be a multiple of the
        /// block cipher block size. 
        ///  
        public byte[] Decrypt(byte[] cryptoText)
        { 
            SecurityHelper.DemandRightsManagementPermission();
            CheckDisposed();

            if (cryptoText == null) 
            {
                throw new ArgumentNullException("cryptoText"); 
            } 

            // validation of the proper size of the cryptoText is done by the unmanaged libraries 

            if (!CanDecrypt)
            {
                throw new RightsManagementException(RightsManagementFailureCode.RightNotGranted); 
            }
 
            // first get the size 
            uint outputBufferSize=0;
            byte[] outputBuffer = null; 
            int hr;

#if DEBUG
            hr= SafeNativeMethods.DRMDecrypt( 
                            DecryptorHandle,
                            0, 
                            (uint)cryptoText.Length, 
                            cryptoText,
                            ref outputBufferSize, 
                            null);
            Errors.ThrowOnErrorCode(hr);

            // We do not expect Decryption changing the size of the buffer; otherwise it will break 
            // basic assumptions behind the encrypted compound file envelope format
            Invariant.Assert(outputBufferSize == cryptoText.Length); 
#else 
            outputBufferSize = (uint)cryptoText.Length;
#endif 

            outputBuffer = new byte[outputBufferSize];

            // THis will decrypt content 
            hr = SafeNativeMethods.DRMDecrypt(
                            DecryptorHandle, 
                            0, 
                            (uint)cryptoText.Length,
                            cryptoText, 
                            ref outputBufferSize,
                            outputBuffer);

            Errors.ThrowOnErrorCode(hr); 
            return outputBuffer;
        } 
 
        //------------------------------------------------------
        // 
        //  Protected Methods
        //
        //-----------------------------------------------------
 
        /// 
        /// Dispose(bool) 
        ///  
        /// 
        protected virtual void Dispose(bool disposing) 
        {
            // close bound license handle which is a DRMHANDLE
            // Encryptor and Decryptor handles as well
            try 
            {
                if (disposing) 
                { 

                    if (_decryptorHandle != null && !_decryptorHandle.IsInvalid) 
                        _decryptorHandle.Close();

                    if (_encryptorHandle != null && !_encryptorHandle.IsInvalid)
                        _encryptorHandle.Close(); 

                    if (_boundLicenseOwnerViewRightsHandle != null && !_boundLicenseOwnerViewRightsHandle.IsInvalid) 
                        _boundLicenseOwnerViewRightsHandle.Close(); 

                    // dispose collection of the bound licenses that we have 
                    if (_boundLicenseHandleList != null)
                    {
                        foreach(SafeRightsManagementHandle boundLicenseHandle in _boundLicenseHandleList)
                        { 
                            if (boundLicenseHandle != null && !boundLicenseHandle.IsInvalid)
                                boundLicenseHandle.Close(); 
                        } 
                    }
                } 
            }
            finally
            {
                _disposed = true; 
                _boundLicenseHandleList = null;
                _boundLicenseOwnerViewRightsHandle = null; 
                _decryptorHandle    = null; 
                _encryptorHandle    = null;
            } 
        }

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //------------------------------------------------------ 

        ///  
        /// This is bock size of the cypther that is currently in use.
        /// 
        public int BlockSize
        { 
            get
            { 
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();
 
                if (_blockSize ==0)
                {
                    _blockSize = QueryBlockSize();
                } 
                return _blockSize;
            } 
        } 

        ///  
        /// This bollean indicates wheter Encrypt Decrypt calls can be made on buffers that are multiple of the BlockSize value.
        /// If the value is false Encrypt Decrypt calls must be made on buffers of the size that is exactly equal to the BlockSize.
        /// 
        public bool CanMergeBlocks 
        {
            get 
            { 
                SecurityHelper.DemandRightsManagementPermission();
                CheckDisposed(); 

                // convention is to return 1 for stream ciphers
                // Stream ciphers (although currently not used) return 1.
                // Block ciphers return size of the block that is always greater than 1. 
                // Comparing block size to 1 is a conventional way to differentiate stream and
                // block ciphers. Block Ciphers can accept data chunks (for both encryption and decryption) 
                // that fall on the block boundary and are a multiple of the block cipher block size. 
                return (BlockSize > 1);
            } 
        }

        /// 
        /// This is a read only property. It enable client application to enumerate list of rights that were 
        /// granted to the user, and also passed all the verification checks.
        ///  
        public ReadOnlyCollection BoundGrants 
        {
            get 
            {
                SecurityHelper.DemandRightsManagementPermission();
                CheckDisposed();
 
                if (_boundGrantReadOnlyCollection == null)
                { 
                    // we need to enumerate all the rights and keep the ones that we can translate into enum 
                    // we ignore the rights that we can not translate for forward compatibility reasons
                    List grantList = new List(_boundRightsInfoList.Count); 

                    foreach(RightNameExpirationInfoPair rightsInfo in _boundRightsInfoList)
                    {
                        Nullable contentRight = ClientSession.GetRightFromString(rightsInfo.RightName); 

                        if (contentRight != null) 
                        { 
                            grantList.Add(new ContentGrant(_owner, contentRight.Value, rightsInfo.ValidFrom, rightsInfo.ValidUntil));
                        } 
                    }
                    _boundGrantReadOnlyCollection = new ReadOnlyCollection (grantList);
                }
                return _boundGrantReadOnlyCollection; 
            }
        } 
 

        ///  
        /// Depending on the set of rights ggranted to the user he or she can do Encryption, Decryption or both.
        /// this property checks whether user was granted rights to encrypt, which means that he or she was granted
        /// either an Edit or an Owner right.
        ///  
        public bool CanEncrypt
        { 
            get 
            {
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();

                return (!EncryptorHandle.IsInvalid);
            } 
        }
 
        ///  
        /// Depending on the set of rights granted to the user he or she can do Encryption, Decryption or both.
        /// this property checks whether user was granted rights to decrypt. Decryption is given to a user if he or 
        /// she was able to successfully bind any right (View, Edit, Print, Owner, ....)
        /// 
        public bool CanDecrypt
        { 
            get
            { 
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();
 
                return (!DecryptorHandle.IsInvalid);
            }
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Constructor 
        //
        //------------------------------------------------------ 

        /// 
        /// Constructor.
        ///  
        internal CryptoProvider(List boundLicenseHandleList,
                                                        List rightsInfoList, 
                                                        ContentUser owner) 
        {
            Invariant.Assert(boundLicenseHandleList != null); 
            Invariant.Assert(boundLicenseHandleList.Count > 0);

            Invariant.Assert(rightsInfoList != null);
            Invariant.Assert(rightsInfoList.Count > 0); 

            // we expect a match between lists of the Right Information and the bound license handles 
            // we will be mapping those lists based on indexes 
            Invariant.Assert(rightsInfoList.Count == boundLicenseHandleList.Count);
 
            Invariant.Assert(owner != null);

            _boundLicenseHandleList = boundLicenseHandleList;
            _boundRightsInfoList = rightsInfoList; 

            _owner = owner; 
        } 

        //----------------------------------------------------- 
        //
        //  Internal Methods
        //
        //----------------------------------------------------- 

        internal UnsignedPublishLicense DecryptPublishLicense(string serializedPublishLicense) 
        { 
            Invariant.Assert(serializedPublishLicense != null);
 
            if ((BoundLicenseOwnerViewRightsHandle == null ) || BoundLicenseOwnerViewRightsHandle.IsInvalid)
            {
                throw new RightsManagementException(RightsManagementFailureCode.RightNotGranted);
            } 
            else
            { 
                return new UnsignedPublishLicense(BoundLicenseOwnerViewRightsHandle, serializedPublishLicense); 
            }
        } 

        //-----------------------------------------------------
        //
        //  Private Methods 
        //
        //------------------------------------------------------ 
 
        /// 
        /// Call this before accepting any API call 
        /// 
        private void CheckDisposed()
        {
            if (_disposed) 
                throw new ObjectDisposedException(null, SR.Get(SRID.CryptoProviderDisposed));
        } 
 

        private int QueryBlockSize() 
        {
            uint attributeSize = 0;
            byte[] dataBuffer = null;
 
            uint encodingType;
 
            int hr = SafeNativeMethods.DRMGetInfo(DecryptorHandle, 
                                                    NativeConstants.QUERY_BLOCKSIZE,
                                                    out encodingType, 
                                                    ref attributeSize,
                                                    null);
            Errors.ThrowOnErrorCode(hr);
 
            // it must return 4 bytes for block size
            Invariant.Assert(attributeSize == 4); 
 
            dataBuffer = new byte[(int)attributeSize];  // this cast is safe based on the Invariant.Assert above.
 
            hr = SafeNativeMethods.DRMGetInfo(DecryptorHandle,
                                                NativeConstants.QUERY_BLOCKSIZE,
                                                out encodingType,
                                                ref attributeSize, 
                                                dataBuffer);
            Errors.ThrowOnErrorCode(hr); 
 
            return BitConverter.ToInt32(dataBuffer,0);
        } 

        //-----------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------ 
 
        private SafeRightsManagementHandle DecryptorHandle
        { 
            get
            {
                if(!_decryptorHandleCalculated)
                { 
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    { 
                        SafeRightsManagementHandle decryptorHandle = null; 

                        int hr = SafeNativeMethods.DRMCreateEnablingBitsDecryptor( 
                            _boundLicenseHandleList[i],
                            _boundRightsInfoList[i].RightName,
                            0,
                            null, 
                            out decryptorHandle);
 
                        if (hr == 0) 
                        {
                            Debug.Assert(decryptorHandle != null); 

                            _decryptorHandle = decryptorHandle;
                             _decryptorHandleCalculated = true;
                             return _decryptorHandle; 
                        }
                    } 
                    _decryptorHandleCalculated = true; // if we got here it means we couldn't find anything; regardless 
                                                                         // we should still mark this calculation as complete
                } 
                return _decryptorHandle;
            }
        }
 
        private SafeRightsManagementHandle EncryptorHandle
        { 
            get 
            {
                if(!_encryptorHandleCalculated) 
                {
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    {
                        SafeRightsManagementHandle encryptorHandle = null; 
                        int hr = SafeNativeMethods.DRMCreateEnablingBitsEncryptor(
                            _boundLicenseHandleList[i], 
                            _boundRightsInfoList[i].RightName, 
                            0,
                            null, 
                            out encryptorHandle);

                        if (hr == 0)
                        { 
                            Debug.Assert(encryptorHandle != null);
 
                            _encryptorHandle = encryptorHandle; 
                            _encryptorHandleCalculated = true;
                            return _encryptorHandle; 
                        }
                    }
                    _encryptorHandleCalculated = true; // if we got here it means we couldn't find anything; regardless
                                                                             // we should still mark this calculation as complete 
                }
                return _encryptorHandle; 
            } 
        }
 

        private SafeRightsManagementHandle BoundLicenseOwnerViewRightsHandle
        {
            get 
            {
                if(!_boundLicenseOwnerViewRightsHandleCalculated) 
                { 
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    { 
                        Nullable right =
                                        ClientSession.GetRightFromString(_boundRightsInfoList[i].RightName);

                        if ((right != null) 
                                &&
                            ((right.Value == ContentRight.Owner) ||(right.Value== ContentRight.ViewRightsData))) 
                        { 
                            _boundLicenseOwnerViewRightsHandle = _boundLicenseHandleList[i];
                            _boundLicenseOwnerViewRightsHandleCalculated = true; 
                            return _boundLicenseOwnerViewRightsHandle;
                        }
                    }
                    _boundLicenseOwnerViewRightsHandleCalculated = true; // if we got here it means we couldn't find anything; regardless 
                                                                         // we should still mark this calculation as complete
                } 
                return _boundLicenseOwnerViewRightsHandle; 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Fields 
        //
        //----------------------------------------------------- 
 
        private int _blockSize;
 
        private SafeRightsManagementHandle _decryptorHandle = SafeRightsManagementHandle.InvalidHandle;
        private bool _decryptorHandleCalculated;

        private SafeRightsManagementHandle _encryptorHandle = SafeRightsManagementHandle.InvalidHandle; 
        private bool _encryptorHandleCalculated;
 
        private SafeRightsManagementHandle _boundLicenseOwnerViewRightsHandle = SafeRightsManagementHandle.InvalidHandle; 
        private bool _boundLicenseOwnerViewRightsHandleCalculated;
 
        // if this is Invalid, we are disposed
        private List _boundLicenseHandleList;
        private List _boundRightsInfoList;
 
        private ReadOnlyCollection _boundGrantReadOnlyCollection;
        private ContentUser _owner; 
 
        private bool _disposed;
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description:  Crypto provider class which is a wrapper around unmanaged DRM SDK Bound License handle 
//   provides ability to Encryt/Decrypt protected content, and enumerate granted rights. 
//
// History: 
//  06/01/2005: IgorBel :   Initial Implementation
//
//-----------------------------------------------------------------------------
 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Security;
using System.Security.Permissions;
using System.Windows;
using System.Collections.ObjectModel; 
using MS.Internal.Security.RightsManagement;
using MS.Internal; 
using SecurityHelper=MS.Internal.WindowsBase.SecurityHelper; 

namespace System.Security.RightsManagement 
{
    /// 
    /// CryptoProvider class is built as a result of UseLicense.Bind call. This class represents a successful RightsManagement
    /// Initialization, and as a result provides Encryption/Decryption services, and exposes list of Bound Grants, which are rights 
    /// that have been given by the publisher to the user, and were properly validated (expiration checks, secure environment, and so on)
    ///  
    ///  
    ///     Critical:    This class expose access to methods that eventually do one or more of the the following
    ///             1. call into unmanaged code 
    ///             2. affects state/data that will eventually cross over unmanaged code boundary
    ///             3. Return some RM related information which is considered private
    ///
    ///     TreatAsSafe: This attrbiute automatically applied to all public entry points. All the public entry points have 
    ///     Demands for RightsManagementPermission at entry to counter the possible attacks that do
    ///     not lead to the unamanged code directly(which is protected by another Demand there) but rather leave 
    ///     some status/data behind which eventually might cross the unamanaged boundary. 
    /// 
    [SecurityCritical(SecurityCriticalScope.Everything)] 
    public class CryptoProvider : IDisposable
    {
        //-----------------------------------------------------
        // 
        //  Public Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// This method is responsible for tearing down crypto provider that was built as a result of UseLicense.Bind call.
        /// 
        ~CryptoProvider()
        { 
            Dispose(false);
        } 
 
        /// 
        /// This method is responsible for tearing down crypto provider that was built as a result of UseLicense.Bind call. 
        /// 
        public void Dispose()
        {
            SecurityHelper.DemandRightsManagementPermission(); 
            Dispose(true);
            GC.SuppressFinalize(this); 
        } 

         ///  
        /// This function encrypts clear text content.
        /// An application is expected to create a padding scheme based on the value returned from
        /// BlockSize property. BlockSize property should be used to determine the amount of extra
        /// padding to be added to the clear text. The length, in bytes, of the buffer holding content to 
        /// be encrypted should be a multiple of the block cipher block size.
        /// RMS system currently uses AES block cipher. All blocks are encrypted independently, so that 2 blocks 
        /// of identical clear text will produce identical results after encryption.  An application 
        /// is encouraged to either compress data prior to encryption or create some other scheme to mitigate
        /// threats potentially arising from independent block encryption. 
        /// 
        public byte[] Encrypt(byte[] clearText)
        {
            SecurityHelper.DemandRightsManagementPermission(); 
            CheckDisposed();
 
            if (clearText == null) 
            {
                throw new ArgumentNullException("clearText"); 
            }

            // validation of the proper size of the clearText is done by the unmanaged libraries
 
            if (!CanEncrypt)
            { 
                throw new RightsManagementException(RightsManagementFailureCode.EncryptionNotPermitted); 
            }
 
            // first get the size
            uint outputBufferSize=0;
            byte[] outputBuffer = null;
            int hr; 

#if DEBUG 
            hr= SafeNativeMethods.DRMEncrypt( 
                            EncryptorHandle,
                            0, 
                            (uint)clearText.Length,
                            clearText,
                            ref outputBufferSize,
                            null); 

            Errors.ThrowOnErrorCode(hr); 
 
            // We do not expect Decryption to change the size of the buffer; otherwise it will break
            // basic assumptions behind the encrypted compound file envelope format 
            Invariant.Assert(outputBufferSize == clearText.Length);
#else
            outputBufferSize = (uint)clearText.Length;
#endif 

            outputBuffer = new byte[outputBufferSize]; 
 
            // This will decrypt content
            hr = SafeNativeMethods.DRMEncrypt( 
                            EncryptorHandle,
                            0,
                            (uint)clearText.Length,
                            clearText, 
                            ref outputBufferSize,
                            outputBuffer); 
            Errors.ThrowOnErrorCode(hr); 

            return outputBuffer; 
        }

        /// 
        /// This function decrypts cipher text content. 
        /// The length, in bytes, of the buffer holding content to be encrypted should be a multiple of the
        /// block cipher block size. 
        ///  
        public byte[] Decrypt(byte[] cryptoText)
        { 
            SecurityHelper.DemandRightsManagementPermission();
            CheckDisposed();

            if (cryptoText == null) 
            {
                throw new ArgumentNullException("cryptoText"); 
            } 

            // validation of the proper size of the cryptoText is done by the unmanaged libraries 

            if (!CanDecrypt)
            {
                throw new RightsManagementException(RightsManagementFailureCode.RightNotGranted); 
            }
 
            // first get the size 
            uint outputBufferSize=0;
            byte[] outputBuffer = null; 
            int hr;

#if DEBUG
            hr= SafeNativeMethods.DRMDecrypt( 
                            DecryptorHandle,
                            0, 
                            (uint)cryptoText.Length, 
                            cryptoText,
                            ref outputBufferSize, 
                            null);
            Errors.ThrowOnErrorCode(hr);

            // We do not expect Decryption changing the size of the buffer; otherwise it will break 
            // basic assumptions behind the encrypted compound file envelope format
            Invariant.Assert(outputBufferSize == cryptoText.Length); 
#else 
            outputBufferSize = (uint)cryptoText.Length;
#endif 

            outputBuffer = new byte[outputBufferSize];

            // THis will decrypt content 
            hr = SafeNativeMethods.DRMDecrypt(
                            DecryptorHandle, 
                            0, 
                            (uint)cryptoText.Length,
                            cryptoText, 
                            ref outputBufferSize,
                            outputBuffer);

            Errors.ThrowOnErrorCode(hr); 
            return outputBuffer;
        } 
 
        //------------------------------------------------------
        // 
        //  Protected Methods
        //
        //-----------------------------------------------------
 
        /// 
        /// Dispose(bool) 
        ///  
        /// 
        protected virtual void Dispose(bool disposing) 
        {
            // close bound license handle which is a DRMHANDLE
            // Encryptor and Decryptor handles as well
            try 
            {
                if (disposing) 
                { 

                    if (_decryptorHandle != null && !_decryptorHandle.IsInvalid) 
                        _decryptorHandle.Close();

                    if (_encryptorHandle != null && !_encryptorHandle.IsInvalid)
                        _encryptorHandle.Close(); 

                    if (_boundLicenseOwnerViewRightsHandle != null && !_boundLicenseOwnerViewRightsHandle.IsInvalid) 
                        _boundLicenseOwnerViewRightsHandle.Close(); 

                    // dispose collection of the bound licenses that we have 
                    if (_boundLicenseHandleList != null)
                    {
                        foreach(SafeRightsManagementHandle boundLicenseHandle in _boundLicenseHandleList)
                        { 
                            if (boundLicenseHandle != null && !boundLicenseHandle.IsInvalid)
                                boundLicenseHandle.Close(); 
                        } 
                    }
                } 
            }
            finally
            {
                _disposed = true; 
                _boundLicenseHandleList = null;
                _boundLicenseOwnerViewRightsHandle = null; 
                _decryptorHandle    = null; 
                _encryptorHandle    = null;
            } 
        }

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //------------------------------------------------------ 

        ///  
        /// This is bock size of the cypther that is currently in use.
        /// 
        public int BlockSize
        { 
            get
            { 
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();
 
                if (_blockSize ==0)
                {
                    _blockSize = QueryBlockSize();
                } 
                return _blockSize;
            } 
        } 

        ///  
        /// This bollean indicates wheter Encrypt Decrypt calls can be made on buffers that are multiple of the BlockSize value.
        /// If the value is false Encrypt Decrypt calls must be made on buffers of the size that is exactly equal to the BlockSize.
        /// 
        public bool CanMergeBlocks 
        {
            get 
            { 
                SecurityHelper.DemandRightsManagementPermission();
                CheckDisposed(); 

                // convention is to return 1 for stream ciphers
                // Stream ciphers (although currently not used) return 1.
                // Block ciphers return size of the block that is always greater than 1. 
                // Comparing block size to 1 is a conventional way to differentiate stream and
                // block ciphers. Block Ciphers can accept data chunks (for both encryption and decryption) 
                // that fall on the block boundary and are a multiple of the block cipher block size. 
                return (BlockSize > 1);
            } 
        }

        /// 
        /// This is a read only property. It enable client application to enumerate list of rights that were 
        /// granted to the user, and also passed all the verification checks.
        ///  
        public ReadOnlyCollection BoundGrants 
        {
            get 
            {
                SecurityHelper.DemandRightsManagementPermission();
                CheckDisposed();
 
                if (_boundGrantReadOnlyCollection == null)
                { 
                    // we need to enumerate all the rights and keep the ones that we can translate into enum 
                    // we ignore the rights that we can not translate for forward compatibility reasons
                    List grantList = new List(_boundRightsInfoList.Count); 

                    foreach(RightNameExpirationInfoPair rightsInfo in _boundRightsInfoList)
                    {
                        Nullable contentRight = ClientSession.GetRightFromString(rightsInfo.RightName); 

                        if (contentRight != null) 
                        { 
                            grantList.Add(new ContentGrant(_owner, contentRight.Value, rightsInfo.ValidFrom, rightsInfo.ValidUntil));
                        } 
                    }
                    _boundGrantReadOnlyCollection = new ReadOnlyCollection (grantList);
                }
                return _boundGrantReadOnlyCollection; 
            }
        } 
 

        ///  
        /// Depending on the set of rights ggranted to the user he or she can do Encryption, Decryption or both.
        /// this property checks whether user was granted rights to encrypt, which means that he or she was granted
        /// either an Edit or an Owner right.
        ///  
        public bool CanEncrypt
        { 
            get 
            {
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();

                return (!EncryptorHandle.IsInvalid);
            } 
        }
 
        ///  
        /// Depending on the set of rights granted to the user he or she can do Encryption, Decryption or both.
        /// this property checks whether user was granted rights to decrypt. Decryption is given to a user if he or 
        /// she was able to successfully bind any right (View, Edit, Print, Owner, ....)
        /// 
        public bool CanDecrypt
        { 
            get
            { 
                SecurityHelper.DemandRightsManagementPermission(); 
                CheckDisposed();
 
                return (!DecryptorHandle.IsInvalid);
            }
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Constructor 
        //
        //------------------------------------------------------ 

        /// 
        /// Constructor.
        ///  
        internal CryptoProvider(List boundLicenseHandleList,
                                                        List rightsInfoList, 
                                                        ContentUser owner) 
        {
            Invariant.Assert(boundLicenseHandleList != null); 
            Invariant.Assert(boundLicenseHandleList.Count > 0);

            Invariant.Assert(rightsInfoList != null);
            Invariant.Assert(rightsInfoList.Count > 0); 

            // we expect a match between lists of the Right Information and the bound license handles 
            // we will be mapping those lists based on indexes 
            Invariant.Assert(rightsInfoList.Count == boundLicenseHandleList.Count);
 
            Invariant.Assert(owner != null);

            _boundLicenseHandleList = boundLicenseHandleList;
            _boundRightsInfoList = rightsInfoList; 

            _owner = owner; 
        } 

        //----------------------------------------------------- 
        //
        //  Internal Methods
        //
        //----------------------------------------------------- 

        internal UnsignedPublishLicense DecryptPublishLicense(string serializedPublishLicense) 
        { 
            Invariant.Assert(serializedPublishLicense != null);
 
            if ((BoundLicenseOwnerViewRightsHandle == null ) || BoundLicenseOwnerViewRightsHandle.IsInvalid)
            {
                throw new RightsManagementException(RightsManagementFailureCode.RightNotGranted);
            } 
            else
            { 
                return new UnsignedPublishLicense(BoundLicenseOwnerViewRightsHandle, serializedPublishLicense); 
            }
        } 

        //-----------------------------------------------------
        //
        //  Private Methods 
        //
        //------------------------------------------------------ 
 
        /// 
        /// Call this before accepting any API call 
        /// 
        private void CheckDisposed()
        {
            if (_disposed) 
                throw new ObjectDisposedException(null, SR.Get(SRID.CryptoProviderDisposed));
        } 
 

        private int QueryBlockSize() 
        {
            uint attributeSize = 0;
            byte[] dataBuffer = null;
 
            uint encodingType;
 
            int hr = SafeNativeMethods.DRMGetInfo(DecryptorHandle, 
                                                    NativeConstants.QUERY_BLOCKSIZE,
                                                    out encodingType, 
                                                    ref attributeSize,
                                                    null);
            Errors.ThrowOnErrorCode(hr);
 
            // it must return 4 bytes for block size
            Invariant.Assert(attributeSize == 4); 
 
            dataBuffer = new byte[(int)attributeSize];  // this cast is safe based on the Invariant.Assert above.
 
            hr = SafeNativeMethods.DRMGetInfo(DecryptorHandle,
                                                NativeConstants.QUERY_BLOCKSIZE,
                                                out encodingType,
                                                ref attributeSize, 
                                                dataBuffer);
            Errors.ThrowOnErrorCode(hr); 
 
            return BitConverter.ToInt32(dataBuffer,0);
        } 

        //-----------------------------------------------------
        //
        //  Private Properties 
        //
        //------------------------------------------------------ 
 
        private SafeRightsManagementHandle DecryptorHandle
        { 
            get
            {
                if(!_decryptorHandleCalculated)
                { 
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    { 
                        SafeRightsManagementHandle decryptorHandle = null; 

                        int hr = SafeNativeMethods.DRMCreateEnablingBitsDecryptor( 
                            _boundLicenseHandleList[i],
                            _boundRightsInfoList[i].RightName,
                            0,
                            null, 
                            out decryptorHandle);
 
                        if (hr == 0) 
                        {
                            Debug.Assert(decryptorHandle != null); 

                            _decryptorHandle = decryptorHandle;
                             _decryptorHandleCalculated = true;
                             return _decryptorHandle; 
                        }
                    } 
                    _decryptorHandleCalculated = true; // if we got here it means we couldn't find anything; regardless 
                                                                         // we should still mark this calculation as complete
                } 
                return _decryptorHandle;
            }
        }
 
        private SafeRightsManagementHandle EncryptorHandle
        { 
            get 
            {
                if(!_encryptorHandleCalculated) 
                {
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    {
                        SafeRightsManagementHandle encryptorHandle = null; 
                        int hr = SafeNativeMethods.DRMCreateEnablingBitsEncryptor(
                            _boundLicenseHandleList[i], 
                            _boundRightsInfoList[i].RightName, 
                            0,
                            null, 
                            out encryptorHandle);

                        if (hr == 0)
                        { 
                            Debug.Assert(encryptorHandle != null);
 
                            _encryptorHandle = encryptorHandle; 
                            _encryptorHandleCalculated = true;
                            return _encryptorHandle; 
                        }
                    }
                    _encryptorHandleCalculated = true; // if we got here it means we couldn't find anything; regardless
                                                                             // we should still mark this calculation as complete 
                }
                return _encryptorHandle; 
            } 
        }
 

        private SafeRightsManagementHandle BoundLicenseOwnerViewRightsHandle
        {
            get 
            {
                if(!_boundLicenseOwnerViewRightsHandleCalculated) 
                { 
                    for(int i=0; i< _boundLicenseHandleList.Count; i++)
                    { 
                        Nullable right =
                                        ClientSession.GetRightFromString(_boundRightsInfoList[i].RightName);

                        if ((right != null) 
                                &&
                            ((right.Value == ContentRight.Owner) ||(right.Value== ContentRight.ViewRightsData))) 
                        { 
                            _boundLicenseOwnerViewRightsHandle = _boundLicenseHandleList[i];
                            _boundLicenseOwnerViewRightsHandleCalculated = true; 
                            return _boundLicenseOwnerViewRightsHandle;
                        }
                    }
                    _boundLicenseOwnerViewRightsHandleCalculated = true; // if we got here it means we couldn't find anything; regardless 
                                                                         // we should still mark this calculation as complete
                } 
                return _boundLicenseOwnerViewRightsHandle; 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Fields 
        //
        //----------------------------------------------------- 
 
        private int _blockSize;
 
        private SafeRightsManagementHandle _decryptorHandle = SafeRightsManagementHandle.InvalidHandle;
        private bool _decryptorHandleCalculated;

        private SafeRightsManagementHandle _encryptorHandle = SafeRightsManagementHandle.InvalidHandle; 
        private bool _encryptorHandleCalculated;
 
        private SafeRightsManagementHandle _boundLicenseOwnerViewRightsHandle = SafeRightsManagementHandle.InvalidHandle; 
        private bool _boundLicenseOwnerViewRightsHandleCalculated;
 
        // if this is Invalid, we are disposed
        private List _boundLicenseHandleList;
        private List _boundRightsInfoList;
 
        private ReadOnlyCollection _boundGrantReadOnlyCollection;
        private ContentUser _owner; 
 
        private bool _disposed;
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK