eToken R2 Open-source Implementation
Abstract:
This project intends to provide open-source support for Aladdin's eToken R2
under Linux and other operating systems by implementing all necessary APIs and
tools.
The project focuses on understanding the operation and protocols of the eToken
R2, and implementing an SDK for Linux to work with these tokens. The project
also aims at creating end-user tools and wrappers.
A link to this project's SourceForge summary page can be found
here.
The (now probably deprecated) eToken R2 was one of the first tokens produced by
Aladdin (now SafeNet)
around 2002.
The device can hold data in one of three
security levels
- Public
- Available to everyone holding the token.
- Private
- Available to everyone holding the token, and knowing the token's
password
- Secret
- Available only to the token itself (and the manufacturer). Isn't
available to the token's holder, owner or perpetrator.
On top of these three security levels, the token implements the following:
- Disk-on-key style storage
- Arbitrary files may be stored on the token,
and accessed freely by just plugging it in. It is referred to as 1-factor
authentication (what-you-have).
- Protected storage
- Along public files, private files may be stored. These
files may also contain arbitrary data, but access to them will not be granted by
the token unless the user has logged into it using a password. This referred to
a 2-factor authentication (what-you-have and what-you-know).
- Key files
- Similarly to public and private files, two types of key files
may be created on the token. These 128-bits (120-bit effective) files are
write-only, and cannot be read once writtencorrect?.
Key files are useful as the token allows you to encrypt and decrypt arbitrary
data using these keys, without getting the keys out of the device. Public
key-files may be used by anyone holding the token, while private key-files may
only be used by logged-in users. Again, these are called 1-factor and 2-factor
keys (not to be confused with private and public keys of an asymmetric cipher).
In addition, the device supports on-chip key
generationverify.
Hardware-wise, it is a simple security device, basically containing two
components: An 8-bit micro-controller responsible for USB communication,
encryption algorithm implementation and the token's secret data storage,
providing the trusted environment for the token; and an external EEPROM, up to
32-kilobytes in size.
The secret token's key is stored on the MCU itself, and is inaccessible, even
to the token's owner. It is known only to the manufacturer. It is claimed to be
generated off of a true random seed for every token. The token's security is
built around this key - having it will compromise all the data on the token,
and everything the token gives access to. However, it should be very hard to
extract this key from the token, even with unlimited physical access and
destructive operations on the chip.
The on-device DES implementation isn't used directly, as 56-keybits isn't secure
enough these days. Instead, the hardware utilizes a variant of the DES-X
algorithm (see section 3.1), which uses a much stronger 120-bit
keys.
The external EEPROM holds the device's storage (files and key-files). It is
encrypted, probably using the token's internal key, making it useless to read
it directly.
1.1 Filesystem Overview
The eToken supports an hierarchical filesystem structure much like any other
filesystem. All files and directories have a 4-letter name representing a
16-bit hexadecimal number composed of four of the letters: 0 through 9 and A
through F.
Four types of files can be stored on the token:
- Root Entry
- Only one exists. It is the base directory, and all other files
on the token must be under it (though not directly). The token's root is
referenced with the path /3f00.
- Directories
- A directory may lay directly under the root, or under another
directory. Directories may be public or private.
- Files
- File may lay right under the root directory, or under another
directory. Files hold arbitrary data.
- Key Files
- Like files, only used for encryption and decryption.
In addition to arbitrary files and directories the user may store on the token,
there are a few built-in files that have special meaning:
- /3f00/a1a1
- Application mapping filewhat
is that?
- /3f00/8000/0004
- Token caching mode. Either 0 or
1. Indicates (and I guess) whether filesystem changes to the token
should be cached, or flushed immediately.
- /3f00/8000/aaaa
- Token's name. User customize-able name for the
token.
Support for the eToken R2 under Linux is under development. I am currently
implementing the basic protocol level (ifdh) to communicate with the token, with
a few user-programs to work with the token on top of that.
Currently, libifdh is capable of the following:
- Attached tokens enumeration
- Config-word fetch and parse
- Complete file-system parsing
- Log-in and Log-out of the token
- Enumerating directories
- Reading public and private files
- Encrypting and decrypting using key files
Still needs to be implemented:
- Writing to public and private files
- Writing 1-factor and 2-factor key files
- Creating files/keys/directories
- Deleting files/keys/directories
- Changing token password
The quickest way to get you're token working.
etrtool is a command-line tool exposing libifdh capabilities to the
user. Its source may be accessed, along with libifdh source on our
SourceForge project page.
See the README file for build instructions.
The latest version's man page
is available
online, too.
Still under developement. Will provide an OpenCT driver for the eToken R2 to
allow use with OpenSC (which will open the eToken R2 to a world of applications
such as OpenSSL, OpenSSH, Firefox, Thunderbird, Enigmail, GnuPG etc.)
This section contains documentation of the research being done on the token. It
is intended to eToken R2 ifdh developers.
3.1 DES-X Application
Internally, the token implements the DES algorithm. However, to increase
security, a variant of the DES-X algorithm is implemented on top of DES, using a
120-bit augmented key (instead of the 56-bit DES key). DES-X is defined as
follows:
Therefore, for a true DES-X application, a 184-bit key is needed (64-bits
for , 56-bits for and 64-bits for ). The eToken uses a shorter,
120-bits key, where .
From now on, we'll reference an eToken DES-X key a a pair of two keys
, where is a 64-bit DES key (56-bits effective, every
8th bit is ignored) and is a 64-bit block corresponding
to and .
The eToken R2 is communicated through USB control
transfers. Every interaction with the token requires the host to send two
control messages: Request and Result.
A basic understanding of USB packets is required for the following sections.
3.2.1 Request Control
The request control directs the token to perform an action with some optional
arguments. It may directs it to read a memory address, or to generate a
challenge for login.
The host should set the request packet's values as follows:
Table 1:
Request Control USB Packet Structure
Request Type |
0x40 |
Request Code |
Command to perform (see table 3) |
Value |
Command argument used in some commands. Set to 0 if not
in use. |
Index |
Not in use (set to 0) |
Buffer |
Command's input data (NULL if none) |
This transfer should be followed with a result control, to obtain the token's
response.
The result control message stimulates the token to give back the result of the
previous operation requested from it with the Request Control (see section
3.2.1).
The host should set the request packet's values as follows:
Table 2:
Result Control USB Packet Structure
Request Type |
0xc0 |
Request Code |
Respective request control request code, ORed
with 0x80. (MSB high) E.g., If this is a result control for
request 0x04, set field to 0x84) |
Value |
Not in use (set to 0) |
Index |
Not in use (set to 0) |
Buffer |
Buffer to store token's response data. Should be at least one
byte in length for result code (see below) |
After sending this control packet, our buffer should contains the token's
result data. You should always check the last byte of this buffer, as it is
appended the the expected data by the token. This byte contains the token's
success code for the operation. 0 indicates success, and all other
values indicate failure.
Table 3:
eToken Request Codes
Request Code |
Function |
Value Field |
Buffer |
0x00 |
Request login challenge |
Not in use |
Not in use |
0x01 |
Submit login response |
Not in use |
Response to token's challenge (see section 3.4) |
0x03 |
Log-out |
Not in use |
Not in use |
0x04 |
Get configuration word (see section 3.3) |
Not in use |
Not in use |
0x05 |
Unknown |
Unknown |
Unknown |
0x06 |
Read from memory address |
Address to read from (Big-endian) |
Not in use |
0x07 |
Write to memory address |
Address to write to (Big-endian) |
Block to write |
0x08 |
Write to key file |
Not in use |
Key buffer (see Section 3.5.4) |
0x09 |
Select DESX Key |
Not in use |
8-byte buffer with three address ranges (see Section 3.5.2) |
0x0a |
Key action |
0 to decrypt, 1 to encrypt |
64-bit block (see section 3.5.3) |
3.3 Configuration Word
The first thing you'd probably want to do when you encounter a token connected
while enumerating attached USB devices is to read its configuration word. The
token's configuration word is essential to know which token is connected, and
what can be done with it.
The configuration ``word'' is an 26 bytes long buffer, structured as follows:
Figure 1:
Configuration word structure
|
- Unidentified
- 16 bytes of unidentified data
- Firmware Version
- eToken's firmware version
- Token ID
- Current token's unique ID
- Filesystem Address
- Address from which to read filesystem (see
section 3.6)
To obtain the configuration word, call the token with request code
0x04 (see table 3). Don't forget to allocate 27
bytes for response, and check the last byte as the operation's status code!
3.4 Log-in Challenge-response
When the token is first connected to a computer, it is in the logged-off state.
In this state, the user is able to access public files and key-files only. To
access private data, the token must be logged-in.
The login process with the token is a simple challenge-response protocol.
First, the host requests the token for a challenge, initiating the login
process. The host does so using the command 0x00 (see
table 3). The token then generates a 64-bit
pseudo-unpredictable challenge, . The host then calculates the response as
follows:
Where:
- is the response to send to the token
- is DES-X key as described in section 3.1. is derived
from the 128-bit digest over the token's password so that
the first 64-bits of the digest are and the last 64-bits are .
- is the DES-X encryption function with key on
block
As expected, the response to the challenge is also a 64-bit block. This response
is sent to the token using command 0x01 (see
table 3). If the last byte of the response buffer is zero,
the token is now in the logged-in state.
3.4.1 Session Key
Once logged-in, all private-data read and written to and from the token is
encrypted using a session key. The session key
is a
120-bit DES-X key as described in 3.1, derived from the response as
follows:
Where:
3.5 Encryption and Decryption using Keys
In order for encrypted data to be portable to the Windows implementation of the
eToken SDK, we must comply with its protocol.
3.5.1 Key Files
Key files are stored on the token as 24-byte files. These files aren't readable,
they are write-only. As described in Section 3.1, the token's
implementation of DESX assumes that , allowing us to store only
16 bytes of key data. However, this is not the case. When addressing a key, we
must specify three address ranges, each 8-bytes long (presumably ranges for
). When writing to a key, we specify 24-bytes addresses, but
supply only 16-bytes of key material. These three address ranges are always
consecutive in memory.
3.5.2 Selecting Key File
To perform a DESX function with a key file, we must first select the current
key file with command 0x09.
The token expects to find an 8-byte buffer with this request, structured to
point to as follows:
Figure 2:
Set DESX Key Command Buffer Structure
|
The token should respond with a single byte indicating success.
3.5.3 DESX Operations with Current Key
After notifying the token which key we would like to use (see Section
3.5.2), we send the 0x0a command, to perform actual DESX
function. (The Value field indicates whether we're encrypting or
decrypting, see Table 3). The token can only operate on
one block at a time.
Since DESX is a block cipher, padding must be used. The eToekn R2 employs the
padding method suggested in
RFC 1423 (Section 1.1):
The input to the DES CBC encryption process shall be padded to a multiple of 8
octets, in the following manner. Let be the length in octets of the input.
Pad the input by appending
octets to the end of the message,
each having the value
, the number of octets being added. In
hexadecimal, the possible paddings are: 01, 0202,
030303, 04040404, 0505050505, 060606060606,
07070707070707, and 0808080808080808. All input is padded
with 1 to 8 octets to produce a multiple of 8 octets in length. The padding
can be removed unambiguously after decryption.
IMPORTANT! Since the token can only handle one block at a time, the
block-cipher mode in use is up to the implementation. It seems that the Windows
SDK implementation has chosen the incredibly inadequate ECB mode
(probably because it's the only mode that doesn't require an IV). This insecure
behavior must be imitated for our implementation to be able to work with the
Windows implementation. I have also introduced into the API an optional cipher
mode argument, allowing the use to select a different cipher mode (such as CBC).
These outputs, however, are not compatible with Windows SDK outputs and
vice-versa.
3.5.4 Writing Key Files
Key files are writable. To write to a key file, you must be logged-in. Key
files are written using the 0x08 command. The buffer expected by the
token is the same buffer as in the select key command, except 16-bytes
of key-data encrypted with the session key (see
section 3.4.1) should be appended, like so:
Figure 3:
Write DESX Key Command Buffer Structure
|
3.6 Filesystem
Please read section 1.1 before reading on.
The eToken should be regarded as a 64-bit block device (corresponding to a DES
block size). Aladdin has implemented a simple block allocation table structure
indexing the block-to-file allocation.
The filesystem is a list of 64-bit entries, as follows:
Figure 4:
Filesystem Structure
|
Notice that the first entry is a header (or signature) entry, which does not
hold file information. Instead, it should read:
Note that entries in the filesystem appear in no particular order, except the
root entry 3f00 is always first.
To get the filesystem from the token, invoke the read-from-memory command (see
table 3) on the address indicated in the configuration
word (see section 3.3). The operation will return the entire
filesystem index. Be sure to allocate enough space for all the entries,
signature and last status byte in the receive buffer. I found that my 16kb token
returns 31 entries in addition to the signature entry.
Each entry should look as follows:
Figure 5:
Filesystem Entry Structure
|
- Name
- Entry's name.
- Size
- File size, in bytes (if file or key file)
- Attributes
- Read as follows:
Figure 6:
Attributes Field Structure
|
- Address
- Address of first file's block to be used with read-from-memory
command
- Key
- Whether the entry is a key file
- Public
- Whether the entry is public
- Type
-
Table 4:
Filesystem Attribute Entry Types
Value |
Type |
1 |
File |
2 |
Directory |
3 |
Key File |
- Parent
- Index of parent's folder entry in the filesystem. Index 0
means this entry is right under the root. See figure 4.
Generated by z9u2k at Sat Jan 15 11:44:58 UTC 2011