/*
** rigol keygen / cybernet & the-eevblog-users
**
** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
** then run 'bash linux' to build the miracle.a library
**
** BUILD WITH:
**
** gcc riglol.c -I../MIRACL ../MIRACL/miracl.a -o riglol
**
** adapt -I and path to miracl.a to your environment
**
** more info: http://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
*/
// #define DEBUG
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"
// ECC SETTINGS
char DP832_private_key[] = "5C393C30FACCF4";
char DS2000_private_key[] = "8EEBD4D04C3771";
char DSA815_private_key[] = "80444DFECE903E";
char private_key[] = "";
char prime1[] = "AEBF94CEE3E707";
char prime2[] = "AEBF94D5C6AA71";
char curve_a[] = "2982";
char curve_b[] = "3408";
char point1[] = "7A3E808599A525";
char point2[] = "28BE7FAFD2A052";
/*
** take serial and options make sha1 hash out of it
*/
static void hashing(char *opt_str, big hash) {
char *p;
char h[20];
int ch;
sha sh;
shs_init(&sh);
p = opt_str;
while(*p) {
shs_process(&sh, *p);
p++;
}
shs_hash(&sh, h);
bytes_to_big(20, h, hash);
}
/*
** sign the secret message (serial + opts) with the private key
*/
void ecssign(char *serial, char *options, char *privk, char *lic1, char *lic2) {
int k_offset = 0; // optionally change ecssign starting offset (changes lic1; makes different licenses)
mirsys(800, 16)->IOBASE = 16;
sha sha1;
shs_init(&sha1);
char *ptr = serial;
while(*ptr) shs_process(&sha1, *ptr++);
ptr = options;
while(*ptr) shs_process(&sha1, *ptr++);
char h[20];
shs_hash(&sha1, h);
big hash = mirvar(0);
bytes_to_big(20, h, hash);
big a = mirvar(0);
instr(a, curve_a);
big b = mirvar(0);
instr(b, curve_b);
big p = mirvar(0);
instr(p, prime1);
big q = mirvar(0);
instr(q, prime2);
big Gx = mirvar(0);
instr(Gx, point1);
big Gy = mirvar(0);
instr(Gy, point2);
big d = mirvar(0);
instr(d, privk);
big k = mirvar(0);
big r = mirvar(0);
big s = mirvar(0);
big k1 = mirvar(0);
big zero = mirvar(0);
big f1 = mirvar(17);
big f2 = mirvar(53);
big f3 = mirvar(905461);
big f4 = mirvar(60291817);
incr(k, k_offset, k);
epoint *G = epoint_init();
epoint *kG = epoint_init();
ecurve_init(a, b, p, MR_PROJECTIVE);
epoint_set(Gx, Gy, 0, G);
for(;;) {
incr(k, 1, k);
if(divisible(k, f1) || divisible(k, f2) || divisible(k, f3) || divisible(k, f4))
continue;
ecurve_mult(k, G, kG);
epoint_get(kG, r, r);
divide(r, q, q);
if(mr_compare(r, zero) == 0)
continue;
xgcd(k, q, k1, k1, k1);
mad(d, r, hash, q, q, s);
mad(s, k1, k1, q, q, s);
if(!divisible(s, f1) && !divisible(s, f2) && !divisible(s, f3) && !divisible(s, f4))
break;
}
cotstr(r, lic1);
cotstr(s, lic2);
}
/*
** convert string to uppercase chars
*/
char * strtoupper(char *str) {
char *newstr, *p;
p = newstr = (char*) strdup((char*)str);
while ((*p++ = toupper(*p)));
return newstr;
}
/*
** prepend a char to a string
*/
char * prepend(char *c, char *str) {
int i;
for (i = strlen(str); i >= 0; i--) {
str[i + 1] = str[i];
}
str[0] = *c;
return c;
}
/*
** convert hex-ascii-string to rigol license format
*/
void map_hex_to_rigol(char *io) {
unsigned long long b = 0;
int i = 0;
char map[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'2', '3', '4', '5', '6', '7', '8', '9'
};
/* hex2dez */
while (io[i] != '\0') {
if (io[i] >= '0' && io[i] <= '9') {
b = b * 16 + io[i] - '0';
} else if (io[i] >= 'A' && io[i] <= 'F') {
b = b * 16 + io[i] - 'A' + 10;
} else if (io[i] >= 'a' && io[i] <= 'f') {
b = b * 16 + io[i] - 'a' + 10;
}
i++;
}
for (i = 3; ; i--) {
io[i] = map[b & 0x1F];
if (i == 0) break;
b >>= 5;
}
io[4] = '\0';
}
void show_help(char *cmd) {
printf("Usage: %s <sn> <opts> <privkey>\n", cmd);
printf(" <sn> serial number of device (D............)\n");
printf(" <opts> device options, 4 characters, see below\n");
printf(" <privkey> private key (optional)\n");
printf("\n");
printf("DS2000 and DS4000 device options:\n");
printf(" first character: D = official, V = trial\n");
printf(" second character: S\n");
printf(" third character: A = DS2000, H = DS4000\n");
printf(" last character : your options, use the following table to generate for DS2000:\n");
printf(" --------- A B C D E F G H J K L M N P Q R S T U V W X Y Z 2 3 4 5 6 7 8 9\n");
printf(" 100MHz ' ' ' ' ' ' ' ' * * * * * * * * ' ' ' ' ' ' ' ' * * * * * * * *\n");
printf(" 200MHz ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' * * * * * * * * * * * * * * * *\n");
printf(" Memory56M ' ' ' ' * * * * ' ' ' ' * * * * ' ' ' ' * * * * ' ' ' ' * * * *\n");
printf(" Decode ' ' * * ' ' * * ' ' * * ' ' * * ' ' * * ' ' * * ' ' * * ' ' * *\n");
printf(" Triggers ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' * ' *\n");
printf(" For DS4000, try DSH9, VSH9 to enable all options.\n");
printf("\n");
printf("DP832 device options:\n");
printf(" first character: M = official, 5 = trial\n");
printf(" MWSS - Trigger\n");
printf(" MWTB - Accuracy\n");
printf(" MWTC - LAN and RS232\n");
printf(" MWTE - Analyzer and Monitor\n");
printf("\n");
printf("DSA815 device options:\n");
printf(" first character: A = official, S = trial\n");
printf(" AAAB - tracking generator\n");
printf(" AAAC - adv measurement kit\n");
printf(" AAAD - 10Hz RBW\n");
printf(" AAAE - EMI/Quasi Peak\n");
printf(" AAAF - VSWR\n");
printf("\n");
printf("MAKE SURE YOUR FIRMWARE IS UP TO DATE BEFORE APPLYING ANY KEYS\n");
}
/*
** the world ends here
*/
int main(int argc, char *argv[0]) {
char *options, *lic1_code, *lic2_code, *lic_all;
char *chunk, *temp, *final;
char *priv_key;
char *serial;
int i = 0, j = 0;
/* parse input */
if (!((argc == 3 || argc == 4))) {
show_help(argv[0]);
exit(-1);
}
serial = strtoupper((char*)argv[1]);
options = strtoupper((char*)argv[2]);
if (argc == 4) priv_key = (char*)argv[3];
else if (!strncmp(serial, "DS2", 3)) priv_key = DS2000_private_key;
else if (!strncmp(serial, "DS4", 3)) priv_key = DS2000_private_key;
else if (!strncmp(serial, "DS6", 3)) priv_key = DS2000_private_key;
else if (!strncmp(serial, "DSA", 3)) priv_key = DSA815_private_key;
else if (!strncmp(serial, "DP8", 3)) priv_key = DP832_private_key;
else {
show_help(argv[0]);
printf("\nERROR: UNKNOW DEVICE WITHOUT PRIVATKEY\n");
exit(-1);
}
strtoupper(priv_key);
if (strlen(priv_key) != 14) {
show_help(argv[0]);
printf("\nERROR: INVALID PRIVATE KEY LENGTH\n");
exit(-1);
}
if (strlen(serial) < 13) {
show_help(argv[0]);
printf("\nERROR: INVALID SERIAL LENGTH\n");
exit(-1);
}
if (strlen(options) != 4) {
show_help(argv[0]);
printf("\nERROR: INVALID OPTIONS LENGTH\n");
exit(-1);
}
#ifdef DEBUG
printf("private-key: %s\n", priv_key);
printf("serial: %s\n", serial);
printf("options: %s\n", options);
#endif
/* sign the message */
lic1_code = calloc(64, 1);
lic2_code = calloc(64, 1);
ecssign(serial, options, priv_key, lic1_code, lic2_code);
/* fix missing zeroes */
while (strlen(lic1_code) < 14) {
prepend("0", lic1_code);
}
while (strlen(lic2_code) < 14) {
prepend("0", lic2_code);
}
#ifdef DEBUG
printf("lic1-code: %s\n", lic1_code);
printf("lic2-code: %s\n", lic2_code);
#endif
/* combine lic1 and lic2 */
lic_all = calloc(128, 1);
temp = calloc(128, 1);
chunk = calloc(6, 1);
final = calloc(128, 1);
strcpy(lic_all, lic1_code);
strcat(lic_all, "0");
strcat(lic_all, lic2_code);
strcat(lic_all, "0");
#ifdef DEBUG
printf("target-code: %s\n", lic_all);
#endif
/* generate serial */
while (i < strlen(lic_all)) {
memcpy(chunk, lic_all + i, 5);
map_hex_to_rigol(chunk);
strcat(temp, chunk);
i = i + 5;
}
/* now add the options */
memcpy(final, temp , 1);
final[1] = options[0];
memcpy(final + 2, temp + 1, 7);
final[9] = options[1];
memcpy(final + 10, temp + 8, 7);
final[17] = options[2];
memcpy(final + 18, temp + 15, 7);
final[25] = options[3];
memcpy(final + 26, temp + 22, 4);
#ifdef DEBUG
printf("----------------------------------------------------\n");
printf("your-license-key: ");
#endif
for(i = 0; i < strlen(final); i++) {
if (i % 7 == 0 && i > 0) printf("-");
printf("%c", final[i]);
}
printf("\n");
#ifdef DEBUG
printf("----------------------------------------------------\n");
#endif
}