In the Basic Challenge protocol, every license issued has one or more keys called secrets. These secrets, chosen by the software publisher, are typically encrypted within the license itself, with only the license server knowing how to decrypt those secrets. Since the application knows the secrets on the license, it can compute the correct expected response to a challenge -- which the server can only compute if it also knows the secret. The secret itself is never passed between the application and the license system (thus preventing snooping).
In order to perform a challenge, the application generates a random value, which it passes as the challenge to the license system. The license system, in turn, combines that random value along with the "secret" off of the license. This data is fed into a one-way encryption scheme, yielding a unique result. The result of the one-way encryption is returned as the response to the challenge.
Protocol Details
In the Basic Challenge protocol, the application chooses the index, X, of the secret to be challenged; generates a random number, R; and computes a message digest of the input parameters, R, X, and the secret SX. This data is passed to the license system which authenticates the message digest, and then computes a new message digest of the input parameters, output parameters, R, X, and SX. This new message digest is passed back to the application, who, in turn, authenticates it. Note that the actual secret, SX, is never passed between the application and license system in plain text. The figure below illustrates the protocol:
Let in be a byte stream which encodes all [in]-parameters, excluding the handle, of an LSAPI function. All parameters should be in the order specified in the "License Function Calls" section.
TYPE
Description
LS_STR *
Array of bytes (excluding null)
UINT32
Least significant byte ascending order
INT32
Least significant byte ascending order
INT16
Least significant byte ascending order
This is taken to include the name of the function being called (e.g., "LSRequest"), but exclude the value of Challenge and LicenseHandle. Let out be a byte stream which encodes all the [out]-parameters. This is taken to include Status, but excludes the value of Challenge and LicenseHandle. All parameters should be in the order specified in the "License Function Calls" section. "Status" will be the last parameter. Let denote concatenation.
The function h(x) is the algorithm which, given input x, returns the output of the MD4 message digest algorithm. This algorithm, invented by R. Rivest and placed in the public domain, is described later in this chapter. The input x for h() is formed by concatenating all the arguments into a byte stream.. Any string arguments are copied without the NULL terminators. The application receives the output parameters (out) and the response to its challenge. The application accepts the result if and only the response is h(in out R X SX). Note that no challenge response is returned if the license request or update does not complete successfully.
The following summarizes what work must be done in the application program in preparing a challenge, and what must be done by the server in preparing the response to a challenge. To prepare a challenge, the application must:
Generate a 32-bit random number, R.
Choose the index, X, of the secret to be challenged (1 - 4).
Look up the secret SX.
Compute h(in R X SX).
To respond to a challenge, the LS must:
Look up the secret SX stored within the license, where X is the index of the secret.
Independently compute h(in R X SX) and compare it with the message digest passed in from the application initiating the challenge.
Compute one more message digest, h(in out R X SX).
On receiving a response from the LS, the application must:
Compute a message digest, h(in out R X SX).
Compare two strings for equality.
Compliant licensing systems permit a minimum of 4 secrets, each being 4 bytes (32-bits) in length.
Generating random numbers
The application needs a source of random numbers. These do not have to be of extremely high quality, but they should have good stochastic properties and must be unique to the extent that no random R generated by one application will be generated by another, or by the same application at a later point in time. Since many operating systems do not provide a reasonable source of random bits. A choice of R=h(t)h(t+1)h(t+2), where t is the machine's estimate of the current time, is acceptable if t is guaranteed to increase monotonically and rapidly.