Introduction
One of the major design goals of the Crypto iButton firmware
is to give the service provider enough flexibility to support
a broad range of security related applications. The two main
components of the firmware that meet this goal are the command
interpreter and the script interpreter. The command interpreter
provides a set of firmware commands that allow the service provider
to create a complete transaction group. A transaction group contains
data objects (money registers, exponents, moduli, etc.) and script
objects. Script objects contain a set of instructions for the
manipulation of the data objects. The script interpreter carries
out these instructions.
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
Script Language
ComponentsObjects
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.
Composite Objects
Composite (or nested) objects are simply objects that contain
embedded objects within their data area. They are used to bundle
several pieces of information together in a single packet that
can be interpreted later by another Crypto iButton. Using composite
objects is a good way to reduce the number of objects contained
within a transaction group. The data area of a composite object
is shown in the Figure 2 below.
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 |
Script Operators
The Crypto iButton script language provides several operators
that allow for the manipulation of object data. There are several
types of operators including arithmetic, assignment, and comparison
operators. This section provides a detailed description of all
operators supported by the Crypto iButton script language.
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.
Assignment Statements
There are 2 different assignment operators, regular assignment
:= and the composite assignment <-. The only difference between
the 2 operators is that the <- operator includes the objects
type and length before copying its data field.
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.
Flow Control
The Crypto iButton executes scripts in sequence unless told to
do otherwise by a conditional or unconditional jump statement.
There are two conditional statements supported in the Crypto iButton
script language, the comparison statement and the If-Then-Else
statement, and three unconditional statements, the Goto,
Continue, and Exit statements.
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.
Functions (Software ICs)
The Crypto iButton script language provides very little in the
way of operators and even less for flow control. Because of these
limitations is it is not convenient for implementing complex cryptographic
algorithms such as hashing functions and block ciphers. In order
to provide support for these and other complex operations the
script interpreter4 allows calls into a function library.
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.
Group Source File
The script compiler requires two input files to generate script
objects, the group source file (with an extension of .ibg) and
a symbol file (with an extension of .sym). The group source file
is comprised of a declaration section and one or more implementation
sections. The declaration section defines all group objects used
by the scripts and specifies their attributes. The implementation
section contains the script source code. These sections will
now be described in detail.
Object Declaration Section
The object declaration section begins with the heading TransactionGroup,
followed by the group name. A transaction group designed for
exchanging a triple DES key might have the following header statement:
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 Implementation Section
A script implementation section consists of 2 parts. The first
is the script declaration that begins with the reserved word script
followed by the name assigned to the script in the object
declaration section.
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.
Symbol File
Symbol information is maintained in a file with a sym extension.
The symbol file assigns object ids to objects declared in the
group source file. The following symbol file would be used with
the key exchange group file described above and is the simplest
form of the symbol file. It gives no information about the objects,
aside from the ids, and would produce objects with default sizes
and initialized with all zeros.
RSAMod =$01 PublicExp =$02 SecretExp =$03 DESKey =$04 EncryptDESKey =$05 DecryptDESKey =$06 Result =$A0 Pad =$A4 |
Symbol File Preprocessor
The script compiler preprocesses the symbol file before processing
the group source file. Lists of preprocessor arguments can be
added for each object in the symbol file to further describe its
attributes such as size and initial data. The list for an object
begins with the sequence {+ and ends with the sequence
-}. The preprocessor is not case sensitive.
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 |
Tools
There are two software development tools currently available for
programming Crypto iButtons. The first tool, scompile,
takes two input files, a group source file, <filename>,
and a symbol file, <filename>.sym. If these files
compile successfully, two output files are generated, an output
listing file, <filename>.out, and an iButton memory
file, <filename>.imf. If the compile does not succeed,
only the output listing file, containing errors, is generated.
The second tool, imftocib uses the contents of the iButton
memory file (iMF) to create the group (described in the input
files) in a Crypto iButton.
Output Listing File (.out)
The output listing file, generated by scompile, contains
information that is dependent on the success or failure of the
compiler. If the compile succeeds, this file contains information
about the transaction group. This information includes the name
of the group, a list of objects contained within the group and
a hex dump of the scripts generated. If the compile fails, the
file contains error information including the reason for failure
and the line number where the failure occurred.
iButton Memory File (.imf)
The iMF contains an image of one (or more) transaction groups
as it might appear in a Crypto iButton's memory space. This intermediate
file allows a transaction group to be programmed into one or more
Crypto iButtons, using imftocib, in a relatively short
period of time (button created objects may stretch this
period significantly depending on object size).
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