Security


Can developers use the RSA code included in Magic Cap?


The RSA code used in Magic Cap is licensed only for Magic Cap's use, and developers can not use it. (That's why the API is not exposed to developers.) If your package needs to do public-key encryption, you'll need to license the code from RSA Data Security, Inc. and include it in your package. Click here for more information about RSADSI.


I don't want users to send my package around. Is there a way I can "bind" my package to a particular device?


There are a couple of approaches. A package can "bind" itself to a device (via UnitID()) or to a user (via AssignedName(iCurrentUser)). Binding to a person is at least as good as binding to a device, and it's better for a couple of reasons. If a device is lost or stolen or broken, then restoring a backup to a different device will leave the authority intact and allow your software to keep working. Also, the desktop versions of Magic Cap on Mac and Windows may not have immutable unique unit IDs. Most desktop machines typically don't have that sort of thing.

Cold boots can be a problem, though, if the user does not have a backup they can restore from. They will end up re-personalizing, which will break their connection with the package. In this case it's okay to require them to reinstall your package from floppy via the link. You could even create a small package that you could mail to them that would re-bind the disconnected package to the new authority. (This "back door" package could kill itself after doing its job, reducing the chance that someone will mail it to other people).

The binding process isn't affected by deleting changes, because it changes some data in the source cluster of the package directly by writing to memory. The "delete changes" command throws away the changes clusters but leaves the source cluster alone.

Here are some snippets that show one way for a package to bind itself to a person. As with all security measures, whether real or virtual, this will stop casual criminals but will fail to deter career felons.

These snippets modify parts of the Puzzle sample slightly to add copy protection. The first time the package is unpacked it binds itself to the personalized authority of iCurrentUser. If the package has been bound before, it compares itself against iCurrentUser. If there is a difference then it puts up an announcement and fails to unpack. There are other ways for the InstallInto to fail and perhaps they should put up announcements also. If you want to use the ID of the device instead of the personalized identity of the current user, you could easily substitue UnitID(someNewOctetString) for Authority(AssignedName(iCurrentUser)) and change the data copying code to copy 6 bytes instead of 17 bytes.

It's very important that the object that checks the binding (PuzzleBox 48 in the following snippets) is the first entry in your installer and receiver lists. This ensures that none of your other objects will be installed if your binding check fails.

This way of doing things has a slight downside or two (doesn't everything?). Inserting a RAM card containg the package into the "wrong" device will cause the copy protection window to appear somewhere along the way. It can be pretty annoying.



In Objects.Def:
...changes in the SoftwarePackage...
   .
   .
   autoActivate: false;
   .
   entry28: (Announcement 12);
   .
   .

Instance OctetString 11;
   data: $ 0000 0000 0000 0000 0000 0000 0000 0000 0000;
End Instance;

Instance Announcement 12;    //ipIWantMyMommy!
   flags: 0x0000008B;        // isError, noStamp, urgent, displayOnce
   info: (Text 13);
   stamp: nilObject;
   sound: nilObject;
   publicAddress: iSystemWarnings;
End Instance;

Instance Text 13;
   info: 'You're not my mommy! I want my mommy!';
End Instance;

Instance ObjectList 'Install' 43;
   length: 2;
    entry: (PuzzleBox 'PuzzleBox' 48);
    entry: (Icon 'PuzzleIcon' 55); // put our nice icon in the desk drawer
End Instance;

Instance ObjectList 'Receiver' 44;
   length: 2;
    entry: (PuzzleBox 'PuzzleBox' 48);
    entry: iGameRoomShelf;   // ...into the gameroom we go!
End Instance;

...added to Instance ObjectList 'Text' 26...
   entry5 : (OctetString 11);

In ProtectPuzzle.Def:
...added to Class PuzzleBox...
   overrides InstallInto;   // to do copy protection

In ProtectPuzzle.c:
#define ipProtection MakePackageIndexical(26,5)
#define ipCopyWarning MakePackageFlatIndexical(28)

Method void
PuzzleBox_InstallInto(ObjectID self, ObjectID other, ulong flags, ObjectID parameter, ObjectID packageInstallList)
{
#pragma unused (other,flags,parameter,packageInstallList)
   ObjectID  currentUser, savedUser;
   char   *dataPtr;
   Boolean   idMatches = true;
   ObjectID  device;

   // don't bother looking if running off of ROM card
   device = ObjectContainer(PackagePersistentSource(Context(self)));
   if (!Writeable(device)) {
   // Must not be run from read only media (since we intend to write to memory)
      Fail( packageMustNotInstall );
   }

   // should announce something here
   if (WriteProtected(device)) {
   // Must not be run from write-protected media (since we intend to write to
   // memory)
      Fail( packageMustNotInstall );
   }
  
   // get the current and saved values of the user's id
   savedUser = DirectID(ipProtection);
   currentUser = AssignedName(iCurrentUser);
   if (currentUser == nilObject) {
   // Must be run from personalized device
      Fail(packageMustNotInstall);
   }
   currentUser = Authority(currentUser);
 
   dataPtr = BeginReadExtra(savedUser);
   if (dataPtr[0] == 0) {
      *dataPtr = 'P';
      CopyBytes(BeginReadExtra(currentUser), dataPtr + 1, 17);
   } else
      idMatches = EqualMem(dataPtr + 1, BeginReadExtra(currentUser), 17);

   EndReadExtra(savedUser);
   EndReadExtra(currentUser); 
 
   if (!idMatches) {
      Announce(ipCopyWarning);   // You're not my mommy!  I want my mommy!
      Fail(packageMustNotInstall);
   }
}


When I beam or mail a package to someone, all of the contents of the package go with it. Is there some way to prevent certain pieces of data from not being sent?


No. All of the changes made to a package (data entered, etc.) will travel with the package. If there's confidential data that a user would not want to travel to another person, you might let them know that in your documentation, and discourage them from sending your package to others.


Is there a way to prevent a package from being beamed or mailed?


Unfortunately, there is no way to prevent the user from sending any package from his communicator to anyone else's. That's why copy-protection schemes have centered around binding a package to a particular device, so that it simply won't function if it finds itself in another communicator.