--- embedtools/src/voucher.c 2012/07/05 09:00:23 1.1.2.4 +++ embedtools/src/voucher.c 2012/07/22 22:46:48 1.2 @@ -164,12 +164,37 @@ CheckConfig(char mode, int rid, int cnt) return 0; } +static inline void +ll2buf(uint64_t ll, u_char * __restrict buf, int len) +{ + register int i; + + for (i = len - 1; i >= 0; i--) { + buf[i] = ll & 0xff; + ll >>= 8; + } +} + +static inline void +buf2ll(u_char * __restrict buf, uint64_t * __restrict ll, int len) +{ + register int i; + + for (i = 1, *ll = buf[0]; i < len; i++) { + *ll <<= 8; + *ll += buf[i]; + } +} + static int -ComputeVouchers(RSA * __restrict key) +ComputeVouchers(int rid, int cnt, RSA * __restrict key) { - int base, vlen, clen, alen; + int base, clen, alen; u_int roll, ticket, cksum, mb; - uint64_t clrcode, magic; + uint64_t clrcode, code, magic; + register int i, num; + const char *charset; + u_char clrbuf[VOUCHER_MAX_RSA], codebuf[VOUCHER_MAX_LEN], *p = codebuf; /* prepare vars */ roll = strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0); @@ -178,11 +203,11 @@ ComputeVouchers(RSA * __restrict key) magic = strtoll(cfg_getAttribute(&cfg, "voucher", "magic"), NULL, 0); - base = strlen(cfg_getAttribute(&cfg, "voucher", "charset")); - vlen = ((roll + ticket + cksum) >> 3) + 1; + charset = cfg_getAttribute(&cfg, "voucher", "charset"); + base = strlen(charset); clen = RSA_size(key); alen = clen < sizeof(clrcode) ? clen : sizeof(clrcode); - if (vlen > alen) { + if (((roll + ticket + cksum) >> 3) + 1 > alen) { printf("Error: roll+ticket+cksum bits too large for given key\n"); return -1; } @@ -195,10 +220,127 @@ ComputeVouchers(RSA * __restrict key) magic ^= magic; } + for (i = 1; i <= cnt; i++) { + clrcode = magic << cksum; + clrcode += (rid + i) % (1 << cksum); + clrcode <<= ticket; + clrcode += i; + clrcode = (clrcode << roll) + rid; + clrcode &= 0xffffffffffffffffLL >> (65 - 8 * clen); + + ll2buf(clrcode, clrbuf, clen); + + if (RSA_private_encrypt(clen, clrbuf, codebuf, key, RSA_NO_PADDING) == -1) { + printf("Error:: ticket[%d] RSA private encrypt %s\n", i, + ERR_error_string(ERR_get_error(), NULL)); + continue; + } + + buf2ll(codebuf, &code, clen); + + /* pretty print */ + memset(codebuf, 0, sizeof codebuf); + for (p = codebuf, num = sizeof codebuf; code && num; num--) { + *p++ = charset[code % base]; + code /= base; + } + if (code) { + printf("Error:: voucher gets too long ... (%llu)\n", code); + continue; + } + + printf("Voucher[%d]= %s\n", i, codebuf); + } + return 0; } +static int +TestVouchers(array_t * __restrict v, RSA * __restrict key) +{ + int base, clen, alen; + u_int roll, ticket, cksum, mb; + uint64_t clrcode, code, magic; + register int i, checksum, rid, cnt; + const char *charset, *voucher; + u_char clrbuf[VOUCHER_MAX_RSA], codebuf[VOUCHER_MAX_LEN], *p, *s; + /* 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); + + charset = cfg_getAttribute(&cfg, "voucher", "charset"); + base = strlen(charset); + clen = RSA_size(key); + alen = clen < sizeof(clrcode) ? clen : sizeof(clrcode); + if (((roll + ticket + cksum) >> 3) + 1 > 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; + } + + for (i = 0, code = 0; i < io_arraySize(v); i++, code = 0) { + voucher = AIT_GET_STR(io_getVars(&v, i)); + + /* convert from voucher string to number */ + p = (u_char*) strrchr(voucher, '\0'); + while (p > (u_char*) voucher) { + p--; + if (*p == ' ') + break; + code *= base; + s = (u_char*) strchr(charset, *p); + if (!s) { + VERB(1) printf("Error:: illegal character (%c) found in %s\n", + *p, voucher); + printf("Ticket[%d] = %s \"%s\"\n", i, VOUCHER_ERR, voucher); + break; + } + code += (s - (u_char*) charset); + } + + ll2buf(code, codebuf, clen); + + if (RSA_public_decrypt(clen, codebuf, clrbuf, key, RSA_NO_PADDING) == -1) { + VERB(1) printf("Error:: ticket[%d] RSA decrypt failed %s\n", i, + ERR_error_string(ERR_get_error(), NULL)); + printf("Ticket[%d] = %s \"%s\"\n", i, VOUCHER_ERR, voucher); + continue; + } + + buf2ll(clrbuf, &clrcode, clen); + + rid = clrcode & ((1 << roll) - 1); + cnt = (clrcode >> roll) & ((1 << ticket) - 1); + checksum = (clrcode >> (ticket + roll)) & ((1 << cksum) - 1); + if (magic != ((clrcode >> (roll + ticket + cksum)))) { + VERB(1) printf("Error:: ticket[%d] invalid magic\n", i); + printf("Ticket[%d] = %s \"%s\"\n", i, VOUCHER_ERR, voucher); + continue; + } + if ((cnt + rid) % (1L << cksum) != checksum) { + VERB(1) printf("Error:: ticket[%d] invalid checksum\n", i); + printf("Ticket[%d] = %s \"%s\"\n", i, VOUCHER_ERR, voucher); + continue; + } + + printf("Ticket[%d] = %s \"%s\" %d %d\n", i, VOUCHER_OK, voucher, rid, cnt); + } + + return 0; +} + + int main(int argc, char **argv) { @@ -210,6 +352,12 @@ main(int argc, char **argv) output = stdout; atexit(AtExit); +#ifdef __NetBSD__ + srandom(getpid() ^ time(NULL)); +#else + srandomdev(); +#endif + while ((ch = getopt(argc, argv, "hvrtgc:o:")) != -1) switch (ch) { case 'r': @@ -276,10 +424,18 @@ main(int argc, char **argv) } else VERB(1) printf(" + Key size %d bits\n\n", RSA_size(key) * 8); - if (ComputeVouchers(key)) { - RSA_free(key); - cfgUnloadConfig(&cfg); - return 6; + if (mode == 1) { + if (ComputeVouchers(rid, cnt, key)) { + RSA_free(key); + cfgUnloadConfig(&cfg); + return 6; + } + } else { + if (TestVouchers(vs, key)) { + RSA_free(key); + cfgUnloadConfig(&cfg); + return 6; + } } RSA_free(key);