Hello,

not much feedback...

Anyway. I manage to implement it and get same result as testVector. Though this is not enough to ensure that it is correct. Computation of s1Len is unchecked.

Here it is. Enjoy. Feedback is welcome.

#include <iostream>

#include "PRF.h"
#include "util.h"

using namespace CryptoPP;
using namespace std;
using namespace DITP;


int main( int argc, char*argv[] )
{
        byte* p;
        // trying the test vector
        SecByteBlock key(48);
        p = key;
        memset( (void*)key, 0xab, 48 );

        SecByteBlock seed( 78 );
        p = seed;
        strcpy( (char*)p, "PRF Testvector" );
        p += 14;
        memset( p, 0xcd, 64 );

        SecByteBlock out(104);
        TLS_PRF( key, seed, out );

        hexDump((byte*)out, out.size() ); 

        return 0;
}
#ifndef DITP_UTIL_H
#define DITP_UTIL_H

namespace DITP
{

// dump to cout data in hexadecimal
void hexDump( void* data, int len );

union EndianessUnion 
{
        unsigned short x;
        char v;
};

// return true if computer is big endian
inline bool isBigEndian()
{
        static EndianessUnion x = { 0x100 };
        return x.v != 0;
}

// byte swap double byte value
inline unsigned short bswap( unsigned short v ) 
{ return v >> 8 | v << 8; }

// byte swap four byte value
inline unsigned long bswap( unsigned long v ) 
{ 
        v = ((v & 0xFF00FF00) >> 8) | (( v & 0xFF00FF) << 8); 
        return v >> 16 | v << 16;
}

// byte swap eight byte value
inline unsigned long long bswap( unsigned long long v ) 
{ 
        v = ((v & 0xFF00FF00FF00FF00LL) >> 8) | (( v & 0xFF00FF00FF00FFLL) << 
8); 
        v = ((v & 0xFFFF0000FFFF0000LL) >> 16) | (( v & 0xFFFF0000FFFFLL) << 
16); 
        return v >> 32 | v << 32;
}



}
#endif
#include "hmac.h"
#include "sha.h"
#include "md5.h"
#include "PRF.h"


// compute TLS pseudo random function to generate MAC secret and encryption keys
// key is secret shared by both ends. Length must be between 36 and 128. TLS 
use 48. 
// Seed is label+srvRnd+cliRnd. Label is only the ascii chars without trailing 
0. 
// out buffer size should be the sum of the two MAC secrets and the two keys. 
void DITP::TLS_PRF( const SecByteBlock& key, const SecByteBlock& seed, 
SecByteBlock& out )
{
        // compute secret halfs for md5 and sha and init hash
        const byte* s1 = key, *s2 = s1 + key.size()/2;
        int s1Len = (key.size()+1)/2, s2Len = s1Len;

        // set up buffer and parameters
        int sLen = seed.size();
        SecByteBlock buf( SHA::DIGESTSIZE + sLen );
        byte *s = (byte*)buf + SHA::DIGESTSIZE;
        memcpy( s, (const byte*)seed, sLen );

        // initialize output pointer
        byte *p = out;
        int len = out.size();

        // generate the MD5 random bits
        byte *md5 = s - MD5::DIGESTSIZE;
        int md5Len = sLen + MD5::DIGESTSIZE;
        HMAC<MD5> hmd5( s1, s1Len );
        hmd5.CalculateDigest( md5, s, sLen );  // compute A(1)
        while( len > MD5::DIGESTSIZE )
        {
                hmd5.CalculateDigest( p, md5, md5Len );
                hmd5.CalculateDigest( md5, md5, MD5::DIGESTSIZE ); //compute 
A(i+1)
                p += MD5::DIGESTSIZE;
                len -= MD5::DIGESTSIZE;
        }
        hmd5.CalculateTruncatedDigest( p, len, md5, md5Len ); 

        // initialize temporary output pointers
        SecByteBlock tmp( out.size() );
        p = tmp; 
        len = tmp.size();

        // generate the SHA random bits
        byte *sha = s - SHA::DIGESTSIZE;
        int shaLen = sLen + SHA::DIGESTSIZE;
        HMAC<SHA> hSha( s2, s2Len );
        hSha.CalculateDigest( sha, s, sLen );  // compute A(1)
        while( len > SHA::DIGESTSIZE )
        {
                hSha.CalculateDigest( p, sha, shaLen );
                hSha.CalculateDigest( sha, sha, SHA::DIGESTSIZE ); //compute 
A(i+1)
                p += SHA::DIGESTSIZE;
                len -= SHA::DIGESTSIZE;
        }
        hSha.CalculateTruncatedDigest( p, len, sha, shaLen ); 

        // XOR md5 and sha output
        byte *d = out;
        p = tmp;
        for( size_t i = 0; i < out.size(); ++i )
                *d++ ^= *p++;
}
#ifndef DITP_PRF_H
#define DITP_PRF_H

#include "secblock.h"
using namespace CryptoPP;

namespace DITP
{

// compute TLS pseudo random function to generate MAC secret and encryption keys
// key is secret shared by both ends. Length must be between 36 and 128. TLS 
use 48. 
// Seed is label+srvRnd+cliRnd. Label is only the ascii chars without trailing 
0. 
// out buffer size should be the sum of the two MAC secrets and the two keys. 
void TLS_PRF( const SecByteBlock& key, const SecByteBlock& seed, SecByteBlock& 
out );

}

#endif
#include <iostream>

#include "util.h"

using namespace std;
namespace DITP
{

void hexDump( void* data, int len )
{
        if( len == 0 )
        {
                cout << endl;
                return;
        }
        int x = 0;
        unsigned long cnt = 0;
        string ascii;
        const unsigned char* p = (unsigned char*)data;
        char buf[5], lineStr[10];
        while( len-- )
        {
                if( x == 0 )
                {
                        sprintf( lineStr, "%5.05lu ", cnt );
                        cout << lineStr;
                }

                if( x++ == 8 ) cout << " ";
                sprintf( buf, "%2.2X ", *p );
                cout << buf;
                if( *p >= ' ' && *p < 127 )
                        ascii.push_back( *p );
                else
                        ascii.push_back( '.' );

                if( x == 16 )
                {
                        cout << " " << ascii.c_str() << endl;
                        x = 0;
                        ascii = "";
                }
                p++;
                cnt++;
        }
        if( x > 0 )
        {
                if( x < 8 ) cout << " ";
                while( x++ < 16 )
                        cout << "   ";
                cout << " " << ascii.c_str() << endl;
        }
        sprintf( lineStr, "%5.05lu ", cnt );
        cout << lineStr << endl;
}
}

Reply via email to