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

📄 writesign.c

📁 voltage 公司提供的一个开发Ibe的工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
       */
      contentInfoLen = outputLen;
      outputLen += VoltDetermineDerLengthLen (contentInfoLen);
      outputLen++;
      /* Add in the length of the SET OF digest algID's. We're assuming
       * here that lengths will never be longer than 127 bytes. This
       * implementation works with only one digest algorithm, so the
       * SET OF is actually a SET OF one algID.
       * Then add in the version (3 bytes).
       */
      outputLen += signCtx->digestAlgId.len + 5;
      /* Figure out the 30 len of the SignedData content. This includes
       * the certs and signerInfo's. Use offset as a temp variable.
       */
      signedDataLen = VoltDetermineDerLengthLen (signCtx->totalCertLen);
      signedDataLen += VoltDetermineDerLengthLen (signCtx->totalSignerInfoLen);
      signedDataLen +=
        outputLen + signCtx->totalCertLen + signCtx->totalSignerInfoLen + 2;
      offset = VoltDetermineDerLengthLen (signedDataLen);
      outputLen += offset + 1;
      /* Figure out the A0 len of the EXPLICIT. Use offset as a temp
       * variable.
       */
      explicitLen = signedDataLen + offset + 1;
      offset = VoltDetermineDerLengthLen (explicitLen);
      outputLen += offset + 1;
      /* Add in the SignedData OID.
       */
      outputLen += VoltP7SignDataOidBytesLen + 2;
      /* What is the 30 len of the total contentInfo?
       */
      totalLen = explicitLen + offset + VoltP7SignDataOidBytesLen + 3;
      outputLen += VoltDetermineDerLengthLen (totalLen);
      outputLen++;

      /* outputLen counts the total input length. However, this call to
       * Update may not have all the data.
       */
      outputLen -= (obj->dataLen - inputDataLen);

      /* Is the buffer big enough?
       */
      status = VT_ERROR_BUFFER_TOO_SMALL;
      *messageLen = outputLen;
      if (bufferSize < outputLen)
        break;

      /* If the caller passed NULL input with non-zero inputLen, they
       * just wanted the length, don't process.
       */
      if ( (inputData == (unsigned char *)0) && (inputDataLen != 0) )
        break;

      /* The buffer is big enough. Place the prefix.
       * First, the 30 len of the overall contentInfo.
       */
      offset = VoltWriteDerTagAndLen (message, 0x30, totalLen);
      /* Write out the SignedData OID.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x06, VoltP7SignDataOidBytesLen);
      Z2Memcpy (message + offset, signedDataOid, VoltP7SignDataOidBytesLen);
      offset += VoltP7SignDataOidBytesLen;
      /* Write out the EXPLICIT and the SignedData's SEQUENCE.
       */
      offset += VoltWriteDerTagAndLen (message + offset, 0xA0, explicitLen);
      offset += VoltWriteDerTagAndLen (message + offset, 0x30, signedDataLen);
      /* Now it's the version.
       */
      message[offset] = 0x02;
      offset++;
      message[offset] = 0x01;
      offset++;
      message[offset] = 0x01;
      offset++;
      /* Write out the SET of digestAlgorithms.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x31, signCtx->digestAlgId.len);
      Z2Memcpy (
        message + offset, signCtx->digestAlgId.data, signCtx->digestAlgId.len);
      offset += signCtx->digestAlgId.len;
      /* Next is contentInfo of the signed data.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x30, contentInfoLen);
      /* Place the Data OID.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x06, VoltP7DataOidBytesLen);
      Z2Memcpy (message + offset, dataOid, VoltP7DataOidBytesLen);
      offset += VoltP7DataOidBytesLen;
      /* Now comes the data itself. First, the EXPLICIT.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0xA0, contentLen);
      /* Now the OCTET STRING.
       */
      offset += VoltWriteDerTagAndLen (
        message + offset, 0x04, obj->dataLen);

      /* We'll start digesting data now.
       */
      status = VtDigestInit (signCtx->digester);
      if (status != 0)
        break;
    }
    else if (obj->state == VOLT_P7_STATE_SIGN_WRITE_UPDATE)
    {
      /* If Update, make sure the amount of input does not exceed the
       * dataLen.
       */
      status = VT_ERROR_INVALID_INPUT_LENGTH;
      if ((inputDataLen + obj->inputLen) > obj->dataLen)
        break;

      /* Is the output buffer big enough?
       */
      status = VT_ERROR_BUFFER_TOO_SMALL;
      *messageLen = inputDataLen;
      if (bufferSize < inputDataLen)
        break;

      /* If the caller passed NULL input with non-zero inputLen, they
       * just wanted the length, don't process.
       */
      if ( (inputData == (unsigned char *)0) && (inputDataLen != 0) )
        break;

      offset = 0;
    }
    else
    {
      status = VT_ERROR_INVALID_CALL_ORDER;
      break;
    }

    /* Digest the input data.
     */
    status = VtDigestUpdate (signCtx->digester, inputData, inputDataLen);
    if (status != 0)
      break;

    /* Write out the input.
     */
    Z2Memcpy (message + offset, inputData, inputDataLen);

    obj->inputLen += inputDataLen;

    obj->state = VOLT_P7_STATE_SIGN_WRITE_UPDATE;

  } while (0);

  return (status);
}

int VoltP7SignWriteFinal (
   VtPkcs7Object pkcs7Obj,
   VtRandomObject random,
   unsigned char *inputData,
   unsigned int inputDataLen,
   unsigned char *message,
   unsigned int bufferSize,
   unsigned int *messageLen
   )
{
  int status;
  unsigned int index, bufSize;
  unsigned int signatureLen, lastMessageLen, digestLen, totalLen;
  VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
  VoltPkcs7WriteSignCtx *signCtx = (VoltPkcs7WriteSignCtx *)(obj->localCtx);
  VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
  VoltDigestClassCtx *digestCtx = (VoltDigestClassCtx *)
    (((VoltAlgorithmObject *)(signCtx->digester))->classCtx);
  unsigned char *buffer, *temp;
  unsigned char *digest = (unsigned char *)0;
  Asn1SignerInfo *nextSignerInfo;

  do
  {
    /* If no dataLen is set, the inputDataLen is that value.
     */
    if (obj->dataLen == 0)
      obj->dataLen = inputDataLen;

    /* The state must be INIT or UPDATE.
     */
    status = VT_ERROR_INVALID_CALL_ORDER;
    if ( (obj->state != VOLT_P7_STATE_SIGN_WRITE_INIT) &&
         (obj->state != VOLT_P7_STATE_SIGN_WRITE_UPDATE) )
      break;

    /* Make sure the total len of input equals the "predicted" len.
     */
    status = VT_ERROR_INVALID_INPUT_LENGTH;
    if ((inputDataLen + obj->inputLen) != obj->dataLen)
      break;

    /* How much space is needed for the last chunk of data?
     * If there's no input data, the outputLen might be 0, which is
     * fine. So if the return is 0, reset status to BUFFER_TOO_SMALL
     * just to make it easier to break out on a different error.
     */
    status = VoltP7SignWriteUpdate (
      pkcs7Obj, random, (unsigned char *)0, inputDataLen,
      (unsigned char *)0, 0, &lastMessageLen);
    if (status == 0)
      status = VT_ERROR_BUFFER_TOO_SMALL;
    if (status != VT_ERROR_BUFFER_TOO_SMALL)
      break;

    /* We now know how long each of the components will be, determine
     * the total length.
     *    last of the message
     *    A0 len
     *       <certs>
     *    --no CRL's for this implementation--
     *    31 len
     *       <SignerInfo's>
     */
    totalLen = VoltDetermineDerLengthLen (signCtx->totalCertLen);
    totalLen += 1 + signCtx->totalCertLen;
    totalLen += VoltDetermineDerLengthLen (signCtx->totalSignerInfoLen);
    totalLen += 1 + signCtx->totalSignerInfoLen;
    totalLen += lastMessageLen;

    status = VT_ERROR_BUFFER_TOO_SMALL;
    *messageLen = totalLen;
    if (bufferSize < totalLen)
      break;

    /* If the caller passed NULL input with non-zero inputLen, they
     * just wanted the length, don't process.
     */
    if ( (inputData == (unsigned char *)0) && (inputDataLen != 0) )
      break;

    /* The buffer is big enough, place data into the output.
     */
    totalLen = 0;
    status = VoltP7SignWriteUpdate (
      pkcs7Obj, random, inputData, inputDataLen,
      message, bufferSize, &lastMessageLen);
    if (status != 0)
      break;

    bufferSize -= lastMessageLen;
    totalLen += lastMessageLen;

    /* Call DigestFinal to get the digest of the data.
     */
    status = VtDigestFinal (
      signCtx->digester, (unsigned char *)0, 0,
      signCtx->digest, signCtx->digestSize, &digestLen);
    if (status != 0)
      break;

    /* Place the certs. IMPLICIT SET OF.
     */
    totalLen += VoltWriteDerTagAndLen (
      message + totalLen, 0xA0, signCtx->totalCertLen);

    for (index = 0; index < signCtx->signerInfosCount; ++index)
    {
      Z2Memcpy (
        message + totalLen, signCtx->signerInfos[index].cert.data,
        signCtx->signerInfos[index].cert.len);
      totalLen += signCtx->signerInfos[index].cert.len;
    }

    for (index = 0; index < signCtx->extraCertsCount; ++index)
    {
      Z2Memcpy (
        message + totalLen, signCtx->extraCerts[index].data,
        signCtx->extraCerts[index].len);
      totalLen += signCtx->extraCerts[index].len;
    }

    /* Next is SingerInfos, that's a SET OF.
     */
    totalLen += VoltWriteDerTagAndLen (
      message + totalLen, 0x31, signCtx->totalSignerInfoLen);

    /* We need a buffer to hold the digest of auth attrs.
     */
    status = VT_ERROR_MEMORY;
    digest = (unsigned char *)Z2Malloc (signCtx->digestSize, 0);
    if (digest == (unsigned char *)0)
      break;

    /* For each of the signer's, place the correct digest into the
     * authAttributes, then create the signature of the authAttributes.
     */
    for (index = 0; index < signCtx->signerInfosCount; ++index)
    {
      nextSignerInfo = signCtx->signerInfos[index].asn1SignerInfo;

      /* We set the Asn1Encoded inside the asn1SignerInfo object with a
       * placeholder. We'll fill the buffer inside the object with the
       * actual data now.
       */
      buffer = nextSignerInfo->authAttributes->base.data;
      bufSize = (unsigned int)(nextSignerInfo->authAttributes->base.length);

      status = BuildAuthAttributes (
        obj, VT_PKCS7_DATA, signCtx->digest, signCtx->digestSize,
        &(signCtx->signingTime), buffer, bufSize, &bufSize);
      if (status != 0)
        break;

      /* Digest the auth attrs for the signature.
       */
      status = VtDigestInit (signCtx->digester);
      if (status != 0)
        break;

      /* P7 says to sign the auth attrs as SET OF. However, we built
       * the authAttrs as IMPLICIT. So for the digesting, change the A0
       * to 31. Then when the digesting is done, change it back.
       */
      buffer[0] = 0x31;
      status = VtDigestFinal (
        signCtx->digester, buffer, bufSize,
        digest, signCtx->digestSize, &digestLen);
      if (status != 0)
        break;
      buffer[0] = 0xA0;

      /* Create a signature for that data.
       */
      status = VtSign (
        signCtx->signerInfos[index].signObj,
        signCtx->signerInfos[index].priKeyRef,
        random, digestCtx->algorithm, digest, digestLen,
        signCtx->signerInfos[index].signature,
        signCtx->signerInfos[index].sigBufSize, &signatureLen);
      if (status != 0)
        break;

      /* If the signature is smaller than the sigBufSize, fix it
       * (prepend 00 bytes in appropriate places) to make it work.
       */
      if (signatureLen != signCtx->signerInfos[index].sigBufSize)
        FixDsaSignature (
          libCtx, signCtx->signerInfos[index].signature,
          signCtx->signerInfos[index].sigBufSize, &signatureLen);

      /* Place the signature into the SignerInfo.
       */
      status = VT_ERROR_MEMORY;
      if (ASN1_OCTET_STRING_set (
        nextSignerInfo->signature,
        signCtx->signerInfos[index].signature, (int)signatureLen) != 1)
        break;

      /* Encode the SignerInfo into the message buffer.
       */
      status = VT_ERROR_INVALID_INPUT;
      temp = message + totalLen;
      signCtx->signerInfos[index].signerInfoLen = i2d_Asn1SignerInfo (
        signCtx->signerInfos[index].asn1SignerInfo, &temp);
      if (temp == (unsigned char *)0)
        break;

⌨️ 快捷键说明

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