📄 certsign.c
字号:
CRYPT_KEYUSAGE_CRLSIGN,
complianceLevel, &certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) && \
certInfoPtr->errorType == CRYPT_ERRTYPE_CONSTRAINT )
/* If there was a constraint problem, it's something in
the issuer's cert rather than the cert being signed
so we have to change the error type accordingly.
What's reported isn't strictly accurate since the
locus is in the issuer rather than subject cert, but
it's the best we can do */
certInfoPtr->errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
}
if( cryptStatusError( status ) )
{
if( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* 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 cert
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 )
{
assert( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );
if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
status = exportCert( NULL, &extraDataLength,
CRYPT_CERTFORMAT_CERTIFICATE,
issuerCertInfoPtr, CRYPT_UNUSED );
else
{
RESOURCE_DATA msgData;
assert( 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( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* If it's a certificate chain, copy over the signing cert(s) */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
{
/* If there's a chain of certs present (for example from a previous
signing attempt that wasn't completed due to an error), free
them */
if( certInfoPtr->cCertCert->chainEnd )
{
for( i = 0; i < certInfoPtr->cCertCert->chainEnd; i++ )
krnlSendNotifier( certInfoPtr->cCertCert->chain[ i ],
IMESSAGE_DECREFCOUNT );
certInfoPtr->cCertCert->chainEnd = 0;
}
/* If it's a self-signed cert, it must be the only cert in the chain
(creating a chain like this doesn't make much sense, but we handle
it anyway) */
if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
{
if( certInfoPtr->cCertCert->chainEnd )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
status = CRYPT_ERROR_INVALID;
}
}
else
/* Copy the cert chain into the cert to be signed */
status = copyCertChain( certInfoPtr, signContext, FALSE );
if( cryptStatusError( status ) )
{
if( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* If it's some certificate variant or CRL/OCSP response and the various
timestamps haven't been set yet, start them at the current time and
give them the default validity period or next update time if these
haven't been set. The time used is the local time, this is converted
to GMT when we write it to the certificate. Issues like validity
period nesting and checking for valid time periods are handled
elsewhere */
if( ( isCertificate || certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE ) && \
certInfoPtr->startTime <= 0 )
{
/* If the time is screwed up we can't provide a signed indication
of the time */
if( currentTime < MIN_TIME_VALUE )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_NOTINITED );
}
certInfoPtr->startTime = currentTime;
}
if( isCertificate && certInfoPtr->endTime <= 0 )
{
int validity;
krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,
&validity, CRYPT_OPTION_CERT_VALIDITY );
certInfoPtr->endTime = certInfoPtr->startTime + \
( ( time_t ) validity * 86400L );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
{
if( certInfoPtr->endTime <= 0 )
{
if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
/* OCSP responses come directly from the certificate store
and represent an atomic (and ephemeral) snapshot of the
store state. Because of this the next-update time is
effectively immediately, since the next snapshot could
provide a different response */
certInfoPtr->endTime = currentTime;
else
{
int updateInterval;
krnlSendMessage( certInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &updateInterval,
CRYPT_OPTION_CERT_UPDATEINTERVAL );
certInfoPtr->endTime = certInfoPtr->startTime + \
( ( time_t ) updateInterval * 86400L );
}
}
if( certInfoPtr->cCertRev->revocationTime <= 0 )
certInfoPtr->cCertRev->revocationTime = currentTime;
}
/* If it's a certificate, set up the certificate serial number */
if( isCertificate )
{
status = setSerialNumber( certInfoPtr, NULL, 0 );
if( cryptStatusError( status ) )
{
if( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( status );
}
}
/* Determine the hash algorithm to use and, if it's a cert or CRL,
remember it for when we write the cert (the value is embedded in
the cert 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 */
for( i = 0; certWriteTable[ i ].type != certInfoPtr->type && \
certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
{
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
writeCertObjectFunction = certWriteTable[ i ].writeFunction;
/* Determine how big the encoded certificate information will be,
allocate memory for it and the full signed certificate, and write the
encoded certificate information */
sMemOpen( &stream, NULL, 0 );
status = writeCertObjectFunction( &stream, certInfoPtr, issuerCertInfoPtr,
signContext );
certObjectLength = stell( &stream );
sMemClose( &stream );
if( cryptStatusError( status ) )
{
if( issuerCertPresent )
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 )
clFree( "signCert", certObjectPtr );
if( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
return( CRYPT_ERROR_MEMORY );
}
sMemOpen( &stream, certObjectPtr, certObjectLength );
status = writeCertObjectFunction( &stream, certInfoPtr, issuerCertInfoPtr,
signContext );
assert( certObjectLength == stream.bufPos );
sMemDisconnect( &stream );
if( issuerCertPresent )
krnlReleaseObject( issuerCertInfoPtr->objectHandle );
if( cryptStatusError( status ) )
{
zeroise( certObjectPtr, certObjectLength );
if( certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
clFree( "signCert", signedCertObject );
return( status );
}
/* 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,
certObjectPtr, certObjectLength );
zeroise( certObjectPtr, certObjectLength );
if( certObjectPtr != certObjectBuffer )
clFree( "signCert", certObjectPtr );
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 )
{
const int extraDataEncodedLength = \
( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \
( int ) sizeofObject( sizeofObject( extraDataLength ) ) : \
( signatureLevel == CRYPT_SIGNATURELEVEL_ALL ) ? \
( int ) sizeofObject( extraDataLength ) : 0;
const int formatInfo = \
( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT ) ? \
1 : ( 0 | 0x80 );
status = createX509signature( signedCertObject,
&signedCertObjectLength, signedCertAllocSize,
certObjectPtr, certObjectLength, signContext,
hashAlgo, formatInfo, extraDataEncodedLength );
}
else
/* It's a standard signature */
status = createX509signature( signedCertObject,
&signedCertObjectLength, signedCertAllocSize,
certObjectPtr, certObjectLength, signContext,
hashAlgo, CRYPT_UNUSED, 0 );
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 sig */
if( extraDataLength > 0 )
{
sMemOpen( &stream, ( BYTE * ) signedCertObject + signedCertObjectLength,
signedCertAllocSize - signedCertObjectLength );
if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
{
writeConstructed( &stream, sizeofObject( extraDataLength ), 0 );
writeSequence( &stream, extraDataLength );
assert( sStatusOK( &stream ) && \
sMemDataLeft( &stream ) >= extraDataLength );
status = exportCert( sMemBufPtr( &stream ), &extraDataLength,
CRYPT_CERTFORMAT_CERTIFICATE,
issuerCertInfoPtr, sMemDataLeft( &stream ) );
}
else
{
writeConstructed( &stream, extraDataLength, 0 );
assert( sStatusOK( &stream ) && \
sMemDataLeft( &stream ) >= extraDataLength );
status = exportCertToStream( &stream,
issuerCertInfoPtr->objectHandle,
CRYPT_ICERTFORMAT_CERTSEQUENCE );
}
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 );
}
}
/* If it's a certification request, it's now self-signed. In addition
the signature has been checked, since we 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 certs inside the chain causes
problems when trying to detect pathkludge certs */
/* If it's a cert chain and the root is self-signed, 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -