📄 smread.c
字号:
break;
Z2Memcpy (
readCtx->extraHeader.data + readCtx->extraHeader.len, readCtx->unprocessedData.data,
readCtx->unprocessedData.len);
readCtx->extraHeader.len += readCtx->unprocessedData.len;
readCtx->unprocessedData.len = 0;
status = 0;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
/* There's more message to read, but we haven't read the BEGIN
* BLOCK header yet, so keep performing this part until we have.
*/
goto VoltSecureMailReadHeader2;
VoltSecureMailBase64:
obj->state = VOLT_SECURE_MAIL_STATE_READ_B64_LEN;
readCtx->unprocessedData.len = 0;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
case VOLT_SECURE_MAIL_STATE_READ_B64_LEN:
/* Any data we read now will be regular message data.
* First, Base64 decode it, then send it to the p7EnvelopedData
* object to read, then any output is sent to the p7SignedData
* object to read.
* Eventually we'll run out of message material and hit the
* footers. We don't want to pass the footers to the Base64
* decoder, so we'll have to check input to make sure the line is
* not a footer.
* What we need to do is decode the first line of the message,
* then we'll have the length of the EnvelopedData.
*/
VoltSecureMailStateReadB64Len:
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
1, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
if (completeFlag == 0)
break;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* this is to handle the situation where there might have been
* empty new lines either inserted deliberately or by accident
* between -----BEGIN VOLTAGE SECURE BLOCK V1----- block and
* the beginning of the base64 encoded data. Skip all those lines.
*/
if ( (amountRead == newLineLen) &&
(readCtx->unprocessedData.len == 0) )
{
goto VoltSecureMailStateReadB64Len;
}
VoltSecureMailBase64A:
/* Set inputLen to the number of bytes read so far.
*/
#if VT_64_BIT_LENGTH == 64
obj->inputLen64 = (VtUInt64)(readCtx->unprocessedData.len);
#else
obj->inputLen = readCtx->unprocessedData.len;
#endif
/* Determine the input and output block sizes of the message.
* First, how many spaces are there to lead off a line?
*/
index = 0;
preSpaceLen = 0;
while (readCtx->unprocessedData.data[index++] == ' ')
preSpaceLen++;
/* How many actual base64 bytes? Don't count spaces or new lines.
*/
valueLen = readCtx->unprocessedData.len - preSpaceLen - newLineLen;
valueLen /= 4;
inBlockLen = valueLen * 3;
/* For each block of input, there will be one line of output,
* which includes space characters and new lines.
*/
outBlockLen = readCtx->unprocessedData.len;
/* Decode this line.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = DoDecodeUpdateOrFinal (
obj, readCtx, 1, readCtx->unprocessedData.data,
readCtx->unprocessedData.len);
if (status != 0)
break;
#if VT_64_BIT_LENGTH == 64
valueLen = 0;
#else
valueLen = 4;
#endif
/* Get the length of the EnvelopedData.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltDecodeTagAndLen (
libCtx, readCtx->unprocessedData.data, readCtx->unprocessedData.len,
&theTag, &lengthLen, &lenLo, &lenHi, valueLen);
if (status != 0)
break;
/* The length of the entire EnvelopedData is the valueLen plus
* the lengthLen plus the length of the tag (1).
*/
#if VT_64_BIT_LENGTH == 64
envelopeLen = (VtUInt64)lenHi;
envelopeLen <<= 32;
envelopeLen += (VtUInt64)lenLo;
envelopeLen += (VtUInt64)(lengthLen + 1);
#else
envelopeLen = (unsigned int)lenLo + lengthLen + 1;
#endif
/* Now determine how long the Base64 encoding of that much data
* will be. First, how many full blocks of input will there be?
*/
#if VT_64_BIT_LENGTH == 64
inBlocks = envelopeLen / (VtUInt64)inBlockLen;
#else
inBlocks = envelopeLen / inBlockLen;
#endif
/* How many bytes in the last line?
*/
#if VT_64_BIT_LENGTH == 64
outLen = inBlocks * (VtUInt64)inBlockLen;
leftovers = (UInt32)(envelopeLen - outLen);
#else
outLen = inBlocks * inBlockLen;
leftovers = envelopeLen - outLen;
#endif
/* How many output bytes will that be?
*/
#if VT_64_BIT_LENGTH == 64
outLen = inBlocks * (VtUInt64)outBlockLen;
#else
outLen = inBlocks * outBlockLen;
#endif
/* If there are any leftovers, there will be a new line, but
* we'll count number of bytes without the new line characters.
* So if there is going to be another line, add the new line
* characters now.
*/
if (leftovers != 0)
#if VT_64_BIT_LENGTH == 64
obj->dataLen64 += (VtUInt64)newLineLen;
#else
obj->dataLen += newLineLen;
#endif
/* How many blocks of 3? Use flag as a temp variable.
*/
flag = leftovers / 3;
/* For each block of three, there are four bytes of output.
* So far, the total output is the number of full blocks
* and the leftover blocks of 3 expanded to 4.
*/
#if VT_64_BIT_LENGTH == 64
outLen += (VtUInt64)(flag * 4);
#else
outLen += (flag * 4);
#endif
/* How many bytes left over? If there are any bytes left over,
* the encoder will pad to one more block.
*/
flag *= 3;
leftovers -= flag;
if (leftovers != 0)
outLen += 4;
/* Add in the number of bytes for the last line. Include the
* spaces.
*/
#if VT_64_BIT_LENGTH == 64
obj->dataLen64 += (outLen + (VtUInt64)(preSpaceLen));
#else
obj->dataLen += outLen + preSpaceLen;
#endif
/* Set the state for the next read. We have data in the
* unprocessedData buffer that needs to go to the Envelope
* object, so set the state for that.
*/
obj->state = VOLT_SECURE_MAIL_STATE_READ_ENV;
goto VoltSecureMailStateReadEnv;
VoltSecureMailStateReadB64:
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
case VOLT_SECURE_MAIL_STATE_READ_B64:
/* Read the Base64 data. If the caller passed in data beyond the
* end of the base64 data, don't read it yet.
*/
#if VT_64_BIT_LENGTH == 64
envelopeLen = obj->dataLen64 - obj->inputLen64;
flag = 1;
valueLen = currentMessageLen;
if (envelopeLen <= (VtUInt64)currentMessageLen)
{
valueLen = (unsigned int)envelopeLen;
flag = 0;
}
#else
valueLen = obj->dataLen - obj->inputLen;
if (valueLen > currentMessageLen)
valueLen = currentMessageLen;
flag = obj->dataLen - valueLen;
#endif
/* Decode the data.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = DoDecodeUpdateOrFinal (
obj, readCtx, flag, currentMessage, valueLen);
if (status != 0)
break;
#if VT_64_BIT_LENGTH == 64
obj->inputLen64 += (VtUInt64)valueLen;
#else
obj->inputLen += valueLen;
#endif
*bytesRead += valueLen;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* The state upon return is either READ_ENV or READ_B64. If
* READ_B64, we've read all the input and there's no more
* processing on it that we can do.
*/
if (obj->state != VOLT_SECURE_MAIL_STATE_READ_ENV)
{
/* If inputLen and dataLen are equal, that means we've read all
* the base64 data. Because the Decode did not set the state to
* READ_ENV, that means there's no more enveloped data (and
* hence no more signed data) to read. Next up:
* VOLT_SECURE_MAIL_STATE_READ_FOOTER_1.
*/
#if VT_64_BIT_LENGTH == 64
if (obj->dataLen64 != obj->inputLen64)
#else
if (obj->dataLen != obj->inputLen)
#endif
break;
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_1;
if (currentMessageLen == 0)
break;
goto VoltSecureMailStateReadFooter1;
}
VoltSecureMailStateReadEnv:
case VOLT_SECURE_MAIL_STATE_READ_ENV:
/* Read the data in the unprocessedData buffer as EnvelopedData.
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = DoEnvelopeRead (obj, readCtx, 1);
if (status != 0)
break;
/* Upon return, the state should be either READ_SIGNED or READ_B64.
*/
if (obj->state == VOLT_SECURE_MAIL_STATE_READ_B64)
goto VoltSecureMailStateReadB64;
case VOLT_SECURE_MAIL_STATE_READ_SIGNED:
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltSMDoSignedDataRead (
obj, readCtx, 1, outputData, bufferSize, outputDataLen);
if (status != 0)
break;
/* If this call read everything in the unprocessedData buffer,
* then there will need to be some more B64 data to read to get
* the next bytes.
*/
obj->state = VOLT_SECURE_MAIL_STATE_READ_B64;
/* At this point, there is either no more data to process, or the
* data to process is footer material.
*/
#if VT_64_BIT_LENGTH == 64
if (obj->dataLen64 == obj->inputLen64)
#else
if (obj->dataLen == obj->inputLen)
#endif
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_1;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
VoltSecureMailStateReadFooter1:
case VOLT_SECURE_MAIL_STATE_READ_FOOTER_1:
/* We're expecting to see
* -----END VOLTAGE SECURE BLOCK V1-----
* Unless this is ZDM attachment.
*/
if (obj->formatType == VOLT_MESSAGE_FORMAT_ZDM_ATTACHMENT)
goto VoltSecureMailStateReadEnvFinal;
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
8, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
if (completeFlag == 0)
break;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* This code is to handle the situation when there are
* unexpected new lines between the end of the base64 encoded
* data and the beginning of the block
* -----END VOLTAGE SECURE BLOCK V1-----. We don't want to fail
* if this situation arises accidently. So skip all the extra empty
* lines until we find something meaningful.
*/
if ( (amountRead == newLineLen) &&
(readCtx->unprocessedData.data[0] == 0) )
{
readCtx->unprocessedData.len = 0;
goto VoltSecureMailStateReadFooter1;
}
/* We have the next block in the unprocessedData buffer, is this
* the block we expect?
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
if (readCtx->unprocessedData.len != VOLT_SECURE_MAIL_END_BLOCK_LEN + newLineLen)
break;
if (Z2Memcmp (
readCtx->unprocessedData.data, endBlk,
VOLT_SECURE_MAIL_END_BLOCK_LEN) != 0)
break;
/* Set up the context for the next block.
*/
status = 0;
readCtx->unprocessedData.len = 0;
obj->state = VOLT_SECURE_MAIL_STATE_READ_FOOTER_2;
/* If there's no more message to read, return.
*/
if (currentMessageLen == 0)
break;
VoltSecureMailStateReadFooter2:
case VOLT_SECURE_MAIL_STATE_READ_FOOTER_2:
/* We're expecting to see
* -----END VOLTAGE MESSAGE BLOCK V1-----
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltSMGetNextBlock (
obj, &(readCtx->unprocessedData), currentMessage, currentMessageLen,
24, &amountRead, &completeFlag, &newLineLen);
if (status != 0)
break;
*bytesRead += amountRead;
currentMessage = message + *bytesRead;
currentMessageLen = messageLen - *bytesRead;
/* This check is to handle the situation when there are
* unexpected new lines between the block
* -----END VOLTAGE SECURE BLOCK V1-----. and the block
* -----END VOLTAGE MESSAGE BLOCK V1-----.
* We don't want to fail if this situation arises accidently.
* So skip all the extra empty lines until we find something
* meaningful.
*/
if ( (completeFlag != 0) && (amountRead == newLineLen) &&
(readCtx->unprocessedData.len == 0) )
goto VoltSecureMailStateReadFooter2;
/* The GetNextBlock function expects a new line character, if
* there is none, then completeFlag is 0.
* But it is possible the SecureMail message ends without the new
* line character.
* If this was called by ReadFinal, then this is the last block.
* If there's no new line character, we want to go ahead and
* read. If the data is the expected footer, who cares if there's
* a new line character or not. If the problem is something else,
* then we'll get that error.
* So if this is ReadFinal and the completeFlag is 0, act as if
* it is complete (but if this is not ReadFinal and we're
* incomplete, go ahead and break and wait for more input).
*/
if ( (completeFlag == 0) && (readCtx->readFinal == 0) )
break;
/* We have the next block in the unprocessedData buffer, is this
* the block we expect?
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_SECURE_MAIL_MSG;
if (readCtx->unprocessedData.len != VOLT_SECURE_MAIL_END_MESSAGE_LEN + newLineLen)
break;
if (Z2Memcmp (
readCtx->unprocessedData.data, endMsg,
VOLT_SECURE_MAIL_END_MESSAGE_LEN) != 0)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -