📄 pgpeckey.c
字号:
if (8*scalarSize == bnBits(&r))
len_seq = pgpBnX509LenLen(scalarSize+1) + 1 + scalarSize+1;
else
len_seq = pgpBnX509LenLen(scalarSize) + 1 + scalarSize;
if (8*scalarSize == bnBits(&s))
len_seq += pgpBnX509LenLen(scalarSize+1) + 1 + scalarSize+1;
else
len_seq += pgpBnX509LenLen(scalarSize) + 1 + scalarSize;
lenlen_seq = pgpBnX509LenLen(len_seq);
sig[t++] = X509_TAG_SEQUENCE | X509_TAG_CONSTRUCTED;
if (--lenlen_seq == 0) {
sig[t++] = len_seq;
} else {
sig[t++] = 0x80 | lenlen_seq;
len_seq <<= 8 * (4-lenlen_seq);
while (lenlen_seq--) {
sig[t++] = (PGPByte)(len_seq >> 24);
len_seq <<= 8;
}
}
}
t += pgpBnPutFormatted(&r, sig+t, scalarSize, format);
t += pgpBnPutFormatted(&s, sig+t, scalarSize, format);
if (siglen)
*siglen = (PGPSize)t;
i = 0;
goto done;
nomem:
i = kPGPError_OutOfMemory;
/* fall through */
done:
bnEnd(&k);
bnEnd(&bn);
bnEnd(&s);
bnEnd(&r);
bnEnd(&bnx);
bnEnd(&bnorder);
if( IsntNull( eck ) )
ecScalarFree( eck );
if( IsntNull( kg ) )
ecPointFree( kg );
if( IsntNull( rc2 ) ) {
pgpRandomDestroy(rc2);
}
return i;
#endif /* PGP_SIGN_DISABLE */ /* ] */
}
/*
* Re-encrypt a PGPSecKey to turn a PGPSecKey into a secret key.
* A secret key is, after a non-specific prefix:
* 0 1 Version (= 2 or 3)
* 1 4 Timestamp
* 5 2 Validity (=0 at present)
* 7 1 Algorithm (=1 for EC)
* The following:
* 0 2 Curve type (=0)
* 2 2+s Curve name (s=strlen(name))
* 4+s 2+p Public curve point (p=pointSize)
* 6+s+p e Encryption algorithm data, S2K info
* 6+s+p+e 2+w MPI for x, secret part (w=scalarSize)
* 8+s+p+e+w
*
*/
#if PGP_MACINTOSH
#pragma global_optimizer on
#endif
static int
ecChangeLock(PGPSecKey *seckey, PGPEnv const *env,
PGPRandomContext const *rc, char const *ophrase, PGPSize oplen,
PGPBoolean oHashedPhrase, char const *phrase, PGPSize plen,
PGPStringToKeyType s2ktype)
{
ECsecPlus *sec = (ECsecPlus *)seckey->priv;
ecContextRef ec = sec->s.ec;
PGPUInt32 coordSize, scalarSize, pointSize;
PGPStringToKey *s2k = NULL; /* Shut up warnings */
PGPCipherVTBL const *cipher = NULL; /* Shut up warnings */
PGPCFBContext *cfb = NULL; /* This is realy needed */
BigNum bnx, bny;
PGPByte *p;
PGPByte key[PGP_CIPHER_MAXKEYSIZE];
PGPBoolean oldf = 0; /* Shut up warnings */
PGPInt32 curve;
PGPSize len;
PGPSize namelen;
PGPUInt32 checksum;
PGPContextRef context = pgpenvGetContext( env );
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( seckey->context );
ASSERTEC(seckey->pkAlg);
if (sec->locked)
if( IsPGPError(ecUnlock( seckey, ophrase, oplen, oHashedPhrase )) )
return kPGPError_KeyIsLocked;
ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );
curve = sCurveIndexFromScalarsize( scalarSize );
pgpAssert( curve >= 0 );
namelen = strlen(sCurves[curve].name);
bnBegin( &bny, mgr, INSECURE );
bnBegin( &bnx, mgr, INSECURE );
sPointtoBN( sec->s.y, &bny, mgr, pointSize );
sScalartoBN( sec->s.x, &bnx, mgr, scalarSize );
len = 11 + namelen + bnBytes(&bny) + bnBytes(&bnx);
if (phrase) {
s2k = pgpS2Kcreate(context, rc, s2ktype);
if (!s2k) {
bnEnd( &bnx );
bnEnd( &bny );
return kPGPError_OutOfMemory;
}
cipher = pgpCipherDefaultKey(env);
pgpAssert(cipher);
if (!cipher) {
bnEnd( &bnx );
bnEnd( &bny );
pgpS2Kdestroy(s2k);
return kPGPError_OutOfMemory;
}
len += cipher->blocksize;
cfb = pgpCFBCreate( mgr, cipher);
if (!cfb) {
bnEnd( &bnx );
bnEnd( &bny );
pgpS2Kdestroy(s2k);
return kPGPError_OutOfMemory;
}
oldf = pgpS2KisOldVers(s2k);
if (!oldf)
len += 1 + s2k->encodelen;
}
if (len > sec->ckalloc) {
PGPError err = kPGPError_NoErr;
if( IsNull( sec->cryptkey ) ) {
sec->cryptkey = (PGPByte *)
pgpContextMemAlloc( sec->context, len, 0 );
if( IsNull( sec->cryptkey ) ) {
err = kPGPError_OutOfMemory;
}
} else {
err = pgpContextMemRealloc( sec->context,
(void **)&sec->cryptkey, len, 0 );
}
if( IsPGPError( err ) ) {
bnEnd( &bnx );
bnEnd( &bny );
PGPFreeCFBContext(cfb);
pgpS2Kdestroy(s2k);
return err;
}
sec->ckalloc = (PGPSize)len;
}
sec->cklen = len;
p = sec->cryptkey;
/* Okay, no more errors possible! Start installing data */
*p++ = 0;
*p++ = 0;
/* Assume namelen has 2nd to highest bit set, typical of ascii */
*p++ = ((8*namelen-1) >> 8) & 0xff;
*p++ = ((8*namelen-1) >> 0) & 0xff;
pgpCopyMemory( sCurves[curve].name, p, namelen );
p += namelen;
p += pgpBnPutPlain(&bny, p);
/* Encryption parameters */
if (!phrase) {
*p++ = 0; /* Unencrypted */
} else {
if (oldf) {
*p++ = cipher->algorithm;
} else {
*p++ = 0xff;
*p++ = cipher->algorithm;
memcpy(p, s2k->encoding, s2k->encodelen);
p += s2k->encodelen;
}
/* Create IV */
pgpRandomGetBytes(rc, p, cipher->blocksize);
pgpStringToKey(s2k, phrase, plen, key, cipher->keysize);
PGPInitCFB(cfb, key, p);
pgpS2Kdestroy(s2k);
p += cipher->blocksize;
/* Wipe key *immediately* */
pgpClearMemory( key, cipher->keysize);
}
/* Now install x, encrypted */
checksum = 0;
p += pgpBnPut(&bnx, p, cfb, &checksum, FALSE);
pgpChecksumPut(checksum, p, cfb, FALSE);
p += 2;
pgpAssert((ptrdiff_t)len == p - sec->cryptkey);
if (cfb)
PGPFreeCFBContext(cfb);
bnEnd(&bnx);
bnEnd(&bny);
return 0; /* Success */
}
#if PGP_MACINTOSH
#pragma global_optimizer reset
#endif
static PGPSize
ecSecBufferLength(PGPSecKey const *seckey)
{
ECsecPlus const *sec = (ECsecPlus *)seckey->priv;
return sec->cklen;
}
static void
ecSecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
{
ECsecPlus const *sec = (ECsecPlus *)seckey->priv;
memcpy(buf, sec->cryptkey, sec->cklen);
}
static int
ecSecParams(PGPSecKey const *seckey,
BigNum *x1, BigNum *x2, BigNum *x3, BigNum *x4, BigNum *x5, BigNum *x6,
BigNum *x7, BigNum *x8)
{
ECsecPlus const *sec = (ECsecPlus *)seckey->priv;
ASSERTEC( seckey->pkAlg );
pgpAssert( !sec->locked );
(void) sec;
(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
ecFillSecKey(PGPSecKey *seckey, ECsecPlus *sec)
{
seckey->pkAlg = kPGPPublicKeyAlgorithm_ECSign;
seckey->priv = sec;
seckey->destroy = ecSecDestroy;
seckey->pubkey = ecPubkey;
seckey->islocked = ecIslocked;
seckey->lockingalgorithm = ecLockingAlgorithm;
seckey->s2ktype = ecS2KType;
seckey->convertpassphrase = ecConvertPassphrase;
seckey->unlock = ecUnlock;
seckey->lock = ecLock;
seckey->decrypt = ecDecrypt;
seckey->maxdecrypted = ecSecMaxdecrypted;
seckey->maxsig = ecSecMaxsig;
seckey->maxesk = ecSecMaxesk;
seckey->sign = ecSign;
seckey->changeLock = ecChangeLock;
seckey->bufferLength = ecSecBufferLength;
seckey->toBuffer = ecSecToBuffer;
seckey->secparams = ecSecParams;
seckey->setkeyid = ecSecSetKeyID;
}
PGPSecKey *
ecSecFromBuf(
PGPContextRef context,
PGPByte const * buf,
PGPSize size,
PGPError * error)
{
PGPSecKey *seckey;
ECsecPlus *sec;
PGPByte *cryptk;
PGPError err = kPGPError_OutOfMemory;
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( context );
bnInit();
cryptk = (PGPByte *)pgpContextMemAlloc(context,
size, kPGPMemoryMgrFlags_Clear);
if (cryptk) {
sec = (ECsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
if (sec) {
pgpClearMemory( sec, sizeof(*sec) );
sec->context = context;
seckey = (PGPSecKey *)
pgpContextMemAlloc(context,
sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
if (seckey) {
seckey->context = context;
memcpy(cryptk, buf, size);
sec->cryptkey = cryptk;
sec->cklen = sec->ckalloc = size;
sec->locked = 1;
/* We only need this to try unlocking... */
seckey->pkAlg = kPGPPublicKeyAlgorithm_ECSign;
seckey->priv = sec;
if (ecUnlock(seckey, NULL, 0, FALSE) >= 0) {
ecFillSecKey(seckey, sec);
*error = 0;
return seckey; /* Success! */
}
/* Ka-boom. Delete and free everything. */
pgpClearMemory( cryptk, size);
pgpContextMemFree( context, seckey);
}
PGPFreeData( sec ); /* Wipes as it frees */
}
pgpContextMemFree(context, cryptk);
}
*error = err;
return NULL;
}
/*
* Generate an EC secret key with prime of the specified number of bits.
* We only support the pre-computed sizes, with fixed curves.
* Make callbacks to progress function periodically.
* Secret key is returned in the unlocked form, with no passphrase set.
* fastgen has no effect.
*/
PGPSecKey *
ecSecGenerate(
PGPContextRef context,
unsigned bits, PGPBoolean fastgen,
PGPRandomContext const *rc,
int progress(void *arg, int c), void *arg, PGPError *error)
{
PGPSecKey *seckey = NULL;
ECsecPlus *sec;
BigNum bnorder, bnx;
ecContextRef ec = NULL;
PGPInt32 curve;
PGPUInt32 coordSize, scalarSize, pointSize;
PGPByte *xbuf = NULL;
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( context );
PGPEnv * pgpEnv = pgpContextGetEnvironment( context );
(void) fastgen;
*error = kPGPError_NoErr;
curve = sCurveIndexFromBitsize( bits );
if( curve < 0 )
{
*error = kPGPError_BadParams;
return NULL;
}
/* Initialize local pointers (simplify cleanup below) */
seckey = NULL;
sec = NULL;
/* Allocate data structures */
seckey = (PGPSecKey *)pgpContextMemAlloc( context,
sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
if (!seckey)
goto memerror;
seckey->context = context;
sec = (ECsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
if (!sec)
goto memerror;
pgpClearMemory( sec, sizeof(*sec) );
sec->context = context;
bnBegin( &bnorder, mgr, INSECURE );
bnBegin( &bnx, mgr, SECURE );
if( ecCreate2mContext( mgr, sCurves[curve].bitsize,
EC_MEM_USAGE_HIGH, &sec->s.ec ) < 0 )
goto memerror;
ec = sec->s.ec;
ecSetEC2mParamAInt( ec, sCurves[curve].a );
ecSetEC2mParamB( ec, sCurves[curve].b );
ecGetBufferSize( ec, &coordSize, &scalarSize, NULL, &pointSize );
if( ecPointCreate( ec, &sec->s.y ) < 0
|| ecPointCreate( ec, &sec->s.g ) < 0
|| ecScalarCreate( ec, &sec->s.order, INSECURE ) < 0
|| ecScalarCreate( ec, &sec->s.x, SECURE ) < 0 )
goto memerror;
sec->s.cofactor = sCurves[curve].cofactor;
/* Use fixed field and generator */
if ( ecPointInsertBytes( sec->s.g, sCurves[curve].g, 0 ) < 0
|| bnInsertBigBytes( &bnorder, sCurves[curve].order,
0, scalarSize ) < 0
|| sBNtoScalar( &bnorder, sec->s.order, mgr, scalarSize ) < 0 )
goto memerror;
/* Choose the random x scalar for the secret key */
xbuf = PGPNewSecureData( mgr, scalarSize+8, 0 );
if( IsNull( xbuf ) )
goto memerror;
pgpRandomGetBytes( rc, xbuf, scalarSize+8 );
if( bnInsertBigBytes( &bnx, xbuf, 0, scalarSize+8 ) < 0
|| bnMod( &bnx, &bnx, &bnorder ) < 0
|| sBNtoScalar( &bnx, sec->s.x, mgr, scalarSize ) < 0 )
goto memerror;
if (progress != NULL)
progress(arg, '.');
/* And calculate x*g as public key */
if( ecPointMul( sec->s.g, sec->s.x, FALSE, sec->s.y ) < 0 )
goto memerror;
if (progress != NULL)
progress(arg, ' ');
/* Fill in structs */
sec->cryptkey = NULL;
sec->ckalloc = sec->cklen = 0;
sec->locked = 0;
ecFillSecKey(seckey, sec);
/* Fill in cryptkey structure, unencrypted */
if( ecChangeLock (seckey, pgpEnv, NULL, NULL, 0, FALSE, NULL, 0,
kPGPStringToKey_Simple) < 0 )
goto memerror;
goto done;
memerror:
if ( IsntNull( seckey ) )
pgpContextMemFree( context, seckey);
if ( IsntNull( sec ) ) {
if( IsntNull( sec->s.y ) )
ecPointFree( sec->s.y );
if( IsntNull( sec->s.g ) )
ecPointFree( sec->s.g );
if( IsntNull( sec->s.x ) )
ecScalarFree( sec->s.x );
if( IsntNull( sec->s.order ) )
ecScalarFree( sec->s.order );
PGPFreeData( sec ); /* Wipes as it frees */
}
if( IsntNull( ec ) )
ecFreeContext( ec );
seckey = NULL;
*error = kPGPError_OutOfMemory;
/* Fall through */
done:
bnEnd( &bnorder );
bnEnd( &bnx );
if( IsntNull( xbuf ) )
PGPFreeData( xbuf );
return seckey;
}
#endif /* PGP_EC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -