static int rtCrX509TbsCertificate_CheckSanityExtra(PCRTCRX509TBSCERTIFICATE pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag) { if ( RTAsn1Integer_IsPresent(&pThis->T0.Version) && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V1) != 0 && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V2) != 0 && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V3) != 0) return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_UNSUPPORTED_VERSION, "%s: Unknown Version number: %llu", pszErrorTag, pThis->T0.Version.uValue.u); if ( pThis->SerialNumber.Asn1Core.cb < 1 || pThis->SerialNumber.Asn1Core.cb > 1024) return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_SERIAL_NUMBER_OUT_OF_BOUNDS, "%s: Bad SerialNumber length: %u", pszErrorTag, pThis->SerialNumber.Asn1Core.cb); if ( ( RTAsn1BitString_IsPresent(&pThis->T1.IssuerUniqueId) || RTAsn1BitString_IsPresent(&pThis->T2.SubjectUniqueId)) && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V2) < 0) return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_UNIQUE_IDS_REQ_V2, "%s: IssuerUniqueId and SubjectUniqueId requires version 2", pszErrorTag); if ( RTCrX509Extensions_IsPresent(&pThis->T3.Extensions) && RTAsn1Integer_UnsignedCompareWithU32(&pThis->T0.Version, RTCRX509TBSCERTIFICATE_V3) < 0) return RTErrInfoSetF(pErrInfo, VERR_CR_X509_TBSCERT_EXTS_REQ_V3, "%s: Extensions requires version 3", pszErrorTag); return VINF_SUCCESS; }
RTDECL(int) RTAsn1Integer_CheckSanity(PCRTASN1INTEGER pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag) { RT_NOREF_PV(fFlags); if (RT_UNLIKELY(!RTAsn1Integer_IsPresent(pThis))) return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (INTEGER).", pszErrorTag); return VINF_SUCCESS; }
RTDECL(int) RTAsn1Integer_Enum(PRTASN1INTEGER pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser) { Assert(pThis && (!RTAsn1Integer_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1Integer_Vtable)); /* No children to enumerate. */ return VINF_SUCCESS; }
RTDECL(int) RTAsn1Integer_Clone(PRTASN1INTEGER pThis, PCRTASN1INTEGER pSrc, PCRTASN1ALLOCATORVTABLE pAllocator) { AssertPtr(pSrc); AssertPtr(pThis); AssertPtr(pAllocator); RT_ZERO(*pThis); if (RTAsn1Integer_IsPresent(pSrc)) { AssertReturn(pSrc->Asn1Core.pOps == &g_RTAsn1Integer_Vtable, VERR_INTERNAL_ERROR_3); int rc; if ( pSrc->Asn1Core.cb != 1 || pSrc->uValue.u >= RT_ELEMENTS(g_abSmall)) { /* Value is too large, copy it. */ rc = RTAsn1Core_CloneContent(&pThis->Asn1Core, &pSrc->Asn1Core, pAllocator); if (RT_FAILURE(rc)) return rc; } else { /* Use one of the const values. */ rc = RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core); if (RT_FAILURE(rc)) return rc; Assert(g_abSmall[pSrc->uValue.u] == pSrc->uValue.u); pThis->Asn1Core.uData.pv = (void *)&g_abSmall[pSrc->uValue.u]; } pThis->uValue.u = pSrc->uValue.u; } return VINF_SUCCESS; }
RTDECL(int) RTAsn1Integer_UnsignedCompare(PCRTASN1INTEGER pLeft, PCRTASN1INTEGER pRight) { Assert(pLeft && (!RTAsn1Integer_IsPresent(pLeft) || pLeft->Asn1Core.pOps == &g_RTAsn1Integer_Vtable)); Assert(pRight && (!RTAsn1Integer_IsPresent(pRight) || pRight->Asn1Core.pOps == &g_RTAsn1Integer_Vtable)); int iDiff; if (RTAsn1Integer_IsPresent(pLeft)) { if (RTAsn1Integer_IsPresent(pRight)) { if ( pLeft->Asn1Core.cb > 8 || pRight->Asn1Core.cb > 8) { uint32_t iLeft = RTAsn1Integer_UnsignedLastBit(pLeft); uint32_t iRight = RTAsn1Integer_UnsignedLastBit(pRight); if (iLeft != iRight) return iLeft < iRight ? -1 : 1; uint32_t i = iLeft / 8; if (i > 8) { uint8_t const *pbLeft = &pLeft->Asn1Core.uData.pu8[pLeft->Asn1Core.cb - i - 1]; uint8_t const *pbRight = &pRight->Asn1Core.uData.pu8[pRight->Asn1Core.cb - i - 1]; for (;;) { if (*pbLeft != *pbRight) return *pbLeft < *pbRight ? -1 : 1; if (--i <= 8) break; pbLeft++; pbRight++; } } } if (pLeft->uValue.u == pRight->uValue.u) iDiff = 0; else iDiff = pLeft->uValue.u < pRight->uValue.u ? -1 : 1; } else iDiff = -1; } else iDiff = 0 - (int)RTAsn1Integer_IsPresent(pRight); return iDiff; }
RTDECL(void) RTAsn1Integer_Delete(PRTASN1INTEGER pThis) { if ( pThis && RTAsn1Integer_IsPresent(pThis)) { Assert(pThis->Asn1Core.pOps == &g_RTAsn1Integer_Vtable); RTAsn1ContentFree(&pThis->Asn1Core); RT_ZERO(*pThis); } }
RTDECL(int) RTAsn1Integer_ToBigNum(PCRTASN1INTEGER pThis, PRTBIGNUM pBigNum, uint32_t fBigNumInit) { AssertReturn(!(fBigNumInit & ~( RTBIGNUMINIT_F_SENSITIVE | RTBIGNUMINIT_F_UNSIGNED | RTBIGNUMINIT_F_SIGNED | RTBIGNUMINIT_F_ENDIAN_LITTLE | RTBIGNUMINIT_F_ENDIAN_BIG)), VERR_INVALID_PARAMETER); AssertReturn(RTAsn1Integer_IsPresent(pThis), VERR_INVALID_PARAMETER); if (!(fBigNumInit & (RTBIGNUMINIT_F_UNSIGNED | RTBIGNUMINIT_F_SIGNED))) fBigNumInit |= RTBIGNUMINIT_F_SIGNED; if (!(fBigNumInit & (RTBIGNUMINIT_F_ENDIAN_BIG | RTBIGNUMINIT_F_ENDIAN_LITTLE))) fBigNumInit |= RTBIGNUMINIT_F_ENDIAN_BIG; return RTBigNumInit(pBigNum, fBigNumInit, pThis->Asn1Core.uData.pv, pThis->Asn1Core.cb); }
RTDECL(int) RTAsn1Integer_FromBigNum(PRTASN1INTEGER pThis, PCRTBIGNUM pBigNum, PCRTASN1ALLOCATORVTABLE pAllocator) { AssertPtr(pThis); AssertPtr(pBigNum); AssertPtr(pAllocator); /* Be nice and auto init the object. */ if (!RTAsn1Integer_IsPresent(pThis)) RTAsn1Integer_Init(pThis, NULL); uint32_t cb = RTBigNumByteWidth(pBigNum); Assert(cb > 0); int rc = RTAsn1ContentReallocZ(&pThis->Asn1Core, cb, pAllocator); if (RT_SUCCESS(rc)) { Assert(cb == pThis->Asn1Core.cb); rc = RTBigNumToBytesBigEndian(pBigNum, (void *)pThis->Asn1Core.uData.pv, cb); if (RT_SUCCESS(rc)) rtAsn1Integer_UpdateNativeValue(pThis); } return rc; }
RTDECL(int) RTAsn1Integer_UnsignedCompareWithU32(PCRTASN1INTEGER pThis, uint32_t u32Const) { int iDiff; if (RTAsn1Integer_IsPresent(pThis)) { if (pThis->Asn1Core.cb > 8) { int32_t iLast = RTAsn1Integer_UnsignedLastBit(pThis); if (iLast >= 32) return 1; } if (pThis->uValue.u == u32Const) iDiff = 0; else iDiff = pThis->uValue.u < u32Const ? -1 : 1; } else iDiff = 1; return iDiff; }
RTDECL(int) RTAsn1Integer_ToString(PRTASN1INTEGER pThis, char *pszBuf, size_t cbBuf, uint32_t fFlags, size_t *pcbActual) { AssertReturn(RTAsn1Integer_IsPresent(pThis), VERR_INVALID_PARAMETER); AssertReturn(fFlags == 0, VERR_INVALID_FLAGS); /* * We only do hex conversions via this API. * Currently we consider all numbers to be unsigned. */ /** @todo Signed ASN.1 INTEGER. */ int rc; size_t cbActual; if (pThis->Asn1Core.cb <= 8) { cbActual = 2 + pThis->Asn1Core.cb*2 + 1; if (cbActual <= cbBuf) { ssize_t cchFormat = RTStrFormatU64(pszBuf, cbBuf, pThis->uValue.u, 16, (int)cbActual - 1 /*cchWidth*/, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD); rc = VINF_SUCCESS; AssertStmt(cchFormat == (ssize_t)cbActual - 1, rc = VERR_INTERNAL_ERROR_3); } else rc = VERR_BUFFER_OVERFLOW; } else { cbActual = pThis->Asn1Core.cb * 3 - 1 /* save one separator */ + 1 /* terminator */; if (cbActual <= cbBuf) { rc = RTStrPrintHexBytes(pszBuf, cbBuf, pThis->Asn1Core.uData.pv, pThis->Asn1Core.cb, RTSTRPRINTHEXBYTES_F_SEP_SPACE); Assert(rc == VINF_SUCCESS); } else rc = VERR_BUFFER_OVERFLOW; } if (pcbActual) *pcbActual = cbActual; return rc; }