📄 derhelp.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "derhelp.h"
#include "errorctx.h"
/* Get the tag and length octets into the given buffer. If the buffer
* is not big enough, realloc so that it is (of course, if it is
* already big enough, no malloc or realloc is necessary).
* <p>This function does not check the tag, it just places what is in
* the tag position into the buffer.
* <p>This function will not return an error if it encounters
* indefinite length, it will simply return the tag and len.
* <p>This function will return an error if the first length octet is
* not valid (such as 0xC3 or 0x8D).
* <p>The caller passes the buffer into which the function will place
* the result, the size of the buffer, and the number of bytes in the
* buffer. There may have been a previous call that deposited some of
* the tag and len bytes into the buffer, but not all.
* <p>The caller passes the address of the size, if this function needs
* to realloc, it will deposit at the size address the new size.
* <p>The length arg is also an address. The function will go to that
* address to get the current length and will deposit at that address
* the new length.
* <p>The function will also return the number of bytes read.
* <p>If the call completes the tag and len, it will set the unsigned
* int at complete to 1. If not, it will set it to 0.
* <p>This function will not check encoding and encodingLen, it is the
* responsibility of the caller to pass in a valid pointer of length
* not zero.
* <p>Because the function might realloc, pass the address of the
* buffer, not the buffer itself.
*/
static int VOLT_CALLING_CONV CollectTagAndLenRealloc VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
unsigned char *encoding,
unsigned int encodingLen,
unsigned char **buffer,
unsigned int *bufferSize,
unsigned int *bufferLen,
unsigned int *bytesRead,
unsigned int *complete
));
/* Store the given data in the element buffer of the derElement struct.
* If the buffer is big enough already, just store the data and set the
* elementLen. If the buffer is not big enough, realloc and store.
* <p>This function will append data. That is, if the elementLen is not
* 0, the routine will keep the old data, append the new data onto the
* end and increment elementLen. If elementLen is 0, this routine will
* store the input as a new element buffer.
*
* @param libCtx
* @param derElement
* @param dataToStore
* @param dataToStoreLen
* @return an int, 0 if the function completed successfully or a
* non-zero error code.
*/
static int VOLT_CALLING_CONV StoreElementData VOLT_PROTO_LIST ((
VoltLibCtx *libCtx,
VoltDerElement *derElement,
unsigned char *dataToStore,
unsigned int dataToStoreLen
));
int VoltDecodeTagAndLen (
VoltLibCtx *libCtx,
unsigned char *encoding,
unsigned int encodingLen,
unsigned int *theTag,
unsigned int *lengthLen,
UInt32 *valueLenLo,
UInt32 *valueLenHi,
unsigned int sizeofResult
)
{
int status;
unsigned int len, index;
UInt32 val;
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_ENCODING;
if (encoding == (unsigned char *)0)
break;
/* There must be at least 2 bytes, tag and len.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (encodingLen < 2)
break;
*theTag = (unsigned int)(encoding[0]);
len = (unsigned int)(encoding[1]);
*valueLenHi = (UInt32)0;
/* If the length octet is <= 0x80, it's the only length octet and it
* is the return value for valueLenLo.
*/
if (len <= 0x80)
{
status = 0;
*lengthLen = 1;
*valueLenLo = (UInt32)len;
break;
}
/* The 1st length octet is > 0x80, it describes how many length octets
* there are: 0x8i where i is the number of length octets in addition
* to the 1st length octet.
* If the first nibble is not 8, error.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_ENCODING;
if ((len & 0xf0) != 0x80)
break;
len &= 0xf;
/* If the caller put a limit on the size of the result, check to
* see if the length exceeds that limit.
*/
VOLT_SET_FNCT_LINE (fnctLine)
if ( ((sizeofResult == 2) || (sizeofResult == 4)) && (len > sizeofResult) )
break;
/* Make sure the encoding has that many bytes (plus the tag and 1st
* length octet).
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (encodingLen < (len + 2))
break;
/* len now has the number of bytes that make up the actual length,
* however, the lengthLen is the number of bytes needed to encode
* the lenght, which includes the 0x8i.
*/
*lengthLen = len + 1;
/* Get the value length from the next len octets.
*/
index = 2;
val = 0;
switch (len)
{
default:
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_ENCODING;
break;
case 8:
val = (UInt32)(encoding[index]);
val <<= 8;
index++;
case 7:
val += (UInt32)(encoding[index]);
val <<= 8;
index++;
case 6:
val += (UInt32)(encoding[index]);
val <<= 8;
index++;
case 5:
val += (UInt32)(encoding[index]);
index++;
*valueLenHi = val;
val = 0;
case 4:
val = (UInt32)(encoding[index]);
val <<= 8;
index++;
case 3:
val += (UInt32)(encoding[index]);
val <<= 8;
index++;
case 2:
val += (UInt32)(encoding[index]);
val <<= 8;
index++;
case 1:
val += (UInt32)(encoding[index]);
*valueLenLo = val;
status = 0;
}
} while (0);
VOLT_LOG_ERROR_INFO_COMPARE (
status, libCtx, 0, status, 0, VT_ERROR_TYPE_PRIMARY,
(char *)0, "VoltDecodeTagAndLen", fnctLine, (char *)0)
return (status);
}
unsigned int VoltDetermineDerLengthLen (
UInt32 valueLenLo,
UInt32 valueLenHi
)
{
unsigned int retVal;
UInt32 checkVal;
retVal = 6;
checkVal = valueLenHi;
if (valueLenHi == 0)
{
if (valueLenLo <= 0x7f)
return (1);
retVal = 2;
checkVal = valueLenLo;
}
/* Find the first byte in checkVal with something in it.
*/
if ((checkVal & 0xffff0000) != 0)
{
checkVal >>= 16;
retVal += 2;
}
if ((checkVal & 0xff00) != 0)
retVal += 1;
return (retVal);
}
unsigned int VoltWriteDerTagAndLen (
unsigned char *buf,
unsigned int tag,
UInt32 valueLenLo,
UInt32 valueLenHi
)
{
unsigned int count;
UInt32 checkVal;
buf[0] = (unsigned char)tag;
count = 5;
checkVal = valueLenHi;
if (valueLenHi == 0)
{
if (valueLenLo <= 0x7f)
{
buf[1] = (unsigned char)valueLenLo;
return (2);
}
count = 1;
checkVal = valueLenLo;
}
/* Find the first byte in checkVal with something in it.
*/
if ((checkVal & 0xffff0000) != 0)
{
checkVal >>= 16;
count += 2;
}
if ((checkVal & 0xff00) != 0)
count += 1;
/* When the length is more than 0x7f, the first octet of length is
* 0x8i, where i is the number of octets that make up the actual
* length value.
*/
buf[1] = (unsigned char)(count + 0x80);
buf += 2;
switch (count)
{
case 8:
*buf = (unsigned char)(valueLenHi >> 24);
buf++;
case 7:
*buf = (unsigned char)(valueLenHi >> 16);
buf++;
case 6:
*buf = (unsigned char)(valueLenHi >> 8);
buf++;
case 5:
*buf = (unsigned char)valueLenHi;
buf++;
case 4:
*buf = (unsigned char)(valueLenLo >> 24);
buf++;
case 3:
*buf = (unsigned char)(valueLenLo >> 16);
buf++;
case 2:
*buf = (unsigned char)(valueLenLo >> 8);
buf++;
default:
*buf = (unsigned char)valueLenLo;
}
return (count + 2);
}
#if VT_64_BIT_LENGTH == 64
#define VOLT_LEN_LIMIT 8
#else
#define VOLT_LEN_LIMIT 4
#endif
int VoltGetNextDerElement (
VoltLibCtx *libCtx,
unsigned char *encoding,
unsigned int encodingLen,
unsigned int explicitTag,
unsigned int expectedTag,
unsigned int valueFlag,
VoltDerElement *derElement,
unsigned int *bytesRead
)
{
int status;
unsigned int octetsRead, complete, lengthLen;
UInt32 lenLo, lenHi;
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* If there's nothing to read, or if it's already captured, there's
* nothing to do.
*/
*bytesRead = 0;
if ( (encodingLen == 0) || (derElement->complete != 0) )
return (0);
do
{
/* If there's an EXPLICIT tag, and it has not been collected yet,
* collect it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -