Routines for accessing certificates and other memory-mapped files
Note: The functions caddcert, cgetcert, cgetvernum
and cfindcertfield, which were present in the AMS 1.xx TIOS jump table, don't
exist in the AMS 2.xx TIOS jump table any more. Fortunately, all of them are only internal routines;
you need to use FL_addCert, FL_getCert
and FL_getVerNum from flash.h instead.
In AMS 2.xx, the function replacing ROM_CALL 12C (cgetcert in AMS 1.xx), is HeapWalk.
short ceof (CFILE *context); |
Returns end-of-file status of the context.
ceof returns TRUE if the end-of-file indicator of the file associated with the file context pointed to by context is set, otherwise it returns FALSE.
short cfindfield (CFILE *context, unsigned short FieldID, CERT_FIELD *dest); |
Finds a matching field from a context.
cfindfield searches a file associated with the file context pointed to by context for a
field which has field ID number equal to FieldID (length bits should be set to 0).
If such field is found, cfindfield fills the field descriptor structure pointed to by dest
and returns TRUE, else returns FALSE.
cfindfield is used often in TIOS to access particular data in a certificate file. Usually,
function copensub is called immediately after cfindfield to get
access to the content of the field. If the field contains subfields, this procedure may be
repeated several times if necessary.
As an illustration of layout of certificate files, the layout of certificate files used in TIOS
is given below. First, the field ID number is shown, then the short description of the field
follows. Indentation shows that a particular field is a subfield of the field with smaller indentation.
Layout of AMS header (AMS is part of TIOS which may be replaced, in opposite to Base Code); it starts at address 0x212000 on TI-89 and 0x412000 on TI-92 Plus:
0x8000 AMS header (organized as a certificate file, although it is not read-protected like "real" certificates) 0x8010 First part of Product ID 0x8020 Third part of Product ID 0x8030 Fourth part of Product ID 0x80A0 Second part of Product ID 0x8040 Product Name: "Advanced Mathematics Software" 0x0320 Product code (6 bytes) 0x0200 Signature - encrypted MD5 (see rsa.h) of 0x320 field (including header) 0x8070 Actual AMS code 0x0200 Signature of entire AMS
Fields with ID numbers 0x0320 and 0x0200 contains some authenticated number. More precise, field with ID number 0x0320 is a unique number for the ROM imate, and field with ID 0x0200 is the encrypted digital signature of it. Product ID is formed by applying format string "%02lX-%lX-%lx-%lX" to the content of fields with ID numbers 0x8010, 0x80A0, 0x8020 and 0x8030.
Layout of Flash ROM certificate (it is stored in the part of the Flash ROM which is read-protected, so reading it is extremely hard from any routine which is not the part of the TIOS Base Code); it starts at address 0x210004 on TI-89 and 0x410004 on TI-92 Plus:
0x0330 Flash ROM certificate 0xA10 Five-byte Serial Number (used as "pass phrase") 0xA20 Certificate Key
Serial number has layout #sssss sssss cccc (all digits are in hex). First ten digits are picked up from the field with ID number 0xA10. Then, the Certificate Key is used to decrypt the MD5 (see rsa.h for more info about RSA encryption) of the Serial Number to get cccc. In fact, decrypting the Serial Number in this way creates a 40 byte number. Only first two bytes (in little endian) are taken for cccc. This method ensures that only TI can create valid Serial Numbers, as both the Serial Number and Key are unique for each machine.
Layout of .cer files, which are attached to the start of Flash applications:
0x0300 Flash application certificate 0x0100 Certificate Revision Number 0x0400 Five-byte Serial Number 0x0500 Optional field in .cer files 0x0510 Author name 0x0320 Product code 0x0200 Product code signature 0x0700 Unknown certificate data 0x0710 Unknown byte data 0x0730 Signature 0x0710 Unknown word data 0x0730 Signature 0x0710 Unknown word data 0x0730 Signature 0x0200 Signature of all certificate data
Of course, such data are present in the certificate memory only if you have installed additional Flash applications. Function FL_addCert is used to add such data to the certificate memory (this routine performs very strong checking of what may be written there and under what conditions, so it is not possible to write a garbage in this area by calling this routine).
As it is not possible to access the certificate part of Flash ROM directly, ecxept from the Base Code part of TIOS (this area of ROM is read-protected), the usuall method for reading certificates is to call FL_getCert first. This function will copy all data from the certificate area which may be shown to the public into the RAM, so the certificate can be read later from the RAM. For example, if you need to access the certificate data which shows the name of the author of an Flash application (assuming that such data is present in the certificate), the usual procedure is:
HANDLE handle; unsigned long size; CFILE context; CERT_FIELD field; ... FL_getCert (&handle, &size, FALSE); copen (&context, HeapDeref (handle), size); cfindfield (&context, 0x300, &field); copensub (&context, &field); cfindfield (&context, 0x500, &field); copensub (&context, &field); cfindfield (&context, 0x510, &field); copensub (&context, &field);
After this, context.Pos will point to the author name. Alternatively, you can pick the name character-by-character using cgetc. If any of calls to cfindfield functions fail (i.e. return FALSE), then such data are not present in the certificate area.
unsigned char cgetc (CFILE *context); |
Gets a character from a context.
cgetc gets a character from the file associated with the file context pointed to by context, and moves the file pointer to the next character. This function is functionally equal to
*(char*) context->Pos++;
short cgetcertrevno (long *dest); |
Gets a certificate revision number.
cgetcertrevno fills the variable pointed to by dest with the certificate revision number. Returns TRUE if the operation was successful, otherwise it returns FALSE.
unsigned long cgetflen (CFILE *context, unsigned short FieldIDWord); |
Gets the length of a field.
cgetflen returns length of the field which has ID word (see cread) equal to FieldIDWord. This information is present in lower 4 bits of FieldIDWord if these bits are smaller or equal to 0xC. If not, necessary information needed to calculate the length are read from the context pointed to by context. cgetflen returns 0 if the end of the file is reached.
long cgetfnl (CERT_FIELD *field); |
Gets a non-aligned long integer from a field.
cgetfnl gets a long integer (which does not necessarily need to be aligned on an even address) from the field described by the structure pointed to by field. The field need not to be exactly four bytes long; it can be of any length, and cgetfnl gets as many bytes as are available, up to the size of a long.
long cgetnl (CFILE *context); |
Gets a non-aligned long integer from a context.
cgetnl gets a long integer (which does not necessarily need to be aligned on an even address) from the file associated with the file context pointed to by context, and moves the file pointer forward by four characters. In fact, it calls cgetc four times, and combines four returned bytes into one doubleword.
short cgetns (CFILE *context); |
Gets a non-aligned short integer from a context.
cgetns gets a short integer (which does not necessarily need to be aligned on an even address) from the file associated with the file context pointed to by context, and moves the file pointer forward by two characters. In fact, it calls cgetc twice, and combines two returned bytes into one word.
void cgetsn (char *dest); |
Gets the calculator serial number from the Flash ROM certificate.
cgetsn fills the buffer pointed to by dest with the calculator serial number picked from the Flash ROM certificate. It has the form "pphnnnnnnn", where "pp" is the platform number (01 for TI-92 Plus, 03 for TI-89), "h" is hardware revision level, and "nnnnnnn" is an ID number which is unique to each calculator. All the above fields consist of hexadecimal digits. buffer must be at least 17 bytes long to accept the serial number.
void copen (CFILE *context, char *data, unsigned long size); |
Opens a certificate file context.
copen opens a memory mapped file which starts at address data, and which is size bytes long. It also initializes file context (this is a file control structure of type CFILE) pointed to by context. It does not reserve any memory. In fact, copen does nothing more than
context->Start = context->Pos = data; context->End = data + size; context->EOF = FALSE;
Note: All functions from this header file are used in TIOS exclusively for accessing certificate files, which are stored in the protected area of Flash ROM, and which contain certificate data. However, these functions are not limited to such files. They may be used with any memory mapped file (i.e. a "headerless" file which does not have an entry in the VAT table), which does not need to be a file which really contains certificate data.
void copensub (CFILE *context, CERT_FIELD *subfield); |
Opens a subcontext.
As the certificate file is usually consist of various field, this function is used for initializing the context pointed to by context to point to the actual content of the field described in the structure pointed to by subfield. This function is equal to
copen (context, subfield->Data, subfield->Len);
copen is used mainly to reset the file pointer to the start of a group of items. See cfindfield for more info.
short cputhdr (CFILE *context, unsigned short FieldID, unsigned short len); |
Puts a field header to a context.
cputhdr puts a field header to the file associated with the file context pointed to by context and moves the file pointer accordingly. The field header includes ID word (i.e. field ID number and four length bits), and up to four length bytes if necessary (see cread for more info about fields). Required data for forming the header are taken from parameters FieldID and len. cputhdr returns TRUE if the operation was successful, otherwise it returns FALSE.
void cputnl (CFILE *context, long l); |
Puts a non-aligned long integer to a context.
cputnl puts a long integer l to the file associated with the file context pointed to by context, and moves the file pointer forward by four characters. The stored integer will not always be aligned on an even address.
void cputns (CFILE *context, short s); |
Puts a non-aligned short integer to a context.
cputns puts a short integer s to the file associated with the file context pointed to by context, and moves the file pointer forward by two characters. The stored integer will not always be aligned on an even address.
short cread (CFILE *context, CERT_FIELD *dest); |
Reads a field from a context.
Certificate files in TIOS (which packages up all the data required to perform
authentification) are well-organized as files of variable-length records called
"fields". So, the different components are split up into various fields, which can
be accessed fairly easily. Each field begins with ID word. High 12 bits of ID
are used as field ID number, and lower 4 bits are used to encode size of the field
(as the length of the field can be a variable size). If these bits are smaller or
equal to 0xC, this value is just the length of the field. If these bits are 0xD,
0xE or 0xF, then the following byte, word or doubleword contains the actual length
of the field. Fields in the file are stored sequentially. They may contain various
data, including other fields (i.e. "subfields"), which are usually opened with
copensub.
cread reads a field from the file associated with the file context pointed to by
context and collects necessary information (field ID number, length
of the field, and the pointer to the actual content of the field) into the
CERT_FIELD structure pointed to by dest. It also
moves the field pointer to the next field, and sets the EOF indicator in the
context if the end of the file is reached. cread returns TRUE
if the operation was successful, otherwise it returns FALSE (this usually
means end-of-file error).
unsigned long ctell (CFILE *context); |
Returns the current position relative to the start of a context.
ctell returns the current position of the file pointer associated with the file context pointed to by context, measured from the start address of the file.
short cwrite (CFILE *context, CERT_FIELD *source); |
Puts a field to a context.
cwrite writes a field described with CERT_FIELD structure pointed to by source to the file associated with the file context pointed to by context. cwrite is the reverse of cread. Returns TRUE if the operation was successful, otherwise it returns FALSE.
unsigned char *const CertificateMemory; |
A pointer to the certificate memory.
This variable contains a pointer to the first byte of the certificate memory.
Note that it always has a value of (unsigned char *const) (ROM_base + 0x10000)
.
typedef struct {
|
A structure describing the records of certificate files.
CERT_FIELD is a structure which describes the variable-length records (usually called "fields") of certificate files. Each field has its ID number, and some ID numbers have predefined meanings in the TIOS (see cfindfield).
typedef struct {
|
A structure representing the context of a memory-mapped file.
CFILE is a structure which represents the context of a memory-mapped file (usually a certificate file).