Did you *really* zeroize that key?

Alan Barrett apb at cequrux.com
Fri Nov 8 03:58:32 EST 2002


No crypto here, just C language lawyering.

On Thu, 07 Nov 2002, Don Davis wrote:
> At 3:07 PM +1300 11/7/02, Peter Gutmann wrote:
> >> [Moderator's note: FYI: no "pragma" is needed.
> >> This is what C's "volatile" keyword is for. 
> >
> > No it isn't.  This was done to death on vuln-dev,
> > see the list archives for the discussion.
> >
> > [Moderator's note: I'd be curious to hear a summary --
> > it appears to work fine on the compilers I've tested.
> >                                           --Perry]

It certainly appears to be guaranteed by my reading of the c89 and c99
standards.  See below for citations.

On Thu, 07 Nov 2002, Don Davis wrote:
>      * michael wojcik explains (to peter, pavel, and
>        kaminsky) why "volatile" isn't as good as his
>        external call:
>          - "passing a volatile object to memset
>             invokes undefined behavior"

I don't believe this, unless you have citations to sections in the
standards.

>          - "access to volatile objects may be
>             significantly slowed" 

Yes, sure.

>          - "volatile seems like the sort of thing
>             broken implementations may get wrong"

Perhaps.

> i asked an expert friend (32 yrs of compiler development)
> [he says:]
>    * the c99 standard and its predecessors don't
>      at all intend "volatile" to mean what we naively
>      think it means.  specifically, in the hands of a
>      high-end compiler developer, the spec's statement:
>         "any expression referring to [a volatile]
>          object shall be evaluated strictly according
>          to the rules of the abstract machine"
>      is really talking about what the compiler can
>      infer about the program's intended semantics.

I strongly disagree. The whole point of the volatile qualifier is to
tell the compiler that external things that it doesn't know about might
read and write the value behind its back, and that the sequence of reads
and writes done by the program are important.

The c89 standard was not quite as clear as c99, but c99 says:

        Accessing a volatile object, modifying an object, modifying a
        file, or calling a function that does any of those operations are
        all side effects, which are changes in the state of the execution
        environment.  [ISO/IEC 9899:1999 section 5.1.2.2.3 paragraph 2]

        In the abstract machine, all expressions are evaluated as
        specified by the semantics. An actual implementation need
        not evaluate part of an expression if it can deduce that its
        value is not used and that no needed side effects are produced
        (including any caused by calling a function or accessing a
        volatile object).  [ISO/IEC 9899:1999 section 5.1.2.3 paragraph 3]

        An object that has volatile-qualified type may be modified
        in ways unknown to the implementation or have other unknown
        side effects.  Therefore any expression referring to such an
        object shall be evaluated strictly according to the rules of the
        abstract machine, as described in 5.1.2.3.  [ISO/IEC 9899:1999
        section 6.7.3 paragraph 6]

Section 5.1.2.3 gives implementations permission to optimise, but only
if no needed side effects are produced.  Section 5.1.2.2.3 says that
accessing a volatile object is a side effect.  Section 6.7.3 says that
external factors unknown to the implementation might depend on accesses
to volatile objects.  Unfortunately, I can't find a definition of a
"needed" side effect, as opposed to an un-needed side effect, but I
think the overall intent is clear, and I think that the parenthetical
phrase in section 5.1.2.3#3 implies that accessing a volatile object is
a "needed" side effect.

The C++ standard makes the intended meanting of the volatile qualifier
even more clear by adding words like "The observable behavior of the
abstract machine is its sequence of reads and writes to volatile data
and calls to library I/O functions."  [ISO/IEC 14882:1998 section 1.9
paragraph 6]

>      a c99-compliant compiler _can_ legitimately
>      remove a volatile access, as long as the compiler
>      can deduce that the removal won't affect the
>      "program's result."  here, "the program's result"
>      is defined by the compiler's sense of what the
>      "abstract machine" is:  the abstract machine
>      is mostly defined by the language features, but
>      can also take into account whether a debugger
>      or specialized hardware are running during
>      compilation & or runtime execution.

An interesting argument.  But I claim that there's no way for an
implementation to know whether the program is running/will run in
emulated hardware rather than real hardware, nor whether or not a logic
alalyser is/will be attached to the bus.  Logic analysers and hardware
emulators would allow the accesses to volatile storage to be observed,
and the implementation would have to ensure that the observations
matched the behaviour intended by (the orthodox interpretation of) the
volatile qualifier.

>    * standards-compliant compilers normally distinguish
>      between "conformant" source programs and "noncon-
>      formant" source programs. [...] so, in the case of
>      "volatile," a compiler won't necessarily be bound
>      by the "rules of the abstract machine," unless the
>      source program strictly conforms to the language
>      spec's "best practice" definition of how a C/C++
>      program ought to look.

True.  But any compiler that tried to use such arguments to weasel out
of the requirement to handle volatile in the expected way would become
unpopular.

>    * finally, my friend gives the example of a compiler
>      that might decide to make a copy of our key buffer
>      at runtime, in pursuit of some optimization.  the
>      compiler might have the program zeroize one copy of
>      the key, but not the other copy.  as long as the
>      program's end result turns out to be "correct,"
>      such a bizarre trick can still fulfill the language
>      spec.

Declaring the buffer as volatile would remove the compiler's licence to
do such optimisation.

--apb (Alan Barrett)

---------------------------------------------------------------------
The Cryptography Mailing List
Unsubscribe by sending "unsubscribe cryptography" to majordomo at wasabisystems.com



More information about the cryptography mailing list