Is memcpy secure?

F

Frank Slootweg

Walter Roberson said:
:> As others have said: make sure your processes memory space cannot be moved
:> to permanent storage due to swapping or hibernation for example.

: This should be done for *performance* reasons, not for *security*
:reasons. The swap area should only be accessible to the super user (the
:OP is using Linux) and the super user can get into the process address
:space anyway, whether on (swap) disk (/dev/[r]dsk) or in memory
:(/dev/[k]mem).

You are assuming, Frank, access while the system is still running.
If the system is decommissioned (or the drive stolen), it is
more secure for the sensitive data to never have been swapped to
disk, than to assume that disk-scrubbing procedures will be used
before the disk was made available.

Good point. While you're at it, you (the OP) might also want to make
sure that the system never crashes and leaves a crash dump on disk.
 
S

Sidney Cadot

Frank said:
That assumes physical access to the machine. If someone has physical
access to the machine, *all* bets are off, not just this one.

You're wrong: not all bets are off. For example, I'm willing to bet that
you would be much less likely to find sensitive information on the
swap disk if a cryptographic application is properly written to use
non-swappable memory. In other words, this diminishes the risk of leaks
quite significantly. Which is the best you can do, since, of course,
perfect security is not attainable in practice.

I must say I fail to see the point you are trying to make. That a writer
of cryptographically sensitive software shouldn't care about the
possibility of swapping (as it gains no extra security, as per your view)?

By the same reasoning, you could also dismiss replacing a typed-in
password on screen by asterixes (or plain nothing), since it doesn't
truly help against an observer who is looking over your shoulder?

Best regards,

Sidney
 
N

newstome

In comp.security.misc Frank Slootweg said:
Andras Tantos said:
As others have said: make sure your processes memory space cannot be moved
to permanent storage due to swapping or hibernation for example.

This should be done for *performance* reasons, not for *security*
reasons. The swap area should only be accessible to the super user (the
OP is using Linux) and the super user can get into the process address
space anyway, whether on (swap) disk (/dev/[r]dsk) or in memory
(/dev/[k]mem).

It's actually fairly challenging to peek into your process memory at
precisely the right time to pull out the key/password/sensitive info.

On the other hand, if it's sent out to swap space, a person who
discovered a root exploit a day later could potentially find this info
from browsing through the swap space.

Yes, the first is a problem, but it's relatively low risk and there's
not a whole lot you can do about it without a stronger security model
(something like SELinux, for example). The second takes considerably
less skill and is a higher risk. That's why it makes sense to take
reasonable precautions to lock these pages into memory.
 
F

Frank Slootweg

Sidney Cadot said:
You're wrong: not all bets are off. For example, I'm willing to bet that
you would be much less likely to find sensitive information on the
swap disk if a cryptographic application is properly written to use
non-swappable memory. In other words, this diminishes the risk of leaks
quite significantly. Which is the best you can do, since, of course,
perfect security is not attainable in practice.

I already conceded that point, non-swappable memory versus swappable
memory, in my response to Walter.

What I was addressing now, was Christian's comment, which implied
physical access to the machine. If a malicious person has physical to
the machine, that opens a whole other can of worms. That was what I was
saying. Yes, some systems can be have reasonable security even with
physical access, but for most run of the mill systems, that will not be
the case, especially for run of the mill Intel systems which probably
will be used here (AFAIK, the OP has not mentioned any specific machine,
only "Linux".)

[deleted]
 
D

Damian Menscher

Finally, someone understands! :)
Wouldn't setting buffers to null characters when I am done with them
take care of this?

Beware the compiler optimizations. If you zero it out, and then
immediately free() it, the compiler may say "it's just going to be
free()d, so why bother zeroing it first? that just takes time! I'll
just optimize out that part of the code, and release the memory with
the plaintext password still in it."

As the previous poster asked, "are you paranoid enough?" ;)

Damian Menscher
 
G

Gordon Burditt

I am trying to make sure that my data doesn't show up anywhere outside
my process unencrypted. I am concerned that if I use memcpy, the bytes
copied will end up in some memory somewhere after I am done with it.
Am I being paranoid?

Worry about the original memory, too, not just the copy.

Always use the pointer to the sensitive data as the *FIRST* argument,
never the second. Don't make copies of sensitive data. Destroy
them.

Remember that the US government has physical access to just about
any machine if they want it bad enough. (Two Mars rovers are a
notable exception.) No, you guys in Europe or Australia aren't safe.
If you hear the door breaking in, can you press the switch setting
off the explosives on the hard disk fast enough?

Always remember that SSL is a security method used by a thief (the
web site operator) to ensure that your credit card number is safely
delivered into his hands so he can steal from it before anyone else
gets a chance to.

Gordon L. Burditt
 
W

Walter Roberson

:>I am trying to make sure that my data doesn't show up anywhere outside
:>my process unencrypted.

:Always use the pointer to the sensitive data as the *FIRST* argument,
:never the second.

Surely that would depend on the ABI (Application Binary Interface) ?

For example, I have seen ABIs in which up to the first 6 (I think it
was) leading data values were passed in registers, but everything
from the first pointer onwards was passed on the stack. In such
an architecture, to be secure you would want to cast your pointer
into a long and make sure it was placed early on -- but blindly
passing a pointer as the first parameter would end up with -nothing-
being passed in registers.
 
D

Dan Pop

In said:
Beware the compiler optimizations. If you zero it out, and then
immediately free() it, the compiler may say "it's just going to be
free()d, so why bother zeroing it first? that just takes time! I'll
just optimize out that part of the code, and release the memory with
the plaintext password still in it."

As the previous poster asked, "are you paranoid enough?" ;)

If you are paranoid enough, you won't use a system that swaps memory to
the disk (if the system's power is cut at the right moment, all your
sensitive data may be on the swap partition, readily accessible to anyone
who has physical access to the disk) and you won't use an OS you haven't
written yourself and compiled with your own compiler.

Dan
 
D

Dan Pop

In said:
:>I am trying to make sure that my data doesn't show up anywhere outside
:>my process unencrypted.

:Always use the pointer to the sensitive data as the *FIRST* argument,
:never the second.

Surely that would depend on the ABI (Application Binary Interface) ?

For example, I have seen ABIs in which up to the first 6 (I think it
was) leading data values were passed in registers, but everything
from the first pointer onwards was passed on the stack. In such
an architecture, to be secure you would want to cast your pointer
into a long and make sure it was placed early on -- but blindly
passing a pointer as the first parameter would end up with -nothing-
being passed in registers.

Registers aren't safe, either, in a multi-tasking OS: when another process
is scheduled for execution, they end up in memory :)

Dan
 
G

Gordon Burditt

:>I am trying to make sure that my data doesn't show up anywhere outside
:>my process unencrypted.

:Always use the pointer to the sensitive data as the *FIRST* argument,
:never the second.

Surely that would depend on the ABI (Application Binary Interface) ?

Not really. memcpy() takes *POINTERS* to data, and the pointer
to where sensitive data used to be isn't particularly sensitive
after the sensitive data has been written over. USE memcpy() to
DESTROY (WRITE OVER) SENSITIVE DATA, NOT MAKE COPIES OF IT!
For example, I have seen ABIs in which up to the first 6 (I think it
was) leading data values were passed in registers, but everything
from the first pointer onwards was passed on the stack. In such

memcpy() doesn't take 6 arguments. The first argument is a pointer
to the destination buffer (sensitive data). The second argument
is a pointer to the source buffer (random trash). You don't get
to re-order the meaning of the arguments to memcpy() to suit your
ABI and your paranoia level.
an architecture, to be secure you would want to cast your pointer
into a long and make sure it was placed early on -- but blindly
passing a pointer as the first parameter would end up with -nothing-
being passed in registers.

It is unlikely that passing a pointer would cause a few bytes of
what the pointer pointed at to also be passed. Since the first
(pointer) argument of memcpy() is used to alter data being pointed
at, it can't use those bytes passed anyway, so what's the point in
passing them?.

memcpy() takes two pointer arguments. You *DO NOT* want to cast
that to a long (which is not necessarily big enough to hold a whole
pointer) before passing it. Doing so may cause a core dump of the
whole process, including the sensitive data, to be posted to
comp.lang.c.
Look out, there are llamas!

C does not support pointers to llamas. Also, llamas weigh too much
and tend to crack the motherboard, plus they smell really bad :-( .

Gordon L. Burditt
 
W

Walter Roberson

|>:>I am trying to make sure that my data doesn't show up anywhere outside
|>:>my process unencrypted.

|>:Always use the pointer to the sensitive data as the *FIRST* argument,
|>:never the second.

|>Surely that would depend on the ABI (Application Binary Interface) ?

|Not really. memcpy() takes *POINTERS* to data, and the pointer
|to where sensitive data used to be isn't particularly sensitive
|after the sensitive data has been written over. USE memcpy() to
|DESTROY (WRITE OVER) SENSITIVE DATA, NOT MAKE COPIES OF IT!

I see what you mean now. Your posting wasn't clear that you
were talking only about memcpy() -- you had appeared to be saying that
if you have a sensitive pointer in any function, then it should be
in the first argument, and I was asking about the reasoning of that.

:memcpy() takes two pointer arguments. You *DO NOT* want to cast
:that to a long (which is not necessarily big enough to hold a whole
:pointer) before passing it.

ANSI C -defines- long as being large enough to hold a pointer,
and guarantees that if you convert a pointer to a long and back
again (with no arithmetic operations on the long) then the result
will point to the original object.

But anyhow, I wasn't talking about memcpy() in particular, I was
meaning to refer to when one was constructing one's own functions
for dealing with pointers to sensitive data: if you must have
such functions, then better to have the data go in registers than
on the stack. The other poster did, though, have a very good point,
about process switching potentially resulting in the registers
getting rolled into memory.


:> Look out, there are llamas!

:C does not support pointers to llamas.

Not ANSI C, no, but there's gcc --with-llama-pointers
and a contingent that is pressing to get them into POSIX.L .
For more details, see http://www.llama-pointers.org .
 
C

Christian Bau

ANSI C -defines- long as being large enough to hold a pointer,
and guarantees that if you convert a pointer to a long and back
again (with no arithmetic operations on the long) then the result
will point to the original object.

That is news to me. And to many others. Including the guys who wrote the
C Standard.
 
W

Walter Roberson

:In article <[email protected]>,
: (e-mail address removed)-cnrc.gc.ca (Walter Roberson) wrote:

:> ANSI C -defines- long as being large enough to hold a pointer,
:> and guarantees that if you convert a pointer to a long and back
:> again (with no arithmetic operations on the long) then the result
:> will point to the original object.

:That is news to me. And to many others. Including the guys who wrote the
:C Standard.

I'll cross-check my references when I next have an opportunity.
 
M

Mark McIntyre

On 29 Jan 2004 20:11:26 GMT, in comp.lang.c ,
:In article <[email protected]>,
: (e-mail address removed)-cnrc.gc.ca (Walter Roberson) wrote:

:> ANSI C -defines- long as being large enough to hold a pointer,
:> and guarantees that if you convert a pointer to a long and back
:> again (with no arithmetic operations on the long) then the result
:> will point to the original object.

:That is news to me. And to many others. Including the guys who wrote the
:C Standard.

I'll cross-check my references when I next have an opportunity.

The standard says:
6.3.2.3 Pointers
(6) Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.

The "previously specified" refers to null pointers.
 
J

J. J. Farrell

ANSI C -defines- long as being large enough to hold a pointer,
and guarantees that if you convert a pointer to a long and back
again (with no arithmetic operations on the long) then the result
will point to the original object.

I don't believe it does. It allows pointers to be converted to
integers in implementation-defined ways. It's not clear to me
that it requires that a big enough integer exists (in C89 at
least) and I'd welcome chapter and verse if it does.

K&R2's Reference Manual says that converting a pointer to a
'big enough' integer and back again will give a pointer that
points to the original object. I can't see how to derive this
from the Standard, so chapter and verse would be welcome again
if it's there. The Standard does imply that this is the
preferred implementation.
 
R

Richard Heathfield

J. J. Farrell said:
(e-mail address removed)-cnrc.gc.ca (Walter Roberson) wrote in message


I don't believe it does.

You are right to be sceptical.

3.3.4 of (my draft copy of) the ANSI C Standard says: "A pointer may be
converted to an integral type. The size of integer required and the
result are implementation-defined. If the space provided is not long
enough, the behavior is undefined. An arbitrary integer may be
converted to a pointer. The result is implementation-defined."

No guarantees there about the original pointer being restored when you
convert it back.

The latest Standard says in 6.3.2.3:

"5 An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced type, and
might be a trap representation.56)

6 Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the result
cannot be represented in the integer type, the behavior is undefined. The
result need not be in the range of values of any integer type."
 
D

Dan Pop

In said:
I don't believe it does. It allows pointers to be converted to
integers in implementation-defined ways. It's not clear to me
that it requires that a big enough integer exists (in C89 at
least) and I'd welcome chapter and verse if it does.

Neither standard requires the existence of such an integer type.

C99 provides the *optional* intptr_t and uintptr_t aliases to the
signed and unsigned flavours of an integer type that is large enough
for the purpose and on which conversions back and forth reproduce
the original value. The aliases are optional because the underlying
types need not exist.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,137
Messages
2,570,797
Members
47,344
Latest member
KamCrowthe

Latest Threads

Top