Share via


Getting the Issuance License Signed

After an issuance license is created, it is signed by an Active Directory Rights Management Services (AD RMS) service. Signing means that the content key is encrypted, and the issuance license is signed into a license chain that makes a valid, usable issuance license. This license is used to acquire a use license, which contains rights pertaining only to the requested user. This use license allows users to exercise the rights granted to them for that piece of content, using an AD RMS-enabled client application.

An unsigned issuance license is signed by calling the AcquireIssuanceLicense SOAP method that is exposed by an AD RMS service. For an application that runs on a server, this is the only supported method of getting an issuance license signed.

When you create a new issuance license, DRMCreateIssuanceLicense returns a handle to an issuance license object. However, to get the license signed, you need an issuance license string (as an XmlNode) to pass to AcquireIssuanceLicense on the server. When you call DRMGetSignedIssuanceLicense with the DRM_SERVER_ISSUANCELICENSE flag, the callback function returns the license string of the unsigned issuance license; it does not get the license signed for you. DRMGetSignedIssuanceLicense also takes the key that is used to encrypt the content as a parameter.

To sign an issuance license by using the AD RMS SOAP function AcquireIssuanceLicense

  1. Obtain the AD RMS service's server licensor certificate, and change it into an appropriate format.

    The function GetLicensorCertificate returns a licensor certificate chain as an XmlNode array. To change this into a format that DRMGetSignedIssuanceLicense can accept, complete the following steps:

    1. Convert the XmlNode array to a string array.
    2. Pass this array into the function DRMConstructCertificateChain.
  2. Call DRMGetSignedIssuanceLicense with the DRM_SERVER_ISSUANCELICENSE flag and the server licensor certificate chain to get the license string.

  3. Call AcquireIssuanceLicense, passing in the chain, and retrieve the signed issuance license.

  4. Extract the leaf certificate in the retrieved chain (the actual signed issuance license) and store it, or pass it to AcquirePreLicense to get a use license.

The following C# example demonstrates these steps.

// Declare global variables that can be accessed in the callback.
private string g_UnsignedIssuanceLicense;
private ManualResetEvent g_UnsignedILAvailable;

...

GCHandle gch = null;

try
{
    // Get the server licensor certificate, using Web proxy for 
    // GetLicensorCertificate.
    string[] LicensorCertChain = rms.GetRMSLicensorCert();

    // Use DRMConstructCertificateChain in a helper function 
    // to convert the server licensor chain into an acceptable 
    // format for DRMGetSignedIssuanceLicense.
    StringBuilder szChain = CreateMsdrmCompatibleChain(
                                  LicensorCertChain);

    // Create the event to signal when the callback is complete.
    g_UnsignedILAvailable = new ManualResetEvent(false);
    
    // Need to pin the callback function in memory.
    gch = GCHandle.Alloc(callback);

    // Need an unsafe block because these functions use pointers.
    unsafe 
    {
        // Prevent the key bytes from moving in memory.
        fixed (byte* keyBuffer = bContentKey)
        {
           // Get the license text from the license handle.
           // Note that this does not get a signed 
           // issuance license.
            Nmc.Check(DRMGetSignedIssuanceLicense(
                IntPtr.Zero,                 // Null pointer
                hIssuanceLicense,            // Issuance license
                DRM_SERVER_ISSUANCELICENSE,  // Unsigned license
                (IntPtr)keyBuffer,           // Content key
                keyLen,                      // Key length
                keyType,                     // Key type
                szChain,                     // Certificate chain
                new MsdrmCallback(OnStatus), // Callback 
                null,                        // Pass null 
                IntPtr.Zero));               // Data not needed
        }
    }

    // Wait for the event to be signaled, 
    // indicating the callback has been called.
    g_UnsignedILAvailable.WaitOne();
}
finally
{
    if(null != gch)
    {
        gch.Free();
    }
}
    

The following callback function retrieves the unsigned issuance license that was requested previously, and assigns it to a global variable. This license can be used to request a signed issuance license by using the AcquireIssuanceLicense SOAP method.

// Declare the delegate for the asynchronous callback function for 
// DRMGetSignedIssuanceLicense.
unsafe delegate void MsdrmCallback(
    DRM_STATUS_MSG msg, 
    int hr, 
    IntPtr pvParam, 
    IntPtr pvContext);

unsafe public void OnStatus(
    DRM_STATUS_MSG msg, // Asynchronous call is occurring
    int hr,             // Did RM function succeed
    IntPtr pvParam,     // Contains unsigned issuance license
    IntPtr pvContext)   // Not used
{
    // DRM_STATUS_MSG.DRM_MSG_SIGN_ISSUANCE_LICENSE must be 
    // declared by your application. It is defined in the 
    // MSDRMDefs.h header file.
    if ( msg == DRM_STATUS_MSG.DRM_MSG_SIGN_ISSUANCE_LICENSE && 
         hr  == S_DRM_COMPLETED && 
         pvParam != IntPtr.Zero )
    {
        try
        {
            // Get the unsigned issuance license from the
            // unmanaged buffer.
            string unSignedIL = Marshal.PtrToStringAuto(pvParam);

            // Assign to global variable.
            g_UnsignedIssuanceLicense = unSignedIL;

            // Signal the event so that the caller knows 
            // to continue.
            g_UnsignedILAvailable.Set();
        }
        finally
        {
            if (pvParam != IntPtr.Zero)
                Marshal.FreeBSTR(pvParam);
        }
    }
}

Now that the application has the unsigned issuance license, use the AcquireIssuanceLicense SOAP call. In this example, this function is handled by a Web proxy called rmsServer.

// Acquire signed issuance license chain from the server 
// using Web proxy.
string[] certs =  rmsServer.AcquirePublishingLicense(
                                 g_UnsignedPublishingLicense);

// An application only needs the leaf certificate of the 
// license chain to obtain a use license. 
StringBuilder g_SignedPublishingLicense  = 
                   new StringBuilder(certs[0]);

The next step would be to save this for later use (either within your custom format or within a compound file stream), or obtain a use license immediately by calling the AcquirePreLicense SOAP method.

See Also

Acquiring the Use License
Creating a Compound File and Adding Content

Send comments about this topic to Microsoft

Build date: 3/13/2008