📄 certsign.c
字号:
/* If we need to include extra data in the signature make sure that it's
available and determine how big it'll be. If there's no issuer
certificate available and we've been asked for extra signature data
we fall back to providing just a raw signature rather than bailing
out completely */
if( signatureLevel > CRYPT_SIGNATURELEVEL_NONE && \
issuerCertInfoPtr != NULL )
{
ENSURES( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );
if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
{
status = exportCert( NULL, 0, &extraDataLength,
CRYPT_CERTFORMAT_CERTIFICATE,
issuerCertInfoPtr );
}
else
{
MESSAGE_DATA msgData;
ENSURES( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( issuerCertInfoPtr->objectHandle,
IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_ICERTFORMAT_CERTSEQUENCE );
extraDataLength = msgData.length;
}
if( cryptStatusError( status ) )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* If it's a certificate chain copy over the signing certificate(s) */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
{
status = copySigningCertChain( certInfoPtr, iSignContext );
if( cryptStatusError( status ) )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* Set up any required timestamps */
status = setCertTimeinfo( certInfoPtr, iSignContext, isCertificate );
if( cryptStatusError( status ) )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
/* If it's a certificate, set up the certificate serial number */
if( isCertificate )
{
status = setSerialNumber( certInfoPtr, NULL, 0 );
if( cryptStatusError( status ) )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* Determine the hash algorithm to use and if it's a certificate or
CRL remember it for when we write the certificate (the value is
embedded in the certificate to prevent an obscure attack on unpadded
RSA signature algorithms) */
krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,
&hashAlgo, CRYPT_OPTION_ENCR_HASH );
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \
certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
certInfoPtr->cCertCert->hashAlgo = hashAlgo;
else
{
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
certInfoPtr->cCertRev->hashAlgo = hashAlgo;
}
/* Select the function to use to write the certificate object to be
signed */
writeCertFunction = getCertWriteFunction( certInfoPtr->type );
if( writeCertFunction == NULL )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
retIntError();
}
/* Determine how big the encoded certificate information will be,
allocate memory for it and the full signed certificate, and write the
encoded certificate information */
sMemNullOpen( &stream );
status = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr,
iSignContext );
certObjectLength = stell( &stream );
sMemClose( &stream );
if( cryptStatusError( status ) )
{
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
signedCertAllocSize = certObjectLength + 1024 + extraDataLength;
if( ( certObjectLength > 1024 && \
( certObjectPtr = clDynAlloc( "signCert", \
certObjectLength ) ) == NULL ) || \
( signedCertObject = clAlloc( "signCert", \
signedCertAllocSize ) ) == NULL )
{
if( certObjectPtr != NULL && certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( CRYPT_ERROR_MEMORY );
}
sMemOpen( &stream, certObjectPtr, certObjectLength );
status = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr,
iSignContext );
ENSURES( cryptStatusError( status ) || \
certObjectLength == stell( &stream ) );
sMemDisconnect( &stream );
if( issuerCertAcquired )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
if( cryptStatusError( status ) )
{
zeroise( certObjectPtr, certObjectLength );
if( certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
clFree( "signCert", signedCertObject );
return( status );
}
ENSURES( !cryptStatusError( checkObjectEncoding( certObjectPtr, \
certObjectLength ) ) );
/* If there's no signing key present pseudo-sign the certificate
information by writing the outer wrapper and moving the object into
the initialised state */
if( nonSigningKey )
{
status = pseudoSignCertificate( certInfoPtr, signedCertObject,
signedCertAllocSize, certObjectPtr,
certObjectLength );
zeroise( certObjectPtr, certObjectLength );
if( certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
ENSURES( !cryptStatusError( \
checkObjectEncoding( certInfoPtr->certificate, \
certInfoPtr->certificateSize ) ) );
return( status );
}
/* Sign the certificate information. CRMF and OCSP use a b0rken
signature format (the authors couldn't quite manage a cut & paste of
two lines of text) so if it's one of these we have to use nonstandard
formatting */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
{
X509SIG_FORMATINFO formatInfo;
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
/* [1] SEQUENCE */
setX509FormatInfo( &formatInfo, 1, FALSE );
}
else
{
/* [0] EXPLICIT SEQUENCE */
setX509FormatInfo( &formatInfo, 0, TRUE );
}
if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
{
formatInfo.extraLength = ( int ) \
sizeofObject( sizeofObject( extraDataLength ) );
}
else
{
if( signatureLevel == CRYPT_SIGNATURELEVEL_ALL )
{
formatInfo.extraLength = ( int ) \
sizeofObject( extraDataLength );
}
}
status = createX509signature( signedCertObject,
signedCertAllocSize, &signedCertObjectLength,
certObjectPtr, certObjectLength, iSignContext,
hashAlgo, &formatInfo );
}
else
{
/* It's a standard signature */
status = createX509signature( signedCertObject,
signedCertAllocSize, &signedCertObjectLength,
certObjectPtr, certObjectLength, iSignContext,
hashAlgo, NULL );
}
zeroise( certObjectPtr, certObjectLength );
if( certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
if( cryptStatusError( status ) )
{
return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ARGERROR_VALUE : status );
}
certInfoPtr->certificate = signedCertObject;
certInfoPtr->certificateSize = signedCertObjectLength;
/* If we need to include extra data with the signature attach it to the
end of the signature */
if( extraDataLength > 0 )
{
const int extraDataType = \
( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \
CRYPT_CERTFORMAT_CERTIFICATE : CRYPT_ICERTFORMAT_CERTSEQUENCE;
sMemOpen( &stream, ( BYTE * ) signedCertObject + signedCertObjectLength,
signedCertAllocSize - signedCertObjectLength );
if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
{
writeConstructed( &stream, sizeofObject( extraDataLength ), 0 );
writeSequence( &stream, extraDataLength );
}
else
{
ENSURES( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );
writeConstructed( &stream, extraDataLength, 0 );
}
status = exportCertToStream( &stream, issuerCertInfoPtr->objectHandle,
extraDataType );
certInfoPtr->certificateSize = signedCertObjectLength + \
stell( &stream );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
zeroise( certInfoPtr->certificate, signedCertAllocSize );
clFree( "signCert", certInfoPtr->certificate );
certInfoPtr->certificate = NULL;
certInfoPtr->certificateSize = 0;
return( status );
}
}
ENSURES( !cryptStatusError( \
checkObjectEncoding( certInfoPtr->certificate, \
certInfoPtr->certificateSize ) ) );
/* If it's a certification request it's now self-signed. In addition
the signature has been checked since we've just created it */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
#if 0 /* 15/6/04 Only the root should be marked as self-signed, having
supposedly self-signed certificates inside the chain
causes problems when trying to detect pathkludge
certificates */
/* If it's a certificate chain and the root is self-signed then the
entire chain counts as self-signed */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
{
int selfSigned;
status = krnlSendMessage( \
certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainEnd - 1 ],
IMESSAGE_GETATTRIBUTE, &selfSigned,
CRYPT_CERTINFO_SELFSIGNED );
if( cryptStatusOK( status ) && selfSigned )
certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
}
#endif /* 0 */
/* If it's not an object type with special-case post-signing
requirements we're done */
if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \
certInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
return( CRYPT_OK );
/* Recover information such as pointers to encoded certificate data */
return( recoverCertData( certInfoPtr, certInfoPtr->type,
signedCertObject, signedCertObjectLength ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -