📄 rsax931impl.c
字号:
/* Copyright 2005-2006, Voltage Security, all rights reserved.
*/
#include "vibecrypto.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "algobj.h"
#include "sign.h"
#include "rsa.h"
#include "rsax931.h"
#include "mpint.h"
#include "errorctx.h"
int X931Pad (
VoltAlgorithmObject *obj,
VtRandomObject random,
Pointer padCtx,
unsigned char *block,
unsigned int inputLen,
unsigned int blockSize
)
{
int status;
unsigned int bbLen, digestLen, x931Byte;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltSignClassCtx *signCtx = (VoltSignClassCtx *)(obj->classCtx);
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* How long is the input supposed to be?
*/
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetDigestLenFromAlg (
libCtx, signCtx->digestAlg, &digestLen, &x931Byte);
if (status != 0)
break;
/* If the x931Byte is 0, this is an unsupported digest algorithm.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT;
if (x931Byte == 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (inputLen != digestLen)
break;
/* X9.31 padding looks like this.
* 6B BB ... BB BA <digest> <digestByte> CC
* If the digest is so big that there's no room for the BB bytes,
* that's OK, but there must be room for the 6B, BA, digestByte and
* CC. The digestByte is an identitfier byte, 0x33 means SHA-1, etc.
* How long will the BB's be?
* First, count the number of bytes that will make up everything
* else, make sure that's not longer than blockSize.
*/
VOLT_SET_FNCT_LINE (fnctLine)
bbLen = digestLen + 4;
if (bbLen > blockSize)
break;
bbLen = blockSize - bbLen;
/* Move the digest to the end (except for the two trailing bits).
*/
Z2Memmove (block + blockSize - (digestLen + 2), block, digestLen);
/* The next byte is the digestByte.
*/
block[blockSize - 2] = (unsigned char)x931Byte;
/* The last byte is 0xcc.
*/
block[blockSize - 1] = 0xcc;
/* The first byte is 0x6b
*/
block[0] = 0x6b;
/* The next bbLen bytes are 0xbb.
*/
Z2Memset (block + 1, 0xbb, bbLen);
/* The byte after the bb's (the byte before the digest) is 0xba.
*/
block[bbLen + 1] = 0xba;
status = 0;
} while (0);
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, obj, status, 0, errorType,
(char *)0, "X931Pad", fnctLine, (char *)0)
return (status);
}
int X931Unpad (
VoltAlgorithmObject *obj,
Pointer padCtx,
unsigned char *block,
unsigned int blockSize,
unsigned int *outputLen
)
{
int status;
unsigned int index, bbLen, digestLen, x931Byte;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltSignClassCtx *signCtx = (VoltSignClassCtx *)(obj->classCtx);
VOLT_DECLARE_ERROR_TYPE (errorType)
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
VOLT_SET_ERROR_TYPE (errorType, 0)
VOLT_SET_FNCT_LINE (fnctLine)
status = VoltGetDigestLenFromAlg (
libCtx, signCtx->digestAlg, &digestLen, &x931Byte);
if (status != 0)
break;
/* If the x931Byte is 0, this is an unsupported digest algorithm.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT;
if (x931Byte == 0)
break;
/* How many 0xbb bytes should there be? While we're computing that,
* make sure blockLen is reasonable.
*/
VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
bbLen = digestLen + 4;
if (bbLen > blockSize)
break;
bbLen = blockSize - bbLen;
VOLT_SET_FNCT_LINE (fnctLine)
/* The next section of code is going to check the pad bytes. If
* they're wrong, we'll set status to an error, but we'll continue
* the check. After the checks, we'll move the digest to the front
* (the Unpad). This way, we can return an error if there is an
* error, but still return the digest, in case the caller wants to
* ignore the error.
*/
status = 0;
/* The first byte must be 0x6B
*/
if (block[0] != 0x6b)
status = VT_ERROR_INVALID_PAD;
/* The next bbLen bytes should be 0xbb.
*/
for (index = 2; index < bbLen + 2; ++index)
if (block[index] != 0xbb)
break;
/* If we broke early, there was an error.
*/
if (index < (bbLen + 1))
status = VT_ERROR_INVALID_PAD;
/* The next byte should be 0xba.
*/
if (block[bbLen + 1] != 0xba)
status = VT_ERROR_INVALID_PAD;
/* The second to las byte should be the digestByte.
*/
if (block[blockSize - 2] != (unsigned char)x931Byte)
status = VT_ERROR_INVALID_PAD;
/* The last byte should be 0xcc.
*/
if (block[blockSize - 1] != 0xcc)
status = VT_ERROR_INVALID_PAD;
/* Move the digest to the front.
*/
Z2Memmove (block, block + bbLen + 2, digestLen);
*outputLen = digestLen;
} while (0);
VOLT_LOG_ERROR_INFO_COMPARE (
status, 0, obj, status, 0, errorType,
(char *)0, "X931Unpad", fnctLine, (char *)0)
return (status);
}
int X931RSASignData (
VoltAlgorithmObject *obj,
VoltKeyObject *key,
VtRandomObject random,
unsigned char *dataToSign,
unsigned int dataToSignLen,
unsigned char *signature,
unsigned int *sigLen
)
{
int status, cmpResult;
unsigned int sign, blockSize;
VoltLibCtx *libCtx = (VoltLibCtx *)(obj->voltObject.libraryCtx);
VoltSignClassCtx *signCtx = (VoltSignClassCtx *)(obj->classCtx);
VoltRsaSignCtx *rsaCtx = (VoltRsaSignCtx *)(signCtx->localSignCtx);
VoltMpIntCtx *mpCtx = key->mpCtx;
VoltMpInt *base = (VoltMpInt *)0;
VoltMpInt *result = (VoltMpInt *)0;
VoltMpInt *temp;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* For RSA, the input block size and the output block size are the
* same.
*/
blockSize = signCtx->paddedBlockLen;
do
{
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &base);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->OctetStringToMpInt (0, dataToSign, dataToSignLen, base);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->CreateMpInt ((Pointer)mpCtx, &result);
if (status != 0)
break;
/* If we have the CRT info, use it. If not, use the private
* exponent.
*/
if (rsaCtx->priKeyData->prime1 != (VoltMpInt *)0)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModExpCRT (
base, rsaCtx->priKeyData->prime1, rsaCtx->priKeyData->prime2,
rsaCtx->priKeyData->expo1, rsaCtx->priKeyData->expo2,
rsaCtx->priKeyData->coeff, result);
if (status != 0)
break;
}
else
{
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->ModExp (
base, rsaCtx->priKeyData->priExpo, rsaCtx->priKeyData->modulus,
result);
if (status != 0)
break;
}
/* Call the result s and the modulus n. The signature is defined as
* the smaller of s and n - s. Is there a way to determine which is
* smaller without performing the subtraction? Yes, but they're
* likely to take as much time as simply performing the subtraction.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Subtract (rsaCtx->priKeyData->modulus, result, base);
if (status != 0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = mpCtx->Compare (result, base, &cmpResult);
if (status != 0)
break;
/* s is in result, n - s is in base. If result > base, we want to
* return what is in base.
*/
if (cmpResult > 0)
{
temp = result;
result = base;
base = temp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -