📄 pgpdiskwiper.c
字号:
/*____________________________________________________________________________
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpDiskWiper.c,v 1.6 1999/03/10 02:50:08 heller Exp $
____________________________________________________________________________*/
/* System Headers */
#if PGP_DEBUG
#include <stdio.h>
#endif
#include <string.h> /* For memcpy(), etc. */
/* PGPsdk Headers */
#include "pgpConfig.h"
#include "pgpErrors.h"
#include "pgpMem.h"
#include "pgpUtilities.h"
#include "pgpPubTypes.h"
#include "pgpUtilities.h"
#include "pgpMemoryMgr.h"
/* Project Headers */
#include "pgpDiskWiper.h"
/*
* These are the disk-wiping patterns. They are repeating patterns of
* 1, 2, 3 and 4 bits, along with some random passes. See Peter Gutmann's
* paper, "Secure Deletion of Data from Magnetic and Solid-State Memory",
* first published in the Sixth USENIX Security Symposium Proceedings,
* San Jose, California, July 22-25, 1996 for the gory details why.
* (http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html)
*/
PGPInt32 patterns[] = {
-1, /* Random */
-1, /* Random */
0x555, 0xAAA,
0x249, 0x492, 0x924,
0x000, 0xFFF,
0x111, 0x222, 0x333, 0x444, 0x666, 0x777,
0x888, 0x999, 0xBBB, 0xCCC, 0xDDD, 0xEEE,
0xDB6, 0xB6D, 0x6DB,
-1, /* Random */
-1 /* Random */
};
#define NUMPATTERNS (sizeof(patterns)/sizeof(patterns[0]))
/* Random number code from Colin */
/*
* This is Bob Jenkins' ISAAC generator
* (http://ourworld.compuserve.com/homepages/bob_jenkins/isaacafa.htm)
* which is designed to be cryptographically strong and very fast.
* I'm not sure if I'd trust it for key material, but it should be
* strong enough for this application, and the speed is nice when
* you need megabytes of output.
*/
#define ISAAC_LOG 8
#define ISAAC_SIZE 256
#define ISAAC_BYTES (ISAAC_SIZE * sizeof(PGPInt32))
typedef struct isaac_state isaac_state;
struct isaac_state
{
PGPInt32 mm[ISAAC_SIZE]; /* State */
PGPInt32 aa, bb, cc;
};
typedef struct PGPDiskWipe PGPDiskWipe;
struct PGPDiskWipe
{
PGPContextRef context;
PGPMemoryMgrRef manager;
PGPInt32 index;
PGPInt32 passes;
isaac_state state;
PGPInt32 patterns[NUMPATTERNS];
};
/* This index operation is more efficient on many processors */
#define ind(mm,x) *(unsigned *)\
((char *)(mm) + ( (x) & (ISAAC_SIZE-1)<<2 ))
/* The central step. This uses two temporaries, x and y. */
#define isaac_step(mix,a,b,mm,m,off,r) \
( \
a = (a^(mix)) + m[off], \
x = *m, \
*(m++) = y = ind(mm,x) + a + b, \
*(r++) = b = ind(mm,y>>ISAAC_LOG) + x \
)
/*
* Refill the entire r array with one call.
*/
static void
isaac_refill(struct isaac_state *s,
PGPInt32 r[ISAAC_SIZE])
{
register PGPInt32 a, b; /* Caches of a and b */
register PGPInt32 x, y; /* Temps needed by isaac_step() macro */
register PGPInt32 *m = s->mm; /* Pointer into state array */
a = s->aa;
b = s->bb + (++s->cc);
do
{
isaac_step(a << 13, a, b, s->mm, m, ISAAC_SIZE/2, r);
isaac_step(a >> 6, a, b, s->mm, m, ISAAC_SIZE/2, r);
isaac_step(a << 2, a, b, s->mm, m, ISAAC_SIZE/2, r);
isaac_step(a >> 16, a, b, s->mm, m, ISAAC_SIZE/2, r);
} while (m < s->mm+ISAAC_SIZE/2);
do
{
isaac_step(a << 13, a, b, s->mm, m, -ISAAC_SIZE/2, r);
isaac_step(a >> 6, a, b, s->mm, m, -ISAAC_SIZE/2, r);
isaac_step(a << 2, a, b, s->mm, m, -ISAAC_SIZE/2, r);
isaac_step(a >> 16, a, b, s->mm, m, -ISAAC_SIZE/2, r);
} while (m < s->mm+ISAAC_SIZE);
s->bb = b;
s->aa = a;
}
/* The basic seed-scrambling step */
#define mix(a,b,c,d,e,f,g,h) \
(a ^= b << 11, d += a, \
b += c, b ^= c >> 2, e += b, \
c += d, c ^= d << 8, f += c, \
d += e, d ^= e >> 16, g += d, \
e += f, e ^= f << 10, h += e, \
f += g, f ^= g >> 4, a += f, \
g += h, g ^= h << 8, b += g, \
h += a, h ^= a >> 9, c += h, \
a += b)
/*
* Initialize the ISAAC RNG with the given 256-entry seed array.
* That array may be the mm[] array.
*/
static void
isaac_init(struct isaac_state *s, PGPInt32 const *seed)
{
PGPInt32 i;
PGPInt32 passes = (seed != 0);
PGPInt32 a, b, c, d, e, f, g, h;
#if 0
/* The original presentation */
a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */
for (i = 0; i < 4; ++i) /* scramble it */
{
mix(a, b, c, d, e, f, g, h);
}
#else
/* A smaller and faster, although more opaque version. */
a = 0x1367df5a;
b = 0x95d90059;
c = 0xc3163e4b;
d = 0x0f421ad8;
e = 0xd92a4a78;
f = 0xa51a3c49;
g = 0xc4efea1b;
h = 0x30609119;
#endif
do
{
/* Fill up mm[] with messy stuff */
for (i = 0; i < ISAAC_SIZE; i += 8)
{
if (seed)
{
/* use all the information in the seed */
a += seed[i];
b += seed[i+1];
c += seed[i+2];
d += seed[i+3];
e += seed[i+4];
f += seed[i+5];
g += seed[i+6];
h += seed[i+7];
}
mix(a, b, c, d, e, f, g, h);
s->mm[i] = a;
s->mm[i+1] = b;
s->mm[i+2] = c;
s->mm[i+3] = d;
s->mm[i+4] = e;
s->mm[i+5] = f;
s->mm[i+6] = g;
s->mm[i+7] = h;
}
seed = s->mm;
/*
* If we were given a seed, do a second pass to make
* all of the seed affect all of mm
*/
} while (passes--);
s->aa = s->bb = s->cc = 0;
}
/*
* Seed the RNG, using 160 bits of seed material, which should be *plenty*.
* This cheats and uses the s->mm[] array to hold the seed material,
* which is allowed by isac_init().
*/
static PGPError
isaac_seed(PGPDiskWipeRef ref)
{
PGPError error = kPGPError_NoErr;
struct isaac_state* s = &(ref->state);
/* Get some good seed material. */
error = PGPContextGetRandomBytes(ref->context, s->mm, 20);
isaac_init(s, s->mm);
return error;
}
/* End RNG code */
/*
* Shuffle an array of ints into random order.
* This is done by swapping the last element in the array
* with a random element of the array and then repeating
* for the array without the last element.
*/
static void
shuffle(PGPInt32 *array,
PGPUInt32 num,
struct isaac_state *s)
{
PGPInt32 i, t;
PGPInt32 r[ISAAC_SIZE];
isaac_refill(s, r);
while (--num)
{
i = (int)(r[num] % (num+1));
t = array[i];
array[i] = array[num];
array[num] = t;
}
}
/* Move the random pass into the middle of the shuffle */
static void
tweakshuffle(PGPInt32 *array,
PGPUInt32 num)
{
PGPUInt32 i;
for (i = 0; i < num; i++)
{
if (array[i] < 0)
{
num /= 2;
array[i] = array[num];
array[num] = -1;
break;
}
}
}
/* Pass types:
* 0xXXX - Repeat XXX to fill file
* -1 - Random
*/
static void
filltable(struct isaac_state *s,
PGPInt32 buf[ISAAC_SIZE],
PGPInt32 type)
{
PGPInt32 i;
if (type < 0)
{
isaac_refill(s, (PGPInt32 *)buf);
}
else
{
((unsigned char *)buf)[0] = 255 & (type >> 4);
((unsigned char *)buf)[1] = 255 & (type << 4 | type >> 8);
((unsigned char *)buf)[2] = 255 & type;
for (i = 3; i < ISAAC_BYTES/2; i *= 2)
{
memcpy((char *)buf+i, (char *)buf, i);
}
memcpy((char *)buf+i, (char *)buf, ISAAC_BYTES-i);
}
}
PGPError
PGPCreateDiskWiper( PGPContextRef context,
PGPDiskWipeRef *wipeRef,
PGPInt32 numPasses)
{
PGPError error = kPGPError_NoErr;
PGPMemoryMgrRef manager = PGPGetContextMemoryMgr (context);
if (IsntNull(wipeRef))
{
*wipeRef = NULL;
}
*wipeRef = (PGPDiskWipeRef) PGPNewData(
manager,
sizeof(PGPDiskWipe),
kPGPMemoryMgrFlags_Clear);
if(IsntNull(*wipeRef))
{
PGPDiskWipeRef ref = *wipeRef;
/* we need this guy for random data */
ref->context = context;
/* we need this guy for deleting ourselves */
ref->manager = manager;
/* keep track of which pass we are on */
ref->index = 0;
/* remember total # of passes */
ref->passes = numPasses;
/* initialize random # generator */
error = isaac_seed( ref );
/* did it initialize ok? */
if( IsPGPError(error) )
{
/* if not clean up */
PGPFreeData(ref);
return error;
}
/* set up the pattern array */
if(numPasses < NUMPATTERNS)
{
PGPInt32 i;
for(i = 0; i < numPasses - 1; i++)
{
ref->patterns[i] = patterns[i];
}
ref->patterns[i] = -1;
}
else
{
memcpy(ref->patterns, patterns, sizeof(patterns));
}
if(numPasses > 3)
{
if(numPasses > NUMPATTERNS)
{
/* only wanna shake up the array*/
numPasses = NUMPATTERNS;
}
/* Shuffle, leaving first & last pass alone */
shuffle(ref->patterns + 1,
(unsigned)numPasses - 2,
&(ref->state));
/* Force a random pass to the middle */
tweakshuffle(ref->patterns + 1,
(unsigned)numPasses - 2);
}
}
else
{
error = kPGPError_OutOfMemory;
*wipeRef = NULL;
}
return error;
}
PGPError
PGPGetDiskWipeBuffer(PGPDiskWipeRef wipeRef,
PGPInt32 buffer[256])
{
PGPError error = kPGPError_NoErr;
if( IsntNull(wipeRef) && IsntNull(buffer))
{
if(wipeRef->index < wipeRef->passes)
{
if(wipeRef->index < NUMPATTERNS - 1)
{
#if PGP_DEBUG
#if ! PGP_MACINTOSH
fprintf(stderr, "pattern is: 0x%x\r\n",
wipeRef->patterns[wipeRef->index]);
#endif
#endif
filltable( &(wipeRef->state),
buffer,
wipeRef->patterns[wipeRef->index++]);
}
else
{
#if PGP_DEBUG
#if ! PGP_MACINTOSH
fprintf(stderr, "pattern is: 0xffffffff\r\n");
#endif
#endif
filltable( &(wipeRef->state),
buffer,
-1);
wipeRef->index++;
}
}
else
{
error = kPGPError_NoMorePatterns;
}
}
else
{
error = kPGPError_BadParams;
}
return error;
}
PGPError
PGPDestroyDiskWiper( PGPDiskWipeRef wipeRef )
{
PGPError error = kPGPError_NoErr;
if( IsntNull(wipeRef) )
{
PGPFreeData( wipeRef );
}
else
{
error = kPGPError_BadParams;
}
return error;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -