⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fipsprime.c

📁 IBE是一种非对称密码技术
💻 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 "mpint.h"
#include "prime.h"
#include "errorctx.h"

int VoltGeneratePrimeFips (
   unsigned int primeSizeBits,
   VtRandomObject random,
   unsigned char *SEED,
   unsigned int *seedLen,
   VoltMpInt *prime
   )
{
  int status, count;
  unsigned int bufferSize, digestLen, index, limit;
  unsigned int bitMask, bitSet, isPrime;
  VoltMpIntCtx *mpCtx = (VoltMpIntCtx *)(prime->mpCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(mpCtx->voltObject.libraryCtx);
  VtAlgorithmObject sha1 = (VtAlgorithmObject)0;
  unsigned char *buffer = (unsigned char *)0;
  unsigned char digest[40];
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  /* How many bytes do we generate.
   */
  bufferSize = (primeSizeBits + 7) / 8;
  *seedLen = bufferSize;

  do
  {
    /* Currently, the toolkit is supporting only 160 bit primes to be
     * generated using the FIPS technique
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_INVALID_PARAM_LENGTH;
    if (primeSizeBits != 160)
      break;

    /* Build a buffer to hold the starting point.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    buffer = (unsigned char *)Z2Malloc (bufferSize, VOLT_MEMORY_SENSITIVE);
    if (buffer == (unsigned char *)0)
      break;

    /* Create a mask for the first byte. Depending on the bit length,
     * we may want to trim some bits off the top.
     */
    bitSet = primeSizeBits % 8;
    if (bitSet == 0)
      bitSet = 8;
    bitMask = 0xff >> (8 - bitSet);
    /* Make sure the msbit is set. Create a value to OR with the first
     * byte that will set the msbit.
     */
    bitSet = 1 << (bitSet - 1);

    /* Build the SHA-1 digest object to be used in step 2 below.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtCreateAlgorithmObject (
      (VtLibCtx)libCtx, VtAlgorithmImplSHA1, (Pointer)0, &sha1);
    if (status != 0)
      break;

    count = 0;
    isPrime = 1;
    do
    {
      /* Step 1: "Choose an arbitrary sequence ... call it SEED."
       */
      VOLT_SET_ERROR_TYPE (errorType, 0)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtGenerateRandomBytes (random, SEED, bufferSize); 
      if (status != 0)
        break;

      /* Step 2: Compute U.
       */
      Z2Memcpy (buffer, SEED, bufferSize);

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtDigestInit (sha1);
      if (status != 0)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtDigestFinal (
        sha1, buffer, bufferSize, digest, sizeof (digest), &digestLen);
      if (status != 0)
        break;

      /* Add 1 to SEED (don't carry beyond the most significant byte).
       */
      for (index = bufferSize; index > 0; --index)
      {
        buffer[index - 1] += 1;
        if (buffer[index - 1] != 0)
          break;
      }

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtDigestInit (sha1);
      if (status != 0)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      status = VtDigestFinal (
        sha1, buffer, bufferSize, digest + digestLen,
        sizeof (digest) - digestLen, &digestLen);
      if (status != 0)
        break;

      /* XOR the two digests.
       */
      limit = digestLen;
      if (digestLen > bufferSize)
        limit = bufferSize;
      for (index = 0; index < limit; ++index)
        buffer[index] = digest[index] ^ digest[index + digestLen];

      /* Step 3: Form q.
       */
      buffer[0] &= (unsigned char)bitMask;
      buffer[0] |= (unsigned char)bitSet;
      buffer[bufferSize - 1] |= 1;

      /* Set the MpInt to this value.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->OctetStringToMpInt (0, buffer, bufferSize, prime);
      if (status != 0)
        break;

      /* Step 4: Run Rabin-Miller on this value.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltRabinMillerTest (
        prime, primeSizeBits, VOLT_RABIN_MILLER_COUNT_186_2,
        random, &isPrime);
      if (status != 0)
        break;

      /* If this came back prime, we're done.
       */
      if (isPrime != 0)
        break;

      /* Step 5: The Rabin-Miller test indicates that the number is not
       * prime, get a new random starting point. But first, don't run
       * this test forever.  Try up to 1000000 times.
       */
      VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VT_ERROR_NO_PRIME_FOUND;
      count++;
      if (count > 1000000)
        break;

    } while (1);

  } while (0);

  VtDestroyAlgorithmObject (&sha1);
  Z2Memset (digest, 0, sizeof (digest));
  if (buffer != (unsigned char *)0)
    Z2Free (buffer);

  VOLT_LOG_ERROR_COMPARE (
    status, (VtLibCtx)libCtx, status, errorType, fnctLine,
    "VoltGeneratePrimeFips", (char *)0)

  return (status);
}

void VoltAddValueToBuffer (
   unsigned char *buffer,
   unsigned int bufferLen,
   UInt32 increment
   )
{
  unsigned int indexB, indexI;
  unsigned char carry, val;
  unsigned char vector[4];

  VOLT_SET_UINT32 (increment, vector)

  /* Add the four words of the increment to the low four words of the
   * buffer.
   */
  carry = 0;
  for (indexI = 4, indexB = bufferLen; indexI > 0; --indexI, --indexB)
  {
    val = carry + vector[indexI - 1];
    if (val >= carry)
      carry = 0;
    buffer[indexB - 1] += val;
    if (buffer[indexB - 1] < val)
      carry = 1;
  }

  /* If there's no carry, we're done.
   */
  if (carry == 0)
    return;

  /* Propagate the carry through the buffer (ignoring any carry beyond
   * the most significant byte.
   */
  for (; indexB > 0; --indexB)
  {
    buffer[indexB - 1] += 1;
    if (buffer[indexB - 1] != 0)
      break;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -