📄 pgpp11key.c
字号:
static PGPError
p11ConvertPassphrase(PGPSecKey *seckey, PGPEnv const *env,
char const *phrase, PGPSize plen, PGPByte *outbuf)
{
PGPByte mask = 0;
(void) env;
(void) seckey;
plen = pgpMin( plen, PASSBUFFERSIZE - 1 - sizeof(PGPUInt32) );
*(PGPUInt32 *)outbuf = PASSBUFMAGIC;
outbuf += sizeof(PGPUInt32);
*outbuf++ = (PGPByte) plen;
while( plen-- )
*outbuf++ = (PGPByte)*phrase++ ^ (mask+=PASSBUFMASK);
return kPGPError_NoErr;
}
/*
* Try to unlock the secret key wih the given passphrase. Returns >0
* if it was the correct passphrase. =0 if it was not, and <0 on error.
* Does not alter the key even if it's the wrong passphrase and already
* unlocked. A NULL passphrae will work if the key is unencrypted.
*/
static int
p11Unlock(PGPSecKey *seckey,
char const *phrase, PGPSize plen, PGPBoolean hashedPhrase)
{
P11Sec *sec = (P11Sec *)seckey->priv;
char passbuf[PASSBUFFERSIZE];
int rslt;
if( pgpFIPSModeEnabled() )
{
/* FIPS does not allow using keys with NULL passphrases */
if( IsNull( phrase ) || plen == 0 )
return( 0 );
}
if( hashedPhrase )
{
if( IsPGPError( sRecoverHashedPhrase( (const unsigned char *) phrase, plen, passbuf, &plen )))
return 0;
phrase = passbuf;
}
rslt = pgpTokenObjAuth( sec->tok, phrase, plen );
if( rslt != 0 )
return 0; /* Failure */
sec->locked = 0;
return 1;
}
/*
* Relock the key.
*/
static void
p11Lock(PGPSecKey *seckey)
{
P11Sec *sec = (P11Sec *)seckey->priv;
(void)pgpTokenObjDeAuth( sec->tok );
sec->locked = 1;
}
static PGPSize
p11SecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format);
/*
* Try to decrypt the given esk. If the key is locked, try the given
* passphrase. It may or may not leave the key unlocked in such a case.
* (Some hardware implementations may insist on a password per usage.)
*/
static int
p11Decrypt(PGPSecKey *seckey, PGPByte const *esk, PGPSize esklen,
PGPByte *key, PGPSize *keylen,
char const *phrase, PGPSize plen,
PGPPublicKeyMessageFormat format)
{
#if PGP_DECRYPT_DISABLE /* [ */
(void)seckey;
(void)esk;
(void)esklen;
(void)key;
(void)keylen;
(void)phrase;
(void)plen;
(void)format;
return kPGPError_FeatureNotAvailable;
#else /* PGP_DECRYPT_DISABLE */ /* ] [ */
P11Sec *sec = (P11Sec *)seckey->priv;
BigNum bn;
PGPInt32 i;
PGPInt32 j;
PGPUInt32 t;
PGPUInt32 modbytes;
PGPMemoryMgrRef mgr = NULL;
mgr = PGPPeekContextMemoryMgr( seckey->context );
if (sec->locked) {
i = p11Unlock(seckey, phrase, plen, FALSE);
if (i <= 0)
return i ? i : kPGPError_KeyIsLocked;
pgpAssert(!sec->locked);
}
if (esklen < 2)
return kPGPError_BadSessionKeySize;
bnBegin(&bn, mgr, TRUE);
modbytes = bnBytes( &sec->mod );
i = pgpBnGetFormatted(&bn, esk, esklen, modbytes, format);
if (i <= 0)
return kPGPError_BadSessionKeySize;
bnExtractBigBytes( &bn, key, 0, modbytes );
bnEnd(&bn);
i = pgpTokenObjDecrypt( sec->tok, (void *)seckey->keyID, key, modbytes,
key, modbytes );
if (i < 0) {
if( i== kPGPError_SmartCardKeyNotFound ) {
pgpKeyOffToken( seckey->keyDBObj );
pgpSyncTokenToKeyDB( seckey->context, NULL, TRUE );
}
return i;
}
if ((PGPSize)i > modbytes || i < 3)
return kPGPError_CorruptData;
if (format == kPGPPublicKeyMessageFormat_PGP) {
/* Check checksum (should this be here?) */
t = 0;
for (j = 1; j < i-2; j++)
t += key[j];
if (t != ((unsigned)key[i-2]<<8) + key[i-1])
return kPGPError_CorruptData;
pgpClearMemory(key+i-2, 2);
/* The actual key */
if (keylen)
*keylen = (PGPSize)i-2;
} else {
/* The actual key */
if (keylen)
*keylen = (PGPSize)i;
}
return 0;
#endif /* PGP_DECRYPT_DISABLE */ /* ] */
}
/*
* Return the size of the buffer needed, worst-case, for the decrypted
* output. This will be the size of the "key" parameter to p11Decrypt.
* We use that as a temp buffer to hold the raw decrypted value so it must
* be the same size as the modulus.
*/
static PGPSize
p11SecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
P11Sec const *sec = (P11Sec *)seckey->priv;
(void) format;
return bnBytes(&sec->mod);
}
/* Return the largest possible PGPESK size for a given key */
static PGPSize
p11SecMaxesk(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
P11Sec const *sec = (P11Sec *)seckey->priv;
if (format == kPGPPublicKeyMessageFormat_PGP)
return 2 + bnBytes(&sec->mod);
else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
format == kPGPPublicKeyMessageFormat_X509 ||
format == kPGPPublicKeyMessageFormat_IKE)
return bnBytes(&sec->mod);
pgpAssert(0);
return 0;
}
static PGPSize
p11SecMaxsig(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
{
P11Sec const *sec = (P11Sec *)seckey->priv;
if (format == kPGPPublicKeyMessageFormat_PGP)
return 2 + bnBytes(&sec->mod);
else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
format == kPGPPublicKeyMessageFormat_IKE ||
format == kPGPPublicKeyMessageFormat_X509)
return bnBytes(&sec->mod);
pgpAssert(0);
return 0;
}
static int
p11Sign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
PGPByte *sig, PGPSize *siglen, PGPRandomContext const *rc,
PGPPublicKeyMessageFormat format)
{
#if PGP_SIGN_DISABLE /* [ */
(void)seckey;
(void)h;
(void)hash;
(void)sig;
(void)siglen;
(void)rc;
(void)format;
return kPGPError_FeatureNotAvailable;
#else
P11Sec *sec = (P11Sec *)seckey->priv;
BigNum bn;
int i;
unsigned t;
PGPUInt32 modbytes;
PGPMemoryMgrRef mgr = NULL;
mgr = PGPPeekContextMemoryMgr( seckey->context );
/* We don't need these arguments, although other algorithms may... */
(void)rc;
(void)format;
if (sec->locked)
return kPGPError_KeyIsLocked;
bnBegin(&bn, mgr, TRUE);
modbytes = bnBytes( &sec->mod );
t = h->DERprefixsize;
/* IKE does not put in hash OID */
if (format == kPGPPublicKeyMessageFormat_IKE)
t = 0;
if (t+h->hashsize > modbytes)
return kPGPError_PublicKeyTooSmall;
pgpClearMemory( sig, t);
memcpy(sig, h->DERprefix, t);
memcpy(sig+t, hash, h->hashsize);
t += h->hashsize;
i = pgpTokenObjSign( sec->tok, seckey->keyID, sig, t, sig, modbytes );
if (bnInsertBigBytes(&bn, sig, 0, modbytes) < 0)
return kPGPError_OutOfMemory;
pgpClearMemory( sig, t);
if (i >= 0) {
t = 0;
if (format == kPGPPublicKeyMessageFormat_X509) {
/* Output unformatted, but with no leading zeros */
format = kPGPPublicKeyMessageFormat_PKCS1;
t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&bn), format);
} else {
t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&sec->mod), format);
}
if (siglen)
*siglen = (PGPSize)t;
i = 0;
}
else if( i== kPGPError_SmartCardKeyNotFound ) {
pgpKeyOffToken( seckey->keyDBObj );
pgpSyncTokenToKeyDB( seckey->context, NULL, TRUE );
}
bnEnd(&bn);
return i;
#endif /* PGP_SIGN_DISABLE */ /* ] */
}
/*
* Change passphrase on token. Not implemented.
*/
static int
p11ChangeLock(PGPSecKey *seckey, PGPEnv const *env,
PGPRandomContext const *rc, char const *ophrase, PGPSize oplen,
PGPBoolean oHashedPhrase, char const *phrase, PGPSize plen,
PGPStringToKeyType s2ktype)
{
P11Sec *sec = (P11Sec *)seckey->priv;
char passbuf[PASSBUFFERSIZE];
PGPError err;
(void) env;
(void) rc;
(void) s2ktype;
if( oHashedPhrase )
{
if( IsPGPError( err = sRecoverHashedPhrase( (const unsigned char *) ophrase, oplen,
passbuf, &oplen ) ) )
return err;
ophrase = passbuf;
}
err = pgpTokenObjSetPIN( sec->tok, (char *)ophrase, oplen,
(char *)phrase, plen );
pgpPurgePassphraseCache_back(seckey->context);
return err;
}
static PGPSize
p11SecBufferLength(PGPSecKey const *seckey)
{
(void) seckey;
return 0;
}
static void
p11SecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
{
(void) seckey;
(void) buf;
}
static int
p11SecParams(PGPSecKey const *seckey, BigNum *x1, BigNum *x2,
BigNum *x3, BigNum *x4, BigNum *x5, BigNum *x6, BigNum *x7, BigNum *x8)
{
(void) seckey;
(void)x1;
(void)x2;
(void)x3;
(void)x4;
(void)x5;
(void)x6;
(void)x7;
(void)x8;
return kPGPError_PublicKeyUnimplemented;
}
/* Fill in secret key structure */
static void
p11FillSecKey(PGPSecKey *seckey, P11Sec *sec)
{
seckey->priv = sec;
seckey->destroy = p11SecDestroy;
seckey->pubkey = p11Pubkey;
seckey->islocked = p11Islocked;
seckey->lockingalgorithm = p11LockingAlgorithm;
seckey->s2ktype = p11S2KType;
seckey->convertpassphrase = p11ConvertPassphrase;
seckey->unlock = p11Unlock;
seckey->lock = p11Lock;
seckey->decrypt = p11Decrypt;
seckey->maxdecrypted = p11SecMaxdecrypted;
seckey->maxsig = p11SecMaxsig;
seckey->maxesk = p11SecMaxesk;
seckey->sign = p11Sign;
seckey->changeLock = p11ChangeLock;
seckey->bufferLength = p11SecBufferLength;
seckey->toBuffer = p11SecToBuffer;
seckey->secparams = p11SecParams;
seckey->setkeyid = p11SecSetKeyID;
}
/* Create a new PGPSecKey object.
*/
PGPSecKey *
p11SecFromBuf(
PGPContextRef context,
PGPByte const * buf,
PGPSize size,
PGPBoolean v3,
void * tok,
PGPError * error)
{
PGPSecKey *seckey;
P11Sec *sec;
PGPError err = kPGPError_OutOfMemory;
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( context );
PGPByte *cryptk;
(void) v3;
bnInit();
/* Holds public part */
cryptk = (PGPByte *)pgpContextMemAlloc(context,
size, kPGPMemoryMgrFlags_Clear);
if (cryptk) {
sec = (P11Sec *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
if (sec) {
pgpClearMemory( sec, sizeof(*sec) );
sec->context = context;
seckey = (PGPSecKey *) pgpContextMemAlloc(context,
sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
if (seckey) {
PGPUInt32 v;
seckey->context = context;
seckey->token = TRUE;
pgpCopyMemory( buf, cryptk, size );
sec->cryptkey = cryptk;
sec->cklen = size;
bnBegin(&sec->mod, mgr, FALSE);
sec->locked = 1;
seckey->priv = sec;
/* Hold pointer to token object */
sec->tok = tok;
/* Parse buf to get modulus */
if (size < 5) {
*error = kPGPError_KeyPacketTruncated;
return NULL;
}
v = ((unsigned)buf[0] << 8) + buf[1];
v = (v+7)/8;
if (size < 5+v) {
*error = kPGPError_KeyPacketTruncated;
return NULL;
}
if (bnInsertBigBytes(&sec->mod, buf+2, 0, v) < 0) {
*error = kPGPError_OutOfMemory;
}
p11FillSecKey(seckey, sec);
*error = kPGPError_NoErr;
return seckey; /* Success! */
}
/* Error, clean up and exit */
PGPFreeData( sec ); /* Wipes as it frees */
}
}
*error = err;
return NULL;
}
PGPSecKey *
p11SecGenerate(
PGPContextRef context, PGPByte pkalg,
unsigned bits, PGPBoolean fastgen, PGPBoolean v3,
int progress(void *arg, int c), void *arg,
void *tokptr, PGPByte const *passphrase, PGPSize passphraseLength,
PGPBoolean genMaster, PGPError *error)
{
#if PGP_WIN32
PGPSecKey *seckey;
PGPMemoryMgrRef mgr;
PGPToken *tok = tokptr;
PGPByte tmpkeyid[8];
PGPUInt32 modlen;
PGPUInt32 pubexplen;
PGPUInt32 pubbuflen;
PGPUInt32 off;
PGPByte *modbuf = NULL;
PGPByte *pubbuf = NULL;
PGPByte *pubexpbuf = NULL;
PGPError err = kPGPError_NoErr;
BigNum mod, exp;
pgpAssert( IsntNull( tok ) );
/* Unlock token */
err = pgpTokenObjAuth( tok, passphrase, passphraseLength );
if( err != 0 )
{
*error = kPGPError_BadPassphrase;
return NULL;
}
pgpFillMemory( tmpkeyid, 8, 0x55 ); /* Temporary keyid value */
mgr = PGPPeekContextMemoryMgr( context );
bnBegin( &mod, mgr, FALSE );
bnBegin( &exp, mgr, FALSE );
modlen = (bits+7)/8;
modbuf = PGPNewData( mgr, modlen, 0 );
pubexpbuf = PGPNewData( mgr, modlen, 0 );
if (progress && IsPGPError( err = progress(arg, '.') ) )
goto error;
err = pgpTokenObjKeygen(tok, tmpkeyid, bits, genMaster, modbuf, pubexpbuf, &pubexplen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -