13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* $Id$ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * IPRT - ASN.1, OBJECT IDENTIFIER Type.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The contents of this file may alternatively be used under the terms
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of the Common Development and Distribution License Version 1.0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * CDDL are applicable instead of those of the GPL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * You may elect to license modified versions of this file under the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "internal/iprt.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/alloca.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/bignum.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/ctype.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/err.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/uni.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/formats/asn1.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic char const g_szDefault[] = "2.16.840.1.113894";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t const g_auDefault[] = { 2, 16, 840, 1, 113894 };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint8_t const g_abDefault[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 2*40 + 16, 0x80 | (840 >> 7), 840 & 0x7f, 1, 0x80 | (113894 >> 14), 0x80 | ((113894 >> 7) & 0x7f), 113894 & 0x7f
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync};
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) rtAsn1ObjId_InternalFormatComponent(uint32_t uValue, char **ppszObjId, size_t *pcbObjId); /* asn1-ut-objid.cpp */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @todo check if we really need this. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * ASN.1 OBJECT IDENTIFIER - Special Methods.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Encodes the ASN.1 byte sequence for a set of components.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cComponents The number of components. Must be at least two.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pauComponents The components array.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pbEncoded The output buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcbEncoded On input, this holds the size of the output buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * On successful return it's the encoded size in bytes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int rtAsn1ObjId_EncodeComponents(uint32_t cComponents, uint32_t const *pauComponents,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t *pbEncoded, uint32_t *pcbEncoded)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t *pbCur = pbEncoded;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cbLeft = *pcbEncoded;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The first two componets are encoded together to save a byte, so the loop
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync organization is a little special. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(cComponents >= 2, VERR_ASN1_INTERNAL_ERROR_1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(pauComponents[0] <= 2, VERR_ASN1_INTERNAL_ERROR_1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(pauComponents[1] <= (pauComponents[0] < 2 ? 39 : UINT32_MAX - 80), VERR_ASN1_INTERNAL_ERROR_1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t i = 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uValue = pauComponents[0] * 40 + pauComponents[1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 0x80)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cbLeft < 1))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_BUFFER_OVERFLOW;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pbCur++ = (uint8_t)uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (uValue < 0x4000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cbLeft < 2))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_BUFFER_OVERFLOW;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[0] = (uValue >> 7) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[1] = uValue & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur += 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (uValue < 0x200000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cbLeft < 3))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_BUFFER_OVERFLOW;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= 3;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[0] = (uValue >> 14) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[1] = ((uValue >> 7) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[2] = uValue & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur += 3;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (uValue < 0x10000000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cbLeft < 4))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_BUFFER_OVERFLOW;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= 4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[0] = (uValue >> 21) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[1] = ((uValue >> 14) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[2] = ((uValue >> 7) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[3] = uValue & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur += 4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cbLeft < 5))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_BUFFER_OVERFLOW;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= 5;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[0] = (uValue >> 28) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[1] = ((uValue >> 21) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[2] = ((uValue >> 14) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[3] = ((uValue >> 7) & 0x7f) | 0x80;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur[4] = uValue & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbCur += 5;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Advance / return. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync i++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (i >= cComponents)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pcbEncoded = (uint32_t)(pbCur - pbEncoded);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uValue = pauComponents[i];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check the string, counting the number of components and checking their validity.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbObjId = strlen(pszObjId) + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(cbObjId < sizeof(pThis->szObjId), VERR_ASN1_OBJID_TOO_LONG_STRING_FORM);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *psz = pszObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Special checking of the first component. It has only three valid values: 0,1,2. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char ch = *psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(ch < '0' || ch > '2'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char const chFirst = ch;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(ch != '.'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The 2nd component. It the first is 0 or 1, it has a max of 39. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cComponents = 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (chFirst < '2')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (*psz == '.')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(ch < '0' || ch > '3'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (*psz != '.')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cComponents++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync psz--;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Subsequent components have max values of UINT32_MAX - 80. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((ch = *psz++) != '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(ch != '.'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszStart = psz;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Special treatment of the first digit. Need to make sure it isn't an
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unnecessary leading 0. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(ch == '0' && RT_C_IS_DIGIT(*psz)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The rest of the digits. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((ch = *psz) != '.' && ch != '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(!RT_C_IS_DIGIT(ch)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Check the value range. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(psz - pszStart >= 9))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( psz - pszStart > 9
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || strncmp(pszStart, "4294967216", 9) >= 0) /* 2^32 - 80 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cComponents++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(cComponents >= 128))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_TOO_MANY_COMPONENTS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->cComponents = (uint8_t)cComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Find space for the component array, either at the unused end of szObjId
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * or on the heap.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbLeft = sizeof(pThis->szObjId) - cbObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cbLeft >= cComponents * sizeof(uint32_t))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= cComponents * sizeof(uint32_t);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents, cComponents * sizeof(uint32_t));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Fill the elements array.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t *pauComponents = (uint32_t *)pThis->pauComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync psz = pszObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < cComponents; i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uValue = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTStrToUInt32Ex(psz, (char **)&psz, 10, &uValue);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (rc == VWRN_TRAILING_CHARS)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[i] = uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertBreakStmt(*psz == '.', rc = VERR_TRAILING_CHARS);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync psz++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (rc == VINF_SUCCESS)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[i] = uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(*psz == '\0');
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = -rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (rc == VINF_SUCCESS && *psz == '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize the core structure before we start on the encoded bytes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1Core_InitEx(&pThis->Asn1Core,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAG_OID,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &g_RTAsn1ObjId_Vtable,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Encode the value into the string buffer. This will NOT overflow
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * because the string representation is much less efficient than the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * binary ASN.1 representation (base-10 + separators vs. base-128).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.cb = (uint32_t)cbObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_EncodeComponents(cComponents, pThis->pauComponents,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (uint8_t *)&pThis->szObjId[0], &pThis->Asn1Core.cb);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Now, find a place for the encoded bytes. There might be
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * enough room left in the szObjId for it if we're lucky.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pThis->Asn1Core.cb >= cbLeft)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.uData.pv = memmove(&pThis->szObjId[cbObjId], &pThis->szObjId[0], pThis->Asn1Core.cb);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1ContentDup(&pThis->Asn1Core, pThis->szObjId, pThis->Asn1Core.cb, pAllocator);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Finally, copy the dotted string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pThis->szObjId, pszObjId, cbObjId);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertMsgFailed(("%Rrc\n", rc));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VERR_ASN1_INTERNAL_ERROR_3;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VERR_ASN1_OBJID_INVALID_DOTTED_STRING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_CompareWithString(PCRTASN1OBJID pThis, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return strcmp(pThis->szObjId, pszRight);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(bool) RTAsn1ObjId_StartsWith(PCRTASN1OBJID pThis, const char *pszStartsWith)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cchStartsWith = strlen(pszStartsWith);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return !strncmp(pThis->szObjId, pszStartsWith, cchStartsWith)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && ( pszStartsWith[cchStartsWith] == '.'
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || pszStartsWith[cchStartsWith] == '\0');
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(uint8_t) RTAsn1ObjIdCountComponents(PCRTASN1OBJID pThis)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pThis->cComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(uint32_t) RTAsn1ObjIdGetComponentsAsUInt32(PCRTASN1OBJID pThis, uint8_t iComponent)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iComponent < pThis->cComponents)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pThis->pauComponents[iComponent];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return UINT32_MAX;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(uint32_t) RTAsn1ObjIdGetLastComponentsAsUInt32(PCRTASN1OBJID pThis)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pThis->pauComponents[pThis->cComponents - 1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * ASN.1 OBJECT IDENTIFIER - Standard Methods.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRT_DECL_DATA_CONST(RTASN1COREVTABLE const) g_RTAsn1ObjId_Vtable =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "RTAsn1ObjId",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(RTASN1OBJID),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAG_OID,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (PFNRTASN1COREVTDTOR)RTAsn1ObjId_Delete,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (PFNRTASN1COREVTCLONE)RTAsn1ObjId_Clone,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (PFNRTASN1COREVTCOMPARE)RTAsn1ObjId_Compare,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (PFNRTASN1COREVTCHECKSANITY)RTAsn1ObjId_CheckSanity,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync};
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_Init(PRTASN1OBJID pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1Core_InitEx(&pThis->Asn1Core,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAG_OID,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &g_RTAsn1ObjId_Vtable,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTASN1CORE_F_PRESENT | RTASN1CORE_F_PRIMITE_TAG_STRUCT);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.cb = sizeof(g_abDefault);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.uData.pv = (void *)&g_abDefault[0];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->cComponents = RT_ELEMENTS(g_auDefault);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->pauComponents = g_auDefault;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertCompile(sizeof(g_szDefault) <= sizeof(pThis->szObjId));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pThis->szObjId, g_szDefault, sizeof(g_szDefault));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_Clone(PRTASN1OBJID pThis, PCRTASN1OBJID pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertPtr(pSrc); AssertPtr(pThis); AssertPtr(pAllocator);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTAsn1ObjId_IsPresent(pSrc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(pSrc->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable, VERR_INTERNAL_ERROR_3);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Copy the dotted string representation. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbObjId = strlen(pSrc->szObjId) + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(cbObjId <= sizeof(pThis->szObjId), VERR_INTERNAL_ERROR_5);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pThis->szObjId, pSrc->szObjId, cbObjId);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Copy the integer component array. Try fit it in the unused space of
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync the dotted object string buffer. We place it at the end of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync buffer as that is simple alignment wise and avoid wasting bytes that
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync could be used to sequueze in the content bytes (see below). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->cComponents = pSrc->cComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbLeft = sizeof(pThis->szObjId);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pSrc->cComponents * sizeof(uint32_t) <= cbLeft)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - pSrc->cComponents * sizeof(uint32_t)];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy((uint32_t *)pThis->pauComponents, pSrc->pauComponents, pSrc->cComponents * sizeof(uint32_t));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbLeft -= pSrc->cComponents * sizeof(uint32_t);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1MemDup(&pThis->Allocation, (void **)&pThis->pauComponents, pSrc->pauComponents,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pSrc->cComponents * sizeof(uint32_t));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* See if we can fit the content value into the szObjId as well.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync It will follow immediately after the string as the component
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync array is the end of the string buffer, when present. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 /** @todo breaks with arrays of ObjIds or structs containing them. They get resized and repositioned in memory, thus invalidating the pointer. Add recall-pointers callback, or just waste memory? Or maybe make all arrays pointer-arrays? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cbContent = pSrc->Asn1Core.cb;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cbContent <= cbLeft)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.uData.pv = memcpy(&pThis->szObjId[cbObjId], pSrc->Asn1Core.uData.pv, cbContent);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1Core_CloneContent(&pThis->Asn1Core, &pSrc->Asn1Core, pAllocator);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* failed, clean up. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pThis->Allocation.cbAllocated)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1MemFree(&pThis->Allocation, (uint32_t *)pThis->pauComponents);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(void) RTAsn1ObjId_Delete(PRTASN1OBJID pThis)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pThis
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && RTAsn1ObjId_IsPresent(pThis))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pThis->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pThis->Allocation.cbAllocated)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1MemFree(&pThis->Allocation, (uint32_t *)pThis->pauComponents);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1ContentFree(&pThis->Asn1Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_Enum(PRTASN1OBJID pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pThis && (!RTAsn1ObjId_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1ObjId_Vtable));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* No children to enumerate. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_Compare(PCRTASN1OBJID pLeft, PCRTASN1OBJID pRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync if (RTAsn1ObjId_IsPresent(pLeft))
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync {
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync if (RTAsn1ObjId_IsPresent(pRight))
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync {
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync uint8_t cComponents = RT_MIN(pLeft->cComponents, pRight->cComponents);
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync for (uint32_t i = 0; i < cComponents; i++)
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync if (pLeft->pauComponents[i] != pRight->pauComponents[i])
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync return pLeft->pauComponents[i] < pRight->pauComponents[i] ? -1 : 1;
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync if (pLeft->cComponents == pRight->cComponents)
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync return 0;
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync return pLeft->cComponents < pRight->cComponents ? -1 : 1;
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync }
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync return 1;
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync }
597418a165dce3e1c1330096dff7ac95c90d7099vboxsync return 0 - (int)RTAsn1ObjId_IsPresent(pRight);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_CheckSanity(PCRTASN1OBJID pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(!RTAsn1ObjId_IsPresent(pThis)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (OBJID).", pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Generate code for the associated collection types.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define RTASN1TMPL_TEMPLATE_FILE "../common/asn1/asn1-ut-objid-template.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1-generator-internal-header.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1-generator-core.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1-generator-init.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/asn1-generator-sanity.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync