--- embedtools/src/voucher.c 2012/07/05 09:00:23 1.1.2.4 +++ embedtools/src/voucher.c 2013/07/19 01:08:43 1.2.4.3 @@ -1,3 +1,48 @@ +/************************************************************************* + * (C) 2011 AITNET - Sofia/Bulgaria - + * by Michael Pounov + * + * $Author: misho $ + * $Id: voucher.c,v 1.2.4.3 2013/07/19 01:08:43 misho Exp $ + * + ************************************************************************* +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ #include "global.h" #include #include @@ -31,7 +76,7 @@ Usage() static void AtExit() { - io_freeVars(&vs); + ait_freeVars(&vs); if (output != stdout) fclose(output); } @@ -113,8 +158,8 @@ ShowConfig(char mode, int rid, int cnt) 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))); + for (i = 0; i < array_Size(vs); i++) + printf(" + Voucher[%d]= %s\n", i, AIT_GET_STR(ait_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) @@ -164,12 +209,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 +248,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 +265,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 < array_Size(v); i++, code = 0) { + voucher = AIT_GET_STR(ait_getVars((array_t**) &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 +397,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': @@ -247,9 +440,9 @@ main(int argc, char **argv) rid = strtol(argv[0], NULL, 0); } else { cnt = argc; - vs = io_allocVars(cnt); + vs = ait_allocVars(cnt); for (i = 0; i < argc; i++) - AIT_SET_STR(io_getVars(&vs, i), argv[i]); + AIT_SET_STR(ait_getVars(&vs, i), argv[i]); } if (cfgLoadConfig(szConfig, &cfg)) { @@ -276,10 +469,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);