📄 comp_set.c
字号:
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->type == CRYPT_CERTTYPE_RTCS_REQUEST && \
certInfoPtr->cCertVal->responderUrl == NULL ) || \
( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST && \
certInfoPtr->cCertRev->responderUrl == NULL ) )
{
const CRYPT_ATTRIBUTE_TYPE aiaAttribute = \
( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
CRYPT_CERTINFO_AUTHORITYINFO_RTCS : \
CRYPT_CERTINFO_AUTHORITYINFO_OCSP;
SELECTION_STATE savedState;
void *responderUrl;
int urlSize = 0;
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( ( responderUrl = \
clAlloc( "copyUserCertInfo", urlSize ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
else
{
status = getCertComponent( userCertInfoPtr,
CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
responderUrl, &urlSize );
}
if( cryptStatusOK( status ) )
{
if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST )
{
certInfoPtr->cCertVal->responderUrl = responderUrl;
certInfoPtr->cCertVal->responderUrlSize = urlSize;
}
else
{
certInfoPtr->cCertRev->responderUrl = responderUrl;
certInfoPtr->cCertRev->responderUrlSize = urlSize;
}
}
}
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->cCertCert->serialNumber, \
userCertInfoPtr->cCertCert->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->cCertRev->revocations,
&certInfoPtr->cCertRev->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->cCertVal->validityInfo,
&certInfoPtr->cCertVal->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->cCertVal->validityInfo,
rtcsRequestInfoPtr->cCertVal->validityInfo );
if( cryptStatusOK( status ) )
status = copyOCSPRequestAttributes( &certInfoPtr->attributes,
rtcsRequestInfoPtr->attributes );
return( status );
}
static int copyOcspReqInfo( CERT_INFO *certInfoPtr,
CERT_INFO *ocspRequestInfoPtr )
{
int status;
/* Copy the revocation information and extensions */
status = copyRevocationEntries( &certInfoPtr->cCertRev->revocations,
ocspRequestInfoPtr->cCertRev->revocations );
if( cryptStatusOK( status ) )
status = copyOCSPRequestAttributes( &certInfoPtr->attributes,
ocspRequestInfoPtr->attributes );
if( cryptStatusError( status ) )
return( status );
return( CRYPT_OK );
}
/* Set or modify data in a cert request based on the PKI user info */
static int copyPkiUserAttributes( CERT_INFO *certInfoPtr,
ATTRIBUTE_LIST *pkiUserAttributes )
{
ATTRIBUTE_LIST *attributeListPtr;
int status;
/* There's one rather ugly special-case situation that we have to handle
which is when the user has submitted a PnP PKI request for a generic
signing cert but their PKI user info indicates that they're intended
to be a CA user. The processing flow for this is as follows:
CMP: readRequestBody()
Read request into state=high cert request object;
Add PKI user info to request;
ca_issue: caIssuerCert()
Add request to newly-created cert object;
Sign cert;
When augmenting the request with the PKI user info, the incoming
request will contain a keyUsage of digitalSignature while the PKI
user info will contain a keyUsage of keyCertSign and/or crlSign. We
can't fix this up at the CMP level because the request is in the high
state and no changes to the attributes can be made (the PKI user info
is a special case that can added to an object in the high state but
which modifies attributes in it as if it were still in the low state).
To avoid the attribute conflict, if we find this situation in the
request/pkiUser combination we delete the keyUsage in the request to
allow it to be replaced by the pkiUser attributes. Hardcoding in
this special case isn't very elegant, but it's the only way to make
the PnP PKI issue work without requiring that the user explicitly
specify that they want to be a CA, which makes it rather non-PnP */
attributeListPtr = findAttributeField( certInfoPtr->attributes,
CRYPT_CERTINFO_KEYUSAGE,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && \
attributeListPtr->intValue == CRYPT_KEYUSAGE_DIGITALSIGNATURE )
{
const ATTRIBUTE_LIST *pkiAttributeListPtr = \
findAttributeField( pkiUserAttributes, CRYPT_CERTINFO_KEYUSAGE,
CRYPT_ATTRIBUTE_NONE );
if( pkiAttributeListPtr != NULL && \
( pkiAttributeListPtr->intValue & ( CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN ) ) )
{
/* The cert contains a digitalSignature keyUsage and the PKI user
info contains a CA usage, delete the digitalSignature usage to
make way for the CA usage */
deleteAttribute( &certInfoPtr->attributes,
&certInfoPtr->attributeCursor, attributeListPtr,
certInfoPtr->currentSelection.dnPtr );
}
}
/* Copy the attributes from the PKI user info into the cert */
status = copyAttributes( &certInfoPtr->attributes, pkiUserAttributes,
&certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
/* The PKI user info contains an sKID that's used to uniquely identify
the user, this applies to the user info itself rather than the cert
that'll be issued from it. Since this will have been copied over
alongside the other attributes, we need to explicitly delete it
before we continue */
attributeListPtr = findAttributeField( certInfoPtr->attributes,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
{
deleteAttribute( &certInfoPtr->attributes,
&certInfoPtr->attributeCursor, attributeListPtr,
certInfoPtr->currentSelection.dnPtr );
}
return( CRYPT_OK );
}
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;
/* Copy any additional attributes across */
return( copyPkiUserAttributes( certInfoPtr,
pkiUserInfoPtr->attributes ) );
}
/* If there's no PKI user DN with the potential to conflict with the one
in the request present, copy any additional attributes across and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -