13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* $Id$ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * IPRT - ASN.1, OBJECT IDENTIFIER Type, Decoder.
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/err.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/ctype.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/formats/asn1.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic char const g_achDigits[11] = "0123456789";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) rtAsn1ObjId_InternalFormatComponent(uint32_t uValue, char **ppszObjId, size_t *pcbObjId); /* asn1-ut-objid.cpp */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Internal worker for RTAsn1ObjId_DecodeAsn1 that formats a component, with a
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * leading dot.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VBox status code (caller complains on failure).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param uValue The component ID value.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param ppszObjId Pointer to the output buffer pointer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcbObjId Pointer to the remaining size of the output buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) rtAsn1ObjId_InternalFormatComponent(uint32_t uValue, char **ppszObjId, size_t *pcbObjId)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Format the number backwards.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char szTmp[32];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *psz = &szTmp[sizeof(szTmp) - 1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *psz = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *--psz = g_achDigits[uValue % 10];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uValue /= 10;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (uValue > 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Do we have enough space?
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We add a dot and save space for the terminator.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cchNeeded = &szTmp[sizeof(szTmp) - 1] - psz;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (1 + cchNeeded < *pcbObjId)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pcbObjId -= cchNeeded + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *pszObjId = *ppszObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *ppszObjId = pszObjId + cchNeeded + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszObjId = '.';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pszObjId + 1, psz, cchNeeded);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertFailed();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_TOO_LONG_STRING_FORM;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Reads one object ID component, returning it's value and encoded length.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns The encoded length (positive) on success, negative IPRT status code
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * on failure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pbContent The start of the component to parse.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbContent The number of content bytes left.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param puValue Where to return the value.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int rtAsn1ObjId_ReadComponent(uint8_t const *pbContent, uint32_t cbContent, uint32_t *puValue)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cbContent >= 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The first byte. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t b = *pbContent;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!(b & 0x80))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *puValue = b;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Encoded as more than one byte. Make sure that it's efficently
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync encoded as 8.19.2 indicates it must. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b != 0x80)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t off = 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uValue = b & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (off < cbContent)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = pbContent[off++];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uValue <<= 7;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uValue |= b & 0x7f;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!(b & 0x80))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *puValue = uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return (int)off;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_UNLIKELY(uValue & UINT32_C(0x0e000000)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_OBJID_COMPONENT_TOO_BIG;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_ASN1_INVALID_OBJID_ENCODING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_NO_DATA;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This function parses the binary content of an OBJECT IDENTIFIER, check the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * encoding as well as calculating the storage requirements.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pbContent Pointer to the content.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbContent The length of the content.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pCursor The cursor (for error reporting).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszErrorTag The error tag.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcComponents Where to return the component count.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcchObjId Where to return the length of the dotted string
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * representation.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int rtAsn1ObjId_PreParse(uint8_t const *pbContent, uint32_t cbContent, PRTASN1CURSOR pCursor, const char *pszErrorTag,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t *pcComponents, uint8_t *pcchObjId)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cbContent >= 1 && cbContent < _1K)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Decode the first two numbers. Monkey business: X*40 + Y
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Where X is the first number, X in {0,1,2}, and Y is the second
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * one. The range of Y is {0,...,39} for X in {0,1}, but has a
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * free range for X = 2.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cComponents = 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (rc > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cchObjId = 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uValue = uValue < 2*40 ? uValue % 40 : uValue - 2*40; /* Y */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cComponents++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Figure the encoded string length, binary search fashion. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 10000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 100)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 10)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 1000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 3;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 1000000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 100000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 5;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 6;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 10000000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 7;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (uValue < 100000000)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 8;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId += 1 + 9;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* advance. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbContent += rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbContent -= rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!cbContent)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cComponents < 128)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cchObjId < RT_SIZEOFMEMB(RTASN1OBJID, szObjId))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pcComponents = cComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pcchObjId = cchObjId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_OBJID_TOO_LONG_STRING_FORM,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Object ID has a too long string form: %#x (max %#x)",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchObjId, RT_SIZEOFMEMB(RTASN1OBJID, szObjId));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTAsn1CursorSetInfo(pCursor, VERR_ASN1_OBJID_TOO_MANY_COMPONENTS,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Object ID has too many components: %#x (max 127)", cComponents);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* next */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (rc > 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1CursorSetInfo(pCursor, rc, "Bad object ID component #%u encoding: %.*Rhxs",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cComponents, cbContent, pbContent);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (cbContent)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1CursorSetInfo(pCursor, VERR_ASN1_INVALID_OBJID_ENCODING, "Object ID content is loo long: %#x", cbContent);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1CursorSetInfo(pCursor, VERR_ASN1_INVALID_OBJID_ENCODING, "Zero length object ID content");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTAsn1ObjId_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pThis, const char *pszErrorTag)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTAsn1CursorReadHdr(pCursor, &pThis->Asn1Core, pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1CursorMatchTagClassFlags(pCursor, &pThis->Asn1Core, ASN1_TAG_OID,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE, fFlags, pszErrorTag, "OID");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Validate and count things first.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
e5df77e70b59a10327e0d2bdd21af0a5c8a551e2vboxsync uint8_t cComponents = 0; /* gcc maybe-crap */
e5df77e70b59a10327e0d2bdd21af0a5c8a551e2vboxsync uint8_t cchObjId = 0; /* ditto */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_PreParse(pCursor->pbCur, pThis->Asn1Core.cb, pCursor, pszErrorTag, &cComponents, &cchObjId);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Allocate memory for the components array, either out of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * string buffer or off the heap.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->cComponents = cComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation);
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 (cComponents * sizeof(uint32_t) <= sizeof(pThis->szObjId) - cchObjId - 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->pauComponents = (uint32_t *)&pThis->szObjId[sizeof(pThis->szObjId) - cComponents * sizeof(uint32_t)];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->pauComponents,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cComponents * sizeof(pThis->pauComponents[0]));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t *pauComponents = (uint32_t *)pThis->pauComponents;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Deal with the two first components first since they are
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * encoded in a weird way to save a byte.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t const *pbContent = pCursor->pbCur;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cbContent = pThis->Asn1Core.cb;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue); AssertRC(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbContent += rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbContent -= rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uValue < 80)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[0] = uValue / 40;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[1] = uValue % 40;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[0] = 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[1] = uValue - 2*40;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *pszObjId = &pThis->szObjId[0];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszObjId++ = g_achDigits[pauComponents[0]];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbObjIdLeft = cchObjId + 1 - 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_InternalFormatComponent(pauComponents[1], &pszObjId, &cbObjIdLeft); AssertRC(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The other components are encoded in less complicated manner.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 2; i < cComponents; i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_ReadComponent(pbContent, cbContent, &uValue);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRCBreak(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pbContent += rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbContent -= rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pauComponents[i] = uValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = rtAsn1ObjId_InternalFormatComponent(uValue, &pszObjId, &cbObjIdLeft);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRCBreak(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(cbObjIdLeft == 1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszObjId = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1CursorSkip(pCursor, pThis->Asn1Core.cb);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.fFlags |= RTASN1CORE_F_PRIMITE_TAG_STRUCT;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pThis->Asn1Core.pOps = &g_RTAsn1ObjId_Vtable;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
375c27aef516595a50459787463506d474668e8cvboxsync RT_ZERO(*pThis);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
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-asn1-decoder.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync