/*----------------------------------------------------------------------- * File: MAF_VALIDATE.C * * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. *----------------------------------------------------------------------- */ #include "maf_include.h" static CSSM_KEYBLOB_FORMAT ValidKeyFormats[] = { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS1, CSSM_KEYBLOB_RAW_FORMAT_PKCS3, CSSM_KEYBLOB_RAW_FORMAT_MSCAPI, CSSM_KEYBLOB_RAW_FORMAT_PGP, CSSM_KEYBLOB_RAW_FORMAT_FIPS186, CSSM_KEYBLOB_RAW_FORMAT_BSAFE, CSSM_KEYBLOB_RAW_FORMAT_CCA, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, CSSM_KEYBLOB_RAW_FORMAT_SPKI, CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, CSSM_KEYBLOB_RAW_FORMAT_OTHER, CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8, CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7, CSSM_KEYBLOB_WRAPPED_FORMAT_MSCAPI, CSSM_KEYBLOB_WRAPPED_FORMAT_OTHER, CSSM_KEYBLOB_REF_FORMAT_INTEGER, CSSM_KEYBLOB_REF_FORMAT_STRING, CSSM_KEYBLOB_REF_FORMAT_SPKI, CSSM_KEYBLOB_REF_FORMAT_UNIQUE_ID, CSSM_KEYBLOB_REF_FORMAT_OTHER }; static const uint32 NumValidKeyFormats = sizeof(ValidKeyFormats) / sizeof(CSSM_KEYBLOB_FORMAT); CSSM_RETURN CSM_ValidateCryptoData( const CSSM_CRYPTO_DATA *pCryptoData, CSSM_BOOL bAllowEmpty, CSSM_BOOL bAllowNULL ) { /* Do a NULL check */ if ( ( bAllowNULL == CSSM_TRUE ) && ( pCryptoData == NULL ) ) { return CSSM_OK; } else if ( pCryptoData == NULL ) { return CSSMERR_CSP_INVALID_CRYPTO_DATA; } /* Do a sanity check on the Param value */ if ( ( ( pCryptoData->Param.Data == NULL ) && ( pCryptoData->Param.Length != 0 ) ) || ( ( pCryptoData->Param.Data != NULL ) && ( pCryptoData->Param.Length == 0 ) ) ) { return CSSMERR_CSP_INVALID_CRYPTO_DATA; } /* Do an empty check */ if ( ( bAllowEmpty == CSSM_TRUE ) && ( pCryptoData->Param.Data == NULL ) && ( pCryptoData->Param.Length == 0 ) && ( pCryptoData->Callback == NULL ) ) { return CSSM_OK; } else if ( ( pCryptoData->Param.Data == NULL ) && ( pCryptoData->Param.Length == 0 ) && ( pCryptoData->Callback == NULL ) ) { return CSSMERR_CSP_INVALID_CRYPTO_DATA; } /* Do a read check on the Param data */ if ( ( pCryptoData->Param.Data != NULL ) && ( port_IsBadReadPtr( pCryptoData->Param.Data, pCryptoData->Param.Length ) == CSSM_TRUE ) ) { return CSSMERR_CSP_INVALID_CRYPTO_DATA; } /* Is the callback pointer valid */ if ( ( pCryptoData->Callback != NULL ) && ( port_IsBadCodePtr( (CSSM_PROC_ADDR)pCryptoData->Callback ) == CSSM_TRUE ) ) { return CSSMERR_CSP_INVALID_CRYPTO_DATA; } return CSSM_OK; } CSSM_RETURN CSM_ValidateInputBuffers( const CSSM_DATA *pInBufs, uint32 uNumInBufs, CSSM_BOOL IsVector ) { uint32 i = 0; const CSSM_DATA *pDataBuf = pInBufs; /* Is the count correct? */ if ( uNumInBufs == 0) { return CSSMERR_CSP_INVALID_DATA_COUNT; } /* Are there actually buffers? */ if ( port_IsBadReadPtr( pInBufs, sizeof(CSSM_DATA) * uNumInBufs ) == CSSM_TRUE ) { return CSSMERR_CSP_INVALID_INPUT_POINTER; } /* Check each buffer for a "sane" state */ for ( i = 0; i < uNumInBufs; i++ ) { /* Check pointer agreement */ if ( ( pDataBuf->Length != 0 ) && ( pDataBuf->Data == NULL ) ) { if ( IsVector ) { return CSSMERR_CSP_INVALID_INPUT_VECTOR; } else { return CSSMERR_CSP_INVALID_DATA; } } /* Check that the buffers are readable */ if ( ( pDataBuf->Length > 0 ) && ( port_IsBadReadPtr( pDataBuf->Data, pDataBuf->Length ) == CSSM_TRUE ) ) { if ( IsVector ) { return CSSMERR_CSP_INVALID_INPUT_VECTOR; } else { return CSSMERR_CSP_INVALID_DATA; } } /* Move to the next buffer */ pDataBuf++; } return CSSM_OK; } CSSM_RETURN CSM_ValidateOutputBuffers( CSSM_DATA *pOutBufs, uint32 uNumOutBufs, CSSM_BOOL IsVector ) { uint32 i = 0; const CSSM_DATA *pDataBuf = pOutBufs; /* Is the count correct? */ if ( uNumOutBufs == 0 ) { return CSSMERR_CSP_INVALID_DATA_COUNT; } /* Are there actually buffers? */ if ( port_IsBadWritePtr( pOutBufs, sizeof(CSSM_DATA) * uNumOutBufs ) == CSSM_TRUE ) { return CSSMERR_CSP_INVALID_OUTPUT_POINTER; } /* Check each buffer for a "sane" state */ for ( i = 0; i < uNumOutBufs; i++) { /* Check pointer agreement */ if ( ( ( pDataBuf->Length == 0 ) && ( pDataBuf->Data != NULL ) ) || ( ( pDataBuf->Length != 0 ) && ( pDataBuf->Data == NULL ) ) ) { if ( IsVector ) { return CSSMERR_CSP_INVALID_OUTPUT_VECTOR; } else { return CSSMERR_CSP_INVALID_DATA; } } /* Check that the buffers are writeable */ if ( ( pDataBuf->Length > 0 ) && ( port_IsBadWritePtr( pDataBuf->Data, pDataBuf->Length ) == CSSM_TRUE ) ) { if ( IsVector ) { return CSSMERR_CSP_INVALID_OUTPUT_VECTOR; } else { return CSSMERR_CSP_INVALID_DATA; } } /* Move to the next buffer */ pDataBuf++; } return CSSM_OK; } /*--------------------------------------------------------------- *Name: TAL_ValidateInKeyParam * *Description: * This function verifies the input key parameter. The following are the rules. * * pKey->KeyData. pKey->KeyData. * KeyBlobLength KeyBlob * ---------------------------------------------------------------------- * 0 NULL Allocate return buf and set size * 0 NOT NULL Error case * >0 NULL Error case * >0 NOT NULL Pass out buf to crypto function * *Parameters: * pKey(input) - key parameter * *Returns: * CSSM_OK - call is successful * CSSM_FAIL - call failed *-------------------------------------------------------------*/ CSSM_RETURN CSM_ValidateInputKey( const CSSM_KEY *pKey ) { if ( pKey == NULL ) { return CSSMERR_CSP_INVALID_KEY_POINTER; } if ( ( pKey->KeyData.Length == 0 ) || ( port_IsBadReadPtr( pKey->KeyData.Data, pKey->KeyData.Length ) == CSSM_TRUE ) ) { return CSSMERR_CSP_INVALID_KEY; } return CSSM_OK; } CSSM_RETURN CSM_ValidateInputKeyFormat(const CSSM_KEY *pKey) { uint32 i; if (pKey == NULL) { return (CSSMERR_CSP_INVALID_KEY_POINTER); } for (i = 0; i < NumValidKeyFormats; i++) { if (pKey->KeyHeader.Format == ValidKeyFormats[i]) { break; } } if (i == NumValidKeyFormats) { return (CSSMERR_CSP_INVALID_KEY_FORMAT); } return (CSSM_OK); } /*--------------------------------------------------------------- *Name: TAL_ValidateOutKeyParam * *Description: * This function verifies the output key parameter. The following are the rules. * * pKey->KeyData. pKey->KeyData. * KeyBlobLength KeyBlob * ---------------------------------------------------------------------- * 0 NULL Allocate return buf and set size * 0 NOT NULL Error case * >0 NULL Error case * >0 NOT NULL Pass out buf to crypto function * *Parameters: * pKey(input) - key parameter * *Returns: * CSSM_OK - call is successful * CSSM_FAIL - call failed *-------------------------------------------------------------*/ CSSM_RETURN CSM_ValidateOutputKey( const CSSM_KEY *pKey ) { if ( pKey == NULL ) { return CSSMERR_CSP_INVALID_KEY_POINTER; } if ( ( ( pKey->KeyData.Length == 0 ) && ( pKey->KeyData.Data != NULL ) ) || ( ( pKey->KeyData.Length != 0 ) && ( pKey->KeyData.Data == NULL ) ) ) { return CSSMERR_CSP_INVALID_KEY; } if ( ( pKey->KeyData.Length != 0 ) && ( port_IsBadWritePtr( pKey->KeyData.Data, pKey->KeyData.Length ) == CSSM_TRUE ) ) { return CSSMERR_CSP_INVALID_KEY; } return CSSM_OK; } /*--------------------------------------------------------------- *Name: TAL_ValidateKeyAttrReturn * *Description: * This function verifies the Key Attr passed in during Key Gen. It makes * sure that conflicting return types are not asked for. * *Parameters: * KeyAttr(input) - key attribute asked for * *Returns: * CSSM_OK - call is successful * CSSM_FAIL - call failed *-------------------------------------------------------------*/ CSSM_BOOL CSM_IsValidKeyReturnType( uint32 KeyAttr ) { uint32 uAttrData = ( (KeyAttr & CSSM_KEYATTR_RETURN_DATA) > 0 ) ? 1 : 0; uint32 uAttrRef = ( (KeyAttr & CSSM_KEYATTR_RETURN_REF) > 0 ) ? 1 : 0; uint32 uAttrNone = ( (KeyAttr & CSSM_KEYATTR_RETURN_NONE) > 0 ) ? 1 : 0; uint32 uTotalAttr = 0; /* if more than one of the return attributes is set then the total value * will be greater than 1 */ uTotalAttr = uAttrData + uAttrRef + uAttrNone; if ( uTotalAttr > 1 ) { return CSSM_FALSE; } return CSSM_TRUE; } CSSM_BOOL CSM_IsValidKeyAttributes( uint32 KeyAttr ) { const uint32 ReturnTypeAttrs = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_NONE; const uint32 ValidAttrs = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PRIVATE | CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE; ; /* Strip off the return type attributes */ KeyAttr &= ~( ReturnTypeAttrs | ValidAttrs ); if ( KeyAttr != 0 ) { return CSSM_FALSE; } return CSSM_TRUE; } /*--------------------------------------------------------------- *Name: TAL_ValidateKeyUsage * *Description: * This function verifies the Key Usage is valid. * *Parameters: * KeyUsage(input) - key usage to be verified. * ValidUsage(input) - Correct key usage. * *Returns: * CSSM_OK - call is successful * CSSM_FAIL - call failed *-------------------------------------------------------------*/ CSSM_BOOL CSM_IsValidKeyUsage( uint32 KeyUsage, uint32 ValidUsage ) { if ( ( ( KeyUsage & ValidUsage ) == 0 ) || ( ( KeyUsage & ~ValidUsage ) != 0 ) ) { return CSSM_FALSE; } return CSSM_TRUE; } CSSM_RETURN MAF_ValidateNetAddress( const CSSM_NET_ADDRESS *pAddress ) { /* The address is not allowed to be NULL */ if ( pAddress == NULL ) { return CSSM_ERRCODE_INVALID_NETWORK_ADDR; } /* Check for readability */ if ( port_IsBadReadPtr( pAddress, sizeof(CSSM_NET_ADDRESS) ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_NETWORK_ADDR; } /* Do a sanity check on the Address value. It must contain data. */ if ( ( pAddress->Address.Data == NULL ) || ( pAddress->Address.Length == 0 ) ) { return CSSM_ERRCODE_INVALID_NETWORK_ADDR; } /* Do a read check on the Address data */ if ( port_IsBadReadPtr( pAddress->Address.Data, pAddress->Address.Length ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_NETWORK_ADDR; } return CSSM_OK; } CSSM_RETURN MAF_ValidateData( const CSSM_DATA *pData, CSSM_BOOL bAllowEmpty, CSSM_BOOL bWriteable ) { /* The structure can not be NULL */ if ( pData == NULL ) { return CSSM_ERRCODE_INVALID_POINTER; } /* Can we access the structure? */ if ( bWriteable == CSSM_TRUE ) { if ( port_IsBadWritePtr( (void*)pData, sizeof(CSSM_DATA) ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_POINTER; } } else { if ( port_IsBadReadPtr( (void*)pData, sizeof(CSSM_DATA) ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_POINTER; } } /* Check the structure contents */ if ( ( pData->Data == NULL ) && ( pData->Length == 0 ) && ( bAllowEmpty != CSSM_TRUE ) ) { return CSSM_ERRCODE_INVALID_POINTER; } if ( bWriteable == CSSM_TRUE ) { if ( port_IsBadWritePtr( (void*)pData->Data, pData->Length ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_POINTER; } } else { if ( port_IsBadReadPtr( (void*)pData->Data, pData->Length ) == CSSM_TRUE ) { return CSSM_ERRCODE_INVALID_POINTER; } } return CSSM_OK; } CSSM_RETURN MAF_ValidateDbAttributeInfo( const CSSM_DB_ATTRIBUTE_INFO *pInfo ) { /* We can assume that the read/write properties of the memory are * acceptable since this structure is embedded in a * CSSM_DB_ATTRIBUTE_DATA structure. */ assert( pInfo != NULL ); /* Validate the label */ if ( pInfo->AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_STRING ) { if ( pInfo->Label.AttributeName == NULL ) { return CSSMERR_DL_INVALID_POINTER; } } else if ( pInfo->AttributeNameFormat == CSSM_DB_ATTRIBUTE_NAME_AS_OID ) { if ( port_IsBadReadPtr( pInfo->Label.AttributeOID.Data, pInfo->Label.AttributeOID.Length ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } } else if ( pInfo->AttributeNameFormat != CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER ) { return CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT; } return CSSM_OK; } CSSM_RETURN MAF_ValidateDbRecordAttribute( const CSSM_DB_ATTRIBUTE_DATA *pAttribute, CSSM_BOOL bRequireEmptyBufs ) { CSSM_RETURN mrReturn; uint32 i; /* Structure can not be NULL */ if ( pAttribute == NULL ) { return CSSMERR_DL_INVALID_POINTER; } if ( bRequireEmptyBufs == CSSM_TRUE ) { /* Can the structure be written? */ if ( port_IsBadWritePtr( (void*)pAttribute, sizeof(CSSM_DB_ATTRIBUTE_DATA) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } /* Make sure the value is empty */ if ( ( pAttribute->NumberOfValues != 0 ) || ( pAttribute->Value != NULL ) ) { return CSSMERR_DL_INVALID_POINTER; } } else { /* Can the structure be read? */ if ( port_IsBadReadPtr( pAttribute, sizeof(CSSM_DB_ATTRIBUTE_DATA) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } if ( port_IsBadReadPtr( pAttribute, ( sizeof(CSSM_DATA) * pAttribute->NumberOfValues ) ) ) { return CSSMERR_DL_INVALID_POINTER; } for ( i = 0; i < pAttribute->NumberOfValues; i++ ) { /* Check the data value, allowing empty buffers */ mrReturn = MAF_ValidateData( &pAttribute->Value[i], CSSM_TRUE, CSSM_FALSE ); if ( mrReturn != CSSM_OK ) { return mrReturn; } } } /* Validate the attribute information */ mrReturn = MAF_ValidateDbAttributeInfo( &pAttribute->Info ); return mrReturn; } CSSM_RETURN MAF_ValidateSelectionPredicate( const CSSM_SELECTION_PREDICATE *pPredicate ) { /* The structure can not be NULL */ if ( pPredicate == NULL ) { return CSSMERR_DL_INVALID_POINTER; } /* Can we read the structure? */ if ( port_IsBadReadPtr( pPredicate, sizeof(CSSM_SELECTION_PREDICATE) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } /* Validate the embedded attribute */ return MAF_ValidateDbRecordAttribute( &pPredicate->Attribute, CSSM_FALSE ); } CSSM_RETURN MAF_ValidateQuery( const CSSM_QUERY *pQuery ) { CSSM_RETURN mrReturn = CSSM_OK; uint32 i; /* Can we read the structure? */ if ( port_IsBadReadPtr( pQuery, sizeof(CSSM_QUERY) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } /* Validate the each of the predicates */ for ( i = 0; ( ( i < pQuery->NumSelectionPredicates ) && ( mrReturn == CSSM_OK ) ); i++ ) { mrReturn = MAF_ValidateSelectionPredicate( &pQuery->SelectionPredicate[i] ); } return mrReturn; } CSSM_RETURN MAF_ValidateInputDbRecordAttributeData( const CSSM_DB_RECORD_ATTRIBUTE_DATA *pAttributes ) { CSSM_RETURN mrReturn = CSSM_OK; uint32 i; /* Can the structure be read? */ if ( port_IsBadReadPtr( pAttributes, sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } /* Validate all input attributes */ for ( i = 0; ( ( i < pAttributes->NumberOfAttributes ) && ( mrReturn == CSSM_OK ) ); i++ ) { mrReturn = MAF_ValidateDbRecordAttribute( &pAttributes->AttributeData[i], CSSM_FALSE ); } return mrReturn; } CSSM_RETURN MAF_ValidateOutputDbRecordAttributeData( const CSSM_DB_RECORD_ATTRIBUTE_DATA *pAttributes ) { CSSM_RETURN mrReturn = CSSM_OK; uint32 i; /* Can the structure be read? */ if ( port_IsBadReadPtr( pAttributes, sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA) ) == CSSM_TRUE ) { return CSSMERR_DL_INVALID_POINTER; } /* Validate all input attributes */ for ( i = 0; ( ( i < pAttributes->NumberOfAttributes ) && ( mrReturn == CSSM_OK ) ); i++ ) { mrReturn = MAF_ValidateDbRecordAttribute( &pAttributes->AttributeData[i], CSSM_TRUE ); } return mrReturn; }