previous next top contents index framed top this page unframed
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.
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
? 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
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
The effect is the same as if the setExpirationDate
command for the originally specified date and key had been
used.
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.
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.
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
The effect is the same as if
the setPassword command had been used.
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.
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: setExpirationDate<eol>
Module file: foo-<sys>.obj<eol>
Expiration date (just <eol> for none): dec 31 2002<eol>
Key: 'H12A8CD0<eol>
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: mixupExpirationDate<eol>
Expiration date (just <eol> for none): dec 31 2002<eol>
Key: 'H12A8CD0<eol>
Mixed up date is 'H7A39F10E
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: setMixedupExpirationDate<eol>
Module file: foo-<sys>.obj<eol>
Mixed up expiration date: 'H7A39F10E<eol>
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.
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: setPassword<eol>
Module file: foo-<sys>.obj<eol>
New password (just <eol> for none): monkey<eol>
Key: 'H12A8CD0<eol>
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: mixupPassword<eol>
Password (just <eol> for none): monkey<eol>
Key: 'H12A8CD0<eol>
Mixed up password is 'H7A39F10E
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: setMixedupPassword<eol>
Module file: foo-<sys>.obj<eol>
Mixed up password: 'H7A39F10E<eol>
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.
| *stamp<eol> MAINSAIL (R) Module Security (? for help) STAMP: setCpuIds<eol> Module file: foo-<sys>.obj<eol> Next CPU Id: AE-3451<eol> Next CPU Id: DD-1298<eol> Next CPU Id: AD-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.
| *stamp<eol> MAINSAIL (R) Module Security (? for help) STAMP: mixupCpuIds<eol> Next CPU Id: AE-3451<eol> Next CPU Id: DD-1298<eol> Next CPU Id: AD-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) STAMP: setMixedupCpuIds<eol> Module file: foo-<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 (tm) Module Security (? for help) STAMP: library bar.lib foo<eol> STAMP: setexpirationdate<eol> Expiration date (just <eol> for none): jan 1 2003<eol> Key: 'H12345678<eol> STAMP: setpassword<eol> New password (just <eol> for 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.
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:
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).
*stamp<eol>
MAINSAIL (R) Module Security (? for help)
STAMP: lib /16/20/sys-usp.olb mainex<eol>
STAMP: show<eol>
MODULE EXPIRATION DATE PASSWORD RESTRICTED CPU IDS
MAINEX 1-May-1997 no yes
STAMP: q<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.
| *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 |
library foo.lib\
abc\
def\
ghi
are equivalent to the single command line:
library foo.lib abc def ghi
Example 32–13. setToCompiledState
| *stamp<eol> MAINSAIL (R) Module Security (? for help) STAMP: setToCompiledState<eol> Module file: foo-<sys>.obj<eol> Key: 'H12A8CD0<eol> |
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.
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(textFile) f); |
$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"); |
MAINSAIL Utilities User's Guide, Chapter 32