defcertvfy.c

来自「IBE是一种非对称密码技术」· C语言 代码 · 共 861 行 · 第 1/2 页

C
861
字号
      break;

    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtCreateAlgorithmObject (
      libCtx, coderInfo.info.getAlgData.DigestImpl, (Pointer)0,
      &digester);
    if (status != 0)
      break;
    
    /* Isolate the TBS portion of the cert.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    x509ToVerify = Asn1X509CertToVerify_new ();
    if (x509ToVerify == (Asn1X509CertToVerify *)0)
      break;

    Asn1SetObjectCopyFlag (
      (VoltAsn1String *)(x509ToVerify->innerCert), VOLT_ASN1_COPY_REFERENCE);

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_UNKNOWN_BER;
    temp = obj->certificate.data;
    d2i_Asn1X509CertToVerify (&x509ToVerify, &temp, obj->certificate.len);

    /* Did it work?
     */
    if (x509ToVerify == (Asn1X509CertToVerify *)0)
      break;

    /* Digest the data.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtDigestInit (digester);
    if (status != 0)
      break;

    /* First call, get the size. We expect to get BUFFER_TOO_SMALL.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtDigestFinal (
      digester, x509ToVerify->innerCert->base.data,
      (unsigned int)(x509ToVerify->innerCert->base.length),
      (unsigned char *)0, 0, &bufferSize);
    if (status == 0)
      status = VT_ERROR_GENERAL;
    if (status != VT_ERROR_BUFFER_TOO_SMALL)
      break;

    /* Allocate a buffer to hold the digest.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    digest = (unsigned char *)Z2Malloc (bufferSize, 0);
    if (digest == (unsigned char *)0)
      break;

    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtDigestFinal (
      digester, x509ToVerify->innerCert->base.data,
      (unsigned int)(x509ToVerify->innerCert->base.length),
      digest, bufferSize, &digestLen);
    if (status != 0)
      break;

    digestAlg = ((VoltDigestClassCtx *)
      (((VoltAlgorithmObject *)digester)->classCtx))->algorithm;

    /* Isolate the signature.
     */
    signature = x509ToVerify->signature->data;
    signatureLen = (unsigned int)(x509ToVerify->signature->length);

    /* Find the issuer. First, what is the issuerName in the leaf cert?
     */
    issuerName = obj->certAsn1->innerCert->issuer->base.data;
    issuerNameLen =
      (unsigned int)(obj->certAsn1->innerCert->issuer->base.length);

    /* Build the verifyInfo to check a cert signing cert.
     */
    newVerifyInfo.keyUsage = VT_KEY_USAGE_KEY_CERT_SIGN;
    newVerifyInfo.usageTime = vInfo->usageTime;

    /* Use this to build keys from certs.
     */
    certInfo.derCoders = derCoders;
    certInfo.derCoderCount = derCoderCount;

    /* Run through all the certs. Check to see if it is the issuer. If
     * we find the issuer, we're done.
     * If we don't find an issuer that passes signature and elements,
     * we may find one that passes signature but not elements. We'll
     * use that one, but set the VerifyFailureList.
     */
    indexA = 0;
    indexB = 0;
    indexC = 0;
    indexD = 0;
    do
    {
      trusted = 0;
      candidate = (VoltCertObject *)0;
      sigVerify = 0;
      elementVerify = 0;
      if (indexA < ctx->trustedCerts.count)
      {
        candidate = (VoltCertObject *)(ctx->trustedCerts.certObjects[indexA]);
        trusted = 1;
        indexA++;
      }
      else if (indexB < tCount)
      {
        candidate = (VoltCertObject *)(trustedCerts->certObjects[indexB]);
        trusted = 1;
        indexB++;
      }
      else if (indexC < ctx->untrustedCerts.count)
      {
        candidate =
          (VoltCertObject *)(ctx->untrustedCerts.certObjects[indexC]);
        indexC++;
      }
      else if (indexD < uCount)
      {
        candidate = (VoltCertObject *)(untrustedCerts->certObjects[indexD]);
        indexD++;
      }

      /* If we ran out of candidates, exit the loop.
       */
      if (candidate == (VoltCertObject *)0)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      status = IsIssuerCert (
        libCtx, obj->mpCtx, verifyCtx, &newVerifyInfo, vfyFailList,
        &certInfo, verifier, issuerName, issuerNameLen,
        digestAlg, digest, digestLen, signature, signatureLen,
        candidate, &sigVerify, &elementVerify);
      if (status != 0)
        break;

      /* If sigVerify is False, forget about that cert.
       * If everything verified, we're done.
       * If sigVerify is True but elementVerify is false, we may want
       * to save the cert anyway.
       */
      if (sigVerify == 0)
        continue;

      if (elementVerify != 0)
        break;

      /* If we reach this point, we found a cert that matched name and
       * verified the signature, but that cert did not verify elements.
       * Save it in case we find nothing that verifies all.
       * If we find multiples, save only the first one.
       */
      if (saveCert != (VoltCertObject *)0)
        continue;

      saveCert = candidate;
      saveTrusted = trusted;

    } while (1);
    if (status != 0)
      break;

    /* If sigVerify and elementVerify are both True, we found a good
     * cert. If it is trusted, we're done. If not, we'll have to check
     * it.
     */
    if ( (sigVerify != 0) && (elementVerify != 0) )
    {
      *verifyResult = 1;
      if (trusted != 0)
        break;

      /* This is not a trusted cert, we'll have to verify this one.
       */
      *verifyResult = 0;
      saveCert = candidate;
      saveTrusted = trusted;
    }

    /* If we reach this point, we need to check a saveCert. Well, if
     * there is one. If not, we found no cert to verify the current
     * cert, so log that in the VerifyList and exit.
     */
    if (saveCert == (VoltCertObject *)0)
    {
      VOLT_SET_FNCT_LINE (fnctLine)
      status = VoltAddVerifyListEntry (
        (VoltVerifyFailureList *)vfyFailList,
        VT_VFY_FAIL_REASON_CERT_CHAIN, certToVerify);
      break;
    }

    /* If elementVerify is False, that means the saveCert verified the
     * signature, but didn't verify the elements. If there's a verify
     * failure list, we'll want to log those errors.
     */
    if (elementVerify == 0)
    {
      if (vfyFailList != (VtVerifyFailureList)0)
      {
        VOLT_SET_FNCT_LINE (fnctLine)
        status = DefaultVerifyCertElements (
          verifyCtx, (Pointer)&newVerifyInfo, saveCert, vfyFailList,
          &elementVerify);
        if (status != 0)
          break;
      }
    }

    /* If this cert is not trusted, verify it.
     */
    if (saveTrusted == 0)
    {
      VOLT_SET_FNCT_LINE (fnctLine)
      status = DefaultVerifyCertSignature (
        verifyCtx, (Pointer)&newVerifyInfo, saveCert,
        storageCtx, trustedCerts, untrustedCerts,
        derCoders, derCoderCount, vfyFailList, verifyResult);
      break;
    }

    *verifyResult = elementVerify;

  } while (0);

  if (digest != (unsigned char *)0)
    Z2Free (digest);
  if (x509ToVerify != (Asn1X509CertToVerify *)0)
    Asn1X509CertToVerify_free (x509ToVerify);
  VtDestroyAlgorithmObject (&verifier);
  VtDestroyAlgorithmObject (&digester);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, verifyCtx, status, 0, errorType,
    (char *)0, "DefaultVerifyCertSignature", fnctLine, (char *)0)

  return (status);
}

static int CheckBasicVerifyInfo (
   VoltLibCtx *libCtx,
   VoltCertObject *obj,
   Pointer info
   )
{
  int status;
  unsigned int keyUsage;
  VtBasicCertVerifyInfo *vInfo;
  unsigned char *temp;
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  do
  {
    /* We must have verifyInfo.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_INVALID_INPUT;
    if (info == (Pointer)0)
      break;

    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    vInfo = (VtBasicCertVerifyInfo *)info;
    status = VoltIsValidTime (libCtx, &(vInfo->usageTime));
    if (status != 0)
      break;

    /* Check to see if any stray keyUsage bits are set.
     */
    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_INVALID_INPUT;
    keyUsage =
      VT_KEY_USAGE_DIGITAL_SIGNATURE | VT_KEY_USAGE_NON_REPUDIATION |
      VT_KEY_USAGE_KEY_ENCIPHERMENT | VT_KEY_USAGE_DATA_ENCIPHERMENT |
      VT_KEY_USAGE_KEY_AGREEMENT | VT_KEY_USAGE_KEY_CERT_SIGN |
      VT_KEY_USAGE_CRL_SIGN | VT_KEY_USAGE_ENCIPHER | VT_KEY_USAGE_DECIPHER;
    keyUsage = ~keyUsage;
    keyUsage &= vInfo->keyUsage;
    if (keyUsage != 0)
      break;

    /* If the object does not contain the ASN.1 structure yet, build
     * it. If it does contain the structure, we're done.
     */
    status = 0;
    if (obj->certAsn1 != (Asn1X509Cert *)0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    obj->certAsn1 = Asn1X509Cert_new ();
    if (obj->certAsn1 == (Asn1X509Cert *)0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_UNKNOWN_BER;
    temp = obj->certificate.data;
    d2i_Asn1X509Cert (&(obj->certAsn1), &temp, obj->certificate.len);
    if (obj->certAsn1 == (Asn1X509Cert *)0)
      break;

    status = 0;

  } while (0);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, libCtx, obj, status, 0, errorType,
    (char *)0, "CheckBasicVerifyInfo", fnctLine, (char *)0)

  return (status);
}

static int IsIssuerCert (
   VoltLibCtx *libCtx,
   VoltMpIntCtx *mpCtx,
   VtCertVerifyCtx verifyCtx,
   VtBasicCertVerifyInfo *verifyInfo,
   VtVerifyFailureList vfyFailList,
   VtCertInfo *certInfo,
   VtAlgorithmObject verifier,
   unsigned char *name,
   unsigned int nameLen,
   unsigned int digestAlg,
   unsigned char *digest,
   unsigned int digestLen,
   unsigned char *signature,
   unsigned int signatureLen,
   VtCertObject candidateCert,
   unsigned int *sigVerify,
   unsigned int *elementVerify
   )
{
  int status;
  unsigned int checkNameLen;
  VtKeyObject verifyKey = (VtKeyObject)0;
  unsigned char *checkName;
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  *sigVerify = 0;
  *elementVerify = 0;

  status = 0;
  do
  {
    /* Check the info, this will build the certAsn1 if it's not
     * already built.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = CheckBasicVerifyInfo (
      libCtx, candidateCert, (Pointer)verifyInfo);
    if (status != 0)
      break;

    /* Is this cert's subject name the same as the issuer name of the
     * leaf cert we're checking?
     */
    checkName = candidateCert->certAsn1->innerCert->subject->base.data;
    checkNameLen =
      (unsigned int)(candidateCert->certAsn1->innerCert->subject->base.length);

    if (checkNameLen != nameLen)
      break;
    if (Z2Memcmp (checkName, name, nameLen) != 0)
      break;

    /* We found a cert with a subject name matching the issuer name of
     * the leaf. Try to verify the signature.
     * Build a public key from this cert.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtCreateKeyObject (
      (VtLibCtx)libCtx, VtKeyImplMpCtx, (Pointer)mpCtx, &verifyKey);
    if (status != 0)
      break;

    certInfo->cert = candidateCert->certificate.data;
    certInfo->certLen = candidateCert->certificate.len;
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtSetKeyParam (
      verifyKey, VtKeyParamX509Cert, (Pointer)certInfo);
    if (status != 0)
      break;

    /* Try to verify the cert using this key.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VtVerifySignature (
      verifier, verifyKey, (VtRandomObject)0, digestAlg,
      digest, digestLen, signature, signatureLen, sigVerify);
    if (status != 0)
      break;

    /* If it did not verify, forget it.
     */
    if (*sigVerify == 0)
      break;

    /* Verify the elements of this cert.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = DefaultVerifyCertElements (
      verifyCtx, (Pointer)verifyInfo, (VtCertObject)candidateCert,
      vfyFailList, elementVerify);

  } while (0);

  VtDestroyKeyObject (&verifyKey);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, libCtx, 0, status, 0, 0,
    (char *)0, "CheckBasicVerifyInfo", fnctLine, (char *)0)

  return (status);
}

⌨️ 快捷键说明

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