Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Security

Security & Palm OS 5.x


June, 2004: Security & Palm OS 5.x

Masking records and encrypting/ decrypting data

Michael explored Palm OS security because he develops Palm applications for the health-care field. He also serves New York's financial district as a C/C++ consultant and can be reached at myamytechnology.com.


Constructor or PilRC Designer?


Security in the first version of the Palm OS relied partly on physical protection. That is, the handheld was stored on your person and you took care of it much like you would your wallet. In terms of software protection, good security could be had if you configured the device to prompt for a password when you turned it on. For this to work though, you had to turn off and lock the device when you were done with it, a task that was easily forgotten. An autolock feature wouldn't arrive until Palm OS 4.0.

Palm OS 1.0 also implemented a "secret" bit that marked records hidden and required a password to view them. A minor weakness, however, was that the secret bit relied on well-behaved programs to honor its meaning. A rogue program could simply ignore the secret bit, dumping the record's information. Attackers, however, needed to have physical possession of the handheld, get past the power-on password if present, have knowledge of Palm programming, and some idea of the record layout. In those days, such knowledge and experience wasn't widely available, making security through obscurity a reasonable strategy, at least for Palm OS 1.0.

Palm OS 3.5 introduced masked records. Unlike hidden records, masked records made their presence known but had their contents masked. Masked records also relied on the secret bit. An internal system security state determined how the record would be displayed—visible, masked, or hidden. Like the secret records in the Palm OS 1.0, the success of this scheme depended on the cooperation of the applications. This weakness, however, had grown more serious because Palm programming had become much more widespread.

Developers intent on protecting their users' data addressed this weakness with third-party cryptography libraries or rolled their own solutions. The latter was a dicey proposition unless you made a living in cryptography. Recognizing the need, Palm OS 5.0 introduced the Cryptography Provider Manager (CPM) to offer cryptographic services such as data encryption and decryption, message hashing, and message authentication. The CPM currently supports only one algorithm provider—RSA—although future versions of the Palm OS will allow you to plug in other providers. There is no key management to facilitate transferring encrypted data to the desktop and decrypting from there. At least with the first release of CPM, cryptography routines must take place on the handheld.

In this article, I present techniques for using masked records and encrypting/decrypting data. I limit my discussion to Palm OS 5.x (Garnet) and earlier. Palm OS 6.0, the new branch that is also known as "Cobalt," is beyond the scope of this article. The sample program I present builds a simple database consisting of names of famous or semifamous programmers (see Programmers at Work, by Susan Lammers, Microsoft Press, 1986). To keep the program self contained, I created the data as a string list resource. When the demo is run for the first time, the Palm database is created from this string list. To keep the program simple, I used exactly 11 records, just enough to fill a table on a 160×160 screen. That way, I didn't have to contend with scrolling issues. As Figure 1 shows, the demo is interactive. Tap on the checkbox to toggle the state of the secret bit. Use the Security button to change how the Palm OS should display the records. Tap on the masked field and you are prompted for a password before the demo exposes the record contents.

Behind the Mask

The demo, maskedRecs, was built with Metrowerks CodeWarrior R9 and Palm OS 5 SDK R3 on Windows 2000. For creating and managing resources, I opted for PalmSource's Constructor 1.9.1. A popular alternative is PilRC Designer (see the accompanying text box "Constructor or PilRC Designer?"). The arbitrary creator ID for this demo is "DJMR" (short for "Dobb's Journal Masked Recs").

When I created a new project with CodeWarrior, it generated a skeleton program for me, naming it Starter.c (available electronically; see "Resource Center," page 3). Starter.c contains some utility functions such as detecting the OS version. In my example, I set the minimum OS version to 3.5. Starter.c also contains the program entry and exit points, AppStart() and AppStop(), respectively. Inside AppStart(), I obtained the system security state, assigning it to a global variable; see Example 1. Depending on this variable, the database is opened in either "read/write" mode or "read/write/show secret" mode. The global, along with a record's secret bit, is necessary to properly show, mask, or hide a given record. Should the user change the system security state, the database needs to be closed and reopened in the proper mode, and the global variable needs to be updated.

CodeWarrior also generated a skeletal resource file: Starter.rsrc. Of interest is the string list resource titled "AtWork" where I stored developer names and the products they are known for. The string list resource allows a prefix that could be useful if you maintain a lot of string lists. For this demo, I left it blank. In creating a database from this string list, I used a handy routine provided by the SDK: SysStringByIndex(). It copies out a string from the list by index. If I had entered a prefix in the string list resource, the prefix would be inserted in front of the extracted string.

Inside the resource file, you'll also find the table object named "AtWork" on the main form. It has two columns—one for the checkbox and one for the developer name—and 11 rows.

I created a new file, MainForm.c (available electronically) to handle events from the main form and to manage the table. Examining MainFormInit(), you'll find that it sets the table to display a checkbox in column zero and text in column one. Columns are unusable by default, so I enabled them. I also set the attribute of column one (developer name) as maskable so that I may control its appearance without affecting the checkbox in column zero.

Text in tables require special attention. To be drawn properly, they require:

  • A handle to the text.
  • The offset into the handle.
  • The length of the text.

Looking again at MainFormInit(), you'll find that it allocates memory to store a list of names. This memory is freed in MainFormCleanup(). You'll also find the following call:

TblSetLoadDataProcedure (tableP, devNameCol, LoadTextTableItemCB);

This establishes LoadTextTableItemCB() as the callback routine responsible for supplying the Palm OS with the three pieces of text information. LoadTextTableItemCB() is invoked during a table redraw and retrieves the record number associated with a particular row:

recordNum = TblGetRowID (tableP, row);

Table rows can be mapped with arbitrary data. In a function invoked earlier, MainFormLoadTable(), I scanned through the database and mapped the rows with the record numbers I wanted to display using TblSetRowID(). Thus associated, a record can be retrieved using DmQueryRecord() and the text portion of the record copied into memory. LoadTextTableItemCB() can then supply a memory handle to the text, initialize the offset into the handle to zero, and measure and return the length of the string.

Take a closer look at MainFormLoadTable() where the mapping occurs. To retrieve records, I looped through the database using DmQueryNextInCategory(). Like DmQueryRecord(), it retrieves a record for read only (busy bit not set). Unlike DmQueryRecord(), if the database were opened to hide secret records, DmQueryNextInCategory() would automatically skip over records that have their secret bit set. Recall that the open mode was set in AppStart().

Even though this demo doesn't use categories, I can still use this function; passing "dmAllCategories" as the third argument ensures that all records are queried.

Determining whether to mask or expose a record required that I check the record's secret bit and the system security state, which is defined in PalmSource's SDK header file, PrivateRecords.h; see Example 2. If the record were private and the security state set to maskPrivateRecords, I masked the row as in Example 3.

Empty rows were set to unusable and, thus, will not respond to user taps. As a redundant defensive measure, I mapped the disabled rows to a value defined by dmMaxRecordIndex or 0xFFFF. Any calls to query such a record number would fail. A robust implementation could follow up with the SDK's ErrTry/ErrThrow/ ErrCatch macros or, if using C++, exception handling.

Table Events

The event handler, MainFormHandleEvent(), processes two table-related events: tblEnterEvent and tblSelectEvent. tblEnterEvent occurs when users hold the stylus down within a column and row boundary of a table. A tblSelectEvent follows if users lift the stylus up within the same column and row boundary.

Checkboxes are automatically toggled on a tblEnterEvent. To override this default behavior, I trapped this event and wrote a handler to toggle the checkbox, set or clear the record's private attribute, and update the table mask. I also set the handled flag to True, indicating to the Palm OS not to autotoggle the checkbox.

Working with the developer name, I wrote a handler in response to a tblSelectEvent. If the record were masked, the handler would prompt the user for a password with a call to SecVerifyPW(). The net effect of this call is to change the internal security state to show all records. Because I need to show only the selected record, I restored the internal security state with a call to PrefSetPreference().

Using masked records in this manner conforms to the built-in Palm applications (MemoPad, for instance), which provides users with a uniform experience—a good thing. But it's also clear from this demo how easy it is to ignore the secret bit and expose a private record. That's where encryption comes in.

Encryption

The architecture of the CPM is robust, with an API that permits low-level tuning (specifying pad characters, for example), but with default options that make it easy to use. Implementation in OS 5.0, however, is incomplete; without key management, encryption/decryption is confined to your handheld. Palm OS 6.0 may address these shortcomings, but you can't ignore the installed base of OS 5.0 devices. If you are writing software where encrypted data moves between the handheld, desktop, back-end server, and beyond, you need a third-party library.

That said, the CPM will improve and protect local databases. The demo, encryptString, encrypts and decrypts a string. There are two fields—one for you to enter plain text, and one that displays the ASCII hex equivalent. For example, the plaintext "abc 123" in hex, including the null terminator, appears as "6162632031323300" (see Figure 2). After encrypting, the hex display will represent the cipher text, which will vary depending on the encryption key. Upon decrypting, the hex field will, if all goes well, display the original sequence.

Like maskedRecs, this demo was also built with CodeWarrior R9, but as an exercise, I used PilRC Designer 2.0.5.1 for managing resources instead of the Constructor. The resource file is in text format with the name "encryptString_Rsc.rcp" (available electronically). The arbitrary creator ID for this demo is "DJES."

Because CPM is a shared library, a little housekeeping is necessary during startup. In the file encryptString.c (available electronically), AppStart() first determines if the library is already loaded, and if not, loads the library. The library is unloaded when the program ends, inside AppStop(). Similarly, the encryption key is generated during startup and released when the program ends. Because the same key is used throughout the demo, this was the simplest approach, but you should generate and release, store and retrieve, keys where it makes sense in your program.

Keys

The CPM stores key information in the structure APKeyInfoStruct. For the most part, you don't need to work with the fields, but you are responsible for allocating memory for the structure, initializing it, and freeing resources when you're done. This structure is used in key generation, key importing and exporting, and of course, encryption and decryption.

The CPMLibGenerateKey() function creates a symmetric key. Passing in a zeroed key structure requests the default key and populates the structure accordingly. CPMLibGenerateKey() also accepts a seed value that can be a password from the user. Unfortunately, under Palm OS 5.0, the function does nothing with this seed, which means an identical key cannot be recreated from the same seed or password. This is known as "key derivation" and without it, your ability to decrypt from another device or platform is limited.

A key, however, can be exported and cached safely somewhere within the handheld: the preferences database, the application info block, a Palm OS database, or somewhere in expansion memory. Wherever you decide, it would be wise for your design to allow for backups of the exported key. For example, the preference database would be a good choice because it can be backed up to the desktop during a hotsync. I emphasize this because, should the exported key become lost or corrupt, your users won't be able to decrypt their data.

On the handheld, keys are normally exported in RAW format. The design of CPM also allows exporting keys in XML and ANS.1 DER (Abstract Syntax Notation, Distinguished Encoding Rules; see http://www.asn1.org/consortium.htm), which should prove useful when transferring keys between the handheld and other platforms. But when I tried to use either of these two formats, the function CPMLibExportKeyInfo() returned an error 0x3810, which indicates a parameter error. (CPM error types can be found in CPMlibCommon.h.) The architecture does show promise, but the implementation is disappointing.

RAW format worked, and you can test it using the demo. From the menu, select "Options|Export Key...". Examining encryptStringsource.c, you find the function ExportKey(), which calls CPMLibExportKeyInfo() twice. The first call determines how much memory is required to store the exported key so that you may allocate memory appropriately. The second call actually exports the key. The exported key is then imported and is used in subsequent encryption and decryption operations.

Cipher Info

To characterize cipher text, the CPM uses the structure APCipherInfoStruct. It contains fields that describe the encryption and decryption operations, such as the algorithm provider, padding constants, and an initialization vector. Like the key structure, the APCipherInfoStruct is initialized in AppStart() and released in AppStop(). Initializing the structure to zeroes requests the default settings, the approach I used because there's only one algorithm provider to choose from in Palm OS 5.0.

APCipherInfoStruct can be exported to facilitate (future) encryption and decryption on other platforms. Currently, the CPMLibExportCipherInfo() function does not work and causes a "fatal reset" on the device I tested with, the Tungsten C. I coded an ExportCipher() routine but did not invoke it as part of the demo. Similar to the way keys are exported, the function CPMLibExportCipherInfo() must also be called twice.

Closing Thoughts

There are good reasons to implement masked records, even though they provide mild security when used alone. Users seem to like masked records. Typically, they are showing their colleagues something on the handheld and don't want to reveal certain bits of information.

There's less of a reason to use CPM in its current form. One remote benefit is to have your application use CPM for local encryption, thus obviating the need for users to tinker with the built-in Palm OS security options and keeping the entire cryptographic experience transparent.

In future versions of the CPM, I expect PalmSource to support key derivation. As part of a wish list, I'd like to see an external (desktop-based) cryptographic toolkit that imports and exports key and cipher information, and that also implements the same algorithm providers found on the handheld. Another possibility would be to incorporate such a toolkit into the Palm Conduit Development Kit (CDK) so that data can be encrypted and decrypted as it moves between the handheld and desktop. This would eliminate a separate decrypt process should you need to import the handheld data into a desktop spreadsheet or back-end database.

DDJ


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.