📄 key_rw.c
字号:
/* Read the wrapper and make sure that it's OK */
readUint32( stream );
status = readString32( stream, buffer, &length, 7 );
if( cryptStatusError( status ) )
return( status );
if( length != 7 || memcmp( buffer, "ssh-rsa", 7 ) )
return( CRYPT_ERROR_BADDATA );
/* Set the maximum permitted actions. SSH keys are only used internally,
so we restrict the usage to internal-only */
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
ACTION_PERM_NONE_EXTERNAL );
/* Read the SSH public key information */
status = readBignumInteger32( stream, &rsaKey->rsaParam_e, 1, 16 );
if( cryptStatusOK( status ) )
status = readBignumInteger32( stream, &rsaKey->rsaParam_n,
bitsToBytes( MIN_PKCSIZE_BITS ),
CRYPT_MAX_PKCSIZE );
return( status );
}
int readSsh2DlpPublicKey( STREAM *stream, CONTEXT_INFO *contextInfoPtr,
int *actionFlags )
{
PKC_INFO *dsaKey = contextInfoPtr->ctxPKC;
const BOOLEAN isDH = \
( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH );
char buffer[ 16 ];
int length, status;
assert( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH );
/* Read the wrapper and make sure that it's OK. SSHv2 uses PKCS #3
rather than X9.42-style DH keys, so we have to treat this algorithm
type specially */
readUint32( stream );
if( isDH )
{
status = readString32( stream, buffer, &length, 6 );
if( cryptStatusError( status ) )
return( status );
if( length != 6 || memcmp( buffer, "ssh-dh", 6 ) )
return( CRYPT_ERROR_BADDATA );
/* Set the maximum permitted actions. SSH keys are only used
internally, so we restrict the usage to internal-only. Since DH
keys can be both public and private keys, we allow both usage
types even though technically it's a public key */
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
ACTION_PERM_NONE_EXTERNAL );
/* Read the SSH public key information. Since SSH uses PKCS #3 DH
values we can end up with very small values for g, so we have to
handle this specially */
status = readBignumInteger32( stream, &dsaKey->dlpParam_p,
bitsToBytes( MIN_PKCSIZE_BITS ),
CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readBignumInteger32( stream, &dsaKey->dlpParam_g,
1, CRYPT_MAX_PKCSIZE );
return( status );
}
/* It's a standard DLP key, read the wrapper and make sure that it's
OK */
status = readString32( stream, buffer, &length, 7 );
if( cryptStatusError( status ) )
return( status );
if( length != 7 || memcmp( buffer, "ssh-dss", 7 ) )
return( CRYPT_ERROR_BADDATA );
/* Set the maximum permitted actions. SSH keys are only used internally,
so we restrict the usage to internal-only */
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
ACTION_PERM_NONE_EXTERNAL );
/* Read the SSH public key information */
status = readBignumInteger32( stream, &dsaKey->dlpParam_p,
bitsToBytes( MIN_PKCSIZE_BITS ),
CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readBignumInteger32( stream, &dsaKey->dlpParam_q,
bitsToBytes( 128 ),
CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readBignumInteger32( stream, &dsaKey->dlpParam_g,
bitsToBytes( MIN_PKCSIZE_BITS ),
CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) && !isDH )
status = readBignumInteger32( stream, &dsaKey->dlpParam_y,
bitsToBytes( 128 ),
CRYPT_MAX_PKCSIZE );
return( status );
}
/* Read PGP public keys:
byte version
uint32 creationTime
[ uint16 validity - version 3 only ]
byte RSA DSA Elgamal
mpi n p p
mpi e q g
mpi g y
mpi y */
int readPgpRsaPublicKey( STREAM *stream, CONTEXT_INFO *contextInfoPtr,
int *actionFlags )
{
PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
time_t creationTime;
int value, status;
assert( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
/* Read the header info */
value = sgetc( stream );
if( value != PGP_VERSION_2 && value != PGP_VERSION_3 && \
value != PGP_VERSION_OPENPGP )
return( CRYPT_ERROR_BADDATA );
status = readUint32Time( stream, &creationTime );
if( cryptStatusError( status ) )
return( status );
rsaKey->pgpCreationTime = creationTime;
if( value == PGP_VERSION_2 || value == PGP_VERSION_3 )
/* Skip validity period */
sSkip( stream, 2 );
/* Set the maximum permitted actions. If there are no restrictions we
allow external usage, if the keys are encryption-only or sig-only we
make the usage internal-only because of RSA's signature/encryption
duality. If the key is a pure public key (rather than merely the
public portions of a private key), the actions will be restricted by
higher-level code to sig-check only */
value = sgetc( stream );
if( value != PGP_ALGO_RSA && value != PGP_ALGO_RSA_ENCRYPT && \
value != PGP_ALGO_RSA_SIGN )
return( CRYPT_ERROR_BADDATA );
*actionFlags = 0;
if( value != PGP_ALGO_RSA_SIGN )
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
if( value != PGP_ALGO_RSA_ENCRYPT )
*actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
if( value != PGP_ALGO_RSA )
*actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( *actionFlags );
/* Read the PGP public key information */
status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_n,
MIN_PKCSIZE_BITS,
bytesToBits( PGP_MAX_MPISIZE ) );
if( cryptStatusOK( status ) )
status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_e, 2,
bytesToBits( PGP_MAX_MPISIZE ) );
return( status );
}
int readPgpDlpPublicKey( STREAM *stream, CONTEXT_INFO *contextInfoPtr,
int *actionFlags )
{
PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;
time_t creationTime;
int value, status;
assert( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );
/* Read the header info */
value = sgetc( stream );
if( value != PGP_VERSION_OPENPGP )
return( CRYPT_ERROR_BADDATA );
status = readUint32Time( stream, &creationTime );
if( cryptStatusError( status ) )
return( status );
dlpKey->pgpCreationTime = creationTime;
/* Set the maximum permitted actions. Because of the special-case data
formatting requirements for DLP algorithms, we make the usage
internal-only. If the key is a pure public key (rather than merely
the public portions of a private key), the actions will be
restricted by higher-level code to sig-check only */
value = sgetc( stream );
if( value != PGP_ALGO_DSA && value != PGP_ALGO_ELGAMAL )
return( CRYPT_ERROR_BADDATA );
if( value == PGP_ALGO_DSA )
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
ACTION_PERM_NONE_EXTERNAL );
else
*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
ACTION_PERM_NONE_EXTERNAL );
/* Read the PGP public key information */
status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_p,
MIN_PKCSIZE_BITS,
bytesToBits( PGP_MAX_MPISIZE ) );
if( cryptStatusOK( status ) && value == PGP_ALGO_DSA )
status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_q, 155,
bytesToBits( PGP_MAX_MPISIZE ) );
if( cryptStatusOK( status ) )
status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_g, 2,
bytesToBits( PGP_MAX_MPISIZE ) );
if( cryptStatusOK( status ) )
status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_y,
MIN_PKCSIZE_BITS,
bytesToBits( PGP_MAX_MPISIZE ) );
return( status );
}
/* Umbrella public-key read functions */
static int readPublicKeyRsaFunction( STREAM *stream, CONTEXT_INFO *contextInfoPtr,
const KEYFORMAT_TYPE formatType )
{
int actionFlags, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
switch( formatType )
{
case KEYFORMAT_CERT:
status = readRsaSubjectPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
case KEYFORMAT_SSH1:
status = readSsh1RsaPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
case KEYFORMAT_SSH2:
status = readSsh2RsaPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
case KEYFORMAT_PGP:
status = readPgpRsaPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
if( cryptStatusError( status ) )
return( status );
return( krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE, &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS ) );
}
static int readPublicKeyDlpFunction( STREAM *stream, CONTEXT_INFO *contextInfoPtr,
const KEYFORMAT_TYPE formatType )
{
int actionFlags, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
switch( formatType )
{
case KEYFORMAT_CERT:
status = readDlpSubjectPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
case KEYFORMAT_SSH2:
status = readSsh2DlpPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
case KEYFORMAT_PGP:
status = readPgpDlpPublicKey( stream, contextInfoPtr,
&actionFlags );
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
if( cryptStatusError( status ) )
return( status );
return( krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE, &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS ) );
}
/****************************************************************************
* *
* Write Public Keys *
* *
****************************************************************************/
/* Write X.509 SubjectPublicKeyInfo public keys */
static int writeRsaSubjectPublicKey( STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
const int length = sizeofBignum( &rsaKey->rsaParam_n ) + \
sizeofBignum( &rsaKey->rsaParam_e );
/* Write the SubjectPublicKeyInfo header field (the +1 is for the
bitstring) */
writeSequence( stream, sizeofAlgoID( CRYPT_ALGO_RSA ) + \
( int ) sizeofObject( \
sizeofObject( length ) + 1 ) );
writeAlgoID( stream, CRYPT_ALGO_RSA );
/* Write the BITSTRING wrapper and the PKC information */
writeBitStringHole( stream, ( int ) sizeofObject( length ),
DEFAULT_TAG );
writeSequence( stream, length );
writeBignum( stream, &rsaKey->rsaParam_n );
return( writeBignum( stream, &rsaKey->rsaParam_e ) );
}
static int writeDlpSubjectPublicKey( STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const CRYPT_ALGO_TYPE cryptAlgo = contextInfoPtr->capabilityInfo->cryptAlgo;
const PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;
const int parameterSize = ( int ) sizeofObject( \
sizeofBignum( &dlpKey->dlpParam_p ) + \
sizeofBignum( &dlpKey->dlpParam_q ) + \
sizeofBignum( &dlpKey->dlpParam_g ) );
const int componentSize = sizeofBignum( &dlpKey->dlpParam_y );
int totalSize;
/* Determine the size of the AlgorithmIdentifier and the BITSTRING-
encapsulated public-key data (the +1 is for the bitstring) */
totalSize = sizeofAlgoIDex( cryptAlgo, CRYPT_ALGO_NONE, parameterSize ) + \
( int ) sizeofObject( componentSize + 1 );
/* Write the SubjectPublicKeyInfo header field */
writeSequence( stream, totalSize );
writeAlgoIDex( stream, cryptAlgo, CRYPT_ALGO_NONE, parameterSize );
/* Write the parameter data */
writeSequence( stream, sizeofBignum( &dlpKey->dlpParam_p ) + \
sizeofBignum( &dlpKey->dlpParam_q ) + \
sizeofBignum( &dlpKey->dlpParam_g ) );
writeBignum( stream, &dlpKey->dlpParam_p );
if( hasReversedParams( cryptAlgo ) )
{
writeBignum( stream, &dlpKey->dlpParam_g );
writeBignum( stream, &dlpKey->dlpParam_q );
}
else
{
writeBignum( stream, &dlpKey->dlpParam_q );
writeBignum( stream, &dlpKey->dlpParam_g );
}
/* Write the BITSTRING wrapper and the PKC information */
writeBitStringHole( stream, componentSize, DEFAULT_TAG );
return( writeBignum( stream, &dlpKey->dlpParam_y ) );
}
/* Write SSH public keys */
static int writeSsh1RsaPublicKey( STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -