MAINSAIL Utilities User's Guide, Chapter 32

previous   next   top   contents   index   framed top   this page unframed


32. STAMP and Object MODULE Security

Several features are provided to give a software distributor some control over the use at other sites of individual object MODULEs. The utility MODULE STAMP is used to set the security fields in an object MODULE.

An expiration date can limit the use of an object MODULE for up to five years from the date the expiration date is put into the object MODULE.

A password can be put into an object MODULE. If a password is present, then whenever the MODULE is initialized for execution, MAINSAIL prompts for the password and allows use only if the user provides the password.

A set of CPU IDs (as would be returned by the $cpuId PROCEDURE) can be put into an object MODULE. MAINSAIL disallows use of the MODULE on a CPU that is not included in the specified set.

The CPU ID is unavailable on some operating systems; therefore, it is not possible to CPU-stamp MODULEs for such target systems (unless an $alternateCpuID PROCEDURE is provided by the user, as is possible on some operating systems; see the operating-system-specific MAINSAIL user's guide for details).

The security fields are stored into the object MODULE in an encrypted form so that the unscrupulous user cannot easily alter their values. STAMP is designed so that the distributor can send information to a customer about how to change the security fields in one way, and yet the customer cannot use that information to alter the fields in other ways.

STAMP stores an encrypted key into each object MODULE. This key must be kept secret. The purpose of the key is to allow secure change access by the customer. A different key should be used for every stamped MODULE/customer pair; the distributor must remember the keys for each MODULE and customer. Typically, only one critical MODULE per “package” need be stamped to control the package's use. For example, a critical MODULE of an application can be stamped with an expiration date two months in the future. At that time, the expiration date can be extended if the customer buys the package.

There is a many-to-one mapping between passwords and CPU IDs and the encrypted values stored in the object MODULE, so that it is possible (although unlikely) that a bogus value would be accepted by the MAINSAIL runtime system.

The security features are designed more for low runtime overhead than absolute security, and hence should not be relied upon to protect truly sensitive data or code. At the very least, a customer could use STAMP with random values until he or she eventually came up with a value that allowed use on an unauthorized CPU (though this might take quite some time). The purpose of the security fields is to require the customer to undertake a non-trivial effort to alter the security fields to his or her advantage, thereby providing clear evidence that the customer has purposely broken a contract. This avoids the situation of a well-intentioned but undisciplined customer claiming that a package was used beyond an agreed-upon expiration date or on an unauthorized CPU due to forgetfulness or uninformed users.

32.1. Expiration Date

An encrypted expiration date can be put into an object MODULE, along with an encrypted key that provides secure change access for the expiration date. The encrypted key and expiration date depend on the contents of the object MODULE, so that neither is valid in another object MODULE. The encrypted expiration date also depends on the key. When an object MODULE is first created, the compiler sets the encrypted date and key to encrypted “match-all” values.

Whenever an objmod is loaded into memory, MAINSAIL aborts the MODULE allocation if the key is not match-all and the current date is greater than the expiration date or the expiration date is more than five years in the future (this makes it more difficult for a user to put a randomly selected bit pattern for an encrypted expiration date into the object MODULE and successfully extend the expiration date). Thus, an expiration date can be at most five years from the current date, which is consistent with the purpose of an expiration date as a means of limiting use of a program to a reasonably short trial period. An expiration date can also be as much as one year before the current date; setting an expiration date before the present allows you to test the stamped system to confirm that it behaves as desired when stamped with an expiration date.

The MODULE STAMP is used to set the expiration date in an object MODULE. The expiration date can be set only if the user knows the key or the key is match-all. Example 32–1 shows how to stamp a MODULE FOO with an expiration date, and at the same time set the key if it is currently match-all.

Example 32–1. setExpirationDate
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetExpirationDate<eol>
Module filefoo-<sys>.obj<eol>
Expiration date (just <eolfor none): dec 31 2002<eol>
Key: 'H12A8CD0<eol>

? may be typed to the “STAMP:” prompt to get a summary of the valid responses. Only as much of a command as is needed to make it unique need be typed; for example, sete is sufficient for setExpirationDate (case is irrelevant). The expiration date can be in any valid MAINSAIL date STRING format. If just <eol> is typed for the date, then the expiration date is set to match-all; i.e., there is no expiration date.

STAMP gives an error message if the expiration date is more than five years in the future or one year in the past, or if the key encrypted in the object MODULE is neither match-all nor the supplied key. The key may be any one- to eight-digit hexadecimal value (case is irrelevant), provided that the value contains at least 4 one-bits. Once a key is set for a MODULE, that key must be used in all subsequent commands for the MODULE (unless a setToCompiledState command is given, which sets the key to match-all and therefore allows a new key to be given for the next command).

Since the above interaction makes explicit use of the key, it is not safe to be carried out by a customer, since the customer, knowing the key, could use STAMP to change the expiration date again. However, STAMP can also be used to change the expiration date in a way that does not reveal the key. This is a two-step process. The first step is carried out privately by the software distributor, who knows the key, and the second by the customer, who does not. First, the distributor secretly gets a “mixed-up” expiration date, as shown in Example 32–2.

Example 32–2. mixupExpirationDate
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPmixupExpirationDate<eol>
Expiration date (just <eolfor none): dec 31 2002<eol>
Key: 'H12A8CD0<eol>
Mixed up date is 'H7A39F10E

The distributor then tells the customer the mixed-up date value, and the customer uses STAMP to set the expiration date, as in Example 32–3.

Example 32–3. setMixedupExpirationDate
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetMixedupExpirationDate<eol>
Module filefoo-<sys>.obj<eol>
Mixed up expiration date: 'H7A39F10E<eol>

The effect is the same as if the setExpirationDate command for the originally specified date and key had been used.

32.2. Password

An encrypted password can be put into an object MODULE, along with an encrypted key (the same key used with the expiration date). Whenever an objmod is loaded into memory for execution, MAINSAIL checks whether the MODULE contains other than the match-all password for that MODULE, and if so, prompts the user for the password. Use of the MODULE is allowed only if the user password matches. The compiler initializes the password to the encrypted match-all value.

The encrypted password depends on the contents of the object MODULE and the key, so that it is not valid in another object MODULE.

STAMP is used to set the password in an object MODULE. The password can be set only if the user knows the key, or the key is match-all. Example 32–4 shows how to stamp a MODULE FOO with a keyword, and at the same time set the key if it is currently match-all.

Example 32–4. setPassword
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetPassword<eol>
Module filefoo-<sys>.obj<eol>
New password (just <eolfor none): monkey<eol>
Key: 'H12A8CD0<eol>

STAMP gives an error message if the key encrypted in the object MODULE is neither match-all nor the supplied key. A password is any STRING. If just <eol> is typed, then the password is set to match-all; i.e., there is no password.

Just as for setting the expiration date, STAMP can be used to have the customer set the password. This is not as useful as remote setting of the expiration date, since while it is in the customer's best interest to extend the expiration date, it is not in his or her interest to stamp a password into a MODULE. Nevertheless, the capability of remotely setting the password is provided in case it proves useful. The distributor does as shown in Example 32–5.

Example 32–5. mixupPassword
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPmixupPassword<eol>
Password (just <eolfor none): monkey<eol>
Key: 'H12A8CD0<eol>
Mixed up password is 'H7A39F10E

The distributor then tells the customer the mixed-up password, and the customer uses STAMP to set the password, as in Example 32–6.

Example 32–6. setMixedupPassword
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetMixedupPassword<eol>
Module filefoo-<sys>.obj<eol>
Mixed up password: 'H7A39F10E<eol>

The effect is the same as if the setPassword command had been used.

32.3. Target CPU IDs

An encrypted set of CPU IDs can be put into an object MODULE, along with an encrypted key (the same key used with the expiration date). Whenever an objmod is loaded into memory for execution, MAINSAIL aborts the MODULE allocation if the encrypted CPU IDs are not match-all and the value returned by $cpuId is not contained in the encrypted set. The compiler sets the encrypted CPU IDs to match-all.

The encrypted CPU IDs depend on the contents of the object MODULE and the key, so that they are not valid in another object MODULE.

The MODULE STAMP is used to set the CPU IDs in an object MODULE. The CPU IDs can be set only if the user knows the key or the key is match-all. To stamp a MODULE FOO with three CPU IDs, and at the same time set the key if it is currently match-all, do as in Example 32–7.

Example 32–7. setCpuIds
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetCpuIds<eol>
Module filefoo-<sys>.obj<eol>
Next CPU IdAE-3451<eol>
Next CPU IdDD-1298<eol>
Next CPU IdAD-8632<eol>
Next CPU Id<eol>
Key: 'H12A8CD0<eol>

A CPU ID is a STRING. Terminate the CPU ID list with <eol>. Use just <eol> for the first CPU ID to indicate the match-all value. STAMP gives an error message if the key encrypted in the object MODULE is neither match-all nor the supplied key.

Just as for setting the expiration date, STAMP can be used to have the customer set the CPU IDs. The software distributor does as shown in Example 32–8.

Example 32–8. mixupCpuIds
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPmixupCpuIds<eol>
Next CPU IdAE-3451<eol>
Next CPU IdDD-1298<eol>
Next CPU IdAD-8632<eol>
Next CPU Id<eol>
Key: 'H12A8CD0<eol>
Mixed up CPU Ids are
            '
H983C879F 'HB3187993 'H8F474CCA 'HCB278901

The distributor then tells the customer the mixed-up CPU ID values (there are always four), and the customer uses STAMP to set the CPU IDs, as shown in Example 32–9.

Example 32–9. setMixedupCpuIds
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetMixedupCpuIds<eol>
Module filefoo-<sys>.obj<eol>
Mixed up CPU Id 1: 'H983C879F<eol>
Mixed up CPU Id 2: 'HB3187993<eol>
Mixed up CPU Id 3: 'H8F474CCA<eol>
Mixed up CPU Id 4: 'HCB278901<eol>

The CPU IDs must be given in the same order as printed out by mixupCpuIds. The effect is the same as if the setCpuIds command had been used.

32.4. Target System

The command target targetSystemAbbreviation specifies the system for which the MODULE to be stamped was compiled. If targetSystemAbbreviation is omitted, the host system is assumed. The command target ? displays a list of possible system abbreviations. The target command remains in effect until either a new target command is given or the STAMP session is terminated.

32.5. Stamping MODULEs in Libraries

The STAMP command library allows MODULEs to be stamped directly in libraries. The forms of the command are shown in
Table 32–10 (libraryName is the file name of a MODULE library; moduleList is a series of MODULE names separated by spaces or tabs).

Table 32–10. Forms of the STAMP library Command
Syntax Description
library libraryName stamp all MODULEs in libraryName.
library libraryName moduleList stamp the MODULEs in libraryName specified in moduleList.
library resume stamping MODULEs not contained in libraries.

The library command stays in effect until either a new library command is given or the STAMP session is terminated. All subsequent STAMP commands affect the MODULEs specified in the library command.

The first time a MODULE is stamped, the user is asked to specify a key, which is encrypted and stored somewhere in the MODULE. The STAMP commands setExpirationDate, setPassword, setCpuIds, and setToCompiledState require the user to specify a key the encrypted value of which must match the value stored in a MODULE in order for the commands to be performed on that MODULE. All MODULEs specified in a single library command are assumed to have the same key, so that if MODULEs in a library are being stamped, the user is requested to enter a key only during the first STAMP command that matches a key against the key stored in a MODULE. If all MODULEs being stamped match that key or have not been stamped before, then subsequent such STAMP commands use that key instead of requiring that the key be respecified. Thus, the dialogue to stamp a MODULE FOO in a library bar.lib with both an expiration date and a password would resemble that shown in Example 32–11.

Example 32–11. Stamping a MODULE in a Library
*stamp<eol>
MAINSAIL (tmModule Security (? for help)
STAMPlibrary bar.lib foo<eol>
STAMPsetexpirationdate<eol>
Expiration date (just <eolfor none): jan 1 2003<eol>
Key: 'H12345678<eol>
STAMPsetpassword<eol>
New password (just <eolfor none): meringue<eol>
STAMP:

If the key specified by the user does not match the key stored in a MODULE, a message to that effect is written to logFile, and that MODULE is not stamped. STAMP still tries to stamp the remaining MODULEs; i.e., it does not stop in the middle of stamping a list of MODULEs because it cannot stamp one. However, at the next STAMP command that uses a key, the user is prompted for another key.

The commands mixUpExpirationDate, mixUpPassword, and mixUpCpuIds always request a key, since they do not match the key against the key stored in a MODULE.

32.6. Information about an Object MODULE

The command show displays an object MODULE's expiration date, whether or not the MODULE requires a password to be run, and whether or not it can only be run on a restricted set of CPUs (the exact list of CPUs cannot be displayed, because it cannot be derived from the information in the MODULE).

If no library command is in effect, STAMP prompts for the name of the object file to examine. Otherwise, it examines the MODULEs specified by the library command.

The syntax of the command is show {all} (the curly braces mean that the all is optional). If the all is omitted, only MODULEs that have actually been stamped in some way are displayed. If no MODULEs have been stamped, STAMP displays a message to that effect. If all is specified, then information is displayed about all MODULEs being examined, even the MODULEs that have not been stamped.

When STAMP decodes a MODULE's expiration date, it displays it only if the expiration date is within five years, either way, of the current date. This is to foil people who might try to beat the system by patching random values into an expired object MODULE's expiration date field and then using STAMP's show command to see what the effect was.

What follows is a session illustrating the use of the show command to find out whether or not the MODULE MAINEX in the library /16/20/sys-usp.olb is stamped:

*stamp<eol>
MAINSAIL (RModule Security (? for help)
STAMPlib /16/20/sys-usp.olb mainex<eol>
STAMPshow<eol>
MODULE  EXPIRATION DATE  PASSWORD  RESTRICTED CPU IDS

MAINEX     1-May-1997       no            yes
STAMPq<eol>
*

32.7. Miscellaneous

32.7.1. List of Commands

Typing question mark to the command prompt gives a summary of the available commands, as shown in
Example 32–12.

Example 32–12. STAMP Help
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP?<eol>

target {targetSystem}
library libName {modList}
setExpirationDate
mixupExpirationDate
setMixedupExpirationDate
setPassword
mixupPassword
setMixedupPassword
setCpuIds
mixupCpuIds
setMixedupCpuIds
setToCompiledState
show {all}
quit

32.7.2. Long Command Lines

A very long STAMP command may be broken across several lines by terminating each line with a backslash (\). Thus, the command lines:

library foo.lib\
 
abc\
 
def\
 
ghi

are equivalent to the single command line:

library foo.lib abc def ghi

32.7.3. setToCompiledState Example

In
Example 32–13, the setToCompiledState command is used to set the encrypted key, expiration date, password, and CPU ID to the match-all values that are set by the compiler.

Example 32–13. setToCompiledState
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMPsetToCompiledState<eol>
Module filefoo-<sys>.obj<eol>
Key: 'H12A8CD0<eol>

32.7.4. Match-All Keys

Whenever a MODULE is initialized for execution, MAINSAIL first checks whether the key is match-all, and if so, it does not bother checking any of the other security values, thereby saving the overhead of doing so. Thus it is a good idea to use setToCompiledState if a MODULE has a key other than match-all, and all of the security fields are match-all (and will never be set again, though there is little reason to set them again since the unscrupulous customer could just continue to use the copy with no values set).

The setToCompiledState command is the only way to change a MODULE's key once it has been set to a value other than match-all.

Note that once the key is set to match-all, there is no way to use the “remote” commands to set the key to a secret value. Thus if there is a chance that a MODULE that is sent to a customer may at some later date be stamped with some values, even though this is not done when the MODULE is sent to the customer, then the MODULE should be stamped with a key before it is shipped to the customer (e.g., use the setPassword command and use just <eol> for the password). The rule of thumb is to stamp a MODULE before distribution if restricted access is desired, and then use the remote commands to change the values (not particularly for changing the password, since if it is discovered, then the customer will not want to change it, and if it is not discovered, then there is no particular reason to change it anyway).

The quit command is used to exit STAMP.

32.8. STAMP Program Interface

STAMP can be called from a program with the PROCEDURE $executeStampCommands, declared as shown in Figure 32–14.

Figure 32–14. $executeStampCommands
BOOLEAN
PROCEDURE       $executeStampCommands
                                (
OPTIONAL STRING cmds;
                                 
OPTIONAL
                                     
POINTER(textFilef);

$executeStampCommands executes a series of STAMP commands until either one of the commands fails, in which case it returns FALSE and ignores the remaining commands, or it encounters a quit command or runs out of commands, in which case it returns TRUE. Commands are first read from the STRING cmds until it is empty, at which point commands are read from the file f until end-of-file is reached.

A command can fail for a number of reasons; e.g., a file cannot be opened, or it is not a library or object file, or a specified key does not match the key stored in any of the MODULEs being stamped. If a key does not match a single MODULE's key, the other MODULEs are still stamped if the specified key matches their keys, but the command is considered to have failed, and the remaining commands are ignored.

The commands are exactly the same as if they were being entered from cmdFile. For example, the call of Example 32–15 stamps the MODULE FOO in the library bar.lib with both an expiration date and a password, as done in Example 32–11.

Example 32–15. Use of $executeStampCommands
$executeStampCommands(
    "
library bar.lib foo" & eol &
    "
setexpirationdate" & eol &
    "
jan 1 2003" & eol &
    "12345678" & 
eol &
    "
setpassword" & eol &
    "
meringue" & eol &
    "
quit");


previous   next   top   contents   index   framed top   this page unframed

MAINSAIL Utilities User's Guide, Chapter 32