📄 fips186impl.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibecrypto.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "algobj.h"
#include "random.h"
#include "fips186.h"
#include "fipsmodule.h"
#include "errorctx.h"
/* Find sum += addend.
* <p>You should not call this function is addendLen is longer than
* sumLen.
* <p>This will add word 0 of addend to the word 0 of sum and retain
* the carry. It will then add word 1 of addend (if there is one) to
* word 1 of sum and then add in the carry from the previous add. It
* will then retain the carry from this addition. It will continue in
* this fashion until adding all of addend's bytes to sum. If there is
* a carry beyond the end of sum, it is lost.
*
* @param addend One of the addends.
* @param sum The other addend, also where the result goes.
* @param len The length of the buffers.
* @return none
*/
static void VOLT_CALLING_CONV AddBuffers VOLT_PROTO_LIST ((
unsigned char *addend,
unsigned int addendLen,
unsigned char *sum,
unsigned int sumLen
));
/* Test a seed buffer to make sure it meets the FIPS seed requirments.
* <p>If the seed passes, return 0, if not, return
* VT_ERROR_INSUFFICIENT_SEED.
*
* @param libCtx The libCtx to use.
* @param fips186Ctx The context containing the seed buffer with the
* seed to test.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV TestSeed VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltFips186PrngCtx *fips186Ctx
));
/* This updates XKEY.
* <p> It also produces a block of output.
*
* @param libCtx The libCtx to use.
* @param fips186Ctx The context containing the XKEY and info
* necessary to update the state.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV UpdateXKEY VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltFips186PrngCtx *fips186Ctx
));
/* Test the output, to make sure it's not the same thing as the last
* block, as required by FIPS.
* <p>If the "previous block" buffer is empty, this is the first call
* to GenerateRandomBytes. We want to copy the output data into the
* previous block buffer, but not return it to the app that called
* VtGenerateRandomBytes.
* <p>If the output passes, return 0, if not, return
* VT_ERROR_RANDOM_OBJECT.
*
* @param libCtx The libCtx to use.
* @param fips186Ctx The context containing the blokc of output to test.
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV TestOutput VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltFips186PrngCtx *fips186Ctx
));
int FIPS186SeedRandom (
VoltRandomObject *obj,
unsigned char *seedData,
unsigned int seedLen
)
{
int status;
unsigned int count;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltFips186PrngCtx *fips186Ctx = (VoltFips186PrngCtx *)(obj->localRandomCtx);
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* If there are no seed bytes, this implementation does nothing.
*/
if ( (seedData == (unsigned char *)0) || (seedLen == 0) )
return (0);
do
{
/* Place the seed bytes into the seed buffer.
*/
count = fips186Ctx->byteSize - fips186Ctx->seedLen;
if (seedLen < count)
count = seedLen;
Z2Memcpy (fips186Ctx->seedBuffer + fips186Ctx->seedLen, seedData, count);
seedLen -= count;
seedData += count;
fips186Ctx->seedLen += count;
if (fips186Ctx->seedCount <= FIPS_186_PRNG_MIN_SEED_LEN)
fips186Ctx->seedCount += count;
if ( (fips186Ctx->seedCount == FIPS_186_PRNG_MIN_SEED_LEN) &&
(fips186Ctx->seedLen == fips186Ctx->byteSize) )
{
/* Test the first block of seed.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = TestSeed (libCtx, fips186Ctx);
if (status != 0)
break;
}
/* If there are no more seed bytes, we're done with this routine,
* we'll do something with the seed when we need to.
*/
status = 0;
if (seedLen == 0)
break;
/* If we have more seed input, Update the internal state with the
* previously saved seed material.
*/
if (fips186Ctx->seedCount <= FIPS_186_PRNG_MIN_SEED_LEN)
fips186Ctx->seedCount = FIPS_186_PRNG_MIN_SEED_LEN + 1;
do
{
/* Copy the seed material into the XSEED buffer.
*/
Z2Memcpy (
fips186Ctx->xseed, fips186Ctx->seedBuffer, fips186Ctx->byteSize);
fips186Ctx->seedLen = 0;
/* Do the XKEY update to alter the internal state.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = UpdateXKEY (libCtx, fips186Ctx);
if (status != 0)
break;
/* The call to UpdateXKEY generated output, but we aren't
* interested in that, we were simply interested in changing the
* state. So set currentBytesLen to indicate we should ignore the
* data therein.
*/
fips186Ctx->currentBytesLen = 0;
/* Copy the next bytes of seedData input into the seedBuffer.
*/
count = fips186Ctx->byteSize;
if (seedLen < count)
count = seedLen;
Z2Memcpy (fips186Ctx->seedBuffer, seedData, count);
seedLen -= count;
seedData += count;
fips186Ctx->seedLen = count;
} while (seedLen != 0);
} while (0);
VOLT_LOG_ERROR_COMPARE (
status, (VtLibCtx)libCtx, status, 0, fnctLine,
"FIPS186SeedRandom", (char *)0)
return (status);
}
int FIPS186GenerateRandomBytes (
VoltRandomObject *obj,
unsigned char *randomBytes,
unsigned int randomLen
)
{
int status, seedStatus;
unsigned int count, offset;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltFips186PrngCtx *fips186Ctx = (VoltFips186PrngCtx *)(obj->localRandomCtx);
unsigned char *source;
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* If the the app has not added a min count of seed bytes yet, hold
* on to that information.
*/
status = 0;
seedStatus = VT_ERROR_INSUFFICIENT_SEED;
if (fips186Ctx->seedCount >= FIPS_186_PRNG_MIN_SEED_LEN)
seedStatus = 0;
/* If we have seed data in the seedBuffer and the count is >
* MIN_SEED_LEN, then we need to update XKEY. If the count is <= to
* MIN_SEED_LEN, then the material in the seedBuffer is the first
* block of seed, just move it into the XSEED buffer.
*/
if (fips186Ctx->seedLen != 0)
{
if (fips186Ctx->seedCount <= FIPS_186_PRNG_MIN_SEED_LEN)
{
Z2Memcpy (
fips186Ctx->xseed, fips186Ctx->seedBuffer, fips186Ctx->seedLen);
fips186Ctx->seedLen = 0;
}
else
{
/* Copy the seed material into the XSEED buffer.
*/
offset = fips186Ctx->byteSize - fips186Ctx->seedLen;
Z2Memset (fips186Ctx->xseed, 0, offset);
Z2Memcpy (
fips186Ctx->xseed + offset, fips186Ctx->seedBuffer,
fips186Ctx->seedLen);
fips186Ctx->seedLen = 0;
/* Do the XKEY update to alter the internal state.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = UpdateXKEY (libCtx, fips186Ctx);
if (status != 0)
break;
/* The call to UpdateXKEY generated output, but we aren't
* interested in that, we were simply interested in changing the
* state. So set currentBytesLen to indicate we should ignore the
* data therein.
*/
fips186Ctx->currentBytesLen = 0;
}
}
/* Do we have any bytes available for output?
*/
if (fips186Ctx->currentBytesLen > 0)
{
/* Copy bytes to the output. If the previousBytesFlag is
* SECOND_BLOCK, copy from the previousBytes buffer. It is the
* first block produced, but we never compared it to another
* block (and never output it) until we got the second block. Now
* that we have compared it, we can return it.
* <p>If previousBytesFlag is not SECOND_BLOCK, get output from
* currentBytes.
*/
source = fips186Ctx->previousBytes;
if (fips186Ctx->previousBytesFlag != VOLT_FIPS_186_PREVIOUS_BUFFER)
source = fips186Ctx->currentBytes;
count = fips186Ctx->currentBytesLen;
if (randomLen < count)
count = randomLen;
Z2Memcpy (randomBytes, source + fips186Ctx->currentBytesOffset, count);
randomLen -= count;
randomBytes += count;
fips186Ctx->currentBytesOffset += count;
fips186Ctx->currentBytesLen -= count;
/* Was that enough?
*/
status = 0;
if (randomLen == 0)
break;
}
/* Generate blocks of output until we've generated enough blocks to
* fill the output buffer.
*/
do
{
/* If previousBytesFlag is PREVIOUS_BUFFER, we already have the
* next block of data in the currentBytes buffer, we don't need
* to update XKEY. But if it is not, generate another block.
*/
if (fips186Ctx->previousBytesFlag != VOLT_FIPS_186_PREVIOUS_BUFFER)
{
/* This will generate a block of output as well as update XKEY.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = UpdateXKEY (libCtx, fips186Ctx);
if (status != 0)
break;
}
/* This function will test the output against the previous block,
* unless there is no previous block, in which case this function
* will only initialize the "previous block" buffer.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = TestOutput (libCtx, fips186Ctx);
if (status != 0)
break;
/* If we have no length of output, generate another block.
*/
if (fips186Ctx->currentBytesLen == 0)
continue;
count = fips186Ctx->currentBytesLen;
if (randomLen < count)
count = randomLen;
/* Copy bytes to the output. The previousBytesFlag tells us which
* buffer to copy from.
*/
source = fips186Ctx->previousBytes;
if (fips186Ctx->previousBytesFlag != VOLT_FIPS_186_PREVIOUS_BUFFER)
source = fips186Ctx->currentBytes;
Z2Memcpy (randomBytes, source, count);
randomLen -= count;
randomBytes += count;
fips186Ctx->currentBytesOffset += count;
fips186Ctx->currentBytesLen -= count;
} while (randomLen != 0);
} while (0);
/* There are two int's holding error codes, status and seedStatus. If
* both are 0, there is no error, return 0. If status is not 0, return
* that error, even if seedStatus is not 0. If status is 0, but
* seedStatus is not 0, return the seedStatus error.
*/
if (status == 0)
status = seedStatus;
VOLT_LOG_ERROR_COMPARE (
status, (VtLibCtx)libCtx, status, 0, fnctLine,
"FIPS186GenerateRandomBytes", (char *)0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -