Scripts are actually created using a compiler that runs on a PC or a workstation. The output of the script compiler is a script object to be added to a transaction group. This document is mainly concerned with describing the input to the script compiler, known as the group file, and the language in which it is written. The language features described in this document exist in E-commerce Firmware, revision 1.00.
Crypto iButton objects are the most primitive data structure operated upon by the script interpreter. This section describes the internal representation of objects and the attributes which determine their accessibility.
All Crypto iButton objects are either user objects or automatic objects. The service provider creates user objects using the CreateCiBObject1 command. This is typically when the object's attributes are set.
The internal representation of all objects is the same (see Figure 1). The first byte of the object structure is the object structure length. This byte is set at the time of object creation and determines the maximum length of the object data field. This implies that an object can shrink after creation but never grow past its initial length. The next byte in the object structure is the attribute byte. The attribute byte is simply the bitwise-or of any (or none) of the possible attribute bits. Currently 4 of the possible 8 attribute bits are being used. Table 1 describes the possible attributes of a Crypto iButton object.
Attribute | Definition | Value |
Open | Anyone knowing the group PIN has full read/write access to an open object. | 00H |
Locked | Anyone knowing the group PIN has read-only access to locked objects. Only a script can alter the contents of a locked object. | 01H |
Private | Private objects may not be read or written from outside the Crypto iButton. Only a script has any access to private objects. | 02H |
Destructible | Destructible scripts become inaccessible to the script interpreter when the value of the Crypto iButton's real time clock exceeds the value of the group's destructor object. | 04H |
CiB Created | CiB created objects are elements of key sets generated by the Crypto iButton2. | 80H |
The next byte in the object structure specifies the object's type. Appendix A contains a complete list of Crypto iButton supported objects and their definitions. The length byte specifies the length in bytes of the current object data.
Object structure length (1 byte) | Attribute (1 byte) | Type (1 Byte) | Length (1 byte) |
The memory required for user objects is contained entirely with its transaction group. Table 2 contains a list of user objects, their allowable sizes and their type bytes.
User Object | Size (bytes) | Type byte |
Modulus | 1-128 | 20H |
Exponent | 1-128 | 21H |
Money | 1-128 | 22H |
Counter | 1-128 | 23H |
Script | 4-128 | 24H |
ClockOffset | 4 | 25H |
SALT | 1-128 | 26H |
Configuration | 1-128 | 27H |
InputData | 1-128 | 28H |
Destructor | 4 | 29H |
Automatic (auto) objects are created by the firmware when the Crypto iButton is initialized. The memory they occupy is reserved and their attributes are pre-set. Table 3 contains a list of automatic objects, their attributes, allowable sizes and corresponding type bytes.
Automatic Object | Attributes | Size (bytes) | Type byte |
OutputData 1 | Locked | 1-128 | A0H |
OutputData 2 | Locked | 1-128 | A1H |
WorkingRegister | Private | 1-128 | A2H |
ROMData | Locked | 8 | A3H |
RandomFill | Private | 1-128 | A4H |
The automatic objects are shared between groups. This leads to a different set of rules for auto objects since it is important that transaction groups be completely isolated from one another. The Crypto iButton firmware manages these objects to make sure that one transaction group can not access (read or write) data belonging to another transaction group. Any time the Crypto iButton's command interpreter processes a group level command, it checks to see if a transition from one group to another has occurred. When a different group is accessed the firmware destroys the contents of the OutputData objects. This implies that the OutputData objects are not to be used for long-term storage. It is important that the group author keep this in mind when designing his/her group. The working register is used as a temporary working space for scripts and is unconditionally cleared every time the command interpreter is executed. Also, the integrity of the ROM data object is verified on every execution of the command interpreter.
T1 | L1 | D1 | T2 | L2 | D2 | … | TN | TN | DN | ||
TN = Type byte of embedded object N | |||||||||||
LN = Length byte of embedded object N | |||||||||||
DN = Data area of embedded object N |
The overall length of a composite object can be described as follows:
Where | |
LC | = Length of composite object |
N | = Number of embedded objects contained in composite |
LE | = Length of embedded object |
Addition (+)
The addition operator provides for the binary addition of two
identically sized objects. If the object data fields have different
lengths or the addition results in an overflow the script interpreter
will abort and return an error code.
Subtraction (-)
The subtraction operator provides for the binary subtraction of
two identically sized objects. If the object data fields have
different lengths or the subtraction results in an underflow the
script interpreter will abort and return an error code. This
prevents a money register from ever becoming negative.
Multiplication (*)
The multiplication operator may be used to multiply 2 objects
of any size. If the result of the multiplication is too large
to store in the target object, the script interpreter will generate
an error code.
Exclusive-Or (Xor)
This operator provides for the bitwise exclusive-or of 2 objects.
Like the addition and subtraction operators the Xor operator
requires identically sized objects.
Exponentiation (^)
The exponentiation operator is used for modular exponentiation
only. If the modulus (see below) operator does not follow the
^ operator the script interpreter will not attempt the exponentiation
and will return an error code.
Temp :=InputPacket ^PublicExp; { Illegal } Temp :=InputPacket ^ PublicExp Mod RSAModulus; { OK } |
Modulus (Mod)
The modulus operator produces the remainder of an integer division.
The modulus operator is used in modular exponentiations such
as those required by RSA and Diffie-Hellman.
r :=g ^ k Mod p; |
It is also used in simple modular reductions such as those required by DSA (the digital signature algorithm).
r := g ^ k Mod p; r := r mod q; { Reduce result modulo q } |
Assignment (:=)
This operator assigns the result of an expression to the object
at the left side of the assignment.
Composite assignment (<-)
The <- operator is identical to the := operator except that
the type and length of the object is copied to the data field
of the object at the left side of <-. Both assignment operators
are described in more detail in the assignment statement section
below.
Comparison (=)
The comparison operator compares the type, length and data fields
of the objects on either side of =. If the comparison fails the
script interpreter aborts and returns an error code. The comparison
operator is described in more detail in the script statement section
below.
Member of (.)
The dot operator references objects embedded within a composite
object.
SALT = temp.Salt[1]; { Check the 1st Salt object in temp } |
In this statement the type and length bytes used in the comparison are the type and length of the SALT object contained within temp, not the type and length bytes of temp itself.
Concatenation (&)
The concatenation operator gives a script the ability to append
objects. When the script interpreter appends one object to another
it always includes the type and length as well as the data field
in the copy.
Output <- Balance & Count; |
After the statement above has been interpreted, the Output object will contain the type, length and data of both the Balance and Count objects.
Type-less concatenation (,)
The type-less concatenation operator is identical to the &
operator except that the type and length are not included in the
result.
Output := Balance , Count; |
After interpretation of the above statement the output object will contain only the contents of Balance followed by the contents of Count.
Output <- Balance; |
After this statement is interpreted the data area of Output contains the type byte of Balance, (a money register) the length of the Balance data field and finally the contents of the Balance data field. Everything described below that applies to the := assignment statements, also applies to the <- assignment statement.
The simplest assignment statement copies the data field of one object to the data field of another object.
Output := Balance; |
In this statement the value of the money register (Balance) is copied into the output data object (Output). This is probably not a very useful statement since Balance is probably a locked object and is therefore readable.
When the script interpreter encounters certain objects (such as counters) on the right side of the assignment operator it interprets the behavior of that object and transfers the new object data field to the assignment target.
Output := Count; |
If the value of Count before this statement is interpreted is 5, the new value of count becomes 6. The new value is placed in Output. The salt, clock offset and random fill objects also have special behavior associated with them (see Appendices A and B for details). If these objects are encountered on the left side of the assignment operator, or anywhere in a comparison statement, the script interpreter treats them like any other object.
A more useful assignment statement might combine some input data (perhaps a random challenge), a counter, ROM data and a time stamp.
Temp := (InputPacket & Count & ROM & Time); |
The Temp object now contains the input data combined with the auto-incremented counter, the Crypto iButton's serial number and a time stamp formed by adding the value of Time, to the Crypto iButton's real time clock. The result might then be hashed and the padded result signed with the group's secret exponent.
Output := (SHA1(Temp) & Pad) ^ SecretExp Mod RSAMod; |
Assignment statements must obey a few rules, which are intended to keep the implementation of the script interpreter simple. Embedded objects must not appear on the left side of either assignment operator. The following statements are both illegal.
Temp.Money[1] := Balance; Temp.Salt[1] <- MySALT; |
Also assignment statements are always evaluated from left to right. Parentheses may however be used when writing scripts to enhance readability.
Comparison statements
If the comparison of two objects fails, the script is aborted
immediately and an error code3 is returned. The following code
fragment shows a common use of the comparison statement.
Temp := InputPacket ^PublicExp
Mod RSAMod; { Decrypt signed packet } MySALT = Temp.Salt[1]; { Challenge properly met? } MyMoney := MyMoney+Temp.Money[1]; { OK to increase balance. } |
In this example a random challenge was generated by the Crypto iButton and contained in the object MySALT. Once the signed challenge was received from the recipient it was written into the InputPacket object. The script listed above decrypts the signed packet with the public key (it is assumed that the public key being used has been previously verified). The comparison statement is used to make sure that the SALT object in the resulting packet is the same as MySALT. If they are identical the group's money register balance is increased and the script interpreter returns a successful status code. If the SALT object in InputPacket is not identical to MySALT the script interpreter generates an error code and does not interpret any statements that follow. The comparison statement does not perform an actual jump. It simply continues if the comparison succeeds and aborts with error if the comparison fails.
If-Then-Else
The If-Then-Else statement, unlike the comparison
statement, will perform a jump to an offset that depends on the
result of a comparison. The following code segment shows a typical
If-Then-Else statement.
Temp := InputPacket ^PublicExp Mod RSAMod;
{ Decrypt signed packet }
If MySALT = Temp.Salt[1] Then Begin { Challenge properly met? }
MyMoney := MyMoney+Temp.Money[1];
ErrorCount := ErrorCount;
{ Increment transaction counter } |
This example is similar to the previous one. The difference is that, after the comparison is made, more statements are executed, regardless of the outcome. If the random challenge was properly signed, the group's money register balance is increased. If the comparison fails, an error counter is incremented to keep track of the total number of failures. Regardless of the outcome, a transaction counter is incremented to keep track of the total number of times this script was executed. The Else can be omitted if there are no statements necessary to handle the failed comparison condition.
Goto
The Goto statement performs an unconditional jump to a
label contained within the script that is currently being executed.
This code segment shows two forward jumps to labels located within
the same script. Backward jumps are also allowed.
Temp := InputPacket ^PublicExp Mod RSAMod; { Decrypt signed packet } TransactionCount := TransactionCount; {Increment Transaction Count} If MySALT = Temp.Salt[1] Then { Challenge properly met? }
DoTransaction: AfterTransaction: |
This example performs the same operations as the previous one using Goto statements instead of using the more natural flow of the If-Then-Else statement.
Continue
The Continue statement performs a jump to another script
within the same group. If a script exceeds the maximum object
size (currently 128 bytes), it can be broken into multiple scripts
and an unconditional jump can be made from one script to another.
Script interpreter execution will continue with the first statement
of the target script. These code fragments demonstrate a typical
continue statement.
Script MajorTransaction1; Begin
{Multiple statements using up almost the entire script object} … TransactionCount := TransactionCount; {Increment Transaction Count} Continue(MajorTransaction2); {Continue with next script} End |
Script MajorTransaction2; Begin If MySALT = Temp.Salt[1] Then Begin { Challenge properly met? }
MyMoney := MyMoney+Temp.Money[1]; End Else Begin
ErrorCount := ErrorCount;
{ Increment transaction counter } |
Note: The Continue statement performs a jump, not a call. There is no return to the original script.
Exit
The Exit statement aborts the execution of a script and
returns a user-defined error code. This error code returns useful
information to an application indicating neither success nor failure
but a user-defined code indicating success or one of many error
codes describing the reason for the failure. This code sample
demonstrates one possible use of the Exit statement.
Temp := InputPacket ^PublicExp
Mod RSAMod; {Decrypt signed packet } TransactionCount := TransactionCount; {Increment Transaction Count} If TransactionCount = Temp.Counter[1] Then {Reached max transaction?}
DoTransaction: |
Here a value of zero is returned if the script executed flawlessly, a value of one is returned if the challenge was not met, and a value of two is returned if the maximum number of transactions allowed was reached. The return code is a single byte value.
Function calls may appear only in assignment statements. The following statement calls the SHA1 hash function and signs the result with the group's secret exponent.
Output := SHA1(InputPacket) ^ SecretExp Mod RSAMod; |
The parameter list is comma delimited and must be contained within parentheses. What is actually passed to the SHA1 function is the object ID of InputPacket, not the object data. This is similar to passing parameters by reference in other languages.
Currently (as of firmware revision 1.00) the only cryptographic functions5 supported are the SHA1 and MD5 hashing functions. Other functions such as DES, triple DES and DSA are being considered for addition to the function library.
TransactionGroup('3DES Exchange'); |
The name of the transaction group must be contained within single quotes. The maximum allowable group name length is 16 bytes and may consist of any ASCII characters other than the single quote or parentheses. Note that the group source file is not case sensitive.
The object declarations follow immediately after the heading and are bracketed by the begin and end reserved words6. This section associates object names with their types and assigns their attributes. A sample declaration section for a group that uses RSA for exchanging a symmetric key follows.
TransactionGroup('3DES Exchange'); {
Begin
Locked: { Read only objects }
PublicExp: Exponent; EncryptDESKey: Script; DecryptDESKey: Script; Result: OutputData; Private: { No read/write access to these objects }
Pad: RandomFill; |
The declaration section is divided into open, locked and private subdivisions. The subdivision in which an object is declared determines its attributes. If objects are declared outside of any of these subdivisions the script compiler assumes they are open objects.
Note that any object can be made destructible by appending the word Destructible to the end of its declaration.
EncryptDESKey: Script; Destructible; |
Since this particular sample group does not contain a destructor, the destructible attribute would have no affect on the group.
Script EncryptDESKey; |
If the script itself is destructible, the word destructible should be appended to the end of the script declaration.
Script EncryptDESKey; Destructible; |
The body of a script is contained within a begin and end block that follows the declaration. The entire EncryptDESKey script follows.
Script EncryptDESKey; {
exponent. Begin
|
This sample script contains only a single statement. However multiple statements may be contained within the begin/end block7.
RSAMod =$01 PublicExp =$02 SecretExp =$03 DESKey =$04 EncryptDESKey =$05 DecryptDESKey =$06 Result =$A0 Pad =$A4 |
Size
The size argument begins with the letter S and is followed
by a number indicating the size of the object. This number can
be decimal or hex (128 or $80). The argument S128 is equivalent
to S$80. The following preprocessor line would tell the
compiler to create the InputData object EncryptedDESKey
with size 128 bytes and, by default, will initialize it with all
zeros.
EncryptedDESKey = $04 {+ S128 -} |
Initial Data
The initial data argument begins with the letter I and
is followed with the actual data. There are three types of initial
data. Random data, byte sequences and strings. A repeat value
can follow this argument to indicate that the data provided is
to be repeated multiple times. The repeat value is optional. The
format for initial data is I(RL) or I(B)n
or I'S'n where L is the number of random bytes,
B is a byte sequence delimited with spaces or commas, S is a text
string and n is the number of times the data is to be repeated.
Random data
Random data is indicated with the letter R and is followed
with a value indicating the number of random bytes to be generated.
This random number is generated using a standard C library function,
seeded with the time. The following preprocessor line will create
a Salt object MySalt with size 64 bytes and initialize
it with 64 bytes of random data.
MySalt = $07 {+ S$40 I(R$40) -} |
Byte Sequence
Byte Sequence data is described by a list of space or comma delimited
bytes enclosed between parenthesis. The following line will create
an Exponent object PublicExponent with size 3 bytes and
initialize it with the value 65537.
PublicExponent = $01 {+ S3 I($01,$00,$01) -} |
String Data
String data is described by a text sequence enclosed between single
quotes. The text between the quotes is copied with case preserved.
The following line will create a Configuration object VersionString
with size 64 and will initialize it with the string 'Debit transaction
group, version 1.00'.
VersionString = 10 {+ S64 I' Debit transaction group, version 1.00' -} |
Composite Data
The composite data argument begins with the letter C and
is followed by composite data enclosed between parentheses. The
format for composite data is
C(type1,len1[,initialdata1][; type2,len2[,initialdata2]]…).
The type can be any of the types that can be allowed in the declaration section of the group source file (Salt, Money, etc.). The length is the number of bytes that the type uses within the configuration data. The initial data is optional and is described in the Initial Data section above. The following line will create a Configuration object Config1 with size 40 and with composite data containing a ROMData object, with size 8 initialized with zeros, and a Salt object, with size 20 initialized with random data.
Config1 = $04 {+ s40 C(ROMData,8,I(0)8;Salt,20,I(R20)) -} |
Button Created
The Crypto iButton can generate its own objects, such as an entire
RSA key set consisting of a modulus, a public exponent and a private
exponent or it can generate the modulus and private exponent when
given the public exponent. Note: The object ids for Button
created objects must be ordered correctly and contiguously or
the objects will not be created properly. When the Crypto
iButton generates an entire key set, it creates the modulus first
followed by the public exponent and then the private exponent.
When the public exponent is supplied, the Crypto iButton creates
the modulus in the next object and the private exponent in the
following object. This ordering must be observed in the symbol
file.
The following two lines show examples of key sets generated by the Crypto iButton.
{complete button created key set} CiBModulus0 = 1 {+ S128 B -} CiBPublicExp0 = 2 {+ S128 B -} CiBPrivateExp0= 3 {+ S128 B -} |
{button created modulus and private key} CiBPublicExp1 = 4 {+ S3 I($01,$00,$01) -} CiBModulus1 = 5 {+ S128 B -} CiBPrivateExp1= 6 {+ S128 B -} |
Group Password
An initial password for the group can be specified at the top
of the symbol file. Please note that anyone that has access to
the symbol file will know the initial group password. The password
argument begins with the letter P and is followed by a
byte sequence or a string, described in the Initial Data section,
of size 8 or less bytes. The following lines will set the group
password to 8 'U's using first a byte sequence and then a string.
P($55, $55, $55, $55, $55, $55, $55, $55) |
P'UUUUUUUU' |
Replace With
The Replace With statement provides a mechanism to replace a numeric
constant with a more readable name.
Replace True With 1 Replace False With 0 |
2When an RSA key set is
generated the Crypto iButton automatically makes on of the exponents private. A host
system may use this attribute bit to determine that no one (even the service provider)
ever knew the private exponent.
Back
3Appendix C contains a complete
list of script interpreter error codes.
Back
4Only Crypto iButton
Firmware versions 0.50 and above support function calling.
Back
5Appendix E contains a complete
description of all functions supported as of firmware revision 1.00.
Back
6Appendix B containts a complete
list of reserved words.
Back
7Appendix F contains several
larger sample scripts.
Back