static int adjustPkiUserAttributes( INOUT CERT_INFO *certInfoPtr ) { int status; assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) ); /* The SCEP protocol requires that the SCEP challenge password be placed in the PKCS #10 request instead of being included in the SCEP metadata. This shouldn't have been copied across to the certificate request since the NOCOPY flag was set for the attribute, but to make absolutely certain we try and delete it anyway. Since this could in theory be present in non-SCEP requests as well (the request- processing code just knows about PKCS #10 requests as a whole, not requests from a SCEP source vs. requests not from a SCEP source), we make the delete unconditional */ if( findAttributeField( certInfoPtr->attributes, CRYPT_CERTINFO_CHALLENGEPASSWORD, CRYPT_ATTRIBUTE_NONE ) != NULL ) { status = deleteCompleteAttribute( &certInfoPtr->attributes, &certInfoPtr->attributeCursor, CRYPT_CERTINFO_CHALLENGEPASSWORD, certInfoPtr->currentSelection.dnPtr ); if( cryptStatusError( status ) ) return( status ); } /* The PKI user information contains an sKID that's used to uniquely identify the user, this applies to the user information itself rather than the certificate 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 */ if( findAttributeField( certInfoPtr->attributes, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, CRYPT_ATTRIBUTE_NONE ) != NULL ) { status = deleteCompleteAttribute( &certInfoPtr->attributes, &certInfoPtr->attributeCursor, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, certInfoPtr->currentSelection.dnPtr ); if( cryptStatusError( status ) ) return( status ); } return( CRYPT_OK ); }
static BOOLEAN checkEmptyDnOK( INOUT CERT_INFO *subjectCertInfoPtr ) { ATTRIBUTE_PTR *attributePtr; int value, complianceLevel, status; assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) ); /* PKIX allows empty subject DNs if a subject altName is present, however creating certificates like this breaks every certificate- using protocol supported by cryptlib so we only allow it at the highest compliance level */ if( cryptStatusError( \ krnlSendMessage( subjectCertInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE, &complianceLevel, CRYPT_OPTION_CERT_COMPLIANCELEVEL ) ) || \ complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL ) { /* We only allow this behaviour at the highest compliance level */ return( FALSE ); } /* We also have to be very careful to ensure that the empty subject DN can't end up becoming an empty issuer DN, which can occur if it's a self-signed certificate */ if( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) { /* We can't have an empty issuer (== subject) DN */ return( FALSE ); } /* In addition if it's a CA certificate then the subject DN can't be empty, for obvious reasons */ status = getAttributeFieldValue( subjectCertInfoPtr->attributes, CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE, &value ); if( cryptStatusOK( status ) && value > 0 ) { /* It's a CA certificate, the subject DN can't be empty */ return( FALSE ); } /* Finally, if there's no subject DN present then there has to be an altName present to take its place */ attributePtr = findAttributeField( subjectCertInfoPtr->attributes, CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_ATTRIBUTE_NONE ); if( attributePtr == NULL ) { /* Either a subject DN or subject altName must be present */ return( FALSE ); } /* There's a subject altName present but no subject DN, mark the altName as critical */ setAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL, 0 ); return( TRUE ); }
static int moveCursorToField( INOUT CERT_INFO *certInfoPtr, IN_ATTRIBUTE \ const CRYPT_ATTRIBUTE_TYPE certInfoType ) { const ATTRIBUTE_PTR *attributePtr; assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) ); REQUIRES( sanityCheckSelectionInfo( certInfoPtr ) ); REQUIRES( certInfoType >= CRYPT_CERTINFO_FIRST_EXTENSION && \ certInfoType <= CRYPT_CERTINFO_LAST ); /* Try and locate the given field in the extension */ attributePtr = findAttributeField( certInfoPtr->attributes, certInfoType, CRYPT_ATTRIBUTE_NONE ); if( attributePtr == NULL ) return( CRYPT_ERROR_NOTFOUND ); /* We've found the given field, update the cursor and select the DN within it if it's present */ certInfoPtr->currentSelection.updateCursor = FALSE; certInfoPtr->attributeCursor = ( ATTRIBUTE_PTR * ) attributePtr; if( isGeneralNameSelectionComponent( certInfoType ) ) { /* If this is a GeneralName, select the DN within it if there's one present. Since this is peripheral to the main operation of moving the cursor we ignore the return status */ ( void ) findDnInGeneralName( certInfoPtr, FALSE ); /* We've selected the GeneralName (possibly as a side-effect of its on-demand creation), clear the saved GeneralName-to-be-created value */ certInfoPtr->currentSelection.generalName = CRYPT_ATTRIBUTE_NONE; } ENSURES( sanityCheckSelectionInfo( certInfoPtr ) ); return( CRYPT_OK ); }