📄 certcset.c
字号:
deleteDN( &certInfoPtr->subjectName );
}
if( cryptStatusError( status ) )
return( status );
/* If it's a CRMF request there could also be a validity period
specified */
if( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
const time_t currentTime = getApproxTime();
/* We don't allow start times backdated by more than a year, or end
times before the start time. Since these are trivial things, we
don't abort if there's a problem but just quietly fix the value */
if( certRequestInfoPtr->startTime > 0 && \
certRequestInfoPtr->startTime > currentTime - ( 86400 * 365 ) )
certInfoPtr->startTime = certRequestInfoPtr->startTime;
if( certRequestInfoPtr->endTime > 0 && \
certRequestInfoPtr->endTime > certInfoPtr->startTime )
certInfoPtr->endTime = certRequestInfoPtr->endTime;
}
return( CRYPT_OK );
}
/* Copy what we need to identify the cert to be revoked and any revocation
information into a certificate object */
static int copyRevReqInfo( CERT_INFO *certInfoPtr,
CERT_INFO *revRequestInfoPtr )
{
int status;
status = copyRevocationInfo( certInfoPtr, revRequestInfoPtr );
if( cryptStatusError( status ) || \
revRequestInfoPtr->attributes == NULL )
return( status );
return( copyRevocationAttributes( &certInfoPtr->attributes,
revRequestInfoPtr->attributes,
&certInfoPtr->errorLocus,
&certInfoPtr->errorType ) );
}
/* Copy user certificate info into a certificate object */
static int copyUserCertInfo( CERT_INFO *certInfoPtr,
CERT_INFO *userCertInfoPtr,
const CRYPT_HANDLE iCryptHandle )
{
STREAM stream;
BYTE certHash[ CRYPT_MAX_HASHSIZE ];
int certHashLength = CRYPT_MAX_HASHSIZE, status;
assert( userCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
userCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
assert( userCertInfoPtr->certificate != NULL );
/* If it's a CRL, copy the revocation information across */
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
return( copyRevocationInfo( certInfoPtr, userCertInfoPtr ) );
/* If it's a CRMF cert request, copy the public key and DN. We copy the
full DN rather than just the encoded form in case the user wants to
query the request details after creating it */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
status = copyDN( &certInfoPtr->subjectName,
userCertInfoPtr->subjectName );
if( cryptStatusError( status ) )
return( status );
if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
certInfoPtr->publicKeyInfo != NULL )
/* If a key has already been added as
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, there's nothing further
to do. Checking for this (rather than returning an error)
allows the DN information from an existing cert to be copied
into a request for a new key */
return( CRYPT_OK );
status = copyPublicKeyInfo( certInfoPtr, iCryptHandle, NULL );
if( cryptStatusError( status ) )
deleteDN( &certInfoPtr->subjectName );
return( status );
}
/* If it's a CRMF revocation request, copy across the issuer and serial
number */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
/* If the info is already present we can't add it again */
if( certInfoPtr->issuerName != NULL )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Copy across the issuer name and allocate any further storage that
we need. We don't care about any internal structure of the issuer
DN so we just copy the pre-encoded form, we could in theory copy
the full DN but it isn't really the issuer (creator) of the object
so it's better if it appears to have no issuer DN than a
misleading one */
status = copyIssuerDnData( certInfoPtr, userCertInfoPtr );
if( cryptStatusError( status ) )
return( status );
status = setSerialNumber( certInfoPtr, userCertInfoPtr->serialNumber,
userCertInfoPtr->serialNumberLength );
if( cryptStatusOK( status ) && \
certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION && \
( certInfoPtr->subjectDNdata = \
clAlloc( "copyUserCertInfo",
userCertInfoPtr->subjectDNsize ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
if( cryptStatusError( status ) )
{
clFree( "copyUserCertInfo", certInfoPtr->issuerDNdata );
certInfoPtr->issuerDNptr = certInfoPtr->issuerDNdata = NULL;
certInfoPtr->issuerDNsize = 0;
if( certInfoPtr->serialNumber != NULL && \
certInfoPtr->serialNumber != certInfoPtr->serialNumberBuffer )
clFree( "copyUserCertInfo", certInfoPtr->serialNumber );
certInfoPtr->serialNumber = NULL;
return( status );
}
/* If it's a CRMF revocation request, copy the subject DN for use in
CMP */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
memcpy( certInfoPtr->subjectDNdata, userCertInfoPtr->subjectDNptr,
userCertInfoPtr->subjectDNsize );
certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
certInfoPtr->subjectDNsize = userCertInfoPtr->subjectDNsize;
}
return( CRYPT_OK );
}
/* It's an RTCS or OCSP request, remember the responder URL if there's
one present (we can't leave it to be read out of the cert because
authorityInfoAccess isn't a valid attribute for RTCS/OCSP requests)
and copy the cert information to the validity/revocation list */
assert( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );
/* If there's no responder URL set, check whether the user cert contains
a responder URL in the RTCS/OCSP authorityInfoAccess GeneralName */
if( certInfoPtr->responderUrl == NULL )
{
const CRYPT_ATTRIBUTE_TYPE aiaAttribute = \
( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
CRYPT_CERTINFO_AUTHORITYINFO_RTCS : \
CRYPT_CERTINFO_AUTHORITYINFO_OCSP;
SELECTION_STATE savedState;
int urlSize;
saveSelectionState( savedState, userCertInfoPtr );
status = selectGeneralName( userCertInfoPtr, aiaAttribute,
MAY_BE_ABSENT );
if( cryptStatusOK( status ) )
status = selectGeneralName( userCertInfoPtr,
CRYPT_ATTRIBUTE_NONE,
MUST_BE_PRESENT );
if( cryptStatusOK( status ) )
status = getCertComponent( userCertInfoPtr,
CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
NULL, &urlSize );
if( cryptStatusOK( status ) )
{
/* There's a responder URL present, copy it to the request */
if( ( certInfoPtr->responderUrl = \
clAlloc( "copyUserCertInfo", urlSize ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
else
getCertComponent( userCertInfoPtr,
CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
certInfoPtr->responderUrl,
&certInfoPtr->responderUrlSize );
}
else
/* If there's no responder URL present it's not a (fatal)
error */
status = CRYPT_OK;
restoreSelectionState( savedState, userCertInfoPtr );
if( cryptStatusError( status ) )
return( status );
}
/* If we're using OCSP, make sure that the CA cert hash (needed for the
weird cert ID) is present. We add the necessary information as a
pre-encoded blob since we can't do much with the ID fields */
if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
{
BYTE idBuffer[ 256 ], *idBufPtr = idBuffer;
const int idLength = ( int ) \
sizeofObject( \
sizeofAlgoID( CRYPT_ALGO_SHA ) + \
sizeofObject( 20 ) + sizeofObject( 20 ) + \
sizeofInteger( userCertInfoPtr->serialNumber, \
userCertInfoPtr->serialNumberLength ) );
/* Make sure there's a CA cert hash present */
if( !certInfoPtr->certHashSet )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Generate the OCSPv1 cert ID */
if( idLength > 256 && \
( idBufPtr = clDynAlloc( "copyUserCertInfo", \
idLength ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
sMemOpen( &stream, idBufPtr, idLength );
status = writeOCSPv1ID( &stream, userCertInfoPtr,
certInfoPtr->certHash );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) )
status = addRevocationEntry( &certInfoPtr->revocations,
&certInfoPtr->currentRevocation,
CRYPT_KEYID_NONE, idBufPtr,
idLength, FALSE );
if( idBufPtr != idBuffer )
clFree( "copyUserCertInfo", idBufPtr );
/* Add the cert information again as an ESSCertID extension to work
around the problems inherent in OCSPv1 IDs. This isn't currently
used because non-cryptlib v1 responders won't understand it and
cryptlib uses RTCS that doesn't have the OCSP problems */
if( status == CRYPT_ERROR_DUPLICATE )
/* If this cert is already present in the list, set the extended
error code for it */
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( status );
}
/* It's an RTCS request, add the cert hash. We read the cert hash
indirectly since it's computed on demand and may not have been
evaluated yet */
status = getCertComponent( userCertInfoPtr,
CRYPT_CERTINFO_FINGERPRINT_SHA, certHash,
&certHashLength );
if( cryptStatusOK( status ) )
status = addValidityEntry( &certInfoPtr->validityInfo,
&certInfoPtr->currentValidity, certHash,
certHashLength );
if( status == CRYPT_ERROR_DUPLICATE )
/* If this cert is already present in the list, set the extended
error code for it */
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( status );
}
/* Get the hash of the public key (for an OCSPv1 request), possibly
overwriting a previous hash if there are multiple entries in the
request */
static int copyCaCertInfo( CERT_INFO *certInfoPtr,
CERT_INFO *caCertInfoPtr )
{
HASHFUNCTION hashFunction;
STREAM stream;
int length, status;
assert( caCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
caCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
assert( caCertInfoPtr->publicKeyInfo != NULL );
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );
/* Dig down into the encoded key data to find the weird bits of key that
OCSP requires us to hash. We store the result as the cert hash,
which is safe because it isn't used for an OCSP request so it can't
be accessed externally */
sMemConnect( &stream, caCertInfoPtr->publicKeyInfo,
caCertInfoPtr->publicKeyInfoSize );
readSequence( &stream, NULL ); /* Wrapper */
readUniversal( &stream ); /* AlgoID */
status = readBitStringHole( &stream, &length, DEFAULT_TAG );
if( cryptStatusError( status ) )/* BIT STRING wrapper */
{
/* There's a problem with the format of the key */
assert( NOTREACHED );
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_INVALID );
}
hashFunction( NULL, certInfoPtr->certHash, sMemBufPtr( &stream ),
length, HASH_ALL );
certInfoPtr->certHashSet = TRUE;
sMemDisconnect( &stream );
return( CRYPT_OK );
}
/* Copy revocation information from an RTCS or OCSP request to a response */
static int copyRtcsReqInfo( CERT_INFO *certInfoPtr,
CERT_INFO *rtcsRequestInfoPtr )
{
int status;
/* Copy the cert validity information and extensions */
status = copyValidityEntries( &certInfoPtr->validityInfo,
rtcsRequestInfoPtr->validityInfo,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
if( cryptStatusOK( status ) )
status = copyRequestAttributes( &certInfoPtr->attributes,
rtcsRequestInfoPtr->attributes,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
return( status );
}
static int copyOcspReqInfo( CERT_INFO *certInfoPtr,
CERT_INFO *ocspRequestInfoPtr )
{
int status;
/* Copy the revocation information and extensions */
status = copyRevocationEntries( &certInfoPtr->revocations,
ocspRequestInfoPtr->revocations,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
if( cryptStatusOK( status ) )
status = copyRequestAttributes( &certInfoPtr->attributes,
ocspRequestInfoPtr->attributes,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
/* Set the response type based on the format specifier in the request */
certInfoPtr->responseType = OCSPRESPONSE_TYPE_OCSP;
return( CRYPT_OK );
}
/* Set or modify data in a cert request based on the PKI user info */
static int copyPkiUserInfo( CERT_INFO *certInfoPtr,
CERT_INFO *pkiUserInfoPtr )
{
char commonName[ CRYPT_MAX_TEXTSIZE ];
int commonNameLength, status;
assert( pkiUserInfoPtr->type == CRYPT_CERTTYPE_PKIUSER );
assert( pkiUserInfoPtr->certificate != NULL );
/* If there's no DN present in the request, try and fill it in from the
CA-supplied PKI user info */
if( certInfoPtr->subjectName == NULL )
{
/* If neither the request nor the PKI user info has a DN present, we
can't continue */
if( pkiUserInfoPtr->subjectName == NULL )
return( CRYPT_ERROR_NOTINITED );
assert( pkiUserInfoPtr->subjectDNptr != NULL );
/* There's no DN present in the request, it's been supplied by the
CA in the PKI user info, copy over the DN and its encoded form
from the user info */
status = copyDN( &certInfoPtr->subjectName,
pkiUserInfoPtr->subjectName );
if( cryptStatusError( status ) )
return( status );
if( ( certInfoPtr->subjectDNdata = \
clAlloc( "copyPkiUserInfo",
pkiUserInfoPtr->subjectDNsize ) ) == NULL )
{
deleteDN( &certInfoPtr->subjectName );
return( CRYPT_ERROR_MEMORY );
}
memcpy( certInfoPtr->subjectDNdata, pkiUserInfoPtr->subjectDNptr,
pkiUserInfoPtr->subjectDNsize );
certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
certInfoPtr->subjectDNsize = pkiUserInfoPtr->subjectDNsize;
return( CRYPT_OK );
}
/* If there's no PKI user DN with the potential to conflict with the one
in the request present, we're done */
if( pkiUserInfoPtr->subjectName == NULL )
return( CRYPT_OK );
/* There's both a request DN and PKI user DN present. If the request
contains only a CN, combine it with the PKI user DN and update the
request */
status = getDNComponentValue( certInfoPtr->subjectName,
CRYPT_CERTINFO_COMMONNAME, commonName,
&commonNameLength, CRYPT_MAX_TEXTSIZE );
if( cryptStatusOK( status ) )
{
void *tempDN = NULL;
BOOLEAN isCommonNameDN;
/* Check whether the request DN contains only a CN. There's no easy
way to do this directly, the only way we can do it is by creating
a temporary DN consisting of only the CN and comparing it to the
request DN. We use sizeofDN() rather than compareDN() since it's
much faster than a full DN comparison, this is safe because we
know that both contain at least the same CN so any size mismatch
indicates a DN value mismatch */
status = insertDNComponent( &tempDN, CRYPT_CERTINFO_COMMONNAME,
commonName, commonNameLength,
&certInfoPtr->errorType );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -