📄 comp_set.c
字号:
}
/* Copy across the canonicalised serial number value */
if( length >= SERIALNO_BUFSIZE && \
( serialNumberPtr = clDynAlloc( "setSerialNumber", length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
certInfoPtr->cCertReq->serialNumber = serialNumberPtr;
certInfoPtr->cCertReq->serialNumberLength = length;
}
else
{
certInfoPtr->cCertCert->serialNumber = serialNumberPtr;
certInfoPtr->cCertCert->serialNumberLength = length;
}
memcpy( serialNumberPtr, buffer + bufPos, length );
return( CRYPT_OK );
}
/* Compare a serial number in canonical form to a generic serial number,
with special handling for leading-zero truncation. This one can get a
bit tricky because Microsoft fairly consistently encode the serial
numbers incorrectly, so we normalise the values to have no leading zero,
which is the lowest common denominator */
int compareSerialNumber( const void *canonSerialNumber,
const int canonSerialNumberLength,
const void *serialNumber,
const int serialNumberLength )
{
const BYTE *canonSerialNumberPtr = canonSerialNumber;
const BYTE *serialNumberPtr = serialNumber;
int canonSerialLength = canonSerialNumberLength;
int serialLength = serialNumberLength;
/* Internal serial numbers are canonicalised, so all we need to do is
strip a possible leading zero */
if( !canonSerialNumberPtr[ 0 ] )
{
canonSerialNumberPtr++;
canonSerialLength--;
}
assert( canonSerialLength == 0 || canonSerialNumberPtr[ 0 ] );
/* Serial numbers from external sources can be arbitarily strangely
encoded, so we strip leading zeroes until we get to actual data */
while( serialLength > 0 && !serialNumberPtr[ 0 ] )
{
serialNumberPtr++;
serialLength--;
}
/* Finally we've got them in a form where we can compare them */
if( canonSerialLength != serialLength || \
memcmp( canonSerialNumberPtr, serialNumberPtr, serialLength ) )
return( 1 );
return( 0 );
}
/****************************************************************************
* *
* Copy Cert Info *
* *
****************************************************************************/
/* Copy public key data into a certificate object */
static int copyPublicKeyInfo( CERT_INFO *certInfoPtr,
const CRYPT_HANDLE cryptHandle,
const CERT_INFO *srcCertInfoPtr )
{
void *publicKeyInfoPtr;
int length, status;
assert( ( isHandleRangeValid( cryptHandle ) && srcCertInfoPtr == NULL ) || \
( !isHandleRangeValid( cryptHandle ) && srcCertInfoPtr != NULL ) );
/* Make sure that we haven't already got a public key present */
if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
certInfoPtr->publicKeyInfo != NULL )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* If we've been given a data-only cert, copy over the public key data */
if( srcCertInfoPtr != NULL )
{
assert( srcCertInfoPtr->publicKeyAlgo > CRYPT_ALGO_NONE );
assert( memcmp( srcCertInfoPtr->publicKeyID,
"\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) );
assert( ( ( BYTE * ) srcCertInfoPtr->publicKeyInfo )[ 0 ] == 0x30 );
length = srcCertInfoPtr->publicKeyInfoSize;
if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo", length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memcpy( publicKeyInfoPtr, srcCertInfoPtr->publicKeyInfo, length );
certInfoPtr->publicKeyAlgo = srcCertInfoPtr->publicKeyAlgo;
certInfoPtr->publicKeyFeatures = srcCertInfoPtr->publicKeyFeatures;
memcpy( certInfoPtr->publicKeyID, srcCertInfoPtr->publicKeyID,
KEYID_SIZE );
}
else
{
CRYPT_CONTEXT iCryptContext;
RESOURCE_DATA msgData;
/* Get the context handle. All other checking has already been
performed by the kernel */
status = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT,
&iCryptContext, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
CRYPT_ERRTYPE_ATTR_VALUE );
return( status );
}
assert( cryptStatusOK( \
krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC ) ) );
/* Get the key information */
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&certInfoPtr->publicKeyAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&certInfoPtr->publicKeyFeatures,
CRYPT_IATTRIBUTE_KEYFEATURES );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, certInfoPtr->publicKeyID, KEYID_SIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
}
if( cryptStatusError( status ) )
return( status );
/* Copy over the public-key data. We copy the data rather than
keeping a reference to the context for two reasons. Firstly,
when the cert is transitioned into the high state it will
constrain the attached context, so a context shared between two
certs could be constrained in unexpected ways. Secondly, the
context could be a private-key context, and attaching that to a
cert would be rather inappropriate. Furthermore, the constraint
issue is even more problematic in that a context constrained by
an encryption-only request could then no longer be used to sign
the request or a PKI protocol message containing the request */
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusOK( status ) )
{
length = msgData.length;
if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo",
length ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
if( cryptStatusError( status ) )
return( status );
msgData.data = publicKeyInfoPtr;
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusError( status ) )
return( status );
}
certInfoPtr->publicKeyData = certInfoPtr->publicKeyInfo = \
publicKeyInfoPtr;
certInfoPtr->publicKeyInfoSize = length;
certInfoPtr->flags |= CERT_FLAG_DATAONLY;
return( CRYPT_OK );
}
/* Copy cert request info into a certificate object. This copies the public
key context, the DN, any valid attributes, and any other relevant bits and
pieces if it's a CRMF request */
static int copyCertReqInfo( CERT_INFO *certInfoPtr,
CERT_INFO *certRequestInfoPtr )
{
int status;
assert( certRequestInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );
/* Copy the public key context, the DN, and the attributes. Type
checking has already been performed by the kernel. We copy the
attributes across after the DN because that copy is the hardest to
undo: If there are already attributes present, the copied attributes
will be mixed in among them so it's not really possible to undo the
copy later without performing a complex selective delete */
status = copyDN( &certInfoPtr->subjectName,
certRequestInfoPtr->subjectName );
if( cryptStatusOK( status ) )
{
if( certRequestInfoPtr->flags & CERT_FLAG_DATAONLY )
status = copyPublicKeyInfo( certInfoPtr, CRYPT_UNUSED,
certRequestInfoPtr );
else
status = copyPublicKeyInfo( certInfoPtr,
certRequestInfoPtr->iPubkeyContext,
NULL );
}
if( cryptStatusOK( status ) && \
certRequestInfoPtr->attributes != NULL )
{
status = copyAttributes( &certInfoPtr->attributes,
certRequestInfoPtr->attributes,
&certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) )
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 ) );
}
/* 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->cCertCert->serialNumber,
userCertInfoPtr->cCertCert->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->cCertCert->serialNumber != NULL && \
certInfoPtr->cCertCert->serialNumber != \
certInfoPtr->cCertCert->serialNumberBuffer )
clFree( "copyUserCertInfo",
certInfoPtr->cCertCert->serialNumber );
certInfoPtr->cCertCert->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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -