📄 readenv.c
字号:
coderInfo.info.getAlgData.algorithm = &algorithm;
coderInfo.info.getAlgData.SymKeyParam = (VtKeyParam *)0;
coderInfo.info.getAlgData.DigestImpl = (VtAlgorithmImpl *)0;
for (index = 0; index < readCtx->derCoderCount; ++index)
{
/* Call the DerCoder. If successful, we found what we were
* looking for.
*/
status = readCtx->DerCoders[index] (
&coderInfo, (Pointer)0, VOLT_DER_TYPE_GET_ALG_FLAG);
if (status == 0)
break;
}
status = VT_ERROR_UNKNOWN_BER;
if (index >= readCtx->derCoderCount)
break;
/* Build a key object using the decrypted key data.
*/
status = VtCreateKeyObject (
(VtLibCtx)libCtx, VtKeyImplDefault, (Pointer)0, &symKey);
if (status != 0)
break;
status = VtSetKeyParam (
symKey, coderInfo.info.getAlgData.SymKeyParam,
(Pointer)&(readCtx->symKeyData));
if (status != 0)
break;
/* DecryptInit to start the process.
*/
status = VtDecryptInit (readCtx->decryptor, symKey);
if (status != 0)
break;
/* Move on to the next element.
*/
obj->state = VOLT_P7_STATE_ENV_READ_ENC_DATA_LEN;
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_ENV_READ_ENC_DATA_LEN:
/* The length of the encrypted data is specified in the IMPLICIT
* OCTET STRING.
*/
status = VoltGetNextDerElement (
libCtx, message, messageLen, 0, 0x80, 0,
derElement, &messageRead);
if (status != 0)
break;
*bytesRead += messageRead;
if (derElement->complete == 0)
break;
/* Keep the length so we can count off the data as it is input.
*/
readCtx->currentLen = derElement->tlvLen;
/* Move on to the next element.
*/
obj->state = VOLT_P7_STATE_ENV_READ_ENC_DATA;
message += messageRead;
messageLen -= messageRead;
VoltResetDerElement (derElement);
if (messageLen == 0)
break;
case VOLT_P7_STATE_ENV_READ_ENC_DATA:
/* If the length of the message is > the length of the
* currentLen, ignore the "extra" stuff.
*/
valueLen = readCtx->currentLen;
if (messageLen <= valueLen)
valueLen = messageLen;
/* If we won't process all the data, call EncryptUpdate. Return
* all errors, even if BUFFER_TOO_SMALL.
* If this is the last chunk of data, call DecryptFinal.
*/
if (valueLen != readCtx->currentLen)
{
status = VtDecryptUpdate (
readCtx->decryptor, (VtRandomObject)0, message, valueLen,
outputData, bufferSize, outputDataLen);
if (status != 0)
break;
}
else
{
status = VtDecryptFinal (
readCtx->decryptor, (VtRandomObject)0, message, valueLen,
outputData, bufferSize, outputDataLen);
if (status != 0)
break;
}
/* If the Decrypt succeeded, move bytesRead up and currentLen
* down.
*/
readCtx->currentLen -= valueLen;
*bytesRead += valueLen;
/* If there's no more data to read, change the state.
*/
if (readCtx->currentLen == 0)
obj->state = VOLT_P7_STATE_ENV_READ_COMPLETE;
status = 0;
}
VtDestroyKeyObject (&symKey);
return (status);
}
int VoltP7ReadEnvelopedFinal (
VtPkcs7Object pkcs7Obj,
unsigned char *message,
unsigned int messageLen,
unsigned int *bytesRead,
unsigned char *outputData,
unsigned int bufferSize,
unsigned int *outputDataLen
)
{
int status;
VoltPkcs7Object *obj = (VoltPkcs7Object *)pkcs7Obj;
*bytesRead = 0;
*outputDataLen = 0;
do
{
/* If we're done, there's nothing to do.
*/
if (obj->state == VOLT_P7_STATE_ENV_READ_COMPLETE)
{
obj->state = VOLT_P7_STATE_ENV_READ_FINAL;
status = 0;
break;
}
/* If we're not done, try to finish.
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (messageLen == 0)
break;
status = VoltP7ReadEnvelopedUpdate (
pkcs7Obj, message, messageLen, bytesRead,
outputData, bufferSize, outputDataLen);
if (status != 0)
break;
/* Are we finished now?
*/
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (obj->state != VOLT_P7_STATE_ENV_READ_COMPLETE)
break;
obj->state = VOLT_P7_STATE_ENV_READ_FINAL;
status = 0;
} while (0);
return (status);
}
static int AddRecipientInfoToList (
VoltLibCtx *libCtx,
VoltPkcs7ReadEnvCtx *readCtx,
unsigned char *recipInfoDer,
unsigned int recipInfoDerLen
)
{
int status;
unsigned int index, theTag, lengthLen, valueLen, offset, len, count;
Asn1RecipientInfo *newRi = (Asn1RecipientInfo *)0;
VtIdentityObject newId = (VtIdentityObject)0;
Asn1RecipientInfo **newList = (Asn1RecipientInfo **)0;
unsigned char *temp;
unsigned char *idString = (unsigned char *)0;
do
{
/* Build a RecipientInfo object out of the encoding.
*/
status = VT_ERROR_MEMORY;
newRi = Asn1RecipientInfo_new ();
if (newRi == (Asn1RecipientInfo *)0)
break;
status = VT_ERROR_INVALID_ENCODING;
temp = recipInfoDer;
d2i_Asn1RecipientInfo (&newRi, &temp, recipInfoDerLen);
if (newRi == (Asn1RecipientInfo *)0)
break;
/* Isolate the Base64 encoded identity. It will be the element with
* the VOLT_PRINT_STRING_TAG.
*/
offset = 0;
temp = newRi->issuerSerial->base.data;
len = (unsigned int)(newRi->issuerSerial->base.length);
do
{
/* Keep decoding TL's until reaching 0C.
*/
status = VoltDecodeTagAndLen (
temp + offset, len - offset, &theTag, &lengthLen, &valueLen);
if (status != 0)
break;
offset += 1 + lengthLen;
/* If we found the tag, quit looking.
*/
if (theTag == VOLT_PRINT_STRING_TAG)
break;
/* If we found the OID tag, skip the data.
*/
if (theTag == VOLT_OID_TAG)
offset += valueLen;
} while (1);
if (status != 0)
break;
/* Decode the identity.
*/
status = VtDecodeInit (readCtx->base64);
if (status != 0)
break;
/* Allocate a buffer to hold the result. There will be 3 characters
* output for each 4 input. Maybe a little less, so just allocate a
* buffer 3/4 the size of the input.
*/
status = VT_ERROR_MEMORY;
len = (3 * valueLen) / 4;
idString = (unsigned char *)Z2Malloc (len, 0);
if (idString == (unsigned char *)0)
break;
status = VtDecodeFinal (
readCtx->base64, (VtRandomObject)0, temp + offset, valueLen,
idString, len, &len);
if (status != 0)
break;
/* Now build an identity object using that identity.
*/
status = VtCreateIdentityObject (
(VtLibCtx)libCtx, VtIdentityImplMpCtx, (Pointer)(readCtx->mpCtx),
&newId);
if (status != 0)
break;
/* If we can't decode this identity, just ignore it. So if the
* error is INVALID_ENCODING or UNKNOWN_SCHEMA, skip everithing.
*/
status = VtDecodeIdentity (
idString, len, readCtx->Decoders, readCtx->decoderCount, &index,
newId);
if (status != 0)
break;
/* Add the Asn1RecipientInfo to the list.
*/
status = VT_ERROR_MEMORY;
count = readCtx->recipInfoCount + 1;
newList = (Asn1RecipientInfo **)Z2Malloc (
count * sizeof (Asn1RecipientInfo *), 0);
if (newList == (Asn1RecipientInfo **)0)
break;
Z2Memset (newList, 0, count * sizeof (Asn1RecipientInfo *));
/* Copy the old into the new.
*/
for (index = 0; index < readCtx->recipInfoCount; ++index)
newList[index] = readCtx->recipInfoList[index];
newList[index] = newRi;
/* Add the identity to the identityList.
*/
status = VtAddIdObjectToIdentityList (readCtx->recipList, newId, &index);
if (status != 0)
break;
/* If everything succeeded, get rid of the old recipInfoList and
* replace it with the new.
*/
if (readCtx->recipInfoList != (Asn1RecipientInfo **)0)
Z2Free (readCtx->recipInfoList);
readCtx->recipInfoList = newList;
readCtx->recipInfoCount++;
} while (0);
/* We added the identity to the recipient list, so we don't need
* this object any more.
*/
VtDestroyIdentityObject (&newId);
if (idString != (unsigned char *)0)
Z2Free (idString);
/* If no error, we're done.
*/
if (status == 0)
return (0);
/* If there was an error, destroy what we created.
*/
if (newRi != (Asn1RecipientInfo *)0)
Asn1RecipientInfo_free (newRi);
if (newList != (Asn1RecipientInfo **)0)
Z2Free (newList);
return (status);
}
static int DecryptSessionKeyData (
VoltLibCtx *libCtx,
VoltPkcs7Object *obj,
VoltPkcs7ReadEnvCtx *readCtx
)
{
int status;
unsigned int bufferSize;
Asn1RecipientInfo *recipInfo;
VtAlgorithmObject decryptor = (VtAlgorithmObject)0;
VoltSurrenderCtx *surrCtx = (VoltSurrenderCtx *)0;
VtSurrenderCallback surrenderCtx;
VtSetAlgIdInfo algIdInfo;
recipInfo = readCtx->recipInfoList[readCtx->chosenRecipient];
do
{
/* Build an algorithm object using the algId in the RecipientInfo.
*/
algIdInfo.derCoders = readCtx->DerCoders;
algIdInfo.derCoderCount = readCtx->derCoderCount;
algIdInfo.berEncoding = recipInfo->keyEncAlg->base.data;
algIdInfo.maxEncodingLen =
(unsigned int)(recipInfo->keyEncAlg->base.length);
status = VtCreateAlgorithmObject (
(VtLibCtx)libCtx, VtAlgorithmImplAlgId, (Pointer)&algIdInfo,
&decryptor);
if (status != 0)
break;
/* If there's a surrender ctx, pass it on to the decryptor.
*/
if ( ((obj->voltObject.objectType & VOLT_OBJECT_TYPE_SURRENDER) != 0) &&
(obj->voltObject.surrenderCtx != (Pointer)0) )
{
surrCtx = (VoltSurrenderCtx *)(obj->voltObject.surrenderCtx);
/* Set the decryption object with the surrender ctx, but don't copy
* the appData, just copy a reference, so we're still using the
* P7 object's appData.
*/
surrenderCtx.Surrender = surrCtx->Surrender;
surrenderCtx.appData = surrCtx->appData;
surrenderCtx.AppDataCopy = (VtSurrenderAppDataCopy)0;
surrenderCtx.AppDataFree = (VtSurrenderAppDataFree)0;
status = VtSetAlgorithmParam (
decryptor, VtAlgorithmParamSurrenderCallback, (Pointer)&surrenderCtx);
if (status != 0)
break;
}
/* Init with the key we have.
*/
status = VtDecryptInit (decryptor, readCtx->priKeyRef);
if (status != 0)
break;
/* How big does the output buffer need to be?
* Don't call this routine, it will decrypt to get the appropriate
* size. Compute "by hand". The length will be encryptedKeyLen -
* primeLen - SHA-1 len. So the max len will be encryptedKeyLen -
* minPrimeLen - SHA-1 len,
*/
/* status = VtDecryptFinal (
decryptor, (VtRandomObject)0, recipInfo->encryptedKey->data,
(unsigned int)(recipInfo->encryptedKey->length),
(unsigned char *)0, 0, &bufferSize);
if (status == 0)
status = VT_ERROR_GENERAL;
if (status != VT_ERROR_BUFFER_TOO_SMALL)
break;
*/
bufferSize = (unsigned int)(recipInfo->encryptedKey->length) - 20;
status = VT_ERROR_MEMORY;
readCtx->symKeyData.data = (unsigned char *)Z2Realloc (
readCtx->symKeyData.data, bufferSize);
if (readCtx->symKeyData.data == (unsigned char *)0)
break;
/* Now decrypt into the buffer.
*/
status = VtDecryptFinal (
decryptor, (VtRandomObject)0, recipInfo->encryptedKey->data,
(unsigned int)(recipInfo->encryptedKey->length),
readCtx->symKeyData.data, bufferSize, &(readCtx->symKeyData.len));
if (status != 0)
break;
} while (0);
VtDestroyAlgorithmObject (&decryptor);
return (status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -