2023-06-16 12:38:10 -07:00
/**
2023-06-16 14:58:22 -07:00
* This file is a part of the UMSKT Project
2023-06-16 12:38:10 -07:00
*
2023-06-16 14:58:22 -07:00
* Copyleft ( C ) 2019 - 2023 UMSKT Contributors ( et . al . )
2023-06-16 12:38:10 -07:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
* @ FileCreated by Andrew on 01 / 06 / 2023
* @ Maintainer Neo
*/
2023-06-01 16:09:22 +03:00
2023-06-07 12:23:59 -07:00
# include "cli.h"
2023-06-01 16:09:22 +03:00
2023-09-25 12:05:23 +01:00
CLI : : ~ CLI ( )
{
EC_GROUP_free ( eCurve ) ;
EC_POINT_free ( genPoint ) ;
EC_POINT_free ( pubPoint ) ;
BN_free ( privateKey ) ;
BN_free ( genOrder ) ;
}
2023-06-07 12:23:59 -07:00
bool CLI : : loadJSON ( const fs : : path & filename , json * output ) {
2023-07-09 00:08:43 -03:00
if ( ! filename . empty ( ) & & ! fs : : exists ( filename ) ) {
2023-06-06 18:04:39 -04:00
fmt : : print ( " ERROR: File {} does not exist \n " , filename . string ( ) ) ;
2023-06-05 08:43:31 -07:00
return false ;
}
2023-07-09 00:08:43 -03:00
else if ( fs : : exists ( filename ) ) {
std : : ifstream f ( filename ) ;
* output = json : : parse ( f , nullptr , false , false ) ;
}
else if ( filename . empty ( ) ) {
cmrc : : embedded_filesystem fs = cmrc : : umskt : : get_filesystem ( ) ;
cmrc : : file keys = fs . open ( " keys.json " ) ;
* output = json : : parse ( keys , nullptr , false , false ) ;
}
2023-06-06 18:04:39 -04:00
if ( output - > is_discarded ( ) ) {
fmt : : print ( " ERROR: Unable to parse keys from {} \n " , filename . string ( ) ) ;
return false ;
}
2023-06-05 08:43:31 -07:00
return true ;
}
2023-06-07 12:23:59 -07:00
void CLI : : showHelp ( char * argv [ ] ) {
2023-06-05 08:43:31 -07:00
fmt : : print ( " usage: {} \n " , argv [ 0 ] ) ;
fmt : : print ( " \t -h --help \t show this message \n " ) ;
fmt : : print ( " \t -v --verbose \t enable verbose output \n " ) ;
2023-06-06 18:04:39 -04:00
fmt : : print ( " \t -n --number \t number of keys to generate (defaults to 1) \n " ) ;
2023-07-09 00:08:43 -03:00
fmt : : print ( " \t -f --file \t specify which keys file to load \n " ) ;
2023-06-06 18:04:39 -04:00
fmt : : print ( " \t -i --instid \t installation ID used to generate confirmation ID \n " ) ;
2023-09-02 23:22:53 +10:00
fmt : : print ( " \t -m --mode \t product family to activate. \n \t \t \t valid options are \" WINDOWS \" , \" OFFICEXP \" , \" OFFICE2K3 \" , \" OFFICE2K7 \" or \" PLUSDME \" \n \t \t \t (defaults to \" WINDOWS \" ) \n " ) ;
fmt : : print ( " \t -p --productid \t the product ID of the Program to activate. only required for Office 2K3 and Office 2K7 programs \n " ) ;
2023-06-05 08:43:31 -07:00
fmt : : print ( " \t -b --binkid \t specify which BINK identifier to load (defaults to 2E) \n " ) ;
fmt : : print ( " \t -l --list \t show which products/binks can be loaded \n " ) ;
fmt : : print ( " \t -c --channelid \t specify which Channel Identifier to use (defaults to 640) \n " ) ;
2023-07-04 11:20:17 +01:00
fmt : : print ( " \t -s --serial \t specifies a serial to use in the product ID (defaults to random, BINK1998 only) \n " ) ;
2023-08-10 16:51:53 +10:00
fmt : : print ( " \t -u --upgrade \t specifies the Product Key will be an \" Upgrade \" version \n " ) ;
2023-06-19 20:41:27 +01:00
fmt : : print ( " \t -V --validate \t product key to validate signature \n " ) ;
2023-09-02 11:39:22 -04:00
fmt : : print ( " \t -N --nonewlines \t disables newlines (for easier embedding in other apps) \n " ) ;
2023-07-09 00:08:43 -03:00
fmt : : print ( " \n " ) ;
2023-06-01 21:25:43 -07:00
}
2023-06-07 12:23:59 -07:00
int CLI : : parseCommandLine ( int argc , char * argv [ ] , Options * options ) {
2023-07-09 00:08:43 -03:00
// set default options
2023-06-05 08:43:31 -07:00
* options = Options {
2023-06-07 12:23:59 -07:00
" 2E " ,
2023-07-09 00:08:43 -03:00
" " ,
2023-06-07 12:23:59 -07:00
" " ,
2023-06-19 20:41:27 +01:00
" " ,
2023-09-02 23:22:53 +10:00
" " ,
2023-06-07 12:23:59 -07:00
640 ,
2023-07-04 11:20:17 +01:00
0 ,
2023-06-07 12:23:59 -07:00
1 ,
false ,
false ,
false ,
false ,
2023-07-09 00:08:43 -03:00
false ,
2023-09-02 23:22:53 +10:00
false ,
2023-09-02 11:37:41 -04:00
false ,
2023-09-02 23:22:53 +10:00
MODE_BINK1998_GENERATE ,
WINDOWS
2023-06-01 21:25:43 -07:00
} ;
for ( int i = 1 ; i < argc ; i + + ) {
std : : string arg = argv [ i ] ;
if ( arg = = " -v " | | arg = = " --verbose " ) {
2023-06-05 08:43:31 -07:00
options - > verbose = true ;
2023-07-09 00:08:43 -03:00
UMSKT : : setDebugOutput ( stderr ) ;
2023-06-01 21:25:43 -07:00
} else if ( arg = = " -h " | | arg = = " --help " ) {
2023-06-05 08:43:31 -07:00
options - > help = true ;
2023-06-06 18:04:39 -04:00
} else if ( arg = = " -n " | | arg = = " --number " ) {
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
int nKeys ;
if ( ! sscanf ( argv [ i + 1 ] , " %d " , & nKeys ) ) {
options - > error = true ;
} else {
options - > numKeys = nKeys ;
}
i + + ;
2023-06-01 21:25:43 -07:00
} else if ( arg = = " -b " | | arg = = " --bink " ) {
2023-06-06 18:04:39 -04:00
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
2023-06-05 08:43:31 -07:00
options - > binkid = argv [ i + 1 ] ;
2023-06-01 21:25:43 -07:00
i + + ;
} else if ( arg = = " -l " | | arg = = " --list " ) {
2023-06-05 08:43:31 -07:00
options - > list = true ;
2023-06-01 21:25:43 -07:00
} else if ( arg = = " -c " | | arg = = " --channelid " ) {
2023-06-06 18:04:39 -04:00
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
2023-06-01 21:25:43 -07:00
int siteID ;
if ( ! sscanf ( argv [ i + 1 ] , " %d " , & siteID ) ) {
2023-06-05 08:43:31 -07:00
options - > error = true ;
2023-06-01 21:25:43 -07:00
} else {
2023-06-05 08:43:31 -07:00
options - > channelID = siteID ;
2023-06-01 21:25:43 -07:00
}
i + + ;
2023-07-04 11:20:17 +01:00
} else if ( arg = = " -s " | | arg = = " --serial " ) {
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
int serial_val ;
if ( ! sscanf ( argv [ i + 1 ] , " %d " , & serial_val ) ) {
options - > error = true ;
} else {
options - > serialSet = true ;
options - > serial = serial_val ;
}
i + + ;
2023-08-10 17:16:24 +10:00
} else if ( arg = = " -u " | | arg = = " --upgrade " ) {
options - > upgrade = true ;
2023-06-05 08:43:31 -07:00
} else if ( arg = = " -f " | | arg = = " --file " ) {
2023-06-06 18:04:39 -04:00
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
2023-06-05 08:43:31 -07:00
options - > keysFilename = argv [ i + 1 ] ;
i + + ;
2023-06-06 18:04:39 -04:00
} else if ( arg = = " -i " | | arg = = " --instid " ) {
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
options - > instid = argv [ i + 1 ] ;
2023-06-08 14:40:11 -04:00
options - > applicationMode = MODE_CONFIRMATION_ID ;
2023-06-06 18:04:39 -04:00
i + + ;
2023-09-02 23:22:53 +10:00
} else if ( arg = = " -m " | | arg = = " --mode " ) {
std : : string mode = argv [ i + 1 ] ;
char * p = & mode [ 0 ] ;
2023-09-02 23:51:08 +10:00
for ( ; * p ; p + + ) {
* p = toupper ( ( unsigned char ) * p ) ;
2023-09-02 23:22:53 +10:00
}
2023-09-02 23:51:08 +10:00
p = & mode [ 0 ] ;
2023-09-02 23:22:53 +10:00
if ( strcmp ( p , " WINDOWS " ) = = 0 ) {
options - > activationMode = WINDOWS ;
} else if ( strcmp ( p , " OFFICEXP " ) = = 0 ) {
options - > activationMode = OFFICE_XP ;
} else if ( strcmp ( p , " OFFICE2K3 " ) = = 0 ) {
options - > activationMode = OFFICE_2K3 ;
} else if ( strcmp ( p , " OFFICE2K7 " ) = = 0 ) {
options - > activationMode = OFFICE_2K7 ;
} else if ( strcmp ( p , " PLUSDME " ) = = 0 ) {
options - > activationMode = PLUS_DME ;
}
i + + ;
} else if ( arg = = " -p " | | arg = = " --productid " ) {
2023-09-25 11:21:42 +01:00
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
2023-09-02 23:22:53 +10:00
options - > productid = argv [ i + 1 ] ;
i + + ;
2023-06-19 20:41:27 +01:00
} else if ( arg = = " -V " | | arg = = " --validate " ) {
if ( i = = argc - 1 ) {
options - > error = true ;
break ;
}
options - > keyToCheck = argv [ i + 1 ] ;
options - > applicationMode = MODE_BINK1998_VALIDATE ;
i + + ;
2023-09-02 11:37:41 -04:00
2023-09-02 11:53:09 -04:00
} else if ( arg = = " -N " | | arg = = " --nonewlines " ) {
2023-09-02 11:37:41 -04:00
options - > nonewlines = true ;
} else {
2023-06-05 08:43:31 -07:00
options - > error = true ;
}
}
2023-09-02 23:22:53 +10:00
// make sure that a product id is entered for OFFICE_2K3 or OFFICE_2K7 IIDs
2023-09-25 11:26:28 +01:00
if ( ( options - > activationMode = = OFFICE_2K3 | | options - > activationMode = = OFFICE_2K7 ) & & ( options - > productid . empty ( ) | | options - > instid . empty ( ) ) ) {
2023-09-02 23:22:53 +10:00
return options - > error = true ;
}
2023-06-05 08:43:31 -07:00
return ! options - > error ;
}
2023-06-07 12:23:59 -07:00
int CLI : : validateCommandLine ( Options * options , char * argv [ ] , json * keys ) {
2023-07-09 00:08:43 -03:00
if ( options - > help | | options - > error ) {
if ( options - > error ) {
fmt : : print ( " error parsing command line options \n " ) ;
}
showHelp ( argv ) ;
return 1 ;
}
2023-06-05 08:43:31 -07:00
if ( options - > verbose ) {
2023-07-09 00:08:43 -03:00
if ( options - > keysFilename . empty ( ) ) {
fmt : : print ( " Loading internal keys file \n " ) ;
} else {
fmt : : print ( " Loading keys file {} \n " , options - > keysFilename ) ;
}
2023-06-05 08:43:31 -07:00
}
if ( ! loadJSON ( options - > keysFilename , keys ) ) {
return 2 ;
}
if ( options - > verbose ) {
2023-07-09 00:08:43 -03:00
if ( options - > keysFilename . empty ( ) ) {
fmt : : print ( " Loaded internal keys file successfully \n " ) ;
} else {
fmt : : print ( " Loaded keys from {} successfully \n " , options - > keysFilename ) ;
2023-06-06 18:04:39 -04:00
}
2023-06-05 08:43:31 -07:00
}
if ( options - > list ) {
for ( auto el : ( * keys ) [ " Products " ] . items ( ) ) {
int id ;
sscanf ( ( el . value ( ) [ " BINK " ] [ 0 ] ) . get < std : : string > ( ) . c_str ( ) , " %x " , & id ) ;
2023-06-06 15:31:31 -07:00
std : : cout < < el . key ( ) < < " : " < < el . value ( ) [ " BINK " ] < < std : : endl ;
2023-10-07 17:37:02 +02:00
if ( ! el . value ( ) [ " CID " ] . is_null ( ) & & ! el . value ( ) [ " CID " ] . empty ( ) ) {
std : : cout < < " \t " < < " Valid Channel IDs: " < < std : : endl ;
for ( auto range : el . value ( ) [ " CID " ] . items ( ) ) {
std : : cout < < " \t \t " < < range . key ( ) < < " : " < < range . value ( ) < < std : : endl ;
}
std : : cout < < std : : endl ;
}
2023-06-01 21:25:43 -07:00
}
2023-06-05 08:43:31 -07:00
fmt : : print ( " \n \n " ) ;
fmt : : print ( " ** Please note: any BINK ID other than 2E is considered experimental at this time ** \n " ) ;
fmt : : print ( " \n " ) ;
return 1 ;
2023-06-01 21:25:43 -07:00
}
2023-06-05 08:43:31 -07:00
int intBinkID ;
sscanf ( options - > binkid . c_str ( ) , " %x " , & intBinkID ) ;
2023-09-01 22:43:32 -04:00
// FE and FF are BINK 1998, but do not generate valid keys, so we throw an error
if ( intBinkID > = 0xFE ) {
fmt : : print ( " ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time \n " ) ;
return 1 ;
}
2023-06-06 18:04:39 -04:00
if ( intBinkID > = 0x40 ) {
2023-06-19 20:41:27 +01:00
// set bink2002 validate mode if in bink1998 validate mode, else set bink2002 generate mode
options - > applicationMode = ( options - > applicationMode = = MODE_BINK1998_VALIDATE ) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE ;
2023-06-05 08:43:31 -07:00
}
if ( options - > channelID > 999 ) {
2023-06-07 12:23:59 -07:00
fmt : : print ( " ERROR: refusing to create a key with a Channel ID greater than 999 \n " ) ;
2023-06-05 08:43:31 -07:00
return 1 ;
}
2023-07-04 11:20:17 +01:00
// don't allow any serial not between 0 and 999999
if ( options - > serial > 999999 | | options - > serial < 0 ) {
fmt : : print ( " ERROR: refusing to create a key with a Serial not between 000000 and 999999 \n " ) ;
return 1 ;
}
2023-06-05 08:43:31 -07:00
return 0 ;
2023-06-01 21:25:43 -07:00
}
2023-07-09 00:08:43 -03:00
void CLI : : printID ( DWORD * pid ) {
2023-06-01 16:09:22 +03:00
char raw [ 12 ] ;
char b [ 6 ] , c [ 8 ] ;
int i , digit = 0 ;
2023-07-04 11:20:17 +01:00
// Convert PID to ascii-number (=raw)
2023-07-25 18:53:42 +12:00
snprintf ( raw , sizeof ( raw ) , " %09u " , pid [ 0 ] ) ;
2023-06-01 16:09:22 +03:00
// Make b-part {640-....}
strncpy ( b , raw , 3 ) ;
b [ 3 ] = 0 ;
// Make c-part {...-123456X...}
strcpy ( c , raw + 3 ) ;
// Make checksum digit-part {...56X-}
assert ( strlen ( c ) = = 6 ) ;
for ( i = 0 ; i < 6 ; i + + )
digit - = c [ i ] - ' 0 ' ; // Sum digits
while ( digit < 0 )
digit + = 7 ;
c [ 6 ] = digit + ' 0 ' ;
c [ 7 ] = 0 ;
2023-07-04 11:20:17 +01:00
fmt : : print ( " > Product ID: PPPPP-{}-{}-23xxx \n " , b , c ) ;
2023-06-01 16:09:22 +03:00
}
2023-06-10 20:52:32 +03:00
void CLI : : printKey ( char * pk ) {
2023-06-19 20:41:27 +01:00
assert ( strlen ( pk ) > = PK_LENGTH ) ;
2023-06-05 08:43:31 -07:00
std : : string spk = pk ;
2023-06-18 03:28:20 -05:00
fmt : : print ( " {}-{}-{}-{}-{} " ,
2023-06-05 08:43:31 -07:00
spk . substr ( 0 , 5 ) ,
spk . substr ( 5 , 5 ) ,
spk . substr ( 10 , 5 ) ,
spk . substr ( 15 , 5 ) ,
spk . substr ( 20 , 5 ) ) ;
2023-06-07 12:23:59 -07:00
}
2023-06-19 20:41:27 +01:00
bool CLI : : stripKey ( const char * in_key , char out_key [ PK_LENGTH ] ) {
// copy out the product key stripping out extraneous characters
const char * p = in_key ;
size_t i = 0 ;
for ( ; * p ; p + + ) {
// strip out space or dash
if ( * p = = ' ' | | * p = = ' - ' )
continue ;
// check if we've passed the product key length to avoid overflow
if ( i > = PK_LENGTH )
return false ;
// convert to uppercase - if character allowed, copy into array
2023-07-09 00:08:43 -03:00
for ( int j = 0 ; j < strlen ( PIDGEN3 : : pKeyCharset ) ; j + + ) {
if ( toupper ( * p ) = = PIDGEN3 : : pKeyCharset [ j ] ) {
2023-06-19 20:41:27 +01:00
out_key [ i + + ] = toupper ( * p ) ;
continue ;
}
}
}
// only return true if we've handled exactly PK_LENGTH chars
return ( i = = PK_LENGTH ) ;
}
2023-06-07 12:23:59 -07:00
CLI : : CLI ( Options options , json keys ) {
2023-06-07 15:43:45 -04:00
this - > options = options ;
2023-06-11 07:03:24 -07:00
this - > keys = keys ;
2023-06-07 15:43:45 -04:00
2023-06-11 07:03:24 -07:00
this - > BINKID = options . binkid . c_str ( ) ;
2023-06-07 12:23:59 -07:00
// We cannot produce a valid key without knowing the private key k. The reason for this is that
// we need the result of the function K(x; y) = kG(x; y).
2023-06-11 07:03:24 -07:00
this - > privateKey = BN_new ( ) ;
2023-06-07 12:23:59 -07:00
// We can, however, validate any given key using the available public key: {p, a, b, G, K}.
// genOrder the order of the generator G, a value we have to reverse -> Schoof's Algorithm.
2023-06-11 07:03:24 -07:00
this - > genOrder = BN_new ( ) ;
2023-06-07 12:23:59 -07:00
/* Computed data */
2023-06-11 07:03:24 -07:00
BN_dec2bn ( & this - > genOrder , this - > keys [ " BINK " ] [ this - > BINKID ] [ " n " ] . get < std : : string > ( ) . c_str ( ) ) ;
BN_dec2bn ( & this - > privateKey , this - > keys [ " BINK " ] [ this - > BINKID ] [ " priv " ] . get < std : : string > ( ) . c_str ( ) ) ;
2023-06-07 12:23:59 -07:00
if ( options . verbose ) {
fmt : : print ( " ----------------------------------------------------------- \n " ) ;
2023-06-11 07:03:24 -07:00
fmt : : print ( " Loaded the following elliptic curve parameters: BINK[{}] \n " , this - > BINKID ) ;
2023-06-07 12:23:59 -07:00
fmt : : print ( " ----------------------------------------------------------- \n " ) ;
2023-06-11 07:03:24 -07:00
fmt : : print ( " P: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " p " ] . get < std : : string > ( ) ) ;
fmt : : print ( " a: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " a " ] . get < std : : string > ( ) ) ;
fmt : : print ( " b: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " b " ] . get < std : : string > ( ) ) ;
fmt : : print ( " Gx: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " g " ] [ " x " ] . get < std : : string > ( ) ) ;
fmt : : print ( " Gy: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " g " ] [ " y " ] . get < std : : string > ( ) ) ;
fmt : : print ( " Kx: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " pub " ] [ " x " ] . get < std : : string > ( ) ) ;
fmt : : print ( " Ky: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " pub " ] [ " y " ] . get < std : : string > ( ) ) ;
fmt : : print ( " n: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " n " ] . get < std : : string > ( ) ) ;
fmt : : print ( " k: {} \n " , this - > keys [ " BINK " ] [ this - > BINKID ] [ " priv " ] . get < std : : string > ( ) ) ;
2023-06-07 12:23:59 -07:00
fmt : : print ( " \n " ) ;
}
2023-07-09 00:08:43 -03:00
eCurve = PIDGEN3 : : initializeEllipticCurve (
2023-06-11 07:03:24 -07:00
this - > keys [ " BINK " ] [ this - > BINKID ] [ " p " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " a " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " b " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " g " ] [ " x " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " g " ] [ " y " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " pub " ] [ " x " ] . get < std : : string > ( ) ,
this - > keys [ " BINK " ] [ this - > BINKID ] [ " pub " ] [ " y " ] . get < std : : string > ( ) ,
this - > genPoint ,
this - > pubPoint
2023-06-07 12:23:59 -07:00
) ;
2023-06-11 07:03:24 -07:00
this - > count = 0 ;
this - > total = this - > options . numKeys ;
2023-06-07 12:23:59 -07:00
}
2023-06-19 20:41:27 +01:00
int CLI : : BINK1998Generate ( ) {
2023-07-04 11:20:17 +01:00
// raw PID/serial value
2023-06-11 07:03:24 -07:00
DWORD nRaw = this - > options . channelID * 1'000'000 ; /* <- change */
2023-06-07 12:23:59 -07:00
2023-07-04 11:20:17 +01:00
// using user-provided serial
if ( this - > options . serialSet ) {
// just in case, make sure it's less than 999999
int serialRnd = ( this - > options . serial % 999999 ) ;
nRaw + = serialRnd ;
} else {
// generate a random number to use as a serial
BIGNUM * bnrand = BN_new ( ) ;
BN_rand ( bnrand , 19 , BN_RAND_TOP_ANY , BN_RAND_BOTTOM_ANY ) ;
int oRaw ;
char * cRaw = BN_bn2dec ( bnrand ) ;
sscanf ( cRaw , " %d " , & oRaw ) ;
nRaw + = ( oRaw % 999999 ) ; // ensure our serial is less than 999999
2023-09-25 12:05:23 +01:00
BN_free ( bnrand ) ;
2023-07-04 11:20:17 +01:00
}
2023-06-07 12:23:59 -07:00
2023-06-11 07:03:24 -07:00
if ( this - > options . verbose ) {
2023-07-04 11:20:17 +01:00
// print the resulting Product ID
// PID value is printed in BINK1998::Generate
printID ( & nRaw ) ;
2023-06-07 12:23:59 -07:00
}
// generate a key
2023-06-11 07:03:24 -07:00
BN_sub ( this - > privateKey , this - > genOrder , this - > privateKey ) ;
2023-06-10 19:38:22 +03:00
2023-06-11 07:03:24 -07:00
for ( int i = 0 ; i < this - > total ; i + + ) {
2023-09-02 23:22:53 +10:00
PIDGEN3 : : BINK1998 : : Generate ( this - > eCurve , this - > genPoint , this - > genOrder , this - > privateKey , nRaw , options . upgrade , this - > pKey ) ;
2023-06-07 12:23:59 -07:00
2023-07-09 00:08:43 -03:00
bool isValid = PIDGEN3 : : BINK1998 : : Verify ( this - > eCurve , this - > genPoint , this - > pubPoint , this - > pKey ) ;
2023-06-18 03:28:20 -05:00
if ( isValid ) {
CLI : : printKey ( this - > pKey ) ;
if ( i < this - > total - 1 | | this - > options . verbose ) {
fmt : : print ( " \n " ) ;
}
this - > count + = isValid ;
}
else {
if ( this - > options . verbose ) {
CLI : : printKey ( this - > pKey ) ;
fmt : : print ( " [Invalid] " ) ;
if ( i < this - > total - 1 ) {
fmt : : print ( " \n " ) ;
}
}
this - > total + + ; // queue a redo, basically
}
}
if ( this - > options . verbose ) {
fmt : : print ( " \n Success count: {}/{} " , this - > count , this - > total ) ;
2023-06-07 12:23:59 -07:00
}
2023-09-02 11:39:22 -04:00
if ( this - > options . nonewlines = = false ) {
2023-09-02 11:37:41 -04:00
fmt : : print ( " \n " ) ;
}
2023-06-07 12:23:59 -07:00
return 0 ;
}
2023-06-19 20:41:27 +01:00
int CLI : : BINK2002Generate ( ) {
2023-06-11 07:03:24 -07:00
DWORD pChannelID = this - > options . channelID ;
2023-06-07 12:23:59 -07:00
2023-06-11 07:03:24 -07:00
if ( this - > options . verbose ) {
fmt : : print ( " > Channel ID: {:03d} \n " , this - > options . channelID ) ;
2023-06-07 12:23:59 -07:00
}
// generate a key
2023-06-11 07:03:24 -07:00
for ( int i = 0 ; i < this - > total ; i + + ) {
2023-06-07 12:23:59 -07:00
DWORD pAuthInfo ;
RAND_bytes ( ( BYTE * ) & pAuthInfo , 4 ) ;
2023-06-10 19:38:22 +03:00
pAuthInfo & = BITMASK ( 10 ) ;
2023-06-07 12:23:59 -07:00
2023-06-11 07:03:24 -07:00
if ( this - > options . verbose ) {
2023-06-07 12:23:59 -07:00
fmt : : print ( " > AuthInfo: {} \n " , pAuthInfo ) ;
}
2023-09-02 23:22:53 +10:00
PIDGEN3 : : BINK2002 : : Generate ( this - > eCurve , this - > genPoint , this - > genOrder , this - > privateKey , pChannelID , pAuthInfo , options . upgrade , this - > pKey ) ;
2023-06-07 12:23:59 -07:00
2023-07-09 00:08:43 -03:00
bool isValid = PIDGEN3 : : BINK2002 : : Verify ( this - > eCurve , this - > genPoint , this - > pubPoint , this - > pKey ) ;
2023-06-18 03:28:20 -05:00
if ( isValid ) {
CLI : : printKey ( this - > pKey ) ;
2023-07-28 16:50:40 -05:00
if ( i < this - > total - 1 | | this - > options . verbose ) { // check if end of list or verbose
2023-06-18 03:28:20 -05:00
fmt : : print ( " \n " ) ;
}
2023-07-28 16:50:40 -05:00
this - > count + = isValid ; // add to count
2023-06-18 03:28:20 -05:00
}
else {
if ( this - > options . verbose ) {
2023-07-28 16:50:40 -05:00
CLI : : printKey ( this - > pKey ) ; // print the key
fmt : : print ( " [Invalid] " ) ; // and add " [Invalid]" to the key
if ( i < this - > total - 1 ) { // check if end of list
2023-06-18 03:28:20 -05:00
fmt : : print ( " \n " ) ;
}
}
this - > total + + ; // queue a redo, basically
}
}
if ( this - > options . verbose ) {
fmt : : print ( " \n Success count: {}/{} " , this - > count , this - > total ) ;
2023-06-07 12:23:59 -07:00
}
2023-09-02 11:39:22 -04:00
if ( this - > options . nonewlines = = false ) {
2023-09-02 11:37:41 -04:00
fmt : : print ( " \n " ) ;
}
2023-06-07 12:23:59 -07:00
return 0 ;
}
2023-06-19 20:41:27 +01:00
int CLI : : BINK1998Validate ( ) {
char product_key [ PK_LENGTH ] { } ;
if ( ! CLI : : stripKey ( this - > options . keyToCheck . c_str ( ) , product_key ) ) {
fmt : : print ( " ERROR: Product key is in an incorrect format! \n " ) ;
return 1 ;
}
CLI : : printKey ( product_key ) ;
fmt : : print ( " \n " ) ;
2023-07-09 00:08:43 -03:00
if ( ! PIDGEN3 : : BINK1998 : : Verify ( this - > eCurve , this - > genPoint , this - > pubPoint , product_key ) ) {
2023-06-19 20:41:27 +01:00
fmt : : print ( " ERROR: Product key is invalid! Wrong BINK ID? \n " ) ;
return 1 ;
}
fmt : : print ( " Key validated successfully! \n " ) ;
return 0 ;
}
int CLI : : BINK2002Validate ( ) {
char product_key [ PK_LENGTH ] { } ;
if ( ! CLI : : stripKey ( this - > options . keyToCheck . c_str ( ) , product_key ) ) {
fmt : : print ( " ERROR: Product key is in an incorrect format! \n " ) ;
return 1 ;
}
CLI : : printKey ( product_key ) ;
fmt : : print ( " \n " ) ;
2023-07-09 00:08:43 -03:00
if ( ! PIDGEN3 : : BINK2002 : : Verify ( this - > eCurve , this - > genPoint , this - > pubPoint , product_key ) ) {
2023-06-19 20:41:27 +01:00
fmt : : print ( " ERROR: Product key is invalid! Wrong BINK ID? \n " ) ;
return 1 ;
}
fmt : : print ( " Key validated successfully! \n " ) ;
return 0 ;
}
2023-06-07 12:23:59 -07:00
int CLI : : ConfirmationID ( ) {
char confirmation_id [ 49 ] ;
2023-09-02 23:22:53 +10:00
int err = ConfirmationID : : Generate ( this - > options . instid . c_str ( ) , confirmation_id , options . activationMode , options . productid ) ;
2023-06-07 12:23:59 -07:00
switch ( err ) {
case ERR_TOO_SHORT :
fmt : : print ( " ERROR: Installation ID is too short. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case ERR_TOO_LARGE :
fmt : : print ( " ERROR: Installation ID is too long. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case ERR_INVALID_CHARACTER :
fmt : : print ( " ERROR: Invalid character in installation ID. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case ERR_INVALID_CHECK_DIGIT :
fmt : : print ( " ERROR: Installation ID checksum failed. Please check that it is typed correctly. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case ERR_UNKNOWN_VERSION :
fmt : : print ( " ERROR: Unknown installation ID version. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case ERR_UNLUCKY :
fmt : : print ( " ERROR: Unable to generate valid confirmation ID. \n " ) ;
return 1 ;
2023-06-11 07:03:24 -07:00
2023-06-07 12:23:59 -07:00
case SUCCESS :
2023-06-18 03:28:20 -05:00
fmt : : print ( confirmation_id ) ;
2023-09-02 11:39:22 -04:00
if ( this - > options . nonewlines = = false ) {
2023-09-02 11:37:41 -04:00
fmt : : print ( " \n " ) ;
}
2023-06-07 12:23:59 -07:00
return 0 ;
default :
fmt : : print ( " Unknown error occurred during Confirmation ID generation: {} \n " , err ) ;
}
return 1 ;
}