How to use a rule-based selector

The following example demonstrates the use of the rule selector and the inclusion of a selection rule to retrieve the characteristics of a symmetric cipher object.

#include <ruleselector.h>
#include <cryptosymmetriccipherapi.h>
#include <cryptospistateapi.h>
#include <cryptospidef.h>
#include <keys.h>

using namespace CryptoSpi;

// Create a CSelectionRules collection object which is used to store the rules
// that influence the choice of plug-in implementation selected

CSelectionRules* rules = CSelectionRules::NewL();
CleanupStack::PushL(rules);

// Add a selection rule selecting symmetric ciphers with a key length of 64 bytes
    
TInt ruleValue = 64;
            
// Create and initialise one or more crypto parameters 
// to store the contents of the rule value 
CCryptoParam* ruleValueParam = CCryptoIntParam::NewL(ruleValue,KMaximumKeyLengthTypeUid);

// Create a selection rule for each crypto parameter (CSelectionRuleContent
// takes ownership of the crypto parameter), by passing in the following parameters:
// *InterfaceScope        The Interface scope of which the rule should be applied
// *AlgorithmScope        The Algorithm scope of which the rule should be applied
// *CharacteristicValue   The parameter type and value of the rule
// *Operator              The operator of the rule
// *IsOptional            Whether this rule is optional (ETrue) or mandatory (EFalse)        
CSelectionRuleContent* rule = CSelectionRuleContent::NewL(KSymmetricCipherInterfaceUid,
                                                          KNoneUid,
                                                          ruleValueParam,
                                                          EOpEqual,
                                                          EFalse);

// Add the newly created selection rule to the CSelectionRules collection by calling
// the 'AddSelectionRuleL' method and passing in a pointer to the constructed rule.
// AddSelectionRuleL() checks that the type of the crypto parameters is correct and 
// leaves with KErrNotSupported if not. For instance, a creator name parameter must 
// be stored using a CCryptoDesC16Param. 
          
rules->AddSelectionRuleL(rule);
                                    
// Create an instance of the rule selector, passing in the selection rules 
// object previously instantiated
CRuleSelector* ruleSelector = CRuleSelector::NewL(rules);
    
// Ownership of the rule collection object is passed to the rule selector, therefore
// the CSelectionRules object needs to be popped off the cleanup stack before pushing on
// the rule selector
CleanupStack::Pop(rules);
CleanupStack::PushL(ruleSelector);
    
// The legacy selector is set within the framework by default. In order to set the rule
// selector, the 'SetSelector' method of CryptoSpiStateApi needs to be called, 
//passing a pointer to the initialized rule selector    
CCryptoSpiStateApi::SetSelector(ruleSelector);

// Create a new CryptoParams object to encapsulate the secret key string for the 
// Symmetric Cipher implementation 
CCryptoParams* keyParams = CCryptoParams::NewLC();

// Add the secret key to the CCryptoParams object by calling the AddL method, passing in 
// the key string and appropriate key parameter UID
keyParams->AddL(_L8("12345678"), KSymmetricKeyParameterUid);

// Create a CKey object by passing in an instance of TKeyProperty and the previously
// created CCryptoParams object containing the secret key
TKeyProperty keyProperty;        
CKey* key=CKey::NewL(keyProperty,*keyParams);
CleanupStack::PushL(key);

// Create and initialise a pointer for the Symmetric Cipher implementation object        
CSymmetricCipher* symmetricCipherImpl = NULL;
        
// If successful, the 'CreateSymmetricCipherL' method returns KErrNone and the framework
// creates an instance of the selected Symmetric Cipher implementation, as chosen by the
// rule selector. The CSymmetricCipher pointer is passed by reference and set to point to
// the new symmetric cipher object
TRAPD(err,CSymmetricCipherFactory::CreateSymmetricCipherL(symmetricCipherImpl,
                                                          KDesUid,
                                                          *key,
                                                          KCryptoModeEncryptUid,
                                                          KOperationModeNoneUid,
                                                          KPaddingModeNoneUid,
                                                          NULL));

// Having successfully constructed the symmetric cipher implementation object, it is
// possible to retrieve the plug-in characteristics associated with it
if (symmetricCipherImpl && (err == KErrNone))
 {
 CleanupStack::PushL(symmetricCipherImpl);
 // Use cipher
 CleanupStack::PopAndDestroy(symmetricCipherImpl);
 }

CleanupStack::PopAndDestroy(2, keyParams);    //key, keyParams

// Unselect rule selector before destruction. This causes CryptoSPI to use the 
// legacy selector again. After calling SetSelector(), the caller 
// keeps ownership of the selector, so after calling UnsetSelector(), the 
// caller needs to delete the selector    
CCryptoSpiStateApi::UnsetSelector();
    
// Pop and destroy the rule selector
CleanupStack::PopAndDestroy(ruleSelector);