--- embedtools/src/voucher.c 2012/07/04 16:15:53 1.1.2.3 +++ embedtools/src/voucher.c 2012/07/05 09:00:23 1.1.2.4 @@ -3,10 +3,11 @@ #include #include -io_enableDEBUG; cfg_root_t cfg; +array_t *vs; FILE *output; +int Verbose; char szConfig[MAXPATHLEN] = VOUCHER_CFG; extern char compiled[], compiledby[], compilehost[]; @@ -30,6 +31,7 @@ Usage() static void AtExit() { + io_freeVars(&vs); if (output != stdout) fclose(output); } @@ -65,12 +67,145 @@ NewRSA() return 0; } +static RSA * +LoadKey(char mode) +{ + FILE *f; + RSA *key = NULL; + ait_val_t v; +#ifndef NDEBUG + ERR_load_crypto_strings(); +#endif + + AIT_INIT_VAL(&v); + if (mode == 1) + cfg_loadAttribute(&cfg, "voucher", "key_private", &v, VOUCHER_KEY); + else + cfg_loadAttribute(&cfg, "voucher", "key_public", &v, VOUCHER_CRT); + + f = fopen(AIT_GET_STR(&v), "r"); + AIT_FREE_VAL(&v); + if (!f) { + printf("Error:: open key #%d - %s\n", errno, strerror(errno)); + return NULL; + } + + if (mode == 1) + key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL); + else + key = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL); + + fclose(f); + + if (!key) + printf("Error:: wrong key !!!\n"); + return key; +} + +static void +ShowConfig(char mode, int rid, int cnt) +{ + register int i; + + if (mode == 1) + printf(">>> Request voucher ticket(s) %d for Roll %d\n", cnt, rid); + else + printf(">>> Test voucher ticket(s) %d\n", cnt); + + for (i = 0; i < io_arraySize(vs); i++) + printf(" + Voucher[%d]= %s\n", i, AIT_GET_STR(io_getVars(&vs, i))); + printf(" + Roll ID %d bits\n", (int) + strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0)); + printf(" + Ticket ID %d bits\n", (int) + strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0)); + printf(" + CheckSum %d bits\n", (int) + strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0)); + printf(" + Magic 0x%llx\n", (uint64_t) + strtoll(cfg_getAttribute(&cfg, "voucher", "magic"), NULL, 0)); + printf(" + Charset %s\n", cfg_getAttribute(&cfg, "voucher", "charset")); + if (!cfg_getAttribute(&cfg, "voucher", "key_private")) + cfg_setAttribute(&cfg, "voucher", "key_private", VOUCHER_KEY); + printf(" + Private key %s\n", cfg_getAttribute(&cfg, "voucher", "key_private")); + if (!cfg_getAttribute(&cfg, "voucher", "key_public")) + cfg_setAttribute(&cfg, "voucher", "key_public", VOUCHER_CRT); + printf(" + Public key %s\n", cfg_getAttribute(&cfg, "voucher", "key_public")); +} + +static int +CheckConfig(char mode, int rid, int cnt) +{ + const char *str; + + str = cfg_getAttribute(&cfg, "voucher", "charset"); + if (!str || strlen(str) < 2) { + printf("Error:: charset too short ... '%s'\n", str); + return -1; + } + if (strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0) > 31 || + strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0) > 31 || + strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0) > 31) { + printf("Error:: bits must be between 1..31\n"); + return -1; + } + if (mode == 1) { + if (rid >= 1LL << strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0)) { + printf("Error:: Roll bits must be 0..%lu\n", + strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0)); + return -1; + } + if (cnt < 1 || cnt >= 1LL << strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0)) { + printf("Error:: Ticket bits count must be 1..%lu\n", + strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0)); + return -1; + } + } + + return 0; +} + +static int +ComputeVouchers(RSA * __restrict key) +{ + int base, vlen, clen, alen; + u_int roll, ticket, cksum, mb; + uint64_t clrcode, magic; + + /* prepare vars */ + roll = strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0); + ticket = strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0); + cksum = strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0); + + magic = strtoll(cfg_getAttribute(&cfg, "voucher", "magic"), NULL, 0); + + base = strlen(cfg_getAttribute(&cfg, "voucher", "charset")); + vlen = ((roll + ticket + cksum) >> 3) + 1; + clen = RSA_size(key); + alen = clen < sizeof(clrcode) ? clen : sizeof(clrcode); + if (vlen > alen) { + printf("Error: roll+ticket+cksum bits too large for given key\n"); + return -1; + } + + mb = alen * 8 - (roll + ticket + cksum + 1); + if (mb > 0) + magic &= (1LL << mb) - 1; + else { + mb ^= mb; + magic ^= magic; + } + + return 0; +} + + int main(int argc, char **argv) { char ch, mode = 0; - int rid, cnt = 1; + int rid = 0, cnt = 1; + register int i; + RSA *key; output = stdout; atexit(AtExit); @@ -92,7 +227,7 @@ main(int argc, char **argv) RedirOutput(optarg); break; case 'v': - io_incDebug; + Verbose++; break; case 'h': default: @@ -101,16 +236,53 @@ main(int argc, char **argv) } argc -= optind; argv += optind; - if (!argc || !mode) { + if (!argc || !mode || mode > 2) { printf("Error:: not enough parameter or unspecified mode ...\n\n"); Usage(); return 1; } + if (mode == 1) { + if (argc > 1) + cnt = strtol(argv[1], NULL, 0); + rid = strtol(argv[0], NULL, 0); + } else { + cnt = argc; + vs = io_allocVars(cnt); + for (i = 0; i < argc; i++) + AIT_SET_STR(io_getVars(&vs, i), argv[i]); + } + if (cfgLoadConfig(szConfig, &cfg)) { printf("Error:: load config #%d - %s\n", cfg_GetErrno(), cfg_GetError()); return 3; + } else { + VERB(1) ShowConfig(mode, rid, cnt); + if (CheckConfig(mode, rid, cnt)) { + cfgUnloadConfig(&cfg); + return 3; + } } + if (!(key = LoadKey(mode))) { + cfgUnloadConfig(&cfg); + return 4; + } + if (RSA_size(key) > VOUCHER_MAX_RSA) { + printf("Error:: RSA key size %d bits. Max %d bits\n", + RSA_size(key) * 8, VOUCHER_MAX_RSA * 8); + RSA_free(key); + cfgUnloadConfig(&cfg); + return 5; + } else + VERB(1) printf(" + Key size %d bits\n\n", RSA_size(key) * 8); + + if (ComputeVouchers(key)) { + RSA_free(key); + cfgUnloadConfig(&cfg); + return 6; + } + + RSA_free(key); cfgUnloadConfig(&cfg); return 0; }