Annotation of embedtools/src/voucher.c, revision 1.1.2.4

1.1.2.1   misho       1: #include "global.h"
1.1.2.3   misho       2: #include <openssl/pem.h>
                      3: #include <openssl/rsa.h>
                      4: #include <openssl/err.h>
1.1.2.1   misho       5: 
1.1.2.2   misho       6: 
                      7: cfg_root_t cfg;
1.1.2.4 ! misho       8: array_t *vs;
1.1.2.2   misho       9: FILE *output;
1.1.2.4 ! misho      10: int Verbose;
1.1.2.2   misho      11: char szConfig[MAXPATHLEN] = VOUCHER_CFG;
                     12: extern char compiled[], compiledby[], compilehost[];
                     13: 
                     14: 
                     15: static void
                     16: Usage()
                     17: {
                     18:        printf( " -= VOUCHER =- management tool\n"
                     19:                "=== %s === %s@%s ===\n\n"
                     20:                "Syntax: voucher [options] -r <RollID> [count]\n"
                     21:                "\tvoucher [options] -t <voucher> [voucher [voucher ...]]\n\n"
                     22:                "\t-v\t\tVerbose (more -v more verbosity)\n"
                     23:                "\t-r\t\tRequest new voucher(s) mode\n"
                     24:                "\t-t\t\tTest voucher(s) mode\n"
1.1.2.3   misho      25:                "\t-g\t\tRequest new RSA pair mode\n"
1.1.2.2   misho      26:                "\t-c <config>\tConfig file\n"
                     27:                "\t-o <output>\tOutput file [default=-]\n"
                     28:                "\n", compiled, compiledby, compilehost);
                     29: }
                     30: 
                     31: static void
                     32: AtExit()
                     33: {
1.1.2.4 ! misho      34:        io_freeVars(&vs);
1.1.2.2   misho      35:        if (output != stdout)
                     36:                fclose(output);
                     37: }
                     38: 
                     39: static inline int
                     40: RedirOutput(const char *name)
                     41: {
                     42:        AtExit();
                     43: 
                     44:        if (strcmp(name, "-")) {
                     45:                output = fopen(name, "w+");
                     46:                if (!output) {
                     47:                        printf("Error:: can't redirect output #%d - %s\n", 
                     48:                                        errno, strerror(errno));
                     49:                        return -1;
                     50:                }
                     51:        } else
                     52:                output = stdout;
                     53:        return 0;
                     54: }
                     55: 
1.1.2.3   misho      56: static int
                     57: NewRSA()
                     58: {
                     59:        RSA *k = RSA_generate_key(VOUCHER_MAX_RSA * 8, 65537, NULL, NULL);
                     60:        if (!k) {
                     61:                printf("Error:: can't generate RSA key\n");
                     62:                return 2;
                     63:        }
                     64: 
                     65:        PEM_write_RSAPrivateKey(output, k, NULL, NULL, 0, NULL, NULL);
                     66:        PEM_write_RSA_PUBKEY(output, k);
                     67:        return 0;
                     68: }
                     69: 
1.1.2.4 ! misho      70: static RSA *
        !            71: LoadKey(char mode)
        !            72: {
        !            73:        FILE *f;
        !            74:        RSA *key = NULL;
        !            75:        ait_val_t v;
        !            76: 
        !            77: #ifndef NDEBUG
        !            78:        ERR_load_crypto_strings();
        !            79: #endif
        !            80: 
        !            81:        AIT_INIT_VAL(&v);
        !            82:        if (mode == 1)
        !            83:                cfg_loadAttribute(&cfg, "voucher", "key_private", &v, VOUCHER_KEY);
        !            84:        else
        !            85:                cfg_loadAttribute(&cfg, "voucher", "key_public", &v, VOUCHER_CRT);
        !            86: 
        !            87:        f = fopen(AIT_GET_STR(&v), "r");
        !            88:        AIT_FREE_VAL(&v);
        !            89:        if (!f) {
        !            90:                printf("Error:: open key #%d - %s\n", errno, strerror(errno));
        !            91:                return NULL;
        !            92:        }
        !            93: 
        !            94:        if (mode == 1)
        !            95:                key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
        !            96:        else
        !            97:                key = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL);
        !            98: 
        !            99:        fclose(f);
        !           100: 
        !           101:        if (!key)
        !           102:                printf("Error:: wrong key !!!\n");
        !           103:        return key;
        !           104: }
        !           105: 
        !           106: static void
        !           107: ShowConfig(char mode, int rid, int cnt)
        !           108: {
        !           109:        register int i;
        !           110: 
        !           111:        if (mode == 1)
        !           112:                printf(">>> Request voucher ticket(s) %d for Roll %d\n", cnt, rid);
        !           113:        else
        !           114:                printf(">>> Test voucher ticket(s) %d\n", cnt);
        !           115: 
        !           116:        for (i = 0; i < io_arraySize(vs); i++)
        !           117:                printf(" + Voucher[%d]= %s\n", i, AIT_GET_STR(io_getVars(&vs, i)));
        !           118:        printf(" + Roll ID %d bits\n", (int) 
        !           119:                        strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0));
        !           120:        printf(" + Ticket ID %d bits\n", (int) 
        !           121:                        strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0));
        !           122:        printf(" + CheckSum %d bits\n", (int) 
        !           123:                        strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0));
        !           124:        printf(" + Magic 0x%llx\n", (uint64_t) 
        !           125:                        strtoll(cfg_getAttribute(&cfg, "voucher", "magic"), NULL, 0));
        !           126:        printf(" + Charset %s\n", cfg_getAttribute(&cfg, "voucher", "charset"));
        !           127:        if (!cfg_getAttribute(&cfg, "voucher", "key_private"))
        !           128:                cfg_setAttribute(&cfg, "voucher", "key_private", VOUCHER_KEY);
        !           129:        printf(" + Private key %s\n", cfg_getAttribute(&cfg, "voucher", "key_private"));
        !           130:        if (!cfg_getAttribute(&cfg, "voucher", "key_public"))
        !           131:                cfg_setAttribute(&cfg, "voucher", "key_public", VOUCHER_CRT);
        !           132:        printf(" + Public key %s\n", cfg_getAttribute(&cfg, "voucher", "key_public"));
        !           133: }
        !           134: 
        !           135: static int
        !           136: CheckConfig(char mode, int rid, int cnt)
        !           137: {
        !           138:        const char *str;
        !           139: 
        !           140:        str = cfg_getAttribute(&cfg, "voucher", "charset");
        !           141:        if (!str || strlen(str) < 2) {
        !           142:                printf("Error:: charset too short ... '%s'\n", str);
        !           143:                return -1;
        !           144:        }
        !           145:        if (strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0) > 31 || 
        !           146:                        strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0) > 31 || 
        !           147:                        strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0) > 31) {
        !           148:                printf("Error:: bits must be between 1..31\n");
        !           149:                return -1;
        !           150:        }
        !           151:        if (mode == 1) {
        !           152:                if (rid >= 1LL << strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0)) {
        !           153:                        printf("Error:: Roll bits must be 0..%lu\n", 
        !           154:                                        strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0));
        !           155:                        return -1;
        !           156:                }
        !           157:                if (cnt < 1 || cnt >= 1LL << strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0)) {
        !           158:                        printf("Error:: Ticket bits count must be 1..%lu\n", 
        !           159:                                        strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0));
        !           160:                        return -1;
        !           161:                }
        !           162:        }
        !           163: 
        !           164:        return 0;
        !           165: }
        !           166: 
        !           167: static int
        !           168: ComputeVouchers(RSA * __restrict key)
        !           169: {
        !           170:        int base, vlen, clen, alen;
        !           171:        u_int roll, ticket, cksum, mb;
        !           172:        uint64_t clrcode, magic;
        !           173: 
        !           174:        /* prepare vars */
        !           175:        roll = strtol(cfg_getAttribute(&cfg, "voucher", "rollbits"), NULL, 0);
        !           176:        ticket = strtol(cfg_getAttribute(&cfg, "voucher", "ticketbits"), NULL, 0);
        !           177:        cksum = strtol(cfg_getAttribute(&cfg, "voucher", "cksumbits"), NULL, 0);
        !           178: 
        !           179:        magic = strtoll(cfg_getAttribute(&cfg, "voucher", "magic"), NULL, 0);
        !           180: 
        !           181:        base = strlen(cfg_getAttribute(&cfg, "voucher", "charset"));
        !           182:        vlen = ((roll + ticket + cksum) >> 3) + 1;
        !           183:        clen = RSA_size(key);
        !           184:        alen = clen < sizeof(clrcode) ? clen : sizeof(clrcode);
        !           185:        if (vlen > alen) {
        !           186:                printf("Error: roll+ticket+cksum bits too large for given key\n");
        !           187:                return -1;
        !           188:        }
        !           189: 
        !           190:        mb = alen * 8 - (roll + ticket + cksum + 1);
        !           191:        if (mb > 0)
        !           192:                magic &= (1LL << mb) - 1;
        !           193:        else {
        !           194:                mb ^= mb;
        !           195:                magic ^= magic;
        !           196:        }
        !           197: 
        !           198:        return 0;
        !           199: }
        !           200: 
1.1.2.2   misho     201: 
1.1.2.1   misho     202: int
                    203: main(int argc, char **argv)
                    204: {
1.1.2.2   misho     205:        char ch, mode = 0;
1.1.2.4 ! misho     206:        int rid = 0, cnt = 1;
        !           207:        register int i;
        !           208:        RSA *key;
1.1.2.2   misho     209: 
                    210:        output = stdout;
                    211:        atexit(AtExit);
                    212: 
1.1.2.3   misho     213:        while ((ch = getopt(argc, argv, "hvrtgc:o:")) != -1)
1.1.2.2   misho     214:                switch (ch) {
                    215:                        case 'r':
                    216:                                mode = 1;
                    217:                                break;
                    218:                        case 't':
                    219:                                mode = 2;
                    220:                                break;
1.1.2.3   misho     221:                        case 'g':
                    222:                                return NewRSA();
1.1.2.2   misho     223:                        case 'c':
                    224:                                strlcpy(szConfig, optarg, sizeof szConfig);
                    225:                                break;
                    226:                        case 'o':
                    227:                                RedirOutput(optarg);
                    228:                                break;
                    229:                        case 'v':
1.1.2.4 ! misho     230:                                Verbose++;
1.1.2.2   misho     231:                                break;
                    232:                        case 'h':
                    233:                        default:
                    234:                                Usage();
                    235:                                return 1;
                    236:                }
                    237:        argc -= optind;
                    238:        argv += optind;
1.1.2.4 ! misho     239:        if (!argc || !mode || mode > 2) {
1.1.2.2   misho     240:                printf("Error:: not enough parameter or unspecified mode ...\n\n");
                    241:                Usage();
                    242:                return 1;
                    243:        }
1.1.2.4 ! misho     244:        if (mode == 1) {
        !           245:                if (argc > 1)
        !           246:                        cnt = strtol(argv[1], NULL, 0);
        !           247:                rid = strtol(argv[0], NULL, 0);
        !           248:        } else {
        !           249:                cnt = argc;
        !           250:                vs = io_allocVars(cnt);
        !           251:                for (i = 0; i < argc; i++)
        !           252:                        AIT_SET_STR(io_getVars(&vs, i), argv[i]);
        !           253:        }
        !           254: 
1.1.2.2   misho     255:        if (cfgLoadConfig(szConfig, &cfg)) {
                    256:                printf("Error:: load config #%d - %s\n", cfg_GetErrno(), cfg_GetError());
1.1.2.3   misho     257:                return 3;
1.1.2.4 ! misho     258:        } else {
        !           259:                VERB(1) ShowConfig(mode, rid, cnt);
        !           260:                if (CheckConfig(mode, rid, cnt)) {
        !           261:                        cfgUnloadConfig(&cfg);
        !           262:                        return 3;
        !           263:                }
        !           264:        }
        !           265: 
        !           266:        if (!(key = LoadKey(mode))) {
        !           267:                cfgUnloadConfig(&cfg);
        !           268:                return 4;
        !           269:        }
        !           270:        if (RSA_size(key) > VOUCHER_MAX_RSA) {
        !           271:                printf("Error:: RSA key size %d bits. Max %d bits\n", 
        !           272:                                RSA_size(key) * 8, VOUCHER_MAX_RSA * 8);
        !           273:                RSA_free(key);
        !           274:                cfgUnloadConfig(&cfg);
        !           275:                return 5;
        !           276:        } else
        !           277:                VERB(1) printf(" + Key size %d bits\n\n", RSA_size(key) * 8);
        !           278: 
        !           279:        if (ComputeVouchers(key)) {
        !           280:                RSA_free(key);
        !           281:                cfgUnloadConfig(&cfg);
        !           282:                return 6;
1.1.2.2   misho     283:        }
                    284: 
1.1.2.4 ! misho     285:        RSA_free(key);
1.1.2.2   misho     286:        cfgUnloadConfig(&cfg);
1.1.2.1   misho     287:        return 0;
                    288: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>