BOOLEAN sanityCheckCapability( const CAPABILITY_INFO *capabilityInfoPtr ) { CRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo; assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) ); /* Check the algorithm and mode parameters. We check for an algorithm name one shorter than the maximum because as returned to an external caller it's an ASCIZ string so we need to allow room for the terminator */ if( cryptAlgo <= CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) return( FALSE ); if( capabilityInfoPtr->algoName == NULL || \ capabilityInfoPtr->algoNameLen < 3 || \ capabilityInfoPtr->algoNameLen > CRYPT_MAX_TEXTSIZE - 1 ) return( FALSE ); /* Make sure that the minimum functions are present. We don't check for the presence of the keygen function since the symmetric capabilities use the generic keygen and the hash capabilities don't do keygen at all */ if( capabilityInfoPtr->selfTestFunction == NULL || \ capabilityInfoPtr->getInfoFunction == NULL ) return( FALSE ); if( !sanityCheckFunctionality( capabilityInfoPtr, cryptAlgo ) ) return( FALSE ); /* Make sure that the algorithm/mode-specific parameters are consistent */ if( capabilityInfoPtr->minKeySize > capabilityInfoPtr->keySize || \ capabilityInfoPtr->maxKeySize < capabilityInfoPtr->keySize ) return( FALSE ); if( isConvAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 8 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) || \ ( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) ) return( FALSE ); if( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE ) return( FALSE ); /* Requirement for key wrap */ if( capabilityInfoPtr->initParamsFunction == NULL || \ capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); if( !isStreamCipher( cryptAlgo ) && \ capabilityInfoPtr->blockSize < bitsToBytes( 64 ) ) return( FALSE ); return( TRUE ); } /* Check any remaining algorithm types */ if( isPkcAlgo( cryptAlgo ) ) { const int minKeySize = isEccAlgo( cryptAlgo ) ? \ MIN_PKCSIZE_ECC : MIN_PKCSIZE; if( capabilityInfoPtr->blockSize != 0 || \ ( capabilityInfoPtr->minKeySize < minKeySize || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_PKCSIZE ) ) return( FALSE ); if( capabilityInfoPtr->initKeyFunction == NULL || \ capabilityInfoPtr->generateKeyFunction == NULL ) return( FALSE ); return( TRUE ); } if( isHashAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 128 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \ ( capabilityInfoPtr->minKeySize != 0 || \ capabilityInfoPtr->keySize != 0 || \ capabilityInfoPtr->maxKeySize != 0 ) ) return( FALSE ); return( TRUE ); } if( isMacAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 128 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \ ( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) ) return( FALSE ); if( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE ) return( FALSE ); /* Requirement for key wrap */ if( capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); return( TRUE ); } if( isSpecialAlgo( cryptAlgo ) ) { if( capabilityInfoPtr->blockSize != 0 || \ capabilityInfoPtr->minKeySize < bitsToBytes( 128 ) || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) return( FALSE ); if( capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); return( TRUE ); } retIntError_Boolean(); }
static BOOLEAN sanityCheckFunctionality( const CAPABILITY_INFO *capabilityInfoPtr, IN_ALGO CRYPT_ALGO_TYPE cryptAlgo ) { const BOOLEAN isCrypt = \ ( capabilityInfoPtr->encryptCBCFunction != NULL || \ capabilityInfoPtr->decryptCBCFunction != NULL || \ capabilityInfoPtr->encryptCFBFunction != NULL || \ capabilityInfoPtr->decryptCFBFunction != NULL || \ capabilityInfoPtr->encryptGCMFunction != NULL || \ capabilityInfoPtr->decryptGCMFunction != NULL ) ? TRUE : FALSE; const BOOLEAN isSig = \ ( capabilityInfoPtr->signFunction != NULL || \ capabilityInfoPtr->sigCheckFunction != NULL ) ? TRUE : FALSE; assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) ); REQUIRES( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST ); /* Generic-secret algorithms are non-capabilities used to to store keying data, but that can't perform any operations themselves */ if( isSpecialAlgo( cryptAlgo ) ) { if( capabilityInfoPtr->encryptFunction != NULL || \ capabilityInfoPtr->decryptFunction != NULL || \ isCrypt || isSig ) return( FALSE ); return( TRUE ); } /* We need at least one mechanism pair to be able to do anything useful with the capability */ if( ( capabilityInfoPtr->encryptFunction == NULL || \ capabilityInfoPtr->decryptFunction == NULL ) && \ ( capabilityInfoPtr->encryptCBCFunction == NULL || \ capabilityInfoPtr->decryptCBCFunction == NULL ) && \ ( capabilityInfoPtr->encryptCFBFunction == NULL || \ capabilityInfoPtr->decryptCFBFunction == NULL ) && \ ( capabilityInfoPtr->encryptGCMFunction == NULL || \ capabilityInfoPtr->decryptGCMFunction == NULL ) && \ ( capabilityInfoPtr->signFunction == NULL || \ capabilityInfoPtr->sigCheckFunction == NULL ) ) return( FALSE ); /* Perform algorithm class-specific checks */ if( isConvAlgo( cryptAlgo ) ) { if( isSig ) return( FALSE ); if( isStreamCipher( cryptAlgo ) ) { if( capabilityInfoPtr->encryptCFBFunction == NULL || \ capabilityInfoPtr->decryptCFBFunction == NULL ) return( FALSE ); if( capabilityInfoPtr->encryptFunction != NULL || \ capabilityInfoPtr->decryptFunction != NULL || \ capabilityInfoPtr->encryptCBCFunction != NULL || \ capabilityInfoPtr->decryptCBCFunction != NULL || \ capabilityInfoPtr->encryptCFBFunction != NULL || \ capabilityInfoPtr->decryptCFBFunction != NULL || \ capabilityInfoPtr->encryptGCMFunction != NULL || \ capabilityInfoPtr->decryptGCMFunction != NULL ) return( FALSE ); } else { if( capabilityInfoPtr->encryptFunction == NULL && \ capabilityInfoPtr->decryptFunction == NULL && \ !isCrypt ) return( FALSE ); } if( ( capabilityInfoPtr->encryptCBCFunction != NULL && \ capabilityInfoPtr->decryptCBCFunction == NULL ) || \ ( capabilityInfoPtr->encryptCBCFunction == NULL && \ capabilityInfoPtr->decryptCBCFunction != NULL ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptCFBFunction != NULL && \ capabilityInfoPtr->decryptCFBFunction == NULL ) || \ ( capabilityInfoPtr->encryptCFBFunction == NULL && \ capabilityInfoPtr->decryptCFBFunction != NULL ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptGCMFunction != NULL && \ capabilityInfoPtr->decryptGCMFunction == NULL ) || \ ( capabilityInfoPtr->encryptGCMFunction == NULL && \ capabilityInfoPtr->decryptGCMFunction != NULL ) ) return( FALSE ); return( TRUE ); } if( isPkcAlgo( cryptAlgo ) ) { if( capabilityInfoPtr->encryptFunction == NULL && \ capabilityInfoPtr->decryptFunction == NULL && \ capabilityInfoPtr->signFunction == NULL && \ capabilityInfoPtr->sigCheckFunction == NULL ) return( FALSE ); if( isCrypt ) return( FALSE ); return( TRUE ); } if( isHashAlgo( cryptAlgo ) || isMacAlgo( cryptAlgo ) ) { if( capabilityInfoPtr->encryptFunction == NULL || \ capabilityInfoPtr->decryptFunction == NULL ) return( FALSE ); if( isCrypt || isSig ) return( FALSE ); return( TRUE ); } retIntError_Boolean(); }
BOOLEAN sanityCheckCapability( const CAPABILITY_INFO *capabilityInfoPtr, const BOOLEAN asymmetricOK ) { CRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo; assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) ); /* Check the algorithm and mode parameters. We check for an algorithm name one shorter than the maximum because as returned to an external caller it's an ASCIZ string so we need to allow room for the terminator */ if( cryptAlgo <= CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST || \ capabilityInfoPtr->algoName == NULL || \ capabilityInfoPtr->algoNameLen < 3 || \ capabilityInfoPtr->algoNameLen > CRYPT_MAX_TEXTSIZE - 1 ) return( FALSE ); /* Make sure that the minimum functions are present. We don't check for the presence of the keygen function since the symmetric capabilities use the generic keygen and the hash capabilities don't do keygen at all */ if( capabilityInfoPtr->selfTestFunction == NULL || \ capabilityInfoPtr->getInfoFunction == NULL ) return( FALSE ); if( isStreamCipher( cryptAlgo ) ) { if( capabilityInfoPtr->encryptOFBFunction == NULL || \ capabilityInfoPtr->decryptOFBFunction == NULL ) return( FALSE ); } else { if( asymmetricOK ) { /* If asymmetric capabilities (e.g. decrypt but not encrypt, present in some tinkertoy tokens) are permitted then we only check that there's at least one useful capability available */ if( capabilityInfoPtr->decryptFunction == NULL && \ capabilityInfoPtr->signFunction == NULL ) return( FALSE ); } else { if( !isSpecialAlgo( cryptAlgo ) ) { /* We need at least one mechanism pair to be able to do anything useful with the capability */ if( ( capabilityInfoPtr->encryptFunction == NULL || \ capabilityInfoPtr->decryptFunction == NULL ) && \ ( capabilityInfoPtr->encryptCBCFunction == NULL || \ capabilityInfoPtr->decryptCBCFunction == NULL ) && \ ( capabilityInfoPtr->encryptCFBFunction == NULL || \ capabilityInfoPtr->decryptCFBFunction == NULL ) && \ ( capabilityInfoPtr->encryptOFBFunction == NULL || \ capabilityInfoPtr->decryptOFBFunction == NULL ) && \ ( capabilityInfoPtr->encryptGCMFunction == NULL || \ capabilityInfoPtr->decryptGCMFunction == NULL ) && \ ( capabilityInfoPtr->signFunction == NULL || \ capabilityInfoPtr->sigCheckFunction == NULL ) ) return( FALSE ); } } } /* Make sure that the algorithm/mode-specific parameters are consistent */ if( capabilityInfoPtr->minKeySize > capabilityInfoPtr->keySize || \ capabilityInfoPtr->maxKeySize < capabilityInfoPtr->keySize ) return( FALSE ); if( isConvAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 8 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) || \ ( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) ) return( FALSE ); if( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE ) return( FALSE ); /* Requirement for key wrap */ if( capabilityInfoPtr->initParamsFunction == NULL || \ capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); if( !isStreamCipher( cryptAlgo ) && \ capabilityInfoPtr->blockSize < bitsToBytes( 64 ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptCBCFunction != NULL && \ capabilityInfoPtr->decryptCBCFunction == NULL ) || \ ( capabilityInfoPtr->encryptCBCFunction == NULL && \ capabilityInfoPtr->decryptCBCFunction != NULL ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptCFBFunction != NULL && \ capabilityInfoPtr->decryptCFBFunction == NULL ) || \ ( capabilityInfoPtr->encryptCFBFunction == NULL && \ capabilityInfoPtr->decryptCFBFunction != NULL ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptOFBFunction != NULL && \ capabilityInfoPtr->decryptOFBFunction == NULL ) || \ ( capabilityInfoPtr->encryptOFBFunction == NULL && \ capabilityInfoPtr->decryptOFBFunction != NULL ) ) return( FALSE ); if( ( capabilityInfoPtr->encryptGCMFunction != NULL && \ capabilityInfoPtr->decryptGCMFunction == NULL ) || \ ( capabilityInfoPtr->encryptGCMFunction == NULL && \ capabilityInfoPtr->decryptGCMFunction != NULL ) ) return( FALSE ); return( TRUE ); } /* We've checked the conventional algorithms, beyond this point there shouldn't be any conventional encryption modes present */ if( capabilityInfoPtr->encryptCBCFunction != NULL || \ capabilityInfoPtr->decryptCBCFunction != NULL || \ capabilityInfoPtr->encryptCFBFunction != NULL || \ capabilityInfoPtr->decryptCFBFunction != NULL || \ capabilityInfoPtr->encryptOFBFunction != NULL || \ capabilityInfoPtr->decryptOFBFunction != NULL || \ capabilityInfoPtr->encryptGCMFunction != NULL || \ capabilityInfoPtr->decryptGCMFunction != NULL ) return( FALSE ); /* Check any remaining algorithm types */ if( isPkcAlgo( cryptAlgo ) ) { const int minKeySize = isEccAlgo( cryptAlgo ) ? \ MIN_PKCSIZE_ECC : MIN_PKCSIZE; if( capabilityInfoPtr->blockSize != 0 || \ ( capabilityInfoPtr->minKeySize < minKeySize || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_PKCSIZE ) ) return( FALSE ); if( capabilityInfoPtr->initKeyFunction == NULL || \ capabilityInfoPtr->generateKeyFunction == NULL ) return( FALSE ); return( TRUE ); } if( isHashAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 128 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \ ( capabilityInfoPtr->minKeySize != 0 || \ capabilityInfoPtr->keySize != 0 || \ capabilityInfoPtr->maxKeySize != 0 ) ) return( FALSE ); return( TRUE ); } if( isMacAlgo( cryptAlgo ) ) { if( ( capabilityInfoPtr->blockSize < bitsToBytes( 128 ) || \ capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \ ( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) ) return( FALSE ); if( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE ) return( FALSE ); /* Requirement for key wrap */ if( capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); return( TRUE ); } if( isSpecialAlgo( cryptAlgo ) ) { if( capabilityInfoPtr->blockSize != 0 || \ capabilityInfoPtr->minKeySize < bitsToBytes( 128 ) || \ capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) return( FALSE ); if( capabilityInfoPtr->encryptFunction != NULL || \ capabilityInfoPtr->decryptFunction != NULL ) return( FALSE ); if( capabilityInfoPtr->initKeyFunction == NULL ) return( FALSE ); return( TRUE ); } retIntError_Boolean(); }