📄 pgpeckey.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpECKey.c,v 1.17 2002/10/24 00:22:00 ajivsov Exp $
____________________________________________________________________________*/
#include "pgpSDKBuildFlags.h"
/* This entire module is dependent on EC being enabled */
#if PGP_EC
#include "pgpConfig.h"
#include <string.h>
#include <stddef.h>
#include "pgpDebug.h"
#include "pgpKeyMisc.h"
#include "pgpECKey.h"
#include "bn.h"
#include "ec.h"
#include "pgpCFBPriv.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpHashPriv.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpRandomX9_17.h"
#include "pgpStr2Key.h"
#include "pgpContext.h"
#include "pgpEnv.h"
#include "pgpEndianConversion.h"
#include "pgpFIPSPriv.h"
#define ASSERTEC(alg) pgpAssert( \
(ALGMASK(alg))==kPGPPublicKeyAlgorithm_ECEncrypt || \
(ALGMASK(alg))==kPGPPublicKeyAlgorithm_ECSign)
#define ASSERTECSIG(alg) \
pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_ECSign)
#define ASSERTECENC(alg) \
pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_ECEncrypt)
/* Size of encryption mask buffer - big enough to hold 256 bit keys */
#define MASKBUF_SIZE 40
/* Defines for ecScalars and BigNums */
#define SECURE 1
#define INSECURE 0
/* A structure to hold a public key */
typedef struct ECpub
{
ecContextRef ec; /* Context */
ecPointRef y; /* Public point */
ecPointRef g; /* Generator */
ecScalarRef order; /* Order of generator */
PGPUInt32 cofactor; /* # curve points / order */
DEBUG_STRUCT_CONSTRUCTOR( ECpub )
} ECpub;
/* A structure to hold a secret key */
typedef struct ECsec
{
ecContextRef ec; /* Context */
ecPointRef y; /* Public point */
ecPointRef g; /* Generator */
ecScalarRef order; /* Order of generator */
PGPUInt32 cofactor; /* # curve points / order */
ecScalarRef x; /* Private exponent */
DEBUG_STRUCT_CONSTRUCTOR( ECsec )
} ECsec ;
/* A PGPSecKey's priv points to this, an ECsec plus the encrypted form... */
/* This struct is always allocated using PGPNewSecureData */
typedef struct ECsecPlus
{
PGPContextRef context;
ECsec s;
PGPByte * cryptkey;
PGPSize ckalloc;
PGPSize cklen;
int locked;
DEBUG_STRUCT_CONSTRUCTOR( ECsecPlus )
} ECsecPlus ;
/** Predefined curves **/
#define BITSIZE1 163
#define NAME1 "sect163r2"
#define COFACTOR1 2
static PGPUInt32 nistb1[] = {
0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x02
};
static PGPByte nistg1[] = {
0x03, 0x03, 0xF0, 0xEB, 0xA1, 0x62,
0x86, 0xA2, 0xD5, 0x7E, 0xA0, 0x99, 0x11, 0x68,
0xD4, 0x99, 0x46, 0x37, 0xE8, 0x34, 0x3E, 0x36
};
static PGPByte nisto1[] = {
0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0xFE,
0x77, 0xE7, 0x0C, 0x12, 0xA4, 0x23, 0x4C, 0x33
};
#define BITSIZE2 283
#define NAME2 "sect283r1"
#define COFACTOR2 2
static PGPUInt32 nistb2[] = {
0x3B79A2F5,
0xF6263E31, 0xA581485A, 0x45309FA2, 0xCA97FD76,
0x19A0303F, 0xA5A4AF8A, 0xC8B8596D, 0x027B680A
};
static PGPByte nistg2[] = {
0x03, 0x05, 0xF9, 0x39, 0x25,
0x8D, 0xB7, 0xDD, 0x90, 0xE1, 0x93, 0x4F, 0x8C,
0x70, 0xB0, 0xDF, 0xEC, 0x2E, 0xED, 0x25, 0xB8,
0x55, 0x7E, 0xAC, 0x9C, 0x80, 0xE2, 0xE1, 0x98,
0xF8, 0xCD, 0xBE, 0xCD, 0x86, 0xB1, 0x20, 0x53
};
static PGPByte nisto2[] = {
0x03, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x90,
0x39, 0x96, 0x60, 0xFC, 0x93, 0x8A, 0x90, 0x16,
0x5B, 0x04, 0x2A, 0x7C, 0xEF, 0xAD, 0xB3, 0x07
};
typedef struct ECcurve
{
PGPUInt32 bitsize;
const char *name;
PGPUInt32 cofactor;
PGPUInt32 a;
PGPUInt32 *b;
PGPByte *g;
PGPByte *order;
DEBUG_STRUCT_CONSTRUCTOR( ECcurve )
} ECcurve ;
static ECcurve sCurves[] = {
{ BITSIZE1, NAME1, COFACTOR1, 1, nistb1, nistg1, nisto1 },
{ BITSIZE2, NAME2, COFACTOR2, 1, nistb2, nistg2, nisto2 }
};
/** Elliptic Curve / BigNum conversion functions **/
/* Convert an EC scalar into a BigNum */
static PGPError
sScalartoBN( ecScalarRef ec, BigNum *bn, PGPMemoryMgrRef mgr,
PGPUInt32 scalarSize )
{
PGPByte *buf;
buf = PGPNewSecureData( mgr, scalarSize, 0 );
if( buf == NULL )
return kPGPError_OutOfMemory;
if( ecScalarExtractBytes( ec, buf ) < 0
|| bnInsertBigBytes( bn, buf, 0, scalarSize ) < 0 )
{
PGPFreeData( buf );
return kPGPError_OutOfMemory;
}
PGPFreeData( buf );
return kPGPError_NoErr;
}
/* Convert an EC point into a BigNum */
static PGPError
sPointtoBN( ecPointRef ec, BigNum *bn, PGPMemoryMgrRef mgr,
PGPUInt32 pointSize )
{
PGPByte *buf;
buf = PGPNewSecureData( mgr, pointSize, 0 );
if( buf == NULL )
return kPGPError_OutOfMemory;
if( ecPointCompress( ec ) < 0
|| ecPointExtractBytes( ec, buf, 0 ) < 0
|| bnInsertBigBytes( bn, buf, 0, pointSize ) < 0 )
{
PGPFreeData( buf );
return kPGPError_OutOfMemory;
}
PGPFreeData( buf );
return kPGPError_NoErr;
}
/* Convert an EC point's X coordinate into a BigNum */
static PGPError
sPointXtoBN( ecPointRef ec, BigNum *bn, PGPMemoryMgrRef mgr,
PGPUInt32 coordSize )
{
PGPByte *buf;
buf = PGPNewSecureData( mgr, coordSize, 0 );
if( buf == NULL )
return kPGPError_OutOfMemory;
if( ecPointExtractXYBytes( ec, buf, NULL, 0 ) < 0 ||
bnInsertBigBytes( bn, buf, 0, coordSize ) < 0 )
{
PGPFreeData( buf );
return kPGPError_OutOfMemory;
}
PGPFreeData( buf );
return kPGPError_NoErr;
}
/* Convert a BigNum into an EC scalar */
static PGPError
sBNtoScalar( BigNum *bn, ecScalarRef ec, PGPMemoryMgrRef mgr,
PGPUInt32 scalarSize )
{
PGPByte *buf;
buf = PGPNewSecureData( mgr, scalarSize, 0 );
if( buf == NULL )
return kPGPError_OutOfMemory;
bnExtractBigBytes( bn, buf, 0, scalarSize );
if( ecScalarInsertBytes( ec, buf, NULL ) < 0 )
{
PGPFreeData( buf );
return kPGPError_OutOfMemory;
}
PGPFreeData( buf );
return kPGPError_NoErr;
}
/* Convert a BigNum into an EC point */
static PGPError
sBNtoPoint( BigNum *bn, ecPointRef ec, PGPMemoryMgrRef mgr,
PGPUInt32 pointSize )
{
PGPByte *buf;
buf = PGPNewSecureData( mgr, pointSize, 0 );
if( buf == NULL )
return kPGPError_OutOfMemory;
bnExtractBigBytes( bn, buf, 0, pointSize );
if( ecPointInsertBytes( ec, buf, 0 ) < 0 )
{
PGPFreeData( buf );
return kPGPError_OutOfMemory;
}
PGPFreeData( buf );
return kPGPError_NoErr;
}
/** Search for known curves **/
static PGPInt32
sCurveIndexFromBitsize( PGPUInt32 bitsize )
{
PGPUInt32 i;
for( i=0; i<sizeof(sCurves)/sizeof(sCurves[0]); ++i )
{
if( sCurves[i].bitsize == bitsize )
return (PGPInt32)i;
}
return -1;
}
static PGPInt32
sCurveIndexFromScalarsize( PGPUInt32 scalarsize )
{
PGPUInt32 i;
for( i=0; i<sizeof(sCurves)/sizeof(sCurves[0]); ++i )
{
if( (sCurves[i].bitsize+7)/8 == scalarsize )
return (PGPInt32)i;
}
return -1;
}
static PGPInt32
sCurveIndexFromName( const char * name, PGPSize namelen )
{
PGPUInt32 i;
for( i=0; i<sizeof(sCurves)/sizeof(sCurves[0]); ++i )
{
if( strlen( sCurves[i].name ) == namelen
&& strncmp( sCurves[i].name, name, namelen ) == 0 )
return (PGPInt32)i;
}
return -1;
}
/* Special entry point used by keyring parsing code to get bitsize */
PGPInt32
pgpECurveBitsFromName( const char * name, PGPSize namelen )
{
PGPUInt32 i;
for( i=0; i<sizeof(sCurves)/sizeof(sCurves[0]); ++i )
{
if( strlen( sCurves[i].name ) == namelen
&& strncmp( sCurves[i].name, name, namelen ) == 0 )
return sCurves[i].bitsize;
}
return -1;
}
/* Create mask buffer for EC encrypt/decrypt from shared secret curve
* point and hash algorithm. Use algorithm MGF1 from IEEE P1363.
*/
static PGPError
sFillEncryptMaskBuf( PGPContextRef context, ecPointRef ec,
PGPSize coordSize, PGPHashAlgorithm hashalg,
PGPByte *hashbuf, PGPSize hashbuflen )
{
PGPHashContextRef hc;
PGPSize hashsize;
PGPUInt32 counter;
PGPByte counterbuf[4];
void *hbuf = NULL;
void *xbuf = NULL;
PGPUInt32 off;
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( context );
PGPError err = kPGPError_NoErr;
err = PGPNewHashContext( context, hashalg, &hc );
pgpAssert( IsntPGPError( err ) );
PGPGetHashSize( hc, &hashsize );
/* Get X coordinate as shared secret */
xbuf = PGPNewSecureData( mgr, coordSize, 0 );
if( IsNull( xbuf ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
if( ecPointExtractXYBytes( ec, xbuf, NULL, 0 ) < 0 ) {
err = kPGPError_BadParams;
goto error;
}
hbuf = PGPNewSecureData( mgr, hashsize, 0 );
if( IsNull( hbuf ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
counter = 0;
for( off = 0; off < hashbuflen; off += hashsize )
{
PGPUInt32ToEndian( counter++, kPGPBigEndian, counterbuf );
PGPContinueHash( hc, counterbuf, sizeof(counterbuf) );
PGPContinueHash( hc, xbuf, coordSize );
PGPFinalizeHash( hc, hbuf );
pgpCopyMemory( hbuf, hashbuf+off, pgpMin(hashsize,hashbuflen-off) );
}
error:
if( IsntNull( hbuf ) )
PGPFreeData( hbuf );
if( IsntNull( xbuf ) )
PGPFreeData( xbuf );
PGPFreeHashContext( hc );
return err;
}
/** Public key functions **/
static void
ecPubDestroy(PGPPubKey *pubkey)
{
ECpub *pub = (ECpub *)pubkey->priv;
PGPContextRef context;
pgpAssertAddrValid( pubkey, PGPPubKey );
context = pubkey->context;
ASSERTEC(pubkey->pkAlg);
ecPointFree( pub->y );
ecPointFree( pub->g );
ecScalarFree( pub->order );
ecFreeContext( pub->ec );
pgpClearMemory( pub, sizeof(pub));
pgpContextMemFree( context, pub);
pgpClearMemory( pubkey, sizeof(pubkey));
pgpContextMemFree(context, pubkey);
}
/* Return the largest possible PGPESK size for a given key */
static PGPSize
ecPubMaxesk(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
ECpub const *pub = (ECpub *)pubkey->priv;
PGPUInt32 pointSize;
ASSERTECENC(pubkey->pkAlg);
ecGetBufferSize( pub->ec, NULL, NULL, NULL, &pointSize );
if (format == kPGPPublicKeyMessageFormat_PGP)
return 1 + 2 + pointSize + 2 + MASKBUF_SIZE;
else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
format == kPGPPublicKeyMessageFormat_IKE)
return 1 + pointSize + MASKBUF_SIZE;
else if (format == kPGPPublicKeyMessageFormat_X509) {
/* SEQUENCE, length, INT, INT */
PGPUInt32 len;
len = pgpBnX509LenLen(pointSize+1) + 1 + pointSize+1 +
pgpBnX509LenLen(MASKBUF_SIZE+1) + 1 + MASKBUF_SIZE+1;
return 1 + 1 + pgpBnX509LenLen(len) + len;
}
pgpAssert(0);
return 0;
}
/* Return the largest possible input size for ecEncrypt */
static PGPSize
ecPubMaxdecrypted(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
(void) format;
ASSERTECENC(pubkey->pkAlg);
return MASKBUF_SIZE - 3;
}
/* Return the largest possible signature input to ecVerify */
static PGPSize
ecPubMaxsig(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
{
ECpub const *pub = (ECpub *)pubkey->priv;
PGPUInt32 scalarSize;
ASSERTECSIG(pubkey->pkAlg);
ecGetBufferSize( pub->ec, NULL, &scalarSize, NULL, NULL );
if (format == kPGPPublicKeyMessageFormat_PGP)
return 2*( 2 + scalarSize );
else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
format == kPGPPublicKeyMessageFormat_IKE)
return 2 * scalarSize;
else if (format == kPGPPublicKeyMessageFormat_X509) {
/* SEQUENCE, length, INT, INT */
PGPUInt32 len;
len = 2*(pgpBnX509LenLen(scalarSize+1) + 1 + scalarSize+1);
return 1 + pgpBnX509LenLen(len) + len;
}
pgpAssert(0);
return 0;
}
/*
* Set keyid
*/
static void
ecPubSetKeyID(PGPPubKey *pubkey, PGPByte *keyid)
{
pgpCopyMemory(keyid, pubkey->keyID, sizeof(pubkey->keyID));
}
static int
ecPubParams(PGPPubKey const *pubkey,
BigNum *x1, BigNum *x2, BigNum *x3, BigNum *x4, BigNum *x5, BigNum *x6,
BigNum *x7, BigNum *x8)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -