📄 certwr.c
字号:
{
RESOURCE_DATA msgData;
int payloadLength, pubKeyDataSize, extensionSize, status;
int subjectDNsize = 0, timeSize = 0;
assert( issuerCertInfoPtr == NULL );
/* Make sure everything is in order */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
CRYPT_CERTTYPE_REQUEST_CERT );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded certificate request will be */
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( subjectCertInfoPtr->iCryptContext,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_PUBLICKEY );
if( cryptStatusError( status ) )
return( status );
pubKeyDataSize = msgData.length;
if( subjectCertInfoPtr->subjectName != NULL )
subjectCertInfoPtr->subjectDNsize = subjectDNsize = \
sizeofDN( subjectCertInfoPtr->subjectName );
if( subjectCertInfoPtr->startTime )
timeSize = ( int ) sizeofObject( sizeofGeneralizedTime() );
if( subjectCertInfoPtr->endTime )
timeSize += ( int ) sizeofObject( sizeofGeneralizedTime() );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
payloadLength = ( timeSize ? ( int ) sizeofObject( timeSize ) : 0 ) + \
( subjectDNsize ? ( int ) sizeofObject( subjectDNsize ) : 0 ) + \
pubKeyDataSize;
if( extensionSize )
payloadLength += ( int ) sizeofObject( extensionSize );
/* Write the header, request ID, inner header, DN, and public key */
writeSequence( stream, sizeofShortInteger( 0 ) + \
sizeofObject( payloadLength ) );
writeShortInteger( stream, 0, DEFAULT_TAG );
writeSequence( stream, payloadLength );
if( timeSize )
{
writeConstructed( stream, timeSize, CTAG_CF_VALIDITY );
if( subjectCertInfoPtr->startTime )
{
writeConstructed( stream, sizeofGeneralizedTime(), 0 );
writeGeneralizedTime( stream, subjectCertInfoPtr->startTime,
DEFAULT_TAG );
}
if( subjectCertInfoPtr->endTime )
{
writeConstructed( stream, sizeofGeneralizedTime(), 1 );
writeGeneralizedTime( stream, subjectCertInfoPtr->endTime,
DEFAULT_TAG );
}
}
if( subjectDNsize )
{
writeConstructed( stream, subjectCertInfoPtr->subjectDNsize,
CTAG_CF_SUBJECT );
writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );
}
if( !sIsNullStream( stream ) )
{
BYTE *dataPtr = sMemBufPtr( stream );
setResourceData( &msgData, dataPtr, pubKeyDataSize );
status = krnlSendMessage( subjectCertInfoPtr->iCryptContext,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_PUBLICKEY );
if( cryptStatusError( status ) )
return( status );
/* Convert the SPKI SEQUENCE tag to the CRMF alternative */
*dataPtr = MAKE_CTAG( CTAG_CF_PUBLICKEY );
}
sSkip( stream, pubKeyDataSize );
/* Write the attributes */
if( extensionSize )
{
writeConstructed( stream, extensionSize, CTAG_CF_EXTENSIONS );
writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_REQUEST_CERT, extensionSize );
}
return( sGetStatus( stream ) );
}
/* Write CMP revocation request information:
RevDetails ::= SEQUENCE {
certTemplate SEQUENCE {
serialNumber [ 1 ] INTEGER,
issuer [ 3 ] EXPLICIT Name,
},
crlEntryDetails SET OF Attribute
} */
int writeRevRequestInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
int payloadLength, extensionSize, status;
assert( issuerCertInfoPtr == NULL );
assert( iIssuerCryptContext == CRYPT_UNUSED );
/* Make sure everything is in order */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
CRYPT_CERTTYPE_REQUEST_REVOCATION );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded certificate request will be */
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
payloadLength = sizeofInteger( subjectCertInfoPtr->serialNumber,
subjectCertInfoPtr->serialNumberLength ) + \
sizeofObject( subjectCertInfoPtr->issuerDNsize ) + \
( extensionSize ? ( int ) sizeofObject( extensionSize ) : 0 );
/* Write the header, inner header, serial number and issuer DN */
writeSequence( stream, sizeofObject( payloadLength ) );
writeSequence( stream, payloadLength );
writeInteger( stream, subjectCertInfoPtr->serialNumber,
subjectCertInfoPtr->serialNumberLength,
CTAG_CF_SERIALNUMBER );
writeConstructed( stream, subjectCertInfoPtr->issuerDNsize,
CTAG_CF_ISSUER );
swrite( stream, subjectCertInfoPtr->issuerDNptr,
subjectCertInfoPtr->issuerDNsize );
if( cryptStatusError( status ) )
return( status );
/* Write the attributes */
if( extensionSize )
{
writeConstructed( stream, extensionSize, CTAG_CF_EXTENSIONS );
writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_REQUEST_REVOCATION, extensionSize );
}
return( sGetStatus( stream ) );
}
/* Write CRL information:
CRLInfo ::= SEQUENCE {
version INTEGER DEFAULT(0),
signature AlgorithmIdentifier,
issuer Name,
thisUpdate UTCTime,
nextUpdate UTCTime OPTIONAL,
revokedCertificates SEQUENCE OF RevokedCerts,
extensions [ 0 ] Extensions OPTIONAL
} */
int writeCRLInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
REVOCATION_INFO *revocationInfo;
int length, extensionSize, revocationInfoLength = 0, status;
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
CRYPT_CERTTYPE_CRL );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded CRL will be */
subjectCertInfoPtr->version = \
( subjectCertInfoPtr->attributes != NULL ) ? 2 : 1;
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
{
if( revocationInfo->attributes != NULL )
/* If there are per-entry extensions present it's a v2 CRL */
subjectCertInfoPtr->version = 2;
revocationInfoLength += sizeofCRLentry( revocationInfo );
}
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
length = ( extensionSize ? sizeofShortInteger( X509VERSION_2 ) : 0 ) +
sizeofContextAlgoID( iIssuerCryptContext, CRYPT_ALGO_SHA,
ALGOID_FLAG_ALGOID_ONLY ) +
issuerCertInfoPtr->subjectDNsize + sizeofUTCTime() +
( subjectCertInfoPtr->endTime ? sizeofUTCTime() : 0 ) +
( int ) sizeofObject( revocationInfoLength ) +
( extensionSize ? \
( int ) sizeofObject( sizeofObject( extensionSize ) ) : 0 );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* If there are extensions present, mark this as a v2 CRL */
if( extensionSize )
writeShortInteger( stream, X509VERSION_2, DEFAULT_TAG );
/* Write the signature algorithm identifier, issuer name, and CRL time */
status = writeContextAlgoID( stream, iIssuerCryptContext, CRYPT_ALGO_SHA,
ALGOID_FLAG_ALGOID_ONLY );
if( cryptStatusError( status ) )
return( status );
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
writeUTCTime( stream, subjectCertInfoPtr->startTime, DEFAULT_TAG );
if( subjectCertInfoPtr->endTime )
writeUTCTime( stream, subjectCertInfoPtr->endTime, DEFAULT_TAG );
/* Write the SEQUENCE OF revoked certificates wrapper and the revoked
certificate information */
writeSequence( stream, revocationInfoLength );
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
writeCRLentry( stream, revocationInfo );
/* Write the extensions if necessary */
if( extensionSize )
writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_CRL, extensionSize );
return( sGetStatus( stream ) );
}
/* Write an OCSP request:
OCSPRequest ::= SEQUENCE { -- Write, v1
reqName [1] EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
reqList SEQUENCE OF SEQUENCE {
SEQUENCE { -- certID
hashAlgo AlgorithmIdentifier,
iNameHash OCTET STRING,
iKeyHash OCTET STRING,
serialNo INTEGER
} }
}
OCSPRequest ::= SEQUENCE { -- Write, v2
version [0] EXPLICIT INTEGER (1),
reqName [1] EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
reqList SEQUENCE OF SEQUENCE {
certID [2] EXPLICIT OCTET STRING -- Cert hash
}
} */
int writeOCSPRequestInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
REVOCATION_INFO *revocationInfo;
int length, extensionSize, revocationInfoLength = 0, status;
/* Make sure we've actually got some requests present to write */
if( subjectCertInfoPtr->revocations == NULL )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Perform any necessary pre-encoding steps. We should really update the
nonce when we write the data for real, but to do that we'd have to re-
calculate the extension information (via preEncodeCertifiate()) for
null-stream and real writes just because the one extension changes, so
we calculate it when we do the dummy write instead. This is safe
because the write process always performs a real write immediately
after the null-stream write */
if( sIsNullStream( stream ) )
{
ATTRIBUTE_LIST *attributeListPtr;
BYTE nonce[ CRYPT_MAX_HASHSIZE ];
/* To ensure freshness we always use a new nonce when we write an
OCSP request. We don't check for problems (which, in any case,
could only occur if there's an out-of-memory error) because
there's not much we can meaningfully do if the add fails */
attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_OCSP_NONCE,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
deleteAttributeField( &subjectCertInfoPtr->attributes,
&subjectCertInfoPtr->attributeCursor,
attributeListPtr );
getNonce( nonce, 16 );
addAttributeField( &subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_OCSP_NONCE, CRYPT_ATTRIBUTE_NONE,
nonce, 16, ATTR_FLAG_NONE, NULL, NULL );
/* Perform the pre-encoding checks */
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
CRYPT_CERTTYPE_OCSP_REQUEST );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded OCSP request will be */
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
revocationInfoLength += sizeofOCSPentry( revocationInfo, TRUE );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
length = ( ( subjectCertInfoPtr->version == 2 ) ? \
( int ) sizeofObject( sizeofShortInteger( CTAG_OR_VERSION ) ) : 0 ) +
( ( issuerCertInfoPtr != NULL ) ? \
( int ) sizeofObject( sizeofObject( issuerCertInfoPtr->subjectDNsize ) ) : 0 ) +
( int ) sizeofObject( revocationInfoLength ) +
( extensionSize ? \
( int ) sizeofObject( sizeofObject( extensionSize ) ) : 0 );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* If we're using v2 identifiers, mark this as a v2 request */
if( subjectCertInfoPtr->version == 2 )
{
writeConstructed( stream, sizeofShortInteger( 1 ), CTAG_OR_VERSION );
writeShortInteger( stream, 1, DEFAULT_TAG );
}
/* If we're signing the request, write the issuer DN as a GeneralName */
if( issuerCertInfoPtr != NULL )
{
writeConstructed( stream,
sizeofObject( issuerCertInfoPtr->subjectDNsize ), 1 );
writeConstructed( stream, issuerCertInfoPtr->subjectDNsize, 4 );
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
}
/* Write the SEQUENCE OF revocation information wrapper and the
revocation information */
writeSequence( stream, revocationInfoLength );
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
writeOCSPentry( stream, revocationInfo, 0, TRUE );
/* Write the attributes if necessary */
if( extensionSize )
writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_OCSP_REQUEST, extensionSize );
return( sGetStatus( stream ) );
}
/* Write an OCSP response:
OCSPResponse ::= SEQUENCE {
version [0] EXPLICIT INTEGER (1),
respID [1] EXPLICIT Name,
producedAt GeneralizedTime,
responses SEQUENCE OF Response
exts [1] EXPLICIT Extensions OPTIONAL,
} */
int writeOCSPResponseInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
REVOCATION_INFO *revocationInfo;
int length, extensionSize, revocationInfoLength = 0, status;
/* Make sure we've actually got some requests present to write */
if( subjectCertInfoPtr->revocations == NULL )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
CRYPT_CERTTYPE_OCSP_REQUEST );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded OCSP response will be */
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
revocationInfoLength += sizeofOCSPentry( revocationInfo, FALSE );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
length = ( int ) sizeofObject( sizeofShortInteger( CTAG_OP_VERSION ) ) +
( int ) sizeofObject( issuerCertInfoPtr->subjectDNsize ) +
sizeofGeneralizedTime() +
( int ) sizeofObject( revocationInfoLength ) +
( extensionSize ? \
( int ) sizeofObject( sizeofObject( extensionSize ) ) : 0 );
/* Write the outer SEQUENCE wrapper, mark this as a v2 response, and
write the issuer DN and producedAt time */
writeSequence( stream, length );
writeConstructed( stream, sizeofShortInteger( 1 ), CTAG_OP_VERSION );
writeShortInteger( stream, 1, DEFAULT_TAG );
writeConstructed( stream, issuerCertInfoPtr->subjectDNsize, 1 );
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
writeGeneralizedTime( stream, subjectCertInfoPtr->startTime,
DEFAULT_TAG );
/* Write the SEQUENCE OF revocation information wrapper and the
revocation information */
writeSequence( stream, revocationInfoLength );
for( revocationInfo = subjectCertInfoPtr->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
writeOCSPentry( stream, revocationInfo,
subjectCertInfoPtr->startTime, FALSE );
/* Write the attributes if necessary */
if( extensionSize )
writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_OCSP_RESPONSE, extensionSize );
return( sGetStatus( stream ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -