Example #1
0
uint32_t Cipher(uint8_t* out, const uint8_t* in, uint32_t len, uint8_t mode, const uint8_t* key, const uint8_t* IV, bool inverse)
{
	Cipher_CTX ctx;
	CipherInit(&ctx, mode, key, IV);
	uint32_t ret = CipherUpdate(&ctx, out, in, len, inverse);
	ret += CipherFinal(&ctx, out, inverse);
	return ret;
}
Example #2
0
VLT_STS CipherDoFinal( VLT_PU8 pDataIn, 
        VLT_U32 DataInLen, 
        VLT_U32 dataInCapacity, 
        VLT_PU8 pDataOut, 
        VLT_PU32 pDataOutLen, 
        VLT_U32 dataOutCapacity )
{
    VLT_STS status = VLT_FAIL;      

    if ( ( ST_UNKNOWN == cipherState ) ||
         ( ST_FINALISED == cipherState ) )

    {
        return( ECPHDFNOTSUPPORTED );   
    }

    /**
     * Ensure we haven't been passed
     * null pointers by the caller.
     */
    if( ( NULL == pDataIn )||
        ( NULL == pDataOutLen ) ||
        ( NULL == pDataOut ) )
    {
        return( ECPHUPDNULLPARAM );
    }
    
    /**
     * Apply the padding if we have been called to
     * encrypt data.
     */
    if( ( VLT_ENCRYPT_MODE == operationalMode ) && 
        ( PADDING_NONE != params.paddingScheme ) )
    {
        status = PaddingAdd( params.paddingScheme, 
            theCipher.cipherGetBlockSize(), 
            pDataIn,
            &DataInLen, 
            dataInCapacity );
    }
    else
    {
        status = VLT_OK;
    }

    /**
     * Process the data, encrypt/decrypt
     */
    if( VLT_OK == status )
    {
        status = CipherUpdate( 
            pDataIn, 
            DataInLen,
            dataInCapacity,
            pDataOut, 
            pDataOutLen,
            dataOutCapacity);
    }
    
    
    if( VLT_OK == status )
    {
        if( VLT_DECRYPT_MODE == operationalMode )
        {
            status = PaddingRemove( params.paddingScheme, 
                theCipher.cipherGetBlockSize(), 
                pDataOut, 
                pDataOutLen );
        }
    }

    /**
     * Set the appropriate cipher state;
     */ 
    cipherState = ST_FINALISED;

    return( status );
}
VLT_STS SignerIso9797Update( VLT_PU8 pMessage, VLT_U32 messageLen, VLT_U32 messageCapacity )
{
    VLT_STS status = VLT_FAIL;
    VLT_U8 blockSize = 0;
    VLT_U32 byteCount = 0;
    VLT_U32 workingLen = 0;
    VLT_U8 workingBuffer[VLT_AES_CMAC_LENGTH];

    if ( ( ST_UNKNOWN == signerState ) ||
         ( ST_FINALISED == signerState ) )
    {
        return( SIGNER_NOT_SETUP );
    }

    
    /**
     * Ensure we haven't been passed
     * a null pointer by the caller.
     */
    if ( NULL == pMessage )
    {
        return( SIGNER_UPD_NULL_PARAMS );
    }


    /**
     * Cache the block size, we'll use it 
     * frequently.
     */
    blockSize = (VLT_U8)CipherGetBlockSize( );


    /**
     * For the SignerIso9797Update the capacity of
     * the buffer passed to us by the caller
     * should be equal or larger than that
     * of the data buffer length.
     */
    if ( ( messageLen > messageCapacity ) ||
         ( messageLen < blockSize )      ||
         ( messageCapacity < blockSize ) )
    {
        return( SIGNER_UPD_INVALID_CAP );
    }


    /**
     * Update only deals with data lengths
     * multiple of the block size, if the 
     * client has passed us anything else 
     * other than that then we should exit
     * gracefully-ish!
     */
    if( 0 != ( messageLen % blockSize ) )
    {
        return( SIGNER_UPD_NON_MUL_BLK_SZ );
    }
    

    while( 0 != ( messageLen - byteCount ) )
    {
        /**
         * Right, the cipher requires the output buffer
         * to be as big as the message buffer, which 
         * this method has no control over, so the signer
         * will send BLOCK_SIZED chunks to the cipher
         * and discard the answer for each block
         * until the last block in do final is processed.
         */
        /*
        * No need to check the return type as pointer has been validated
        */
        (void)host_memcpy(&workingBuffer[0], &pMessage[byteCount], blockSize);

        if( VLT_OK == ( status = CipherUpdate(
            workingBuffer,
            blockSize,
            messageCapacity,
            workingBuffer,
            &workingLen,
            NELEMS(workingBuffer)) ) )
        {
            /**
             * It should be impossible for the cipher 
             * to return a length not equal to 
             * the blockSize, nevertheless if it does
             * exit with an appropriate error code.
             */
            if( workingLen != blockSize )
            {               
                return( SIGNER_UPD_INVALID_BLOCK );
            }                   
        }
        else
        {
            return( status );
        }
        
        byteCount += blockSize;
        blockCounter++;
    }

    /**
     * Setup the IV in the IV buffer if the 
     * do final is called with a message 
     * shorter or equal to the block size.
     * In this case the cipher will be re-
     * initalized with a new algorithm.
     */
    /*
    * No need to check the return type as pointer has been validated
    */
    (void)host_memcpy(&aIv[0], &workingBuffer[0], params.ivSize);

    return( VLT_OK );
}
VLT_STS SignerIso9797DoFinal(
    VLT_PU8 pMessage, 
    VLT_U32 messageLen, 
    VLT_U32 messageCapacity, 
    VLT_PU8 pMac, 
    VLT_PU32 pMacLen, 
    VLT_U32 macCapacity )
{
    VLT_STS status = VLT_FAIL;  
    VLT_U8 blockSize = 0;
    VLT_U32 byteCount = 0;
    VLT_U32 workingLen = 0;
    VLT_U8 paddingPerformed = VLT_PAD_NOT_DONE;
    VLT_PU8 pMessageIt = &pMessage[byteCount];
    VLT_U8 hasGrownByBlockSize = FALSE;
    /**
     * With padding the final block can be double the 
     * block size, so double the size of the buffer. 
     */
    VLT_U8 workingBuffer[VLT_AES_CMAC_LENGTH * 2]; 

    

    if ( ( ST_UNKNOWN == signerState ) ||
         ( ST_FINALISED == signerState ) )

    {
        return( SIGNER_NOT_SETUP ); 
    }


    /**
     * Ensure we haven't been passed
     * a null pointer by the caller.
     */
    if ( ( NULL == pMessage ) ||
         ( NULL == pMac )     ||
         ( NULL == pMacLen ) )
    {
        return( SIGNER_DOF_NULL_PARAMS );
    }


    /**
     * Cache the block size, we'll use it 
     * frequently.
     */
    workingLen = blockSize = (VLT_U8)CipherGetBlockSize( );

    
    /**
     * For the SignerIso9797Update the capacity of
     * the buffer passed to us by the caller
     * should be equal or larger than that
     * of the data buffer length.
     */
    if ( ( messageLen > messageCapacity ) ||
         ( messageLen == 0 )              ||
         ( blockSize > macCapacity) )
    {
        return( SIGNER_DOF_INVALID_CAP );
    }

    
    if ( ( blockCounter == 0 )      &&
         ( messageLen < blockSize ) &&
         ( params.paddingScheme == PADDING_NONE ) )
    {
        /**
         * Can not process an empty do final 
         * with no padding.
         */
        return ( SIGNER_EMPT_DOFIN_NPAD );
    }

    while( 0 != ( messageLen - byteCount ) )
    {
        /**
         * The cipher requires the output buffer
         * to be as big as the message buffer, which 
         * this method has no control over, so the signer
         * will send BLOCK_SIZED chunks to the cipher
         * and discard the answer for each block
         * until the last block in do final is processed.
         */        
        if ( ( messageLen - byteCount ) <= blockSize )
        {
            if ( messageLen > blockSize )
            {
                /**
                 * Copy the last block, to setup the IV for the next if 
                 * MAC algo 1 is being used.
                 */
                /*
                * No need to check the return type as pointer has been validated
                */
                (void)host_memcpy( &aIv[0], &workingBuffer[0], blockSize );
            }
            
            /**
             * Check if Padding is needed
             */
            if ( ( PADDING_NONE != params.paddingScheme ) &&
                 ( VLT_PAD_DONE != paddingPerformed ) )
            {
                /**
                 * Working in a small internal buffer so
                 * the current count (byteCount) has to be 
                 * removed from the message size to ensure
                 * the correct sizes are passed to padding
                 * to ensure padding thinks there is enough
                 * room in the working buffer.  The working
                 * length is left so the correct number of 
                 * remaining bytes are copied.
                 */
                messageLen = workingLen = messageLen - byteCount;
              
                if ( VLT_OK != ( status = PaddingAdd( 
                    params.paddingScheme, 
                    blockSize, 
                    &workingBuffer[0],
                    &messageLen, /* Used because of the copying blockSize bytes at a time. */
                    NELEMS(workingBuffer) ) ) )
                {
                    return ( status );
                }
                /**
                 * Add the padding length onto the message.
                 */
                messageLen += byteCount;
                

                paddingPerformed = VLT_PAD_DONE;
            }

            /**
             * Padding can make the remaining bytes double
             * and result in two blocks remaining to be signed
             * Re-test the message length and take different 
             * action if the message length has grown such 
             * another block is required.
             */
            if ( ( messageLen - byteCount ) <= blockSize )
            {
                signerState = ST_FINALISED;

                /**
                 * Get the cipher to perform a different 
                 * action on do final.  Mac Alg3 switchs from DES to
                 * TDES on the do final, and AES_CMAC can use one of
                 * two different session keys on final!
                 */
                DoFinalSetup ( aIv, blockSize );

                
                if ( ( VLT_PAD_DONE == paddingPerformed ) &&
                     ( hasGrownByBlockSize ) )
                {
                    /**
                    * Setup the the latst block copy from the end 
                    * of the buffer to the start, no needed
                    * but simpler than more logic later.
                    */
                    pMessageIt = &workingBuffer[blockSize];
                }
            }
            else
            {
                /**
                 * Padding has added block size
                 * more bytes so another round 
                 * is required.
                 */
                 hasGrownByBlockSize = TRUE;
            }
        }
        
        
        
        /*
        * No need to check the return type as pointer has been validated
        */
        (void)host_memcpy(&workingBuffer[0], pMessageIt, workingLen);
        

        if ( ST_FINALISED != signerState )
        {
            if( VLT_OK == ( status = CipherUpdate(
                workingBuffer,
                blockSize,
                messageCapacity,
                workingBuffer,
                &workingLen,
                NELEMS(workingBuffer)) ) )
            {
                /**
                 * It is possible for the cipher 
                 * to return a length twice 
                 * the blockSize, or the blockSize, 
                 * if it is any other value exit 
                 * with an appropriate error code.
                 */
                if ( ( workingLen != blockSize ) &&
                     ( workingLen != ( blockSize * 2 ) ) )
                {               
                    return( SIGNER_UPD_INVALID_BLOCK );
                }                   
            }
            else
            {
                return( status );
            }
        }
        else if ( ST_FINALISED == signerState )
        {
            if( VLT_OK == ( status = CipherDoFinal(
                workingBuffer,
                blockSize,
                messageCapacity,
                workingBuffer,
                &workingLen,
                NELEMS(workingBuffer)) ) )
            {
                /**
                 * It is possible for the cipher 
                 * to return a length twice 
                 * the blockSize, or the blockSize, 
                 * if it is any other value exit 
                 * with an appropriate error code.
                 */
                if ( ( workingLen != blockSize ) &&
                     ( workingLen != ( blockSize * 2 ) ) )
                {               
                    return( SIGNER_UPD_INVALID_BLOCK );
                }                   
            }
            else
            {
                return( status );
            }
            
            if ( workingLen == ( blockSize * 2 ) )
            {
                workingLen = blockSize;
            }
            else
            {
                workingLen = 0;
            }
            /**
             * Take a block sized chunk and 
             * copy it into the output buffer.
             */
            /*
            * No need to check the return type as pointer has been validated
            */
            (void)host_memcpy(pMac, &workingBuffer[workingLen], blockSize);
            
            /**
             * Set the length of the Mac
             */
            *pMacLen = blockSize;

            break;
        }
        
        /**
         * Add block size to the byte count and 
         * increment the message ptr by block size.
         */
        byteCount += blockSize;
        pMessageIt += blockSize;
        blockCounter++;
    }
    return ( VLT_OK );
}
Example #5
0
VLT_STS VltUnwrapKey( VLT_U8 u8KeyGroup,
    VLT_U8 u8KeyIndex,
    const VLT_FILE_PRIVILEGES *pKeyFilePrivileges,
    const VLT_KEY_OBJ_RAW* pKeyObj )
{
#if( VLT_ENABLE_KEY_WRAPPING == VLT_ENABLE )
    VLT_STS status = VLT_FAIL;
    VLT_U8 u8SecChnlState = VLT_USER_NOT_AUTHENTICATED;
    
    /*
    * Check the validity of the input parameters
    */
    if( ( NULL == pKeyFilePrivileges ) || 
        ( NULL == pKeyObj ) || 
        ( NULL == pKeyObj->pu16ClearKeyObjectLen ) || 
        ( NULL == pKeyObj->pu8KeyObject ) )
    {
        return( EKWWKNULLPARAM );
    }

    /*
    * Check that the key wrapping has been initialised
    */
    if( ST_UNINIT == keyWrappingState )
    {
        return ( EKWWKUNINIT );
    }

    /*
    * Check if a Secure channel is enabled.  If it is, don't allow the wrap
    */
    if( VLT_OK == VltScpGetState( &u8SecChnlState ) )
    {
        if( u8SecChnlState == VLT_USER_AUTHENTICATED )
        {
            status = EKWWKSCPENBLD;
        }
        else
        {
            status = VLT_OK;
        }
    }
    else
    {
        /*
        * As Secure Channel hasn't been enabled the wrap call can proceed
        */
        status = VLT_OK;
    }

    if( VLT_OK == status )
    {
        /*
        * Initialise the Cipher
        */
        status = CipherInit( VLT_ENCRYPT_MODE,
            &theKey,
            (VLT_PU8)&theWrapParams );

        if( VLT_OK == status )
        {
            /*
            * The cipher was initialised correctly so update the state
            */
            keyWrappingState = ST_CIPHER_INIT;
        }
    }

    if( ( VLT_OK == status ) && ( WRAP_MODE != keyWrappingMode ) )
    {
        /*
        * Call Initialize Algorithm on the VaultIC to set it up to unwrap the
        * wrapped key we are about to send down. Only do this if it hasn't 
        * already been called
        */
        VLT_ALGO_PARAMS algorithm;

        algorithm.u8AlgoID = theWrapParams.algoID;
        algorithm.data.SymCipher.u8Padding = theWrapParams.paddingScheme;
        algorithm.data.SymCipher.u8Mode = theWrapParams.chainMode;

		if (theWrapParams.pIV != NULL)
		{
        /*
        * No need to check the return type as pointer has been validated
        */
        (void)host_memcpy( &(algorithm.data.SymCipher.u8Iv[0]),
            theWrapParams.pIV,
            CipherGetBlockSize() );

        algorithm.data.SymCipher.u8IvLength = (VLT_U8)CipherGetBlockSize();
		}
		else
			 algorithm.data.SymCipher.u8IvLength = 0;

        status = VltInitializeAlgorithm( u8CachedKTSKeyGroup, 
            u8CachedKTSKeyIndex,
            VLT_UNWRAP_KEY_MODE,
            &algorithm );

        if( VLT_OK == status )
        {
            /*
            * Update the mode to wrap
            */
            keyWrappingMode = WRAP_MODE;
        }
    }

    if( VLT_OK == status )
    {
        VLT_U16 u16Remaining = 
                VLT_PUTKEY_FIXED_DATA_LENGTH + *pKeyObj->pu16ClearKeyObjectLen;
        VLT_U16 u16KeyBytesRemaining = *(pKeyObj->pu16ClearKeyObjectLen);
        VLT_U16 u16MaxChunk = VltCommsGetMaxSendSize();
        VLT_U16 u16Offset = 0;

        while( 0 != u16Remaining )
        {
            VLT_SW Sw = VLT_STATUS_NONE;
            VLT_U16 u16Avail = 0;
            VLT_U16 u16PartialKeyLen = 0;
            VLT_U32 u32CipherDataLen = 0;
            VLT_U8 u8Final = 0;

            /*
            * Set index at the start of the data portion of the buffer
            */
            idx = VLT_APDU_DATA_OFFSET;

            /*
            * Build the data in
            */
            if( 0 == u16Offset )
            {
                /* 
                * Add the Key Priviliges 
                */
                Command.pu8Data[idx++] = pKeyFilePrivileges->u8Read;
                Command.pu8Data[idx++] = pKeyFilePrivileges->u8Write;
                Command.pu8Data[idx++] = pKeyFilePrivileges->u8Delete;
                Command.pu8Data[idx++] = pKeyFilePrivileges->u8Execute;

                /*
                * Add the Key Length
                */
                Command.pu8Data[idx++] = 
                    (VLT_U8)( (*pKeyObj->pu16ClearKeyObjectLen >> 8 ) & 0xFF );

                Command.pu8Data[idx++] = 
                    (VLT_U8)( (*pKeyObj->pu16ClearKeyObjectLen >> 0 ) & 0xFF );
            }

            u16Avail = NumBufferBytesAvail( u16MaxChunk, idx );

            if(u16KeyBytesRemaining > u16Avail)
            {
                /*
                * There is more key data remaining than can be transferred
                * in one transaction
                */
                u16PartialKeyLen = ( u16Avail / CipherGetBlockSize() )
                    * CipherGetBlockSize();
            }
            else
            {
                /*
                * The remaining data might all be able to be transferred in
                * one transaction
                */
                if( u16Avail >= (u16KeyBytesRemaining + CipherGetBlockSize() ) )
                {
                    u16PartialKeyLen = u16KeyBytesRemaining;

                    /*
                    * Flag that this will be the final block to be encrypted
                    */
                    u8Final = 1;
                }
                else
                {
                    u16PartialKeyLen = 
                        u16KeyBytesRemaining - CipherGetBlockSize();
                }
            }

            /*
            * Copy the number of bytes of the partial key into the buffer
            */
            /*
            * No need to check the return type as pointer has been validated
            */
            (void)host_memcpy( &(Command.pu8Data[idx]),
                &( (pKeyObj->pu8KeyObject[u16Offset]) ), 
                u16PartialKeyLen  );

            /*
            * Now encrypt the data in the buffer
            */
            if( 1 == u8Final )
            {
                status = CipherDoFinal( &(Command.pu8Data[idx]), 
                    u16PartialKeyLen, 
                    Command.u16Capacity - VLT_APDU_DATA_OFFSET, 
                    &(Command.pu8Data[idx]),
                    &u32CipherDataLen,
                    Command.u16Capacity - VLT_APDU_DATA_OFFSET );
            }
            else
            {
                status = CipherUpdate( &(Command.pu8Data[idx]), 
                    u16PartialKeyLen, 
                    Command.u16Capacity - VLT_APDU_DATA_OFFSET, 
                    &(Command.pu8Data[idx]),
                    &u32CipherDataLen,
                    Command.u16Capacity - VLT_APDU_DATA_OFFSET );
            }

            if( VLT_OK == status )
            {
                /*
                * Update the index to reflect the data that has just been added
                */
                idx += (VLT_U16)u32CipherDataLen;

                /*
                * Subtract the number of key bytes that have just been added to
                * the buffer from the number of key bytes remaining to be sent
                */
                u16KeyBytesRemaining -= u16PartialKeyLen;

                /*
                * Decrement the remaining number of bytes to be sent.
                */
                if( 0 == u16Offset )
                {
                    /*
                    * The first time the File Privileges and the length are
                    * included so include them plus the partial key length
                    * which won't incude any padding bytes if some have been
                    * added
                    */
                    u16Remaining -= 
                        ( VLT_PUTKEY_FIXED_DATA_LENGTH - NUM_CRC_BYTES ) +
                        u16PartialKeyLen;
                }
                else
                {
                    /*
                    * Subtract the partial key length that was added to
                    * the buffer
                    */
                    u16Remaining -= u16PartialKeyLen;
                }

                /*
                * Update the offset into the key
                */
                u16Offset += u16PartialKeyLen;

                /*
                * We need two bytes free in the buffer for the wCRC field.
                */
                if( ( NUM_CRC_BYTES == u16Remaining ) &&
                    ( NumBufferBytesAvail( u16MaxChunk, idx ) >= NUM_CRC_BYTES ) )
                {
                    Command.pu8Data[idx++] = 
                        (VLT_U8)( ( pKeyObj->u16Crc >> 8 ) & 0xFF );

                    Command.pu8Data[idx++] = 
                        (VLT_U8)( (pKeyObj->u16Crc >> 0 ) & 0xFF );

                    u16Remaining -= NUM_CRC_BYTES;
                }
Example #6
0
uint32_t DecryptUpdate(Decrypt_CTX* ctx, uint8_t* out, const uint8_t* in, uint32_t len)
{
	return CipherUpdate(ctx, out, in, len, true);
}
Example #7
0
uint32_t EncryptUpdate(Encrypt_CTX* ctx, uint8_t* out, const uint8_t* in, uint32_t len)
{
	return CipherUpdate(ctx, out, in, len, false);
}