📄 key_wr.c
字号:
/****************************************************************************
* *
* Public/Private Key Write Routines *
* Copyright Peter Gutmann 1992-2007 *
* *
****************************************************************************/
#include <stdio.h>
#define PKC_CONTEXT /* Indicate that we're working with PKC contexts */
#if defined( INC_ALL )
#include "context.h"
#include "asn1.h"
#include "asn1_ext.h"
#include "misc_rw.h"
#include "pgp.h"
#else
#include "context/context.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#include "misc/misc_rw.h"
#include "misc/pgp.h"
#endif /* Compiler-specific includes */
/* Although there is a fair amount of commonality between public and private-
key functions, we keep them distinct to enforce red/black separation.
The DLP algorithms split the key components over the information in the
AlgorithmIdentifier and the actual public/private key components, with the
(p, q, g) set classed as domain parameters and included in the
AlgorithmIdentifier and y being the actual key.
params = SEQ {
p INTEGER,
q INTEGER,
g INTEGER,
j INTEGER OPTIONAL, -- X9.42 only
validationParams [...] -- X9.42 only
}
key = y INTEGER -- g^x mod p
For peculiar historical reasons (copying errors and the use of obsolete
drafts as reference material) the X9.42 interpretation used in PKIX
reverses the second two parameters from FIPS 186 (so it uses p, g, q
instead of p, q, g), so when we read/write the parameter information we
have to switch the order in which we read the values if the algorithm
isn't DSA */
#define hasReversedParams( cryptAlgo ) \
( ( cryptAlgo ) == CRYPT_ALGO_DH || \
( cryptAlgo ) == CRYPT_ALGO_ELGAMAL )
#ifdef USE_PKC
/****************************************************************************
* *
* Write Public Keys *
* *
****************************************************************************/
/* Write X.509 SubjectPublicKeyInfo public keys */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeRsaSubjectPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
const int length = sizeofBignum( &rsaKey->rsaParam_n ) + \
sizeofBignum( &rsaKey->rsaParam_e );
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
/* 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 ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeDlpSubjectPublicKey( INOUT 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;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );
/* If it's an Elgamal key created by PGP or a DH key from SSL/SSH then
the q parameter isn't present so we can't write the key in this format */
if( BN_is_zero( &dlpKey->dlpParam_q ) )
{
assert( DEBUG_WARN );
return( CRYPT_ERROR_NOTAVAIL );
}
/* 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 ) );
}
#ifdef USE_ECC
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeEccSubjectPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDSA );
return( CRYPT_ERROR_NOTAVAIL );
}
#endif /* USE_ECC */
#ifdef USE_SSH1
/* Write SSH public keys */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeSsh1RsaPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
writeUint32( stream, BN_num_bits( &rsaKey->rsaParam_n ) );
writeBignumInteger16Ubits( stream, &rsaKey->rsaParam_e );
return( writeBignumInteger16Ubits( stream, &rsaKey->rsaParam_n ) );
}
#endif /* USE_SSH1 */
#ifdef USE_SSH
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeSshRsaPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
writeUint32( stream, sizeofString32( "ssh-rsa", 7 ) + \
sizeofBignumInteger32( &rsaKey->rsaParam_e ) + \
sizeofBignumInteger32( &rsaKey->rsaParam_n ) );
writeString32( stream, "ssh-rsa", 7 );
writeBignumInteger32( stream, &rsaKey->rsaParam_e );
return( writeBignumInteger32( stream, &rsaKey->rsaParam_n ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeSshDlpPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *dsaKey = contextInfoPtr->ctxPKC;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA ) );
/* SSHv2 uses PKCS #3 rather than X9.42-style DH keys so we have to
treat this algorithm type specially */
if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH )
{
writeUint32( stream, sizeofString32( "ssh-dh", 6 ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_p ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_g ) );
writeString32( stream, "ssh-dh", 6 );
writeBignumInteger32( stream, &dsaKey->dlpParam_p );
return( writeBignumInteger32( stream, &dsaKey->dlpParam_g ) );
}
writeUint32( stream, sizeofString32( "ssh-dss", 7 ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_p ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_q ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_g ) + \
sizeofBignumInteger32( &dsaKey->dlpParam_y ) );
writeString32( stream, "ssh-dss", 7 );
writeBignumInteger32( stream, &dsaKey->dlpParam_p );
writeBignumInteger32( stream, &dsaKey->dlpParam_q );
writeBignumInteger32( stream, &dsaKey->dlpParam_g );
return( writeBignumInteger32( stream, &dsaKey->dlpParam_y ) );
}
#endif /* USE_SSH */
#ifdef USE_SSL
/* Write SSL public keys */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeSslDlpPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *dhKey = contextInfoPtr->ctxPKC;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH );
writeBignumInteger16U( stream, &dhKey->dlpParam_p );
return( writeBignumInteger16U( stream, &dhKey->dlpParam_g ) );
}
#endif /* USE_SSL */
#ifdef USE_PGP
/* Write PGP public keys */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writePgpRsaPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
sputc( stream, PGP_VERSION_OPENPGP );
writeUint32Time( stream, rsaKey->pgpCreationTime );
sputc( stream, PGP_ALGO_RSA );
writeBignumInteger16Ubits( stream, &rsaKey->rsaParam_n );
return( writeBignumInteger16Ubits( stream, &rsaKey->rsaParam_e ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writePgpDlpPublicKey( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr )
{
const PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;
const CRYPT_ALGO_TYPE cryptAlgo = contextInfoPtr->capabilityInfo->cryptAlgo;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );
sputc( stream, PGP_VERSION_OPENPGP );
writeUint32Time( stream, dlpKey->pgpCreationTime );
sputc( stream, ( cryptAlgo == CRYPT_ALGO_DSA ) ? \
PGP_ALGO_DSA : PGP_ALGO_ELGAMAL );
writeBignumInteger16Ubits( stream, &dlpKey->dlpParam_p );
if( cryptAlgo == CRYPT_ALGO_DSA )
writeBignumInteger16Ubits( stream, &dlpKey->dlpParam_q );
writeBignumInteger16Ubits( stream, &dlpKey->dlpParam_g );
return( writeBignumInteger16Ubits( stream, &dlpKey->dlpParam_y ) );
}
#endif /* USE_PGP */
/* Umbrella public-key write functions */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int writePublicKeyRsaFunction( INOUT STREAM *stream,
const CONTEXT_INFO *contextInfoPtr,
IN_ENUM( KEYFORMAT ) \
const KEYFORMAT_TYPE formatType,
IN_BUFFER( accessKeyLen ) \
const char *accessKey,
IN_LENGTH_FIXED( 10 ) \
const int accessKeyLen )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( accessKey, accessKeyLen ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
REQUIRES( formatType > KEYFORMAT_NONE && formatType < KEYFORMAT_LAST );
REQUIRES( accessKeyLen == 10 );
/* Make sure that we really intended to call this function */
if( accessKeyLen != 10 || memcmp( accessKey, "public_key", 10 ) )
retIntError();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -