-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

(My PGP client botched the signature last time when I used the 
clipboard method.  This time I'm using the plugin button and it should 
work.  Stupid GUI crap.)


I have devised what I believe to be a foolproof and completely
portable way of setting an array of bytes to all zeroes, a common
security operation in cryptography programs.


void
clear_bytes(char magic, char p[], int n)
{
     int i;

     p[0] &= magic;

     for (i = 1; i < n; i++)
         p[i] &= p[i-1];

     for (i = 0; i < n; i++)
         if (p[i] != magic)
             exit(magic);
}


In order to guarantee that this works, you must pass in 0 as the
value of the 'magic' parameter, and you also must establish that 0
value using a method that is completely undecidable even to the most
intelligent compiler optimizer theoretically possible.

Here is a simple example of how we can generate this "undecidable
zero" and pass it into the routine.

int
main(int argc, char *argv[])
{
     char array[32];
     char magic = (argc < 1 ? 0 : 255);

     clear_bytes(magic, array, sizeof(array));

     return 0;
}


If you call this program with no command line arguments, the value of
magic will be 0 and the clear_bytes is guaranteed to zero out the
array.

If you call this program with any command line arguments at all, the
value of magic will be 255 and the clear_bytes routine will exit with
code 255.  So the clear_bytes routine serves a dual purpose as an
assertion that the clearing operation actually occurs properly.  If
it doesn't, your program aborts.

It is impossible for a compiler to optimize away any of this code,
because you can always find a way from OUTSIDE the program to make
magic take on a nonzero value and thus reach the abort condition.

Of course, your program will very likely expect command line
arguments, but you can use a slightly altered technique for
generating the necessary "magic undecidable zero."  For example, if
you know that your program will never be called with more than 5
arguments, just use this line:

     char magic = (argc < 6 ? 0 : 255);

In the very worst case the number of arguments to your program will
be totally indeterminate, with no theoretical upper bound.  This
could easily happen if you expect file names with shell expansion,
for example.  In this case, you could simply require that the very
first argument to your program must always be a specific character,
for example 't'.

     char magic = ((argc > 1 && argv[1][0] == 't') ? 0 : 255);

With this line, if the first argument to the program starts with a
't', magic will take on the correct value of 0.

I do not recommend using anything in argv[0] because that is the
actual name of your program as invoked from the command line.  This
could change if the executable file is renamed or if you call it with
a leading path.

You can always find some way to generate a magic undecidable zero.
Some variation of the argc/argv technique should serve you well in
all reasonable circumstances, but if you absolutely had to you could
read a zero byte out of a file somewhere.

Note that the clear_bytes function 'ands' each byte of the array with
the previous byte, starting with the magic value.  Only a magic value
of 0 is guaranteed to make all the bytes zero.  The second loop then
checks the operation, ensuring that each byte is equal to the magic
byte.  This can only succeed if magic is 0 and all the bytes are 0.
(Actually it could succeed with a nonzero magic value, but only if
all the bytes were already equal to magic to begin with.  Obviously
this case is irrelevant.)

So folks, this routine will definitely zero out an array, and it
doesn't rely on the va_list (vararg) technique described in
Welschenbach's book.

Personally I rarely use global variables, so I like to pass the magic
value around as an explicit parameter wherever it is needed.  But you
could use a global magic variable if you preferred.

- - -- Patrick
http://fexl.com


-----BEGIN PGP SIGNATURE-----
Version: PGP 8.0

iQA/AwUBPl71Y1A7g7bodUwLEQKoywCgg50VenX0boJAeIxrNIYI9KAmhR0AoOvJ
XByLpkEtgt9QhFbmiHokzC3V
=ZLC3
-----END PGP SIGNATURE-----

Reply via email to