/******************************************************************** created: 2006/08/28 created: 28:8:2006 19:46 filename: radeadecoder.cpp author: Seb Martel (smartel@real.com) RealNetworks, Inc (C) 2006, All rights reserved purpose: Sample implementation of a RAD/EA decoder. *********************************************************************/ /*************************************************************************** * (c)2003-2009 Broadcom Corporation * * This program is the proprietary software of Broadcom Corporation and/or its licensors, * and may only be used, duplicated, modified or distributed pursuant to the terms and * conditions of a separate, written license agreement executed between you and Broadcom * (an "Authorized License"). Except as set forth in an Authorized License, Broadcom grants * no license (express or implied), right to use, or waiver of any kind with respect to the * Software, and Broadcom expressly reserves all rights in and to the Software and all * intellectual property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU * HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY * NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. * * Except as expressly set forth in the Authorized License, * * 1. This program, including its structure, sequence and organization, constitutes the valuable trade * secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof, * and to use this information only in connection with your use of Broadcom integrated circuit products. * * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO * THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF * USE OR PERFORMANCE OF THE SOFTWARE. * * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF * ANY LIMITED REMEDY. * * $brcm_Workfile: radeadecoder.cpp $ * $brcm_Revision: $ * $brcm_Date: $ * * Description: RAD/EA module crypto file * * Revision History: * * $brcm_Log: /nexus/lib/playback_ip/src/radeadecoder.cpp $ * ***************************************************************************/ #include #include #include #include #include "string.h" #include "b_playback_ip_rad_ea.h" #include "cryptdes.h" static CCryptDES cCrypt; extern "C" { #if 0 static void initEaHeader( ) { int i = 0; std::vector mBuf; std::auto_ptr mHeader( new EA_HEADER ); // LISTEN verification. Assume version 3 first, for ( i = 0; i < LISTEN_VERIFY_NUM_CHARS; ++i ) { mBuf.push_back( read() ); } if ( !isVersion3(&mBuf[0]) ) { throw RADEAException( "Not a version 3 EA header" ); } mBuf.clear(); // EA verification for ( i = 0; i < EA_VERIFY_NUM_CHARS; ++ i ) { mBuf.push_back( read() ); } if ( !isEa( &mBuf[0] ) ) { throw RADEAException( "Invalid EA header verification" ); } // Read Header size now mBuf.clear(); for ( i = 0; i < sizeof( int ); ++i ) { mBuf.push_back( read() ); } int bHeaderSize = *reinterpret_cast( &mBuf[0] ); if ( bHeaderSize < EA_MIN_BYTES_TO_FOLLOW ) { throw RADEAException( "EA header isn't big enough for a version 3 header"); } // If this isn't 0 we need to skip bytes at end of header. int mExtraCharsAtEndOfHeader = bHeaderSize - EA_MIN_BYTES_TO_FOLLOW; // Init header. mHeader->nSize = bHeaderSize; for ( i = 0; i < EA_MIN_BYTES_TO_FOLLOW; ++i ) { *( (char*)mHeader.get() + sizeof( int ) + i ) = (char)read(); } // skip over extra data unknown to this header. for ( i = 0; i < mExtraCharsAtEndOfHeader; ++i ) { read(); } if ( mHeader->sMajorVersion < RAD_MAJOR_VERSION ) { throw RADEAException( "Wrong EA major version" ); // we shouldn't be here if the version is less than 3.0 } if ( mHeader->sMajorVersion == RAD_MAJOR_VERSION && mHeader->Header.v3.sMinorVersion < RAD_MINOR_VERSION ) { throw RADEAException( "Wrong EA minor version" ); // we shouldn't be here if the version is less than 3.0 } // All is good, save header. std::swap( cHeader, mHeader ); } static void initRadHeader() { int i = 0; std::vector mBuf; std::auto_ptr mHeader( new RAD_HEADER ); // LISTEN verification. Assume version 3 first, for ( i = 0; i < LISTEN_VERIFY_NUM_CHARS; ++i ) { mBuf.push_back( read() ); } if ( !isVersion3(&mBuf[0]) ) { throw RADEAException( "Not a version 3 RAD header" ); } mBuf.clear(); // we should read "RAD_" now for ( i = 0; i < EA_VERIFY_NUM_CHARS; ++ i ) { mBuf.push_back( read() ); } if ( !isRad( &mBuf[0] ) ) { throw RADEAException( "Invalid RAD header verification" ); // this is a rhapsody file but not a RAD! } // Read Header size now mBuf.clear(); for ( i = 0; i < sizeof( int ); ++i ) { mBuf.push_back( read() ); } int bHeaderSize = *reinterpret_cast( &mBuf[0] ); if ( bHeaderSize < RAD_MIN_BYTES_TO_FOLLOW ) { throw RADEAException( "RAD header isn't big enough for a version 3 header"); } // If this isn't 0 we need to skip bytes at end of header. int mExtraCharsAtEndOfHeader = bHeaderSize - RAD_MIN_BYTES_TO_FOLLOW; // Init header. mHeader->nSize = bHeaderSize; for ( i = 0; i < RAD_MIN_BYTES_TO_FOLLOW; ++i ) { *( (char*)mHeader.get() + sizeof( int ) + i ) = (char)read(); } // skip over extra data unknown to this header. for ( i = 0; i < mExtraCharsAtEndOfHeader; ++i ) { read(); } if ( mHeader->sMajorVersion < RAD_MAJOR_VERSION) { throw RADEAException( "unsupported RAD major version" ); } if ( mHeader->sMajorVersion == RAD_MAJOR_VERSION && mHeader->Header.v3.sMinorVersion < RAD_MINOR_VERSION ) { throw RADEAException( "unsupported RAD minor version" ); } // All is good, save header. std::swap( cHeader, mHeader ); } #endif void radea_decrypt_frame( unsigned char* radBuffer, unsigned char* eaBuffer, int radBufferSize, char* decryptedBuffer ) { int i = 0; int mNbDesBlocks = radBufferSize / MIN_RAD_BYTES_FOR_DES; char* reassembledPtr; // assert( radBufferSize <= RAD_BYTES_PER_FRAME); // triple des decryption is the reverse of the encryption process, so it's: // 1. decrypt with last 8 bytes of key // 2. encrypt with middle 8 bytes of key // 3. decrypt with first 8 bytes of key cCrypt.Init(eaBuffer + 2 * MIN_RAD_BYTES_FOR_DES); cCrypt.des_dec(radBuffer, mNbDesBlocks); /* Nb of 8 bytes blocks */ cCrypt.Init(eaBuffer + MIN_RAD_BYTES_FOR_DES); cCrypt.des_enc(radBuffer, mNbDesBlocks); /* Nb of 8 bytes blocks */ cCrypt.Init(eaBuffer); cCrypt.des_dec(radBuffer, mNbDesBlocks); /* Nb of 8 bytes blocks */ // Reassemble EA and RAD int mBlocksToInterleave = radBufferSize / RAD_BYTES_PER_BLOCK; for ( i = 0, reassembledPtr = decryptedBuffer; i < mBlocksToInterleave; ++i ) { // 1 byte from the EA *reassembledPtr = eaBuffer[i]; reassembledPtr++; // 128 from the RAD int start = i * RAD_BYTES_PER_BLOCK; // int end = (i + 1 ) * RAD_BYTES_PER_BLOCK; memcpy( reassembledPtr, radBuffer + start, RAD_BYTES_PER_BLOCK ); reassembledPtr += RAD_BYTES_PER_BLOCK; } } }