📄 hw_ibmca.c
字号:
}
IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED);
return 0;
}
static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
/* I need somewhere to store temporary serialised values for
* use with the Ibmca API calls. A neat cheat - I'll use
* BIGNUMs from the BN_CTX but access their arrays directly as
* byte arrays <grin>. This way I don't have to clean anything
* up. */
BIGNUM *argument=NULL;
BIGNUM *result=NULL;
BIGNUM *key=NULL;
int to_return;
int inLen, outLen, tmpLen;
ICA_KEY_RSA_MODEXPO *publKey=NULL;
unsigned int rc;
to_return = 0; /* expect failure */
if(!ibmca_dso)
{
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED);
goto err;
}
/* Prepare the params */
BN_CTX_start(ctx);
argument = BN_CTX_get(ctx);
result = BN_CTX_get(ctx);
key = BN_CTX_get(ctx);
if( !argument || !result || !key)
{
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL);
goto err;
}
if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) ||
!bn_wexpand(key, sizeof(*publKey)/BN_BYTES))
{
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL);
goto err;
}
publKey = (ICA_KEY_RSA_MODEXPO *)key->d;
if (publKey == NULL)
{
goto err;
}
memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO));
publKey->keyType = CORRECT_ENDIANNESS(ME_KEY_TYPE);
publKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_MODEXPO));
publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey;
/* A quirk of the card: the exponent length has to be the same
as the modulus (key) length */
outLen = BN_num_bytes(m);
/* check for modulus length SAB*/
if (outLen > 256 ) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE);
goto err;
}
/* check for modulus length SAB*/
publKey->expLength = publKey->nLength = outLen;
/* SAB Check for underflow condition
the size of the exponent is less than the size of the parameter
then we have a big problem and will underflow the keyRecord
buffer. Bad stuff could happen then
*/
if (outLen < BN_num_bytes(p)){
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD);
goto err;
}
/* SAB End check for underflow */
BN_bn2bin(p, &publKey->keyRecord[publKey->expLength -
BN_num_bytes(p)]);
BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]);
publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8);
publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset +
publKey->expLength);
publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord -
(char *) publKey);
tmpLen = outLen;
publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen);
/* Prepare the argument */
memset(argument->d, 0, outLen);
BN_bn2bin(a, (unsigned char *)argument->d + outLen -
BN_num_bytes(a));
inLen = outLen;
/* Perform the operation */
if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d,
publKey, &outLen, (unsigned char *)result->d))
!=0 )
{
printf("rc = %d\n", rc);
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED);
goto err;
}
/* Convert the response */
BN_bin2bn((unsigned char *)result->d, outLen, r);
to_return = 1;
err:
BN_CTX_end(ctx);
return to_return;
}
#ifndef OPENSSL_NO_RSA
static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
{
BN_CTX *ctx;
int to_return = 0;
if((ctx = BN_CTX_new()) == NULL)
goto err;
if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
{
if(!rsa->d || !rsa->n)
{
IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP,
IBMCA_R_MISSING_KEY_COMPONENTS);
goto err;
}
to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx);
}
else
{
to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
rsa->dmq1, rsa->iqmp, ctx);
}
err:
if(ctx)
BN_CTX_free(ctx);
return to_return;
}
#endif
/* Ein kleines chinesisches "Restessen" */
static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *q, const BIGNUM *dmp1,
const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx)
{
BIGNUM *argument = NULL;
BIGNUM *result = NULL;
BIGNUM *key = NULL;
int to_return = 0; /* expect failure */
char *pkey=NULL;
ICA_KEY_RSA_CRT *privKey=NULL;
int inLen, outLen;
int rc;
unsigned int offset, pSize, qSize;
/* SAB New variables */
unsigned int keyRecordSize;
unsigned int pbytes = BN_num_bytes(p);
unsigned int qbytes = BN_num_bytes(q);
unsigned int dmp1bytes = BN_num_bytes(dmp1);
unsigned int dmq1bytes = BN_num_bytes(dmq1);
unsigned int iqmpbytes = BN_num_bytes(iqmp);
/* Prepare the params */
BN_CTX_start(ctx);
argument = BN_CTX_get(ctx);
result = BN_CTX_get(ctx);
key = BN_CTX_get(ctx);
if(!argument || !result || !key)
{
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL);
goto err;
}
if(!bn_wexpand(argument, p->top + q->top) ||
!bn_wexpand(result, p->top + q->top) ||
!bn_wexpand(key, sizeof(*privKey)/BN_BYTES ))
{
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL);
goto err;
}
privKey = (ICA_KEY_RSA_CRT *)key->d;
/* SAB Add check for total size in bytes of the parms does not exceed
the buffer space we have
do this first
*/
keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes;
if ( keyRecordSize > sizeof(privKey->keyRecord )) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
goto err;
}
if ( (qbytes + dmq1bytes) > 256 ){
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
goto err;
}
if ( pbytes + dmp1bytes > 256 ) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
goto err;
}
/* end SAB additions */
memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT));
privKey->keyType = CORRECT_ENDIANNESS(CRT_KEY_TYPE);
privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT));
privKey->modulusBitLength =
CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8);
/*
* p,dp & qInv are 1 QWORD Larger
*/
privKey->pLength = CORRECT_ENDIANNESS(BN_num_bytes(p)+8);
privKey->qLength = CORRECT_ENDIANNESS(BN_num_bytes(q));
privKey->dpLength = CORRECT_ENDIANNESS(BN_num_bytes(dmp1)+8);
privKey->dqLength = CORRECT_ENDIANNESS(BN_num_bytes(dmq1));
privKey->qInvLength = CORRECT_ENDIANNESS(BN_num_bytes(iqmp)+8);
offset = (char *) privKey->keyRecord
- (char *) privKey;
qSize = BN_num_bytes(q);
pSize = qSize + 8; /* 1 QWORD larger */
/* SAB probably aittle redundant, but we'll verify that each of the
components which make up a key record sent ot the card does not exceed
the space that is allocated for it. this handles the case where even if
the total length does not exceed keyrecord zied, if the operands are funny sized
they could cause potential side affects on either the card or the result */
if ( (pbytes > pSize) || (dmp1bytes > pSize) ||
(iqmpbytes > pSize) || ( qbytes >qSize) ||
(dmq1bytes > qSize) ) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE);
goto err;
}
privKey->dpOffset = CORRECT_ENDIANNESS(offset);
offset += pSize;
privKey->dqOffset = CORRECT_ENDIANNESS(offset);
offset += qSize;
privKey->pOffset = CORRECT_ENDIANNESS(offset);
offset += pSize;
privKey->qOffset = CORRECT_ENDIANNESS(offset);
offset += qSize;
privKey->qInvOffset = CORRECT_ENDIANNESS(offset);
pkey = (char *) privKey->keyRecord;
/* SAB first check that we don;t under flow the buffer */
if ( pSize < pbytes ) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION);
goto err;
}
/* pkey += pSize - BN_num_bytes(p); WROING this should be dmp1) */
pkey += pSize - BN_num_bytes(dmp1);
BN_bn2bin(dmp1, pkey);
pkey += BN_num_bytes(dmp1); /* move the pointer */
BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */
pkey += qSize; /* move pointer */
pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */
BN_bn2bin(p, pkey);
pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */
BN_bn2bin(q, pkey);
pkey += qSize ; /* move the pointer */
pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */
BN_bn2bin(iqmp, pkey);
/* Prepare the argument and response */
outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used
because the fields were converted above */
if (outLen > 256) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE);
goto err;
}
/* SAB check for underflow here on the argeument */
if ( outLen < BN_num_bytes(a)) {
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_UNDERFLOW_CONDITION);
goto err;
}
BN_bn2bin(a, (unsigned char *)argument->d + outLen -
BN_num_bytes(a));
inLen = outLen;
memset(result->d, 0, outLen);
/* Perform the operation */
if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d,
privKey, &outLen, (unsigned char *)result->d)) != 0)
{
printf("rc = %d\n", rc);
IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED);
goto err;
}
/* Convert the response */
BN_bin2bn((unsigned char *)result->d, outLen, r);
to_return = 1;
err:
BN_CTX_end(ctx);
return to_return;
}
#ifndef OPENSSL_NO_DSA
/* This code was liberated and adapted from the commented-out code in
* dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration
* (it doesn't have a CRT form for RSA), this function means that an
* Ibmca system running with a DSA server certificate can handshake
* around 5 or 6 times faster/more than an equivalent system running with
* RSA. Just check out the "signs" statistics from the RSA and DSA parts
* of "openssl speed -engine ibmca dsa1024 rsa1024". */
static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *in_mont)
{
BIGNUM t;
int to_return = 0;
BN_init(&t);
/* let rr = a1 ^ p1 mod m */
if (!ibmca_mod_exp(rr,a1,p1,m,ctx)) goto end;
/* let t = a2 ^ p2 mod m */
if (!ibmca_mod_exp(&t,a2,p2,m,ctx)) goto end;
/* let rr = rr * t mod m */
if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
to_return = 1;
end:
BN_free(&t);
return to_return;
}
static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *m_ctx)
{
return ibmca_mod_exp(r, a, p, m, ctx);
}
#endif
/* This function is aliased to mod_exp (with the mont stuff dropped). */
static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
{
return ibmca_mod_exp(r, a, p, m, ctx);
}
#ifndef OPENSSL_NO_DH
/* This function is aliased to mod_exp (with the dh and mont dropped). */
static int ibmca_mod_exp_dh(DH const *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
{
return ibmca_mod_exp(r, a, p, m, ctx);
}
#endif
/* Random bytes are good */
static int ibmca_rand_bytes(unsigned char *buf, int num)
{
int to_return = 0; /* assume failure */
unsigned int ret;
if(handle == 0)
{
IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED);
goto err;
}
ret = p_icaRandomNumberGenerate(handle, num, buf);
if (ret < 0)
{
IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED);
goto err;
}
to_return = 1;
err:
return to_return;
}
static int ibmca_rand_status(void)
{
return 1;
}
/* This stuff is needed if this ENGINE is being compiled into a self-contained
* shared-library. */
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_fn(ENGINE *e, const char *id)
{
if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */
return 0;
if(!bind_helper(e))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
#endif /* ENGINE_DYNAMIC_SUPPORT */
#endif /* !OPENSSL_NO_HW_IBMCA */
#endif /* !OPENSSL_NO_HW */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -