LCOV - code coverage report
Current view: top level - xmlsecurity/source/xmlsec/nss - ciphercontext.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 91 127 71.7 %
Date: 2012-08-25 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 90 220 40.9 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : 
      21                 :            : #include <osl/time.h>
      22                 :            : #include <rtl/random.h>
      23                 :            : #include <rtl/ref.hxx>
      24                 :            : 
      25                 :            : #include "ciphercontext.hxx"
      26                 :            : 
      27                 :            : using namespace ::com::sun::star;
      28                 :            : 
      29                 :         24 : uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding )
      30                 :            : {
      31         [ +  - ]:         24 :     ::rtl::Reference< OCipherContext > xResult = new OCipherContext;
      32                 :            : 
      33         [ +  - ]:         24 :     xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, NULL );
      34         [ +  - ]:         24 :     if ( xResult->m_pSlot )
      35                 :            :     {
      36                 :         24 :         SECItem aKeyItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aKey.getConstArray() ) ), sal::static_int_cast<unsigned>( aKey.getLength() ) };
      37 [ +  - ][ -  + ]:         24 :         xResult->m_pSymKey = PK11_ImportSymKey( xResult->m_pSlot, nNSSCipherID, PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, NULL );
      38         [ +  - ]:         24 :         if ( xResult->m_pSymKey )
      39                 :            :         {
      40                 :         24 :             SECItem aIVItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aInitializationVector.getConstArray() ) ), sal::static_int_cast<unsigned>( aInitializationVector.getLength() ) };
      41         [ +  - ]:         24 :             xResult->m_pSecParam = PK11_ParamFromIV( nNSSCipherID, &aIVItem );
      42         [ +  - ]:         24 :             if ( xResult->m_pSecParam )
      43                 :            :             {
      44 [ -  + ][ +  - ]:         24 :                 xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam);
      45         [ +  - ]:         24 :                 if ( xResult->m_pContext )
      46                 :            :                 {
      47                 :         24 :                     xResult->m_bEncryption = bEncryption;
      48                 :         24 :                     xResult->m_bW3CPadding = bW3CPadding;
      49 [ #  # ][ #  # ]:         24 :                     xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID );
                 [ -  + ]
      50         [ +  - ]:         24 :                     xResult->m_nBlockSize = PK11_GetBlockSize( nNSSCipherID, xResult->m_pSecParam );
      51         [ +  - ]:         24 :                     if ( xResult->m_nBlockSize <= SAL_MAX_INT8 )
      52 [ +  - ][ +  - ]:         24 :                         return xResult.get();
      53                 :            :                 }
      54                 :            :             }
      55                 :            :         }
      56                 :            :     }
      57                 :            : 
      58                 :         24 :     return uno::Reference< xml::crypto::XCipherContext >();
      59                 :            : }
      60                 :            : 
      61                 :         48 : void OCipherContext::Dispose()
      62                 :            : {
      63         [ +  - ]:         48 :     ::osl::MutexGuard aGuard( m_aMutex );
      64                 :            : 
      65         [ +  + ]:         48 :     if ( m_pContext )
      66                 :            :     {
      67         [ +  - ]:         24 :         PK11_DestroyContext( m_pContext, PR_TRUE );
      68                 :         24 :         m_pContext = NULL;
      69                 :            :     }
      70                 :            : 
      71         [ +  + ]:         48 :     if ( m_pSecParam )
      72                 :            :     {
      73         [ +  - ]:         24 :         SECITEM_FreeItem( m_pSecParam, PR_TRUE );
      74                 :         24 :         m_pSecParam = NULL;
      75                 :            :     }
      76                 :            : 
      77         [ +  + ]:         48 :     if ( m_pSymKey )
      78                 :            :     {
      79         [ +  - ]:         24 :         PK11_FreeSymKey( m_pSymKey );
      80                 :         24 :         m_pSymKey = NULL;
      81                 :            :     }
      82                 :            : 
      83         [ +  + ]:         48 :     if ( m_pSlot )
      84                 :            :     {
      85         [ +  - ]:         24 :         PK11_FreeSlot( m_pSlot );
      86                 :         24 :         m_pSlot = NULL;
      87                 :            :     }
      88                 :            : 
      89         [ +  - ]:         48 :     m_bDisposed = true;
      90                 :         48 : }
      91                 :            : 
      92                 :         24 : uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData )
      93                 :            :     throw ( lang::IllegalArgumentException, lang::DisposedException, uno::RuntimeException)
      94                 :            : {
      95         [ +  - ]:         24 :     ::osl::MutexGuard aGuard( m_aMutex );
      96                 :            : 
      97         [ -  + ]:         24 :     if ( m_bBroken )
      98         [ #  # ]:          0 :         throw uno::RuntimeException();
      99                 :            : 
     100         [ -  + ]:         24 :     if ( m_bDisposed )
     101         [ #  # ]:          0 :         throw lang::DisposedException();
     102                 :            : 
     103         [ +  - ]:         24 :     uno::Sequence< sal_Int8 > aToConvert;
     104         [ +  - ]:         24 :     if ( aData.getLength() )
     105                 :            :     {
     106                 :         24 :         sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength();
     107                 :            :         OSL_ENSURE( nOldLastBlockLen <= m_nBlockSize, "Unexpected last block size!" );
     108                 :            : 
     109                 :         24 :         sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength();
     110                 :         24 :         sal_Int32 nToConvertLen = nAvailableData;
     111 [ -  + ][ +  - ]:         24 :         if ( m_bEncryption || !m_bW3CPadding )
     112                 :            :         {
     113         [ #  # ]:          0 :             if ( nAvailableData % m_nBlockSize == 0 )
     114                 :          0 :                 nToConvertLen = nAvailableData;
     115         [ #  # ]:          0 :             else if ( nAvailableData < m_nBlockSize )
     116                 :          0 :                 nToConvertLen = 0;
     117                 :            :             else
     118                 :          0 :                 nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize;
     119                 :            :         }
     120                 :            :         else
     121                 :            :         {
     122                 :            :             // decryption with W3C padding needs at least one block for finalizing
     123         [ -  + ]:         24 :             if ( nAvailableData < m_nBlockSize * 2 )
     124                 :          0 :                 nToConvertLen = 0;
     125                 :            :             else
     126                 :         24 :                 nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize;
     127                 :            :         }
     128                 :            : 
     129         [ +  - ]:         24 :         aToConvert.realloc( nToConvertLen );
     130         [ -  + ]:         24 :         if ( nToConvertLen == 0 )
     131                 :            :         {
     132         [ #  # ]:          0 :             m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() );
     133         [ #  # ]:          0 :             memcpy( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() );
     134                 :            :             // aToConvert stays empty
     135                 :            :         }
     136         [ -  + ]:         24 :         else if ( nToConvertLen < nOldLastBlockLen )
     137                 :            :         {
     138         [ #  # ]:          0 :             memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen );
     139         [ #  # ]:          0 :             memcpy( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen );
     140         [ #  # ]:          0 :             m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() );
     141         [ #  # ]:          0 :             memcpy( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() );
     142                 :            :         }
     143                 :            :         else
     144                 :            :         {
     145         [ +  - ]:         24 :             memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen );
     146         [ +  - ]:         24 :             if ( nToConvertLen > nOldLastBlockLen )
     147         [ +  - ]:         24 :                 memcpy( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen );
     148         [ +  - ]:         24 :             m_aLastBlock.realloc( nAvailableData - nToConvertLen );
     149         [ +  - ]:         24 :             memcpy( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen );
     150                 :            :         }
     151                 :            :     }
     152                 :            : 
     153         [ +  - ]:         24 :     uno::Sequence< sal_Int8 > aResult;
     154                 :            :     OSL_ENSURE( aToConvert.getLength() % m_nBlockSize == 0, "Unexpected size of the data to encrypt!" );
     155         [ +  - ]:         24 :     if ( aToConvert.getLength() )
     156                 :            :     {
     157                 :         24 :         int nResultLen = 0;
     158         [ +  - ]:         24 :         aResult.realloc( aToConvert.getLength() + m_nBlockSize );
     159 [ +  - ][ +  - ]:         24 :         if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ) ), aToConvert.getLength() ) != SECSuccess )
                 [ -  + ]
     160                 :            :         {
     161                 :          0 :             m_bBroken = true;
     162         [ #  # ]:          0 :             Dispose();
     163         [ #  # ]:          0 :             throw uno::RuntimeException();
     164                 :            :         }
     165                 :            : 
     166                 :         24 :         m_nConverted += aToConvert.getLength();
     167         [ +  - ]:         24 :         aResult.realloc( nResultLen );
     168                 :            :     }
     169                 :            : 
     170 [ +  - ][ +  - ]:         24 :     return aResult;
     171                 :            : }
     172                 :            : 
     173                 :         24 : uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose()
     174                 :            :     throw (lang::DisposedException, uno::RuntimeException)
     175                 :            : {
     176         [ +  - ]:         24 :     ::osl::MutexGuard aGuard( m_aMutex );
     177                 :            : 
     178         [ -  + ]:         24 :     if ( m_bBroken )
     179         [ #  # ]:          0 :         throw uno::RuntimeException();
     180                 :            : 
     181         [ -  + ]:         24 :     if ( m_bDisposed )
     182         [ #  # ]:          0 :         throw lang::DisposedException();
     183                 :            : 
     184                 :            :     OSL_ENSURE( m_nBlockSize <= SAL_MAX_INT8, "Unexpected block size!" );
     185                 :            :     OSL_ENSURE( m_nConverted % m_nBlockSize == 0, "Unexpected amount of bytes is already converted!" );
     186                 :         24 :     sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize;
     187                 :            : 
     188                 :            :     // if it is decryption, the amount of data should be rounded to the block size even in case of padding
     189 [ +  - ][ -  + ]:         24 :     if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding )
                 [ +  - ]
     190 [ #  # ][ #  # ]:          0 :         throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The data should contain complete blocks only." ) ), uno::Reference< uno::XInterface >() );
     191                 :            : 
     192 [ +  - ][ -  + ]:         24 :     if ( m_bW3CPadding && m_bEncryption )
     193                 :            :     {
     194                 :            :         // in this case the last block should be smaller than standtard block
     195                 :            :         // it will be increased with the padding
     196                 :            :         OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize, "Unexpected size of cashed incomplete last block!" );
     197                 :            : 
     198                 :            :         // W3CPadding handling for encryption
     199                 :          0 :         sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding;
     200                 :          0 :         sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength();
     201         [ #  # ]:          0 :         m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize );
     202                 :            : 
     203         [ #  # ]:          0 :         if ( nPaddingSize > 1 )
     204                 :            :         {
     205                 :            :             TimeValue aTime;
     206         [ #  # ]:          0 :             osl_getSystemTime( &aTime );
     207                 :          0 :             rtlRandomPool aRandomPool = rtl_random_createPool();
     208                 :          0 :             rtl_random_addBytes( aRandomPool, &aTime, 8 );
     209         [ #  # ]:          0 :             rtl_random_getBytes( aRandomPool, m_aLastBlock.getArray() + nOldLastBlockLen, nPaddingSize - 1 );
     210                 :          0 :             rtl_random_destroyPool ( aRandomPool );
     211                 :            :         }
     212         [ #  # ]:          0 :         m_aLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize );
     213                 :            :     }
     214                 :            : 
     215                 :            :     // finally should the last block be smaller than two standard blocks
     216                 :            :     OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize * 2 , "Unexpected size of cashed incomplete last block!" );
     217                 :            : 
     218         [ +  - ]:         24 :     uno::Sequence< sal_Int8 > aResult;
     219         [ +  - ]:         24 :     if ( m_aLastBlock.getLength() )
     220                 :            :     {
     221                 :         24 :         int nPrefResLen = 0;
     222         [ +  - ]:         24 :         aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize );
     223 [ +  - ][ +  - ]:         24 :         if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ) ), m_aLastBlock.getLength() ) != SECSuccess )
                 [ -  + ]
     224                 :            :         {
     225                 :          0 :             m_bBroken = true;
     226         [ #  # ]:          0 :             Dispose();
     227         [ #  # ]:          0 :             throw uno::RuntimeException();
     228                 :            :         }
     229                 :            : 
     230         [ +  - ]:         24 :         aResult.realloc( nPrefResLen );
     231         [ +  - ]:         24 :         m_aLastBlock.realloc( 0 );
     232                 :            :     }
     233                 :            : 
     234                 :         24 :     sal_Int32 nPrefixLen = aResult.getLength();
     235         [ +  - ]:         24 :     aResult.realloc( nPrefixLen + m_nBlockSize * 2 );
     236                 :         24 :     unsigned nFinalLen = 0;
     237 [ +  - ][ +  - ]:         24 :     if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess )
                 [ -  + ]
     238                 :            :     {
     239                 :          0 :         m_bBroken = true;
     240         [ #  # ]:          0 :         Dispose();
     241         [ #  # ]:          0 :         throw uno::RuntimeException();
     242                 :            :     }
     243                 :            : 
     244         [ +  - ]:         24 :     aResult.realloc( nPrefixLen + nFinalLen );
     245                 :            : 
     246 [ +  - ][ +  - ]:         24 :     if ( m_bW3CPadding && !m_bEncryption )
     247                 :            :     {
     248                 :            :         // W3CPadding handling for decryption
     249                 :            :         // aResult should have anough data, since we let m_aLastBlock be big enough in case of decryption
     250                 :            :         OSL_ENSURE( aResult.getLength() >= m_nBlockSize, "Not enough data to handle the padding!" );
     251                 :            : 
     252         [ +  - ]:         24 :         sal_Int8 nBytesToRemove = aResult[aResult.getLength() - 1];
     253 [ +  + ][ +  + ]:         24 :         if ( nBytesToRemove <= 0 || nBytesToRemove > aResult.getLength() )
                 [ +  + ]
     254                 :            :         {
     255                 :         12 :             m_bBroken = true;
     256         [ +  - ]:         12 :             Dispose();
     257         [ +  - ]:         12 :             throw uno::RuntimeException();
     258                 :            :         }
     259                 :            : 
     260         [ +  - ]:         12 :         aResult.realloc( aResult.getLength() - nBytesToRemove );
     261                 :            :     }
     262                 :            : 
     263         [ +  - ]:         12 :     Dispose();
     264                 :            : 
     265         [ +  - ]:         24 :     return aResult;
     266                 :            : }
     267                 :            : 
     268                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10