tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pk11util.c (70650B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include <stdio.h>
      6 #include <string.h>
      7 
      8 #if defined(WIN32)
      9 #undef __STDC__
     10 #include "fcntl.h"
     11 #include "io.h"
     12 #include <fcntl.h>
     13 #else
     14 #include <unistd.h>
     15 #include <fcntl.h>
     16 #endif
     17 
     18 #include "secutil.h"
     19 
     20 #include "nspr.h"
     21 #include "prtypes.h"
     22 #include "prtime.h"
     23 #include "prlong.h"
     24 #include "prinrval.h"
     25 #include "prenv.h"
     26 
     27 #include "pkcs11.h"
     28 
     29 #include "pk11table.h"
     30 
     31 #ifndef O_BINARY
     32 #define O_BINARY 0
     33 #endif
     34 
     35 CK_ULONG systemFlags;
     36 #define FLAG_NEGATE 0x80000000
     37 #define FLAG_Verify 0x00000001
     38 #define FLAG_VerifyFile 0x00000002
     39 #define CKR_QUIT 0x80000000
     40 
     41 int ArgSize(ArgType type);
     42 const char *constLookup(const char *bp, CK_ULONG *value, ConstType *type);
     43 
     44 int
     45 isNum(char c)
     46 {
     47    return (c >= '0' && c <= '9');
     48 }
     49 
     50 int
     51 isConst(const char *c)
     52 {
     53    CK_ULONG value;
     54    ConstType type;
     55 
     56    constLookup(c, &value, &type);
     57    return type != ConstNone;
     58 }
     59 
     60 /*
     61 * see if the variable is really a 'size' function. This
     62 * function may modify var if it is a size function.
     63 */
     64 char *
     65 isSize(char *var, int *isArray)
     66 {
     67    char *ptr = NULL;
     68    char *end;
     69    int array = 0;
     70 
     71    if (PL_strncasecmp(var, "sizeof(", /*)*/ 7) == 0) {
     72        ptr = var + 7;
     73    } else if (PL_strncasecmp(var, "size(", /*)*/ 5) == 0) {
     74        ptr = var + 5;
     75    } else if (PL_strncasecmp(var, "sizeofarray(", /*)*/ 12) == 0) {
     76        ptr = var + 12;
     77        array = 1;
     78    } else if (PL_strncasecmp(var, "sizea(", /*)*/ 6) == 0) {
     79        ptr = var + 6;
     80        array = 1;
     81    } else {
     82        return NULL;
     83    }
     84    end = strchr(ptr, /*(*/ ')');
     85    if (end == NULL) {
     86        return NULL;
     87    }
     88    if (isArray)
     89        *isArray = array;
     90    *end = 0;
     91    return ptr;
     92 }
     93 
     94 void
     95 printConst(CK_ULONG value, ConstType type, int newLine)
     96 {
     97    int i;
     98 
     99    for (i = 0; i < constCount; i++) {
    100        if (consts[i].type == type && consts[i].value == value) {
    101            printf("%s", consts[i].name);
    102            break;
    103        }
    104        if (type == ConstNone && consts[i].value == value) {
    105            printf("%s", consts[i].name);
    106            break;
    107        }
    108    }
    109    if (i == constCount) {
    110        if ((type == ConstAvailableSizes) || (type == ConstCurrentSize)) {
    111            printf("%lu", value);
    112        } else {
    113            printf("Unknown %s (%lu:0x%lx)", constTypeString[type], value, value);
    114        }
    115    }
    116    if (newLine) {
    117        printf("\n");
    118    }
    119 }
    120 
    121 ConstType
    122 getConstFromAttribute(CK_ATTRIBUTE_TYPE type)
    123 {
    124    int i;
    125 
    126    for (i = 0; i < constCount; i++) {
    127        if (consts[i].type == ConstAttribute && consts[i].value == type) {
    128            return consts[i].attrType;
    129        }
    130    }
    131    return ConstNone;
    132 }
    133 
    134 void
    135 printChars(const char *name, CK_ULONG size)
    136 {
    137    CK_ULONG i;
    138    for (i = 0; i < size; i++) {
    139        if (name[i] == 0) {
    140            break;
    141        }
    142        printf("%c", name[i]);
    143    }
    144    printf("\n");
    145 }
    146 
    147 #define DUMP_LEN 16
    148 void
    149 printDump(const unsigned char *buf, int size)
    150 {
    151    int i, j;
    152 
    153    for (i = 0; i < size; i += DUMP_LEN) {
    154        printf(" ");
    155        for (j = 0; j < DUMP_LEN; j++) {
    156            if (i + j < size) {
    157                printf("%02x ", buf[i + j]);
    158            } else {
    159                printf("   ");
    160            }
    161        }
    162        for (j = 0; j < DUMP_LEN; j++) {
    163            if (i + j < size) {
    164                if (buf[i + j] < ' ' || buf[i + j] >= 0x7f) {
    165                    printf(".");
    166                } else {
    167                    printf("%c", buf[i + j]);
    168                }
    169            } else {
    170                printf(" ");
    171            }
    172        }
    173        printf("\n");
    174    }
    175 }
    176 
    177 /*
    178 * free an argument structure
    179 */
    180 void
    181 argFreeData(Value *arg)
    182 {
    183    if (arg->data && ((arg->type & ArgStatic) == 0)) {
    184        if ((arg->type & ArgMask) == ArgAttribute) {
    185            int i;
    186            CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)arg->data;
    187 
    188            for (i = 0; i < arg->arraySize; i++) {
    189                free(template[i].pValue);
    190            }
    191        }
    192        if ((arg->type & ArgMask) == ArgInitializeArgs) {
    193            CK_C_INITIALIZE_ARGS *init = (CK_C_INITIALIZE_ARGS *)arg->data;
    194            if (init->LibraryParameters) {
    195                free(init->LibraryParameters);
    196            }
    197        }
    198        free(arg->data);
    199    }
    200    arg->type &= ~ArgStatic;
    201    arg->data = NULL;
    202 }
    203 
    204 void
    205 argFree(Value *arg)
    206 {
    207    if (arg == NULL)
    208        return;
    209 
    210    arg->reference--;
    211    if (arg->reference == 0) {
    212        if (arg->type & ArgFile) {
    213            free(arg->filename);
    214        }
    215        argFreeData(arg);
    216        free(arg);
    217    }
    218 }
    219 
    220 /*
    221 * free and argument list
    222 */
    223 void
    224 parseFree(Value **ap)
    225 {
    226    int i;
    227    for (i = 0; i < MAX_ARGS; i++) {
    228        argFree(ap[i]);
    229    }
    230 }
    231 
    232 /*
    233 * getEnd: how for to the end of this argmument list?
    234 */
    235 int
    236 getEnd(const char *bp)
    237 {
    238    int count = 0;
    239 
    240    while (*bp) {
    241        if (*bp == ' ' || *bp == '\t' || *bp == '\n')
    242            return count;
    243        count++;
    244        bp++;
    245    }
    246    return (count);
    247 }
    248 
    249 /*
    250 * strip: return the first none white space character
    251 */
    252 const char *
    253 strip(const char *bp)
    254 {
    255    while (*bp && (*bp == ' ' || *bp == '\t' || *bp == '\n'))
    256        bp++;
    257    return bp;
    258 }
    259 
    260 /*
    261 * read in the next argument into dp ... don't overflow
    262 */
    263 const char *
    264 readChars(const char *bp, char *dp, int max)
    265 {
    266    int count = 1;
    267    while (*bp) {
    268        if (*bp == ' ' || *bp == '\t' || *bp == '\n') {
    269            *dp = 0;
    270            return bp;
    271        }
    272        *dp++ = *bp++;
    273        if (++count == max)
    274            break;
    275    }
    276    while (*bp && (*bp != ' ' && *bp != '\t' && *bp != '\n'))
    277        bp++;
    278    *dp = 0;
    279    return (bp);
    280 }
    281 
    282 Value *varLookup(const char *bp, char *vname, int max, int *error);
    283 
    284 CK_ULONG
    285 getValue(const char *v, int *error)
    286 {
    287    Value *varVal = NULL;
    288    CK_ULONG retVal = 0;
    289    ConstType type;
    290    char tvar[512];
    291 
    292    *error = 0;
    293 
    294    varVal = varLookup(v, tvar, sizeof(tvar), error);
    295 
    296    if (varVal) {
    297        if ((varVal->type & ArgMask) == ArgULong) {
    298            retVal = *(CK_ULONG *)varVal->data;
    299        } else {
    300            fprintf(stderr, "%s: is not a ulong\n", v);
    301            *error = 1;
    302        }
    303        argFree(varVal);
    304        return retVal;
    305    }
    306    constLookup(v, &retVal, &type);
    307    return retVal;
    308 }
    309 
    310 Value *
    311 NewValue(ArgType type, CK_ULONG arraySize)
    312 {
    313    Value *value;
    314 
    315    value = (Value *)malloc(sizeof(Value));
    316    if (!value)
    317        return NULL;
    318    value->size = ArgSize(type) * arraySize;
    319    value->type = type;
    320    value->filename = NULL;
    321    value->constType = ConstNone;
    322    value->data = (void *)malloc(value->size);
    323    if (!value->data) {
    324        free(value);
    325        return NULL;
    326    }
    327    value->reference = 1;
    328    value->arraySize = (type == ArgChar) ? 1 : arraySize;
    329 
    330    memset(value->data, 0, value->size);
    331    return value;
    332 }
    333 
    334 #define INVALID_INDEX 0xffffffff
    335 
    336 CK_ULONG
    337 handleArray(char *vname, int *error)
    338 {
    339    char *bracket;
    340    CK_ULONG index = INVALID_INDEX;
    341 
    342    if ((bracket = strchr(vname, '[')) != 0) {
    343        char *tmpv = bracket + 1;
    344        *bracket = 0;
    345        bracket = strchr(tmpv, ']');
    346 
    347        if (bracket == 0) {
    348            fprintf(stderr, "%s: missing closing brace\n", vname);
    349            return INVALID_INDEX;
    350        }
    351        *bracket = 0;
    352 
    353        index = getValue(tmpv, error);
    354        if (*error == 1) {
    355            return INVALID_INDEX;
    356        } else if (index == INVALID_INDEX) {
    357            fprintf(stderr, "%s: 0x%lx is an invalid index\n", vname, index);
    358            *error = 1;
    359        }
    360    }
    361    return index;
    362 }
    363 
    364 void *
    365 makeArrayTarget(const char *vname, const Value *value, CK_ULONG index)
    366 {
    367    char *target;
    368    CK_ULONG elementSize;
    369 
    370    if (index >= (CK_ULONG)value->arraySize) {
    371        fprintf(stderr, "%s[%lu]: index larger than array size (%d)\n",
    372                vname, index, value->arraySize);
    373        return NULL;
    374    }
    375 
    376    target = (char *)value->data;
    377    elementSize = value->size / value->arraySize;
    378    target += index * elementSize;
    379    return target;
    380 }
    381 
    382 /*
    383 * look up a variable from the variable chain
    384 */
    385 static Variable *varHead = NULL;
    386 Value *
    387 varLookup(const char *bp, char *vname, int max, int *error)
    388 {
    389    Variable *current;
    390    CK_ULONG index = INVALID_INDEX;
    391    int isArray = 0;
    392    char *ptr;
    393    *error = 0;
    394 
    395    if (bp != NULL) {
    396        readChars(bp, vname, max);
    397    }
    398 
    399    /* don't make numbers into variables */
    400    if (isNum(vname[0])) {
    401        return NULL;
    402    }
    403    /* nor consts */
    404    if (isConst(vname)) {
    405        return NULL;
    406    }
    407    /* handle sizeof() */
    408    if ((ptr = isSize(vname, &isArray)) != NULL) {
    409        CK_ULONG size;
    410        Value *targetValue = NULL;
    411        Value *sourceValue = varLookup(NULL, ptr, 0, error);
    412        if (!sourceValue) {
    413            if (*error == 0) {
    414                /* just didn't find it */
    415                *error = 1;
    416                fprintf(stderr, "Couldn't find variable %s to take size of\n",
    417                        ptr);
    418                return NULL;
    419            }
    420        }
    421        size = isArray ? sourceValue->arraySize : sourceValue->size;
    422        targetValue = NewValue(ArgULong, 1);
    423        memcpy(targetValue->data, &size, sizeof(size));
    424 
    425        return targetValue;
    426    }
    427 
    428    /* modifies vname */
    429    index = handleArray(vname, error);
    430    if (*error == 1) {
    431        return NULL;
    432    }
    433 
    434    for (current = varHead; current; current = current->next) {
    435        if (PL_strcasecmp(current->vname, vname) == 0) {
    436            char *target;
    437            if (index == INVALID_INDEX) {
    438                (current->value->reference)++;
    439                return current->value;
    440            }
    441            target = makeArrayTarget(vname, current->value, index);
    442            if (target) {
    443                Value *element = NewValue(current->value->type, 1);
    444                if (!element) {
    445                    fprintf(stderr, "MEMORY ERROR!\n");
    446                    *error = 1;
    447                }
    448                argFreeData(element);
    449                element->data = target;
    450                element->type |= ArgStatic;
    451                return element;
    452            }
    453            *error = 1;
    454            return NULL;
    455        }
    456    }
    457    return NULL;
    458 }
    459 
    460 static CK_RV
    461 list(void)
    462 {
    463    Variable *current;
    464 
    465    if (varHead) {
    466        printf(" %10s\t%16s\t%8s\tSize\tElements\n", "Name", "Type", "Const");
    467    } else {
    468        printf(" no variables set\n");
    469    }
    470 
    471    for (current = varHead; current; current = current->next) {
    472        printf(" %10s\t%16s\t%8s\t%d\t%d\n", current->vname,
    473               valueString[current->value->type & ArgMask],
    474               constTypeString[current->value->constType],
    475               current->value->size, current->value->arraySize);
    476    }
    477    return CKR_OK;
    478 }
    479 
    480 CK_RV
    481 printFlags(const char *s, CK_ULONG flags, ConstType type)
    482 {
    483    CK_ULONG i;
    484    int needComma = 0;
    485 
    486    printf("%s", s);
    487    for (i = 1; i; i = i << 1) {
    488        if (flags & i) {
    489            printf("%s", needComma ? "," : "");
    490            printConst(i, type, 0);
    491            needComma = 1;
    492        }
    493    }
    494    if (!needComma) {
    495        printf("Empty");
    496    }
    497    printf("\n");
    498    return CKR_OK;
    499 }
    500 
    501 /*
    502 * add a new variable to the chain
    503 */
    504 const char *
    505 AddVariable(const char *bp, Value **ptr)
    506 {
    507    char vname[512];
    508    Variable *current;
    509    int index = INVALID_INDEX;
    510    int size;
    511    int error = 0;
    512 
    513    bp = readChars(bp, vname, sizeof(vname));
    514 
    515    /* don't make numbers into variables */
    516    if (isNum(vname[0])) {
    517        return bp;
    518    }
    519    /* or consts */
    520    if (isConst(vname)) {
    521        return bp;
    522    }
    523    /* or NULLs */
    524    if (vname[0] == 0) {
    525        return bp;
    526    }
    527    /* or sizeof */
    528    if (isSize(vname, NULL)) {
    529        return bp;
    530    }
    531    /* arrays values should be written back to the original */
    532    index = handleArray(vname, &error);
    533    if (error == 1) {
    534        return bp;
    535    }
    536 
    537    for (current = varHead; current; current = current->next) {
    538        if (PL_strcasecmp(current->vname, vname) == 0) {
    539            char *target;
    540            /* found a complete object, return the found one */
    541            if (index == INVALID_INDEX) {
    542                argFree(*ptr);
    543                *ptr = current->value;
    544                return bp;
    545            }
    546            /* found an array, update the array element */
    547            target = makeArrayTarget(vname, current->value, index);
    548            if (target) {
    549                memcpy(target, (*ptr)->data, (*ptr)->size);
    550                argFreeData(*ptr);
    551                (*ptr)->data = target;
    552                (*ptr)->type |= ArgStatic;
    553            }
    554            return bp;
    555        }
    556    }
    557 
    558    /* we are looking for an array and didn't find one */
    559    if (index != INVALID_INDEX) {
    560        return bp;
    561    }
    562 
    563    current = (Variable *)malloc(sizeof(Variable));
    564    size = strlen(vname);
    565    current->vname = (char *)malloc(size + 1);
    566    strcpy(current->vname, vname);
    567    current->value = *ptr;
    568    (*ptr)->reference++;
    569 
    570    current->next = varHead;
    571    varHead = current;
    572    return bp;
    573 }
    574 
    575 ArgType
    576 FindTypeByName(const char *typeName)
    577 {
    578    int i;
    579 
    580    for (i = 0; i < valueCount; i++) {
    581        if (PL_strcasecmp(typeName, valueString[i]) == 0) {
    582            return (ArgType)i;
    583        }
    584        if (valueString[i][0] == 'C' && valueString[i][1] == 'K' &&
    585            valueString[i][2] == '_' &&
    586            (PL_strcasecmp(typeName, &valueString[i][3]) == 0)) {
    587            return (ArgType)i;
    588        }
    589    }
    590    return ArgNone;
    591 }
    592 
    593 CK_RV
    594 ArrayVariable(const char *bp, const char *typeName, CK_ULONG count)
    595 {
    596    ArgType type;
    597    Value *value; /* new Value */
    598 
    599    type = FindTypeByName(typeName);
    600    if (type == ArgNone) {
    601        fprintf(stderr, "Invalid type (%s)\n", typeName);
    602        return CKR_FUNCTION_FAILED;
    603    }
    604    value = NewValue(type, count);
    605    (void)AddVariable(bp, &value);
    606    return CKR_OK;
    607 }
    608 
    609 #define MAX_TEMPLATE 25
    610 
    611 CK_RV
    612 ArrayTemplate(const char *bp, char *attributes)
    613 {
    614    char aname[512];
    615    CK_ULONG attributeTypes[MAX_TEMPLATE];
    616    CK_ATTRIBUTE *template;
    617    Value *value; /* new Value */
    618    char *ap;
    619    int i, count = 0;
    620 
    621    memcpy(aname, attributes, strlen(attributes) + 1);
    622 
    623    for (ap = aname, count = 0; ap && *ap && count < MAX_TEMPLATE; count++) {
    624        char *cur = ap;
    625        ConstType type;
    626 
    627        ap = strchr(ap, ',');
    628        if (ap) {
    629            *ap++ = 0;
    630        }
    631 
    632        (void)constLookup(cur, &attributeTypes[count], &type);
    633        if ((type != ConstAttribute) && (type != ConstNone)) {
    634            fprintf(stderr, "Unknown Attribute %s\n", cur);
    635            return CKR_FUNCTION_FAILED;
    636        }
    637    }
    638 
    639    value = NewValue(ArgAttribute, count);
    640 
    641    template = (CK_ATTRIBUTE *)value->data;
    642    for (i = 0; i < count; i++) {
    643        template[i].type = attributeTypes[i];
    644    }
    645    (void)AddVariable(bp, &value);
    646    return CKR_OK;
    647 }
    648 
    649 CK_RV
    650 BuildTemplate(Value *vp)
    651 {
    652    CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)vp->data;
    653    int i;
    654 
    655    for (i = 0; i < vp->arraySize; i++) {
    656        if (((signed long)template[i].ulValueLen) > 0) {
    657            if (template[i].pValue)
    658                free(template[i].pValue);
    659            template[i].pValue = malloc(template[i].ulValueLen);
    660        }
    661    }
    662    return CKR_OK;
    663 }
    664 
    665 CK_RV
    666 SetTemplate(Value *vp, CK_ULONG index, CK_ULONG value)
    667 {
    668    CK_ATTRIBUTE *template = (CK_ATTRIBUTE *)vp->data;
    669    int isbool = 0;
    670    CK_ULONG len;
    671    ConstType attrType;
    672 
    673    if (index >= (CK_ULONG)vp->arraySize) {
    674        fprintf(stderr, "index (%lu) greater than array (%d)\n",
    675                index, vp->arraySize);
    676        return CKR_ARGUMENTS_BAD;
    677    }
    678    attrType = getConstFromAttribute(template[index].type);
    679 
    680    if (attrType == ConstNone) {
    681        fprintf(stderr, "can't set index (%lu) because ", index);
    682        printConst(template[index].type, ConstAttribute, 0);
    683        fprintf(stderr, " is not a CK_BBOOL or CK_ULONG\n");
    684        return CKR_ARGUMENTS_BAD;
    685    }
    686    isbool = (attrType == ConstBool);
    687    len = isbool ? sizeof(CK_BBOOL) : sizeof(CK_ULONG);
    688    if ((template[index].ulValueLen != len) || (template[index].pValue)) {
    689        free(template[index].pValue);
    690        template[index].pValue = malloc(len);
    691        template[index].ulValueLen = len;
    692    }
    693    if (isbool) {
    694        *(CK_BBOOL *)template[index].pValue = (CK_BBOOL)value;
    695    } else {
    696        *(CK_ULONG *)template[index].pValue = (CK_ULONG)value;
    697    }
    698    return CKR_OK;
    699 }
    700 
    701 CK_RV
    702 NewMechanism(const char *bp, CK_ULONG mechType)
    703 {
    704    Value *value; /* new Value */
    705    CK_MECHANISM *mechanism;
    706 
    707    value = NewValue(ArgMechanism, 1);
    708    mechanism = (CK_MECHANISM *)value->data;
    709    mechanism->mechanism = mechType;
    710    mechanism->pParameter = NULL;
    711    mechanism->ulParameterLen = 0;
    712    (void)AddVariable(bp, &value);
    713    return CKR_OK;
    714 }
    715 
    716 CK_RV
    717 NewInitializeArgs(const char *bp, CK_ULONG flags, const char *param)
    718 {
    719    Value *value; /* new Value */
    720    CK_C_INITIALIZE_ARGS *init;
    721 
    722    value = NewValue(ArgInitializeArgs, 1);
    723    init = (CK_C_INITIALIZE_ARGS *)value->data;
    724    init->flags = flags;
    725    if (strcmp(param, "null") != 0) {
    726        init->LibraryParameters = (CK_CHAR_PTR *)strdup(param);
    727    }
    728    (void)AddVariable(bp, &value);
    729    return CKR_OK;
    730 }
    731 
    732 /*
    733 * add a new variable to the chain
    734 */
    735 CK_RV
    736 DeleteVariable(const char *bp)
    737 {
    738    char vname[512];
    739    Variable **current;
    740 
    741    bp = readChars(bp, vname, sizeof(vname));
    742 
    743    for (current = &varHead; *current; current = &(*current)->next) {
    744        if (PL_strcasecmp((*current)->vname, vname) == 0) {
    745            argFree((*current)->value);
    746            *current = (*current)->next;
    747            break;
    748        }
    749    }
    750    return CKR_OK;
    751 }
    752 
    753 /*
    754 * convert an octal value to integer
    755 */
    756 CK_ULONG
    757 otoi(const char *o)
    758 {
    759    CK_ULONG value = 0;
    760 
    761    while (*o) {
    762        if ((*o >= '0') && (*o <= '7')) {
    763            value = (value << 3) | (unsigned)(*o - '0');
    764        } else {
    765            break;
    766        }
    767    }
    768    return value;
    769 }
    770 
    771 /*
    772 * convert a hex value to integer
    773 */
    774 CK_ULONG
    775 htoi(const char *x)
    776 {
    777    CK_ULONG value = 0;
    778 
    779    while (*x) {
    780        if ((*x >= '0') && (*x <= '9')) {
    781            value = (value << 4) | (unsigned)(*x - '0');
    782        } else if ((*x >= 'a') && (*x <= 'f')) {
    783            value = (value << 4) | (unsigned)(*x - 'a');
    784        } else if ((*x >= 'A') && (*x <= 'F')) {
    785            value = (value << 4) | (unsigned)(*x - 'A');
    786        } else {
    787            break;
    788        }
    789    }
    790    return value;
    791 }
    792 
    793 /*
    794 * look up or decode a constant value
    795 */
    796 const char *
    797 constLookup(const char *bp, CK_ULONG *value, ConstType *type)
    798 {
    799    char vname[512];
    800    int i;
    801 
    802    bp = readChars(bp, vname, sizeof(vname));
    803 
    804    for (i = 0; i < constCount; i++) {
    805        if ((PL_strcasecmp(consts[i].name, vname) == 0) ||
    806            PL_strcasecmp(consts[i].name + 5, vname) == 0) {
    807            *value = consts[i].value;
    808            *type = consts[i].type;
    809            return bp;
    810        }
    811    }
    812 
    813    *type = ConstNone;
    814    if (vname[0] == '0' && vname[1] == 'X') {
    815        *value = htoi(&vname[2]);
    816    } else if (vname[0] == '0') {
    817        *value = otoi(&vname[1]);
    818    } else {
    819        *value = atoi(vname);
    820    }
    821    return bp;
    822 }
    823 
    824 int
    825 ArgSize(ArgType type)
    826 {
    827    int size = 0;
    828    type &= ArgMask;
    829 
    830    switch (type) {
    831        case ArgNone:
    832            size = 0;
    833            break;
    834        case ArgULong:
    835            size = sizeof(CK_ULONG);
    836            break;
    837        case ArgVar:
    838            size = 1; /* get's changed later */
    839            break;
    840        case ArgChar:
    841        case ArgUTF8:
    842            size = 1;
    843            break;
    844        case ArgInfo:
    845            size = sizeof(CK_INFO);
    846            break;
    847        case ArgSlotInfo:
    848            size = sizeof(CK_SLOT_INFO);
    849            break;
    850        case ArgTokenInfo:
    851            size = sizeof(CK_TOKEN_INFO);
    852            break;
    853        case ArgSessionInfo:
    854            size = sizeof(CK_SESSION_INFO);
    855            break;
    856        case ArgAttribute:
    857            size = sizeof(CK_ATTRIBUTE);
    858            break;
    859        case ArgMechanism:
    860            size = sizeof(CK_MECHANISM);
    861            break;
    862        case ArgMechanismInfo:
    863            size = sizeof(CK_MECHANISM_INFO);
    864            break;
    865        case ArgInitializeArgs:
    866            size = sizeof(CK_C_INITIALIZE_ARGS);
    867            break;
    868        case ArgFunctionList:
    869            size = sizeof(CK_FUNCTION_LIST);
    870            break;
    871        default:
    872            break;
    873    }
    874 
    875    return (size);
    876 }
    877 
    878 CK_RV
    879 restore(const char *filename, Value *ptr)
    880 {
    881    int fd, size;
    882 
    883    fd = open(filename, O_RDONLY | O_BINARY);
    884    if (fd < 0) {
    885        perror(filename);
    886        return CKR_FUNCTION_FAILED;
    887    }
    888 
    889    size = read(fd, ptr->data, ptr->size);
    890    if (systemFlags & FLAG_VerifyFile) {
    891        printDump(ptr->data, ptr->size);
    892    }
    893    if (size < 0) {
    894        perror(filename);
    895        return CKR_FUNCTION_FAILED;
    896    } else if (size != ptr->size) {
    897        fprintf(stderr, "%s: only read %d bytes, needed to read %d bytes\n",
    898                filename, size, ptr->size);
    899        return CKR_FUNCTION_FAILED;
    900    }
    901    close(fd);
    902    return CKR_OK;
    903 }
    904 
    905 CK_RV
    906 save(const char *filename, Value *ptr)
    907 {
    908    int fd, size;
    909 
    910    fd = open(filename, O_WRONLY | O_BINARY | O_CREAT, 0666);
    911    if (fd < 0) {
    912        perror(filename);
    913        return CKR_FUNCTION_FAILED;
    914    }
    915 
    916    size = write(fd, ptr->data, ptr->size);
    917    if (size < 0) {
    918        perror(filename);
    919        return CKR_FUNCTION_FAILED;
    920    } else if (size != ptr->size) {
    921        fprintf(stderr, "%s: only wrote %d bytes, need to write %d bytes\n",
    922                filename, size, ptr->size);
    923        return CKR_FUNCTION_FAILED;
    924    }
    925    close(fd);
    926    return CKR_OK;
    927 }
    928 
    929 static CK_RV
    930 increment(Value *ptr, CK_ULONG value)
    931 {
    932    if ((ptr->type & ArgMask) != ArgULong) {
    933        return CKR_ARGUMENTS_BAD;
    934    }
    935    *(CK_ULONG *)ptr->data += value;
    936    return CKR_OK;
    937 }
    938 
    939 static CK_RV
    940 decrement(Value *ptr, CK_ULONG value)
    941 {
    942    if ((ptr->type & ArgMask) != ArgULong) {
    943        return CKR_ARGUMENTS_BAD;
    944    }
    945    *(CK_ULONG *)ptr->data -= value;
    946    return CKR_OK;
    947 }
    948 
    949 CK_RV
    950 printArg(Value *ptr, int arg_number)
    951 {
    952    ArgType type = ptr->type & ArgMask;
    953    CK_INFO *info;
    954    CK_SLOT_INFO *slotInfo;
    955    CK_TOKEN_INFO *tokenInfo;
    956    CK_SESSION_INFO *sessionInfo;
    957    CK_ATTRIBUTE *attribute;
    958    CK_MECHANISM *mechanism;
    959    CK_MECHANISM_INFO *mechanismInfo;
    960    CK_C_INITIALIZE_ARGS *initArgs;
    961    CK_FUNCTION_LIST *functionList;
    962    CK_RV ckrv = CKR_OK;
    963    ConstType constType;
    964 
    965    if (arg_number) {
    966        printf("Arg %d: \n", arg_number);
    967    }
    968    if (ptr->arraySize > 1) {
    969        Value element;
    970        int i;
    971        int elementSize = ptr->size / ptr->arraySize;
    972        char *dp = (char *)ptr->data;
    973 
    974        /* build a temporary Value to hold a single element */
    975        element.type = type;
    976        element.constType = ptr->constType;
    977        element.size = elementSize;
    978        element.filename = ptr->filename;
    979        element.reference = 1;
    980        element.arraySize = 1;
    981        for (i = 0; i < ptr->arraySize; i++) {
    982            printf(" -----[ %d ] -----\n", i);
    983            element.data = (void *)&dp[i * elementSize];
    984            (void)printArg(&element, 0);
    985        }
    986        return ckrv;
    987    }
    988    if (ptr->data == NULL) {
    989        printf(" NULL ptr to a %s\n", valueString[type]);
    990        return ckrv;
    991    }
    992    switch (type) {
    993        case ArgNone:
    994            printf(" None\n");
    995            break;
    996        case ArgULong:
    997            printf(" %lu (0x%lx)\n", *((CK_ULONG *)ptr->data),
    998                   *((CK_ULONG *)ptr->data));
    999            if (ptr->constType != ConstNone) {
   1000                printf(" ");
   1001                printConst(*(CK_ULONG *)ptr->data, ptr->constType, 1);
   1002            }
   1003            break;
   1004        case ArgVar:
   1005            printf(" %s\n", (char *)ptr->data);
   1006            break;
   1007        case ArgUTF8:
   1008            printf(" %s\n", (char *)ptr->data);
   1009            break;
   1010        case ArgChar:
   1011            printDump(ptr->data, ptr->size);
   1012            break;
   1013        case ArgInfo:
   1014 #define VERSION(x) (x).major, (x).minor
   1015            info = (CK_INFO *)ptr->data;
   1016            printf(" Cryptoki Version: %d.%02d\n",
   1017                   VERSION(info->cryptokiVersion));
   1018            printf(" Manufacturer ID: ");
   1019            printChars((char *)info->manufacturerID,
   1020                       sizeof(info->manufacturerID));
   1021            printFlags(" Flags: ", info->flags, ConstInfoFlags);
   1022            printf(" Library Description: ");
   1023            printChars((char *)info->libraryDescription,
   1024                       sizeof(info->libraryDescription));
   1025            printf(" Library Version: %d.%02d\n",
   1026                   VERSION(info->libraryVersion));
   1027            break;
   1028        case ArgSlotInfo:
   1029            slotInfo = (CK_SLOT_INFO *)ptr->data;
   1030            printf(" Slot Description: ");
   1031            printChars((char *)slotInfo->slotDescription,
   1032                       sizeof(slotInfo->slotDescription));
   1033            printf(" Manufacturer ID: ");
   1034            printChars((char *)slotInfo->manufacturerID,
   1035                       sizeof(slotInfo->manufacturerID));
   1036            printFlags(" Flags: ", slotInfo->flags, ConstSlotFlags);
   1037            printf(" Hardware Version: %d.%02d\n",
   1038                   VERSION(slotInfo->hardwareVersion));
   1039            printf(" Firmware Version: %d.%02d\n",
   1040                   VERSION(slotInfo->firmwareVersion));
   1041            break;
   1042        case ArgTokenInfo:
   1043            tokenInfo = (CK_TOKEN_INFO *)ptr->data;
   1044            printf(" Label: ");
   1045            printChars((char *)tokenInfo->label, sizeof(tokenInfo->label));
   1046            printf(" Manufacturer ID: ");
   1047            printChars((char *)tokenInfo->manufacturerID,
   1048                       sizeof(tokenInfo->manufacturerID));
   1049            printf(" Model: ");
   1050            printChars((char *)tokenInfo->model, sizeof(tokenInfo->model));
   1051            printf(" Serial Number: ");
   1052            printChars((char *)tokenInfo->serialNumber,
   1053                       sizeof(tokenInfo->serialNumber));
   1054            printFlags(" Flags: ", tokenInfo->flags, ConstTokenFlags);
   1055            printf(" Max Session Count: ");
   1056            printConst(tokenInfo->ulMaxSessionCount, ConstAvailableSizes, 1);
   1057            printf(" Session Count: ");
   1058            printConst(tokenInfo->ulSessionCount, ConstCurrentSize, 1);
   1059            printf(" RW Session Count: ");
   1060            printConst(tokenInfo->ulMaxRwSessionCount, ConstAvailableSizes, 1);
   1061            printf(" Max Pin Length : ");
   1062            printConst(tokenInfo->ulMaxPinLen, ConstCurrentSize, 1);
   1063            printf(" Min Pin Length : ");
   1064            printConst(tokenInfo->ulMinPinLen, ConstCurrentSize, 1);
   1065            printf(" Total Public Memory: ");
   1066            printConst(tokenInfo->ulTotalPublicMemory, ConstAvailableSizes, 1);
   1067            printf(" Free Public Memory: ");
   1068            printConst(tokenInfo->ulFreePublicMemory, ConstCurrentSize, 1);
   1069            printf(" Total Private Memory: ");
   1070            printConst(tokenInfo->ulTotalPrivateMemory, ConstAvailableSizes, 1);
   1071            printf(" Free Private Memory: ");
   1072            printConst(tokenInfo->ulFreePrivateMemory, ConstCurrentSize, 1);
   1073            printf(" Hardware Version: %d.%02d\n",
   1074                   VERSION(tokenInfo->hardwareVersion));
   1075            printf(" Firmware Version: %d.%02d\n",
   1076                   VERSION(tokenInfo->firmwareVersion));
   1077            printf(" UTC Time: ");
   1078            printChars((char *)tokenInfo->utcTime, sizeof(tokenInfo->utcTime));
   1079            break;
   1080        case ArgSessionInfo:
   1081            sessionInfo = (CK_SESSION_INFO *)ptr->data;
   1082            printf(" SlotID: 0x%08lx\n", sessionInfo->slotID);
   1083            printf(" State: ");
   1084            printConst(sessionInfo->state, ConstSessionState, 1);
   1085            printFlags(" Flags: ", sessionInfo->flags, ConstSessionFlags);
   1086            printf(" Device error: %lu 0x%08lx\n", sessionInfo->ulDeviceError,
   1087                   sessionInfo->ulDeviceError);
   1088            break;
   1089        case ArgAttribute:
   1090            attribute = (CK_ATTRIBUTE *)ptr->data;
   1091            printf(" Attribute Type: ");
   1092            printConst(attribute->type, ConstAttribute, 1);
   1093            printf(" Attribute Data: ");
   1094            if (attribute->pValue == NULL) {
   1095                printf("NULL\n");
   1096                printf("Attribute Len: %lu\n", attribute->ulValueLen);
   1097            } else {
   1098                constType = getConstFromAttribute(attribute->type);
   1099                if (constType != ConstNone) {
   1100                    CK_ULONG value = (constType == ConstBool) ? *(CK_BBOOL *)attribute->pValue
   1101                                                              : *(CK_ULONG *)attribute->pValue;
   1102                    printConst(value, constType, 1);
   1103                } else {
   1104                    printf("\n");
   1105                    printDump(attribute->pValue, attribute->ulValueLen);
   1106                }
   1107            }
   1108            break;
   1109        case ArgMechanism:
   1110            mechanism = (CK_MECHANISM *)ptr->data;
   1111            printf(" Mechanism Type: ");
   1112            printConst(mechanism->mechanism, ConstMechanism, 1);
   1113            printf(" Mechanism Data:\n");
   1114            printDump(mechanism->pParameter, mechanism->ulParameterLen);
   1115            break;
   1116        case ArgMechanismInfo:
   1117            mechanismInfo = (CK_MECHANISM_INFO *)ptr->data;
   1118            printf(" Minimum Key Size: %ld\n", mechanismInfo->ulMinKeySize);
   1119            printf(" Maximum Key Size: %ld\n", mechanismInfo->ulMaxKeySize);
   1120            printFlags(" Flags: ", mechanismInfo->flags, ConstMechanismFlags);
   1121            break;
   1122        case ArgInitializeArgs:
   1123            initArgs = (CK_C_INITIALIZE_ARGS *)ptr->data;
   1124            printFlags(" Flags: ", initArgs->flags, ConstInitializeFlags);
   1125            if (initArgs->LibraryParameters) {
   1126                printf("Params: %s\n", (char *)initArgs->LibraryParameters);
   1127            }
   1128        case ArgFunctionList:
   1129            functionList = (CK_FUNCTION_LIST *)ptr->data;
   1130            printf(" Version: %d.%02d\n", VERSION(functionList->version));
   1131 #ifdef notdef
   1132 #undef CK_NEED_ARG_LIST
   1133 #define CK_PKCS11_FUNCTION_INFO(func) \
   1134    printf(" %s: 0x%08lx\n", #func, (unsigned long)functionList->func);
   1135 #include "pkcs11f.h"
   1136 #undef CK_NEED_ARG_LIST
   1137 #undef CK_PKCS11_FUNCTION_INFO
   1138 #endif
   1139        default:
   1140            ckrv = CKR_ARGUMENTS_BAD;
   1141            break;
   1142    }
   1143 
   1144    return ckrv;
   1145 }
   1146 
   1147 /*
   1148 * Feeling ambitious? turn this whole thing into lexx yacc parser
   1149 * with full expressions.
   1150 */
   1151 Value **
   1152 parseArgs(int index, const char *bp)
   1153 {
   1154    const Commands *cp = &commands[index];
   1155    int size = strlen(cp->fname);
   1156    int i;
   1157    CK_ULONG value;
   1158    char vname[512];
   1159    Value **argList, *possible;
   1160    ConstType constType;
   1161 
   1162    /*
   1163     * skip pass the command
   1164     */
   1165    if ((cp->fname[0] == 'C') && (cp->fname[1] == '_') && (bp[1] != '_')) {
   1166        size -= 2;
   1167    }
   1168    bp += size;
   1169 
   1170    /*
   1171     * Initialize our argument list
   1172     */
   1173    argList = (Value **)malloc(sizeof(Value *) * MAX_ARGS);
   1174    for (i = 0; i < MAX_ARGS; i++) {
   1175        argList[i] = NULL;
   1176    }
   1177 
   1178    /*
   1179     * Walk the argument list parsing it...
   1180     */
   1181    for (i = 0; i < MAX_ARGS; i++) {
   1182        ArgType type = cp->args[i] & ArgMask;
   1183        int error;
   1184 
   1185        /* strip blanks */
   1186        bp = strip(bp);
   1187 
   1188        /* if we hit ArgNone, we've nabbed all the arguments we need */
   1189        if (type == ArgNone) {
   1190            break;
   1191        }
   1192 
   1193        /* if we run out of space in the line, we weren't given enough
   1194         * arguments... */
   1195        if (*bp == '\0') {
   1196            /* we're into optional arguments, ok to quit now */
   1197            if (cp->args[i] & ArgOpt) {
   1198                break;
   1199            }
   1200            fprintf(stderr, "%s: only %d args found,\n", cp->fname, i);
   1201            parseFree(argList);
   1202            return NULL;
   1203        }
   1204 
   1205        /* collect all the rest of the command line and send
   1206         * it as a single argument */
   1207        if (cp->args[i] & ArgFull) {
   1208            int size = strlen(bp) + 1;
   1209            argList[i] = NewValue(type, size);
   1210            memcpy(argList[i]->data, bp, size);
   1211            break;
   1212        }
   1213 
   1214        /*
   1215         * look up the argument in our variable list first... only
   1216         * exception is the new argument type for set...
   1217         */
   1218        error = 0;
   1219        if ((cp->args[i] != (ArgVar | ArgNew)) &&
   1220            (possible = varLookup(bp, vname, sizeof(vname), &error))) {
   1221            /* ints are only compatible with other ints... all other types
   1222             * are interchangeable... */
   1223            if (type != ArgVar) { /* ArgVar's match anyone */
   1224                if ((type == ArgULong) ^
   1225                    ((possible->type & ArgMask) == ArgULong)) {
   1226                    fprintf(stderr, "%s: Arg %d incompatible type with <%s>\n",
   1227                            cp->fname, i + 1, vname);
   1228                    argFree(possible);
   1229                    parseFree(argList);
   1230                    return NULL;
   1231                }
   1232                /*
   1233                 * ... that is as long as they are big enough...
   1234                 */
   1235                if (ArgSize(type) > possible->size) {
   1236                    fprintf(stderr,
   1237                            "%s: Arg %d %s is too small (%d bytes needs to be %d bytes)\n",
   1238                            cp->fname, i + 1, vname, possible->size, ArgSize(type));
   1239                    argFree(possible);
   1240                    parseFree(argList);
   1241                    return NULL;
   1242                }
   1243            }
   1244 
   1245            /* everything looks kosher here, use it */
   1246            argList[i] = possible;
   1247 
   1248            bp = readChars(bp, vname, sizeof(vname));
   1249            if (cp->args[i] & ArgOut) {
   1250                possible->type |= ArgOut;
   1251            }
   1252            continue;
   1253        }
   1254 
   1255        if (error == 1) {
   1256            parseFree(argList);
   1257            return NULL;
   1258        }
   1259 
   1260        /* create space for our argument */
   1261        argList[i] = NewValue(type, 1);
   1262 
   1263        if ((PL_strncasecmp(bp, "null", 4) == 0) && ((bp[4] == 0) ||
   1264                                                     (bp[4] ==
   1265                                                      ' ') ||
   1266                                                     (bp[4] ==
   1267                                                      '\t') ||
   1268                                                     (bp[4] == '\n'))) {
   1269            if (cp->args[i] == ArgULong) {
   1270                fprintf(stderr, "%s: Arg %d CK_ULONG can't be NULL\n",
   1271                        cp->fname, i + 1);
   1272                parseFree(argList);
   1273                return NULL;
   1274            }
   1275            argFreeData(argList[i]);
   1276            argList[i]->data = NULL;
   1277            argList[i]->size = 0;
   1278            bp += 4;
   1279            if (*bp)
   1280                bp++;
   1281            continue;
   1282        }
   1283 
   1284        /* if we're an output variable, we need to add it */
   1285        if (cp->args[i] & ArgOut) {
   1286            if (PL_strncasecmp(bp, "file(", 5) == 0 /* ) */) {
   1287                char filename[512];
   1288                bp = readChars(bp + 5, filename, sizeof(filename));
   1289                size = PL_strlen(filename);
   1290                if ((size > 0) && (/* ( */ filename[size - 1] == ')')) {
   1291                    filename[size - 1] = 0;
   1292                }
   1293                filename[size] = 0;
   1294                argList[i]->filename = (char *)malloc(size + 1);
   1295 
   1296                PL_strcpy(argList[i]->filename, filename);
   1297 
   1298                argList[i]->type |= ArgOut | ArgFile;
   1299                break;
   1300            }
   1301            bp = AddVariable(bp, &argList[i]);
   1302            argList[i]->type |= ArgOut;
   1303            continue;
   1304        }
   1305 
   1306        if (PL_strncasecmp(bp, "file(", 5) == 0 /* ) */) {
   1307            char filename[512];
   1308 
   1309            bp = readChars(bp + 5, filename, sizeof(filename));
   1310            size = PL_strlen(filename);
   1311            if ((size > 0) && (/* ( */ filename[size - 1] == ')')) {
   1312                filename[size - 1] = 0;
   1313            }
   1314 
   1315            if (restore(filename, argList[i]) != CKR_OK) {
   1316                parseFree(argList);
   1317                return NULL;
   1318            }
   1319            continue;
   1320        }
   1321 
   1322        switch (type) {
   1323            case ArgULong:
   1324                bp = constLookup(bp, &value, &constType);
   1325                *(int *)argList[i]->data = value;
   1326                argList[i]->constType = constType;
   1327                break;
   1328            case ArgVar:
   1329                argFreeData(argList[i]);
   1330                size = getEnd(bp) + 1;
   1331                argList[i]->data = (void *)malloc(size);
   1332                argList[i]->size = size;
   1333            /* fall through */
   1334            case ArgInfo:
   1335            case ArgSlotInfo:
   1336            case ArgTokenInfo:
   1337            case ArgSessionInfo:
   1338            case ArgAttribute:
   1339            case ArgMechanism:
   1340            case ArgMechanismInfo:
   1341            case ArgInitializeArgs:
   1342            case ArgUTF8:
   1343            case ArgChar:
   1344                bp = readChars(bp, (char *)argList[i]->data, argList[i]->size);
   1345            case ArgNone:
   1346            default:
   1347                break;
   1348        }
   1349    }
   1350 
   1351    return argList;
   1352 }
   1353 
   1354 /* lookup the command in the array */
   1355 int
   1356 lookup(const char *buf)
   1357 {
   1358    int size, i;
   1359    int buflen;
   1360 
   1361    buflen = PL_strlen(buf);
   1362 
   1363    for (i = 0; i < commandCount; i++) {
   1364        size = PL_strlen(commands[i].fname);
   1365 
   1366        if (size <= buflen) {
   1367            if (PL_strncasecmp(buf, commands[i].fname, size) == 0) {
   1368                return i;
   1369            }
   1370        }
   1371        if (size - 2 <= buflen) {
   1372            if (commands[i].fname[0] == 'C' && commands[i].fname[1] == '_' &&
   1373                (PL_strncasecmp(buf, &commands[i].fname[2], size - 2) == 0)) {
   1374                return i;
   1375            }
   1376        }
   1377    }
   1378    fprintf(stderr, "Can't find command %s\n", buf);
   1379    return -1;
   1380 }
   1381 
   1382 void
   1383 putOutput(Value **ptr)
   1384 {
   1385    int i;
   1386 
   1387    for (i = 0; i < MAX_ARGS; i++) {
   1388        ArgType type;
   1389 
   1390        if (ptr[i] == NULL)
   1391            break;
   1392 
   1393        type = ptr[i]->type;
   1394 
   1395        ptr[i]->type &= ~ArgOut;
   1396        if (type == ArgNone) {
   1397            break;
   1398        }
   1399        if (type & ArgOut) {
   1400            (void)printArg(ptr[i], i + 1);
   1401        }
   1402        if (type & ArgFile) {
   1403            save(ptr[i]->filename, ptr[i]);
   1404            free(ptr[i]->filename);
   1405            ptr[i]->filename = NULL; /* paranoia */
   1406        }
   1407    }
   1408 }
   1409 
   1410 CK_RV
   1411 unloadModule(Module *module)
   1412 {
   1413    char *disableUnload = NULL;
   1414 
   1415    disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
   1416 
   1417    if (module->library && !disableUnload) {
   1418        PR_UnloadLibrary(module->library);
   1419    }
   1420 
   1421    module->library = NULL;
   1422    module->functionList = NULL;
   1423 
   1424    return CKR_OK;
   1425 }
   1426 
   1427 CK_RV
   1428 loadModule(Module *module, char *library)
   1429 {
   1430    PRLibrary *newLibrary;
   1431    CK_C_GetFunctionList getFunctionList;
   1432    CK_FUNCTION_LIST *functionList;
   1433    CK_RV ckrv;
   1434 
   1435    newLibrary = PR_LoadLibrary(library);
   1436    if (!newLibrary) {
   1437        fprintf(stderr, "Couldn't load library %s\n", library);
   1438        return CKR_FUNCTION_FAILED;
   1439    }
   1440    getFunctionList = (CK_C_GetFunctionList)
   1441        PR_FindSymbol(newLibrary, "C_GetFunctionList");
   1442    if (!getFunctionList) {
   1443        fprintf(stderr, "Couldn't find \"C_GetFunctionList\" in %s\n", library);
   1444        return CKR_FUNCTION_FAILED;
   1445    }
   1446 
   1447    ckrv = (*getFunctionList)(&functionList);
   1448    if (ckrv != CKR_OK) {
   1449        return ckrv;
   1450    }
   1451 
   1452    if (module->library) {
   1453        PR_UnloadLibrary(module->library);
   1454    }
   1455 
   1456    module->library = newLibrary;
   1457    module->functionList = functionList;
   1458 
   1459    return CKR_OK;
   1460 }
   1461 
   1462 static void
   1463 printHelp(int index, int full)
   1464 {
   1465    int j;
   1466    printf(" %s", commands[index].fname);
   1467    for (j = 0; j < MAX_ARGS; j++) {
   1468        ArgType type = commands[index].args[j] & ArgMask;
   1469        if (type == ArgNone) {
   1470            break;
   1471        }
   1472        printf(" %s", valueString[type]);
   1473    }
   1474    printf("\n");
   1475    printf(" %s\n", commands[index].helpString);
   1476 }
   1477 
   1478 /* add Topical help here ! */
   1479 static CK_RV
   1480 printTopicHelp(char *topic)
   1481 {
   1482    int size, i;
   1483    int topicLen;
   1484 
   1485    topicLen = PL_strlen(topic);
   1486 
   1487    for (i = 0; i < topicCount; i++) {
   1488        size = PL_strlen(topics[i].name);
   1489 
   1490        if (size <= topicLen) {
   1491            if (PL_strncasecmp(topic, topics[i].name, size) == 0) {
   1492                break;
   1493            }
   1494        }
   1495    }
   1496 
   1497    if (i == topicCount) {
   1498        fprintf(stderr, "Can't find topic '%s'\n", topic);
   1499        return CKR_DATA_INVALID;
   1500    }
   1501 
   1502    printf(" %s", topic);
   1503    printf("\n");
   1504    printf(" %s\n", topics[i].helpString);
   1505    return CKR_OK;
   1506 }
   1507 
   1508 static CK_RV
   1509 printGeneralHelp(void)
   1510 {
   1511    int i;
   1512    printf(" To get help on commands, select from the list below:");
   1513    for (i = 0; i < commandCount; i++) {
   1514        if (i % 5 == 0)
   1515            printf("\n");
   1516        printf("%s,", commands[i].fname);
   1517    }
   1518    printf("\n");
   1519    /* print help topics */
   1520    printf(" To get help on a topic, select from the list below:");
   1521    for (i = 0; i < topicCount; i++) {
   1522        if (i % 5 == 0)
   1523            printf("\n");
   1524        printf("%s,", topics[i].name);
   1525    }
   1526    printf("\n");
   1527    return CKR_OK;
   1528 }
   1529 
   1530 static CK_RV
   1531 quitIf(CK_ULONG a, const char *cmp, CK_ULONG b)
   1532 {
   1533    if (strcmp(cmp, "<") == 0) {
   1534        return (a < b) ? CKR_QUIT : CKR_OK;
   1535    } else if (strcmp(cmp, ">") == 0) {
   1536        return (a > b) ? CKR_QUIT : CKR_OK;
   1537    } else if (strcmp(cmp, "<=") == 0) {
   1538        return (a <= b) ? CKR_QUIT : CKR_OK;
   1539    } else if (strcmp(cmp, ">=") == 0) {
   1540        return (a >= b) ? CKR_QUIT : CKR_OK;
   1541    } else if (strcmp(cmp, "=") == 0) {
   1542        return (a == b) ? CKR_QUIT : CKR_OK;
   1543    } else if (strcmp(cmp, "!=") == 0) {
   1544        return (a != b) ? CKR_QUIT : CKR_OK;
   1545    }
   1546    printf("Unkown integer comparator: '%s'\n", cmp);
   1547    return CKR_ARGUMENTS_BAD;
   1548 }
   1549 
   1550 static CK_RV
   1551 quitIfString(const char *a, const char *cmp, const char *b)
   1552 {
   1553 
   1554    if (strcmp(cmp, "=") == 0) {
   1555        return (strcmp(a, b) == 0) ? CKR_QUIT : CKR_OK;
   1556    } else if (strcmp(cmp, "!=") == 0) {
   1557        return (strcmp(a, b) != 0) ? CKR_QUIT : CKR_OK;
   1558    }
   1559    printf("Unkown string comparator: '%s'\n", cmp);
   1560    return CKR_ARGUMENTS_BAD;
   1561 }
   1562 
   1563 CK_RV run(const char *);
   1564 CK_RV timeCommand(const char *);
   1565 CK_RV loop(const char *filename, const char *var,
   1566           CK_ULONG start, CK_ULONG end, CK_ULONG step);
   1567 
   1568 /*
   1569 * Actually dispatch the function... Bad things happen
   1570 * if these don't match the commands array.
   1571 */
   1572 CK_RV
   1573 do_func(int index, Value **a)
   1574 {
   1575    int value, helpIndex;
   1576    static Module module = { NULL, NULL };
   1577    CK_FUNCTION_LIST *func = module.functionList;
   1578 
   1579    switch (commands[index].fType) {
   1580        case F_C_Initialize:
   1581            if (!func)
   1582                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1583            return func->C_Initialize((void *)a[0]->data);
   1584        case F_C_Finalize:
   1585            if (!func)
   1586                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1587            return func->C_Finalize((void *)a[0]->data);
   1588        case F_C_GetInfo:
   1589            if (!func)
   1590                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1591            return func->C_GetInfo((CK_INFO *)a[0]->data);
   1592        case F_C_GetFunctionList:
   1593            if (!func)
   1594                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1595            return func->C_GetFunctionList((CK_FUNCTION_LIST **)a[0]->data);
   1596        case F_C_GetSlotList:
   1597            if (!func)
   1598                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1599            return func->C_GetSlotList((CK_BBOOL) * (CK_ULONG *)a[0]->data,
   1600                                       (CK_SLOT_ID *)a[1]->data,
   1601                                       (CK_ULONG *)a[2]->data);
   1602        case F_C_GetSlotInfo:
   1603            if (!func)
   1604                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1605            return func->C_GetSlotInfo(*(CK_ULONG *)a[0]->data,
   1606                                       (CK_SLOT_INFO *)a[1]->data);
   1607        case F_C_GetTokenInfo:
   1608            if (!func)
   1609                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1610            return func->C_GetTokenInfo(*(CK_ULONG *)a[0]->data,
   1611                                        (CK_TOKEN_INFO *)a[1]->data);
   1612        case F_C_GetMechanismList:
   1613            if (!func)
   1614                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1615            if (a[1]->data) {
   1616                a[1]->constType = ConstMechanism;
   1617            }
   1618            return func->C_GetMechanismList(*(CK_ULONG *)a[0]->data,
   1619                                            (CK_MECHANISM_TYPE *)a[1]->data,
   1620                                            (CK_ULONG *)a[2]->data);
   1621        case F_C_GetMechanismInfo:
   1622            if (!func)
   1623                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1624            return func->C_GetMechanismInfo(*(CK_ULONG *)a[0]->data,
   1625                                            *(CK_ULONG *)a[1]->data,
   1626                                            (CK_MECHANISM_INFO *)a[2]->data);
   1627        case F_C_InitToken:
   1628            if (!func)
   1629                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1630            return func->C_InitToken(*(CK_ULONG *)a[0]->data,
   1631                                     (CK_CHAR *)a[1]->data,
   1632                                     *(CK_ULONG *)a[2]->data,
   1633                                     (CK_CHAR *)a[3]->data);
   1634        case F_C_InitPIN:
   1635            if (!func)
   1636                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1637            return func->C_InitPIN(*(CK_ULONG *)a[0]->data,
   1638                                   (CK_CHAR *)a[1]->data,
   1639                                   *(CK_ULONG *)a[2]->data);
   1640        case F_C_SetPIN:
   1641            if (!func)
   1642                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1643            return func->C_SetPIN(*(CK_ULONG *)a[0]->data,
   1644                                  (CK_CHAR *)a[1]->data,
   1645                                  *(CK_ULONG *)a[2]->data,
   1646                                  (CK_CHAR *)a[3]->data,
   1647                                  *(CK_ULONG *)a[4]->data);
   1648        case F_C_OpenSession:
   1649            if (!func)
   1650                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1651            return func->C_OpenSession(*(CK_ULONG *)a[0]->data,
   1652                                       *(CK_ULONG *)a[1]->data,
   1653                                       (void *)NULL,
   1654                                       (CK_NOTIFY)NULL,
   1655                                       (CK_ULONG *)a[2]->data);
   1656        case F_C_CloseSession:
   1657            if (!func)
   1658                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1659            return func->C_CloseSession(*(CK_ULONG *)a[0]->data);
   1660        case F_C_CloseAllSessions:
   1661            if (!func)
   1662                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1663            return func->C_CloseAllSessions(*(CK_ULONG *)a[0]->data);
   1664        case F_C_GetSessionInfo:
   1665            if (!func)
   1666                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1667            return func->C_GetSessionInfo(*(CK_ULONG *)a[0]->data,
   1668                                          (CK_SESSION_INFO *)a[1]->data);
   1669        case F_C_GetOperationState:
   1670            if (!func)
   1671                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1672            return func->C_GetOperationState(*(CK_ULONG *)a[0]->data,
   1673                                             (CK_BYTE *)a[1]->data,
   1674                                             (CK_ULONG *)a[2]->data);
   1675        case F_C_SetOperationState:
   1676            if (!func)
   1677                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1678            return func->C_SetOperationState(*(CK_ULONG *)a[0]->data,
   1679                                             (CK_CHAR *)a[1]->data,
   1680                                             *(CK_ULONG *)a[2]->data,
   1681                                             *(CK_ULONG *)a[3]->data,
   1682                                             *(CK_ULONG *)a[4]->data);
   1683        case F_C_Login:
   1684            if (!func)
   1685                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1686            return func->C_Login(*(CK_ULONG *)a[0]->data,
   1687                                 *(CK_ULONG *)a[1]->data,
   1688                                 (CK_CHAR *)a[2]->data,
   1689                                 *(CK_ULONG *)a[3]->data);
   1690        case F_C_Logout:
   1691            if (!func)
   1692                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1693            return func->C_Logout(*(CK_ULONG *)a[0]->data);
   1694        case F_C_CreateObject:
   1695            if (!func)
   1696                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1697            return func->C_CreateObject(*(CK_ULONG *)a[0]->data,
   1698                                        (CK_ATTRIBUTE *)a[1]->data,
   1699                                        *(CK_ULONG *)a[2]->data,
   1700                                        (CK_ULONG *)a[3]->data);
   1701        case F_C_CopyObject:
   1702            if (!func)
   1703                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1704            return func->C_CopyObject(*(CK_ULONG *)a[0]->data,
   1705                                      *(CK_ULONG *)a[0]->data,
   1706                                      (CK_ATTRIBUTE *)a[1]->data,
   1707                                      *(CK_ULONG *)a[2]->data,
   1708                                      (CK_ULONG *)a[3]->data);
   1709        case F_C_DestroyObject:
   1710            if (!func)
   1711                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1712            return func->C_DestroyObject(*(CK_ULONG *)a[0]->data,
   1713                                         *(CK_ULONG *)a[1]->data);
   1714        case F_C_GetObjectSize:
   1715            if (!func)
   1716                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1717            return func->C_GetObjectSize(*(CK_ULONG *)a[0]->data,
   1718                                         *(CK_ULONG *)a[1]->data,
   1719                                         (CK_ULONG *)a[2]->data);
   1720        case F_C_GetAttributeValue:
   1721            if (!func)
   1722                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1723            return func->C_GetAttributeValue(*(CK_ULONG *)a[0]->data,
   1724                                             *(CK_ULONG *)a[1]->data,
   1725                                             (CK_ATTRIBUTE *)a[2]->data,
   1726                                             *(CK_ULONG *)a[3]->data);
   1727        case F_C_SetAttributeValue:
   1728            if (!func)
   1729                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1730            return func->C_SetAttributeValue(*(CK_ULONG *)a[0]->data,
   1731                                             *(CK_ULONG *)a[1]->data,
   1732                                             (CK_ATTRIBUTE *)a[2]->data,
   1733                                             *(CK_ULONG *)a[3]->data);
   1734        case F_C_FindObjectsInit:
   1735            if (!func)
   1736                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1737            return func->C_FindObjectsInit(*(CK_ULONG *)a[0]->data,
   1738                                           (CK_ATTRIBUTE *)a[1]->data,
   1739                                           *(CK_ULONG *)a[2]->data);
   1740        case F_C_FindObjects:
   1741            if (!func)
   1742                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1743            return func->C_FindObjects(*(CK_ULONG *)a[0]->data,
   1744                                       (CK_ULONG *)a[1]->data,
   1745                                       *(CK_ULONG *)a[2]->data,
   1746                                       (CK_ULONG *)a[3]->data);
   1747        case F_C_FindObjectsFinal:
   1748            if (!func)
   1749                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1750            return func->C_FindObjectsFinal(*(CK_ULONG *)a[0]->data);
   1751        case F_C_EncryptInit:
   1752            if (!func)
   1753                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1754            return func->C_EncryptInit(*(CK_ULONG *)a[0]->data,
   1755                                       (CK_MECHANISM *)a[1]->data,
   1756                                       *(CK_ULONG *)a[2]->data);
   1757        case F_C_Encrypt:
   1758            if (!func)
   1759                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1760            return func->C_Encrypt(*(CK_ULONG *)a[0]->data,
   1761                                   (CK_CHAR *)a[1]->data,
   1762                                   *(CK_ULONG *)a[2]->data,
   1763                                   (CK_CHAR *)a[3]->data,
   1764                                   (CK_ULONG *)a[4]->data);
   1765        case F_C_EncryptUpdate:
   1766            if (!func)
   1767                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1768            return func->C_EncryptUpdate(*(CK_ULONG *)a[0]->data,
   1769                                         (CK_CHAR *)a[1]->data,
   1770                                         *(CK_ULONG *)a[2]->data,
   1771                                         (CK_CHAR *)a[3]->data,
   1772                                         (CK_ULONG *)a[4]->data);
   1773        case F_C_EncryptFinal:
   1774            if (!func)
   1775                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1776            return func->C_EncryptFinal(*(CK_ULONG *)a[0]->data,
   1777                                        (CK_CHAR *)a[1]->data,
   1778                                        (CK_ULONG *)a[2]->data);
   1779        case F_C_DecryptInit:
   1780            if (!func)
   1781                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1782            return func->C_DecryptInit(*(CK_ULONG *)a[0]->data,
   1783                                       (CK_MECHANISM *)a[1]->data,
   1784                                       *(CK_ULONG *)a[2]->data);
   1785        case F_C_Decrypt:
   1786            if (!func)
   1787                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1788            return func->C_Decrypt(*(CK_ULONG *)a[0]->data,
   1789                                   (CK_CHAR *)a[1]->data,
   1790                                   *(CK_ULONG *)a[2]->data,
   1791                                   (CK_CHAR *)a[3]->data,
   1792                                   (CK_ULONG *)a[4]->data);
   1793        case F_C_DecryptUpdate:
   1794            if (!func)
   1795                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1796            return func->C_DecryptUpdate(*(CK_ULONG *)a[0]->data,
   1797                                         (CK_CHAR *)a[1]->data,
   1798                                         *(CK_ULONG *)a[2]->data,
   1799                                         (CK_CHAR *)a[3]->data,
   1800                                         (CK_ULONG *)a[4]->data);
   1801        case F_C_DecryptFinal:
   1802            if (!func)
   1803                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1804            return func->C_DecryptFinal(*(CK_ULONG *)a[0]->data,
   1805                                        (CK_CHAR *)a[1]->data,
   1806                                        (CK_ULONG *)a[2]->data);
   1807        case F_C_DigestInit:
   1808            if (!func)
   1809                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1810            return func->C_DigestInit(*(CK_ULONG *)a[0]->data,
   1811                                      (CK_MECHANISM *)a[1]->data);
   1812        case F_C_Digest:
   1813            if (!func)
   1814                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1815            return func->C_Digest(*(CK_ULONG *)a[0]->data,
   1816                                  (CK_CHAR *)a[1]->data,
   1817                                  *(CK_ULONG *)a[2]->data,
   1818                                  (CK_CHAR *)a[3]->data,
   1819                                  (CK_ULONG *)a[4]->data);
   1820        case F_C_DigestUpdate:
   1821            if (!func)
   1822                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1823            return func->C_DigestUpdate(*(CK_ULONG *)a[0]->data,
   1824                                        (CK_CHAR *)a[1]->data,
   1825                                        *(CK_ULONG *)a[2]->data);
   1826        case F_C_DigestKey:
   1827            if (!func)
   1828                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1829            return func->C_DigestKey(*(CK_ULONG *)a[0]->data,
   1830                                     *(CK_ULONG *)a[1]->data);
   1831        case F_C_DigestFinal:
   1832            if (!func)
   1833                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1834            return func->C_DigestFinal(*(CK_ULONG *)a[0]->data,
   1835                                       (CK_CHAR *)a[1]->data,
   1836                                       (CK_ULONG *)a[2]->data);
   1837        case F_C_SignInit:
   1838            if (!func)
   1839                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1840            return func->C_SignInit(*(CK_ULONG *)a[0]->data,
   1841                                    (CK_MECHANISM *)a[1]->data,
   1842                                    *(CK_ULONG *)a[2]->data);
   1843        case F_C_Sign:
   1844            if (!func)
   1845                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1846            return func->C_Sign(*(CK_ULONG *)a[0]->data,
   1847                                (CK_CHAR *)a[1]->data,
   1848                                *(CK_ULONG *)a[2]->data,
   1849                                (CK_CHAR *)a[3]->data,
   1850                                (CK_ULONG *)a[4]->data);
   1851        case F_C_SignUpdate:
   1852            if (!func)
   1853                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1854            return func->C_SignUpdate(*(CK_ULONG *)a[0]->data,
   1855                                      (CK_CHAR *)a[1]->data,
   1856                                      *(CK_ULONG *)a[2]->data);
   1857        case F_C_SignFinal:
   1858            if (!func)
   1859                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1860            return func->C_SignFinal(*(CK_ULONG *)a[0]->data,
   1861                                     (CK_CHAR *)a[1]->data,
   1862                                     (CK_ULONG *)a[2]->data);
   1863 
   1864        case F_C_SignRecoverInit:
   1865            if (!func)
   1866                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1867            return func->C_SignRecoverInit(*(CK_ULONG *)a[0]->data,
   1868                                           (CK_MECHANISM *)a[1]->data,
   1869                                           *(CK_ULONG *)a[2]->data);
   1870        case F_C_SignRecover:
   1871            if (!func)
   1872                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1873            return func->C_SignRecover(*(CK_ULONG *)a[0]->data,
   1874                                       (CK_CHAR *)a[1]->data,
   1875                                       *(CK_ULONG *)a[2]->data,
   1876                                       (CK_CHAR *)a[3]->data,
   1877                                       (CK_ULONG *)a[4]->data);
   1878        case F_C_VerifyInit:
   1879            if (!func)
   1880                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1881            return func->C_VerifyInit(*(CK_ULONG *)a[0]->data,
   1882                                      (CK_MECHANISM *)a[1]->data,
   1883                                      *(CK_ULONG *)a[2]->data);
   1884        case F_C_Verify:
   1885            if (!func)
   1886                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1887            return func->C_Verify(*(CK_ULONG *)a[0]->data,
   1888                                  (CK_CHAR *)a[1]->data,
   1889                                  *(CK_ULONG *)a[2]->data,
   1890                                  (CK_CHAR *)a[3]->data,
   1891                                  *(CK_ULONG *)a[4]->data);
   1892        case F_C_VerifyUpdate:
   1893            if (!func)
   1894                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1895            return func->C_VerifyUpdate(*(CK_ULONG *)a[0]->data,
   1896                                        (CK_CHAR *)a[1]->data,
   1897                                        *(CK_ULONG *)a[2]->data);
   1898        case F_C_VerifyFinal:
   1899            if (!func)
   1900                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1901            return func->C_VerifyFinal(*(CK_ULONG *)a[0]->data,
   1902                                       (CK_CHAR *)a[1]->data,
   1903                                       *(CK_ULONG *)a[2]->data);
   1904 
   1905        case F_C_VerifyRecoverInit:
   1906            if (!func)
   1907                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1908            return func->C_VerifyRecoverInit(*(CK_ULONG *)a[0]->data,
   1909                                             (CK_MECHANISM *)a[1]->data,
   1910                                             *(CK_ULONG *)a[2]->data);
   1911        case F_C_VerifyRecover:
   1912            if (!func)
   1913                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1914            return func->C_VerifyRecover(*(CK_ULONG *)a[0]->data,
   1915                                         (CK_CHAR *)a[1]->data,
   1916                                         *(CK_ULONG *)a[2]->data,
   1917                                         (CK_CHAR *)a[3]->data,
   1918                                         (CK_ULONG *)a[4]->data);
   1919        case F_C_DigestEncryptUpdate:
   1920            if (!func)
   1921                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1922            return func->C_DigestEncryptUpdate(*(CK_ULONG *)a[0]->data,
   1923                                               (CK_CHAR *)a[1]->data,
   1924                                               *(CK_ULONG *)a[2]->data,
   1925                                               (CK_CHAR *)a[3]->data,
   1926                                               (CK_ULONG *)a[4]->data);
   1927        case F_C_DecryptDigestUpdate:
   1928            if (!func)
   1929                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1930            return func->C_DecryptDigestUpdate(*(CK_ULONG *)a[0]->data,
   1931                                               (CK_CHAR *)a[1]->data,
   1932                                               *(CK_ULONG *)a[2]->data,
   1933                                               (CK_CHAR *)a[3]->data,
   1934                                               (CK_ULONG *)a[4]->data);
   1935        case F_C_SignEncryptUpdate:
   1936            if (!func)
   1937                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1938            return func->C_SignEncryptUpdate(*(CK_ULONG *)a[0]->data,
   1939                                             (CK_CHAR *)a[1]->data,
   1940                                             *(CK_ULONG *)a[2]->data,
   1941                                             (CK_CHAR *)a[3]->data,
   1942                                             (CK_ULONG *)a[4]->data);
   1943        case F_C_DecryptVerifyUpdate:
   1944            if (!func)
   1945                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1946            return func->C_DecryptVerifyUpdate(*(CK_ULONG *)a[0]->data,
   1947                                               (CK_CHAR *)a[1]->data,
   1948                                               *(CK_ULONG *)a[2]->data,
   1949                                               (CK_CHAR *)a[3]->data,
   1950                                               (CK_ULONG *)a[4]->data);
   1951        case F_C_GenerateKey:
   1952            if (!func)
   1953                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1954            return func->C_GenerateKey(*(CK_ULONG *)a[0]->data,
   1955                                       (CK_MECHANISM *)a[1]->data,
   1956                                       (CK_ATTRIBUTE *)a[2]->data,
   1957                                       *(CK_ULONG *)a[3]->data,
   1958                                       (CK_ULONG *)a[4]->data);
   1959        case F_C_GenerateKeyPair:
   1960            if (!func)
   1961                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1962            return func->C_GenerateKeyPair(*(CK_ULONG *)a[0]->data,
   1963                                           (CK_MECHANISM *)a[1]->data,
   1964                                           (CK_ATTRIBUTE *)a[2]->data,
   1965                                           *(CK_ULONG *)a[3]->data,
   1966                                           (CK_ATTRIBUTE *)a[4]->data,
   1967                                           *(CK_ULONG *)a[5]->data,
   1968                                           (CK_ULONG *)a[6]->data,
   1969                                           (CK_ULONG *)a[7]->data);
   1970        case F_C_WrapKey:
   1971            if (!func)
   1972                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1973            return func->C_WrapKey(*(CK_ULONG *)a[0]->data,
   1974                                   (CK_MECHANISM *)a[1]->data,
   1975                                   *(CK_ULONG *)a[2]->data,
   1976                                   *(CK_ULONG *)a[3]->data,
   1977                                   (CK_CHAR *)a[5]->data,
   1978                                   (CK_ULONG *)a[6]->data);
   1979        case F_C_UnwrapKey:
   1980            if (!func)
   1981                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1982            return func->C_UnwrapKey(*(CK_ULONG *)a[0]->data,
   1983                                     (CK_MECHANISM *)a[1]->data,
   1984                                     *(CK_ULONG *)a[2]->data,
   1985                                     (CK_CHAR *)a[3]->data,
   1986                                     *(CK_ULONG *)a[4]->data,
   1987                                     (CK_ATTRIBUTE *)a[5]->data,
   1988                                     *(CK_ULONG *)a[6]->data,
   1989                                     (CK_ULONG *)a[7]->data);
   1990        case F_C_DeriveKey:
   1991            if (!func)
   1992                return CKR_CRYPTOKI_NOT_INITIALIZED;
   1993            return func->C_DeriveKey(*(CK_ULONG *)a[0]->data,
   1994                                     (CK_MECHANISM *)a[1]->data,
   1995                                     *(CK_ULONG *)a[2]->data,
   1996                                     (CK_ATTRIBUTE *)a[3]->data,
   1997                                     *(CK_ULONG *)a[4]->data,
   1998                                     (CK_ULONG *)a[5]->data);
   1999        case F_C_SeedRandom:
   2000            if (!func)
   2001                return CKR_CRYPTOKI_NOT_INITIALIZED;
   2002            return func->C_SeedRandom(*(CK_ULONG *)a[0]->data,
   2003                                      (CK_CHAR *)a[1]->data,
   2004                                      *(CK_ULONG *)a[2]->data);
   2005        case F_C_GenerateRandom:
   2006            if (!func)
   2007                return CKR_CRYPTOKI_NOT_INITIALIZED;
   2008            return func->C_GenerateRandom(*(CK_ULONG *)a[0]->data,
   2009                                          (CK_CHAR *)a[1]->data,
   2010                                          *(CK_ULONG *)a[2]->data);
   2011        case F_C_GetFunctionStatus:
   2012            if (!func)
   2013                return CKR_CRYPTOKI_NOT_INITIALIZED;
   2014            return func->C_GetFunctionStatus(*(CK_ULONG *)a[0]->data);
   2015        case F_C_CancelFunction:
   2016            if (!func)
   2017                return CKR_CRYPTOKI_NOT_INITIALIZED;
   2018            return func->C_CancelFunction(*(CK_ULONG *)a[0]->data);
   2019        case F_C_WaitForSlotEvent:
   2020            if (!func)
   2021                return CKR_CRYPTOKI_NOT_INITIALIZED;
   2022            return func->C_WaitForSlotEvent(*(CK_ULONG *)a[0]->data,
   2023                                            (CK_ULONG *)a[1]->data,
   2024                                            (void *)a[2]->data);
   2025        /* set a variable */
   2026        case F_SetVar:
   2027        case F_SetStringVar:
   2028            (void)DeleteVariable(a[0]->data);
   2029            (void)AddVariable(a[0]->data, &a[1]);
   2030            return CKR_OK;
   2031        /* print a value */
   2032        case F_Print:
   2033            return printArg(a[0], 0);
   2034        case F_SaveVar:
   2035            return save(a[0]->data, a[1]);
   2036        case F_RestoreVar:
   2037            return restore(a[0]->data, a[1]);
   2038        case F_Delete:
   2039            return DeleteVariable(a[0]->data);
   2040        case F_Increment:
   2041            return increment(a[0], *(CK_ULONG *)a[1]->data);
   2042        case F_Decrement:
   2043            return decrement(a[0], *(CK_ULONG *)a[1]->data);
   2044        case F_List:
   2045            return list();
   2046        case F_Run:
   2047            return run(a[0]->data);
   2048        case F_Time:
   2049            return timeCommand(a[0]->data);
   2050        case F_Load:
   2051            return loadModule(&module, a[0]->data);
   2052        case F_Unload:
   2053            return unloadModule(&module);
   2054        case F_NewArray:
   2055            (void)DeleteVariable(a[0]->data);
   2056            return ArrayVariable(a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data);
   2057        case F_NewTemplate:
   2058            (void)DeleteVariable(a[0]->data);
   2059            return ArrayTemplate(a[0]->data, a[1]->data);
   2060        case F_BuildTemplate:
   2061            return BuildTemplate(a[0]);
   2062        case F_SetTemplate:
   2063            return SetTemplate(a[0],
   2064                               *(CK_ULONG *)a[1]->data,
   2065                               *(CK_ULONG *)a[2]->data);
   2066        case F_NewMechanism:
   2067            (void)DeleteVariable(a[0]->data);
   2068            return NewMechanism(a[0]->data, *(CK_ULONG *)a[1]->data);
   2069        case F_NewInitializeArgs:
   2070            (void)DeleteVariable(a[0]->data);
   2071            return NewInitializeArgs(a[0]->data, *(CK_ULONG *)a[1]->data, a[2]->data);
   2072        case F_System:
   2073            value = *(int *)a[0]->data;
   2074            if (value & 0x80000000) {
   2075                systemFlags &= ~value;
   2076            } else {
   2077                systemFlags |= value;
   2078            }
   2079            return CKR_OK;
   2080        case F_Loop:
   2081            return loop(a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data,
   2082                        *(CK_ULONG *)a[3]->data, *(CK_ULONG *)a[4]->data);
   2083        case F_Help:
   2084            if (a[0]) {
   2085                helpIndex = lookup(a[0]->data);
   2086                if (helpIndex < 0) {
   2087                    return printTopicHelp(a[0]->data);
   2088                }
   2089                printHelp(helpIndex, 1);
   2090                return CKR_OK;
   2091            }
   2092            return printGeneralHelp();
   2093        case F_QuitIfString:
   2094            return quitIfString(a[0]->data, a[1]->data, a[2]->data);
   2095        case F_QuitIf:
   2096            return quitIf(*(CK_ULONG *)a[0]->data, a[1]->data, *(CK_ULONG *)a[2]->data);
   2097        case F_Quit:
   2098            return CKR_QUIT;
   2099        default:
   2100            fprintf(stderr,
   2101                    "Function %s not yet supported\n", commands[index].fname);
   2102            return CKR_OK;
   2103    }
   2104    /* Not Reached */
   2105    return CKR_OK;
   2106 }
   2107 
   2108 CK_RV
   2109 processCommand(const char *buf)
   2110 {
   2111    CK_RV error = CKR_OK;
   2112    int index;
   2113    const char *bp;
   2114    Value **arglist;
   2115 
   2116    bp = strip(buf);
   2117    /* allow comments and blank lines in scripts */
   2118    if ((*bp == '#') || (*bp == 0) || (*bp == '\n')) {
   2119        return CKR_OK;
   2120    }
   2121 
   2122    index = lookup(bp);
   2123 
   2124    if (index < 0) {
   2125        return CKR_OK;
   2126    }
   2127 
   2128    arglist = parseArgs(index, bp);
   2129    if (arglist == NULL) {
   2130        return CKR_OK;
   2131    }
   2132 
   2133    error = do_func(index, arglist);
   2134    if (error == CKR_OK) {
   2135        putOutput(arglist);
   2136    } else if (error != CKR_QUIT) {
   2137        printf(">> Error : ");
   2138        printConst(error, ConstResult, 1);
   2139    }
   2140 
   2141    parseFree(arglist);
   2142    return error;
   2143 }
   2144 
   2145 CK_RV
   2146 timeCommand(const char *command)
   2147 {
   2148    CK_RV ckrv;
   2149    PRIntervalTime startTime = PR_IntervalNow();
   2150    PRIntervalTime endTime;
   2151    PRIntervalTime elapsedTime;
   2152 
   2153    ckrv = processCommand(command);
   2154 
   2155    endTime = PR_IntervalNow();
   2156    elapsedTime = endTime - startTime;
   2157    printf("Time -- %d msec \n",
   2158           PR_IntervalToMilliseconds(elapsedTime));
   2159 
   2160    return ckrv;
   2161 }
   2162 
   2163 CK_RV
   2164 process(FILE *inFile, int user)
   2165 {
   2166    char buf[2048];
   2167    CK_RV error;
   2168    CK_RV ckrv = CKR_OK;
   2169 
   2170    if (user) {
   2171        printf("pkcs11> ");
   2172        fflush(stdout);
   2173    }
   2174 
   2175    while (fgets(buf, 2048, inFile) != NULL) {
   2176 
   2177        if (!user)
   2178            printf("* %s", buf);
   2179        error = processCommand(buf);
   2180        if (error == CKR_QUIT) {
   2181            break;
   2182        } else if (error != CKR_OK) {
   2183            ckrv = error;
   2184        }
   2185        if (user) {
   2186            printf("pkcs11> ");
   2187            fflush(stdout);
   2188        }
   2189    }
   2190    return ckrv;
   2191 }
   2192 
   2193 CK_RV
   2194 run(const char *filename)
   2195 {
   2196    FILE *infile;
   2197    CK_RV ckrv;
   2198 
   2199    infile = fopen(filename, "r");
   2200 
   2201    if (infile == NULL) {
   2202        perror(filename);
   2203        return CKR_FUNCTION_FAILED;
   2204    }
   2205 
   2206    ckrv = process(infile, 0);
   2207 
   2208    fclose(infile);
   2209    return ckrv;
   2210 }
   2211 
   2212 CK_RV
   2213 loop(const char *filename, const char *var,
   2214     CK_ULONG start, CK_ULONG end, CK_ULONG step)
   2215 {
   2216    CK_ULONG i = 0;
   2217    Value *value = 0;
   2218    CK_RV ckrv;
   2219 
   2220    for (i = start; i < end; i += step) {
   2221        value = NewValue(ArgULong, 1);
   2222        *(CK_ULONG *)value->data = i;
   2223        DeleteVariable(var);
   2224        AddVariable(var, &value);
   2225        ckrv = run(filename);
   2226        argFree(value);
   2227        if (ckrv == CKR_QUIT) {
   2228            break;
   2229        }
   2230    }
   2231    return ckrv;
   2232 }
   2233 
   2234 int
   2235 main(int argc, char **argv)
   2236 {
   2237    /* I suppose that some day we could parse some arguments */
   2238    (void)process(stdin, 1);
   2239    return 0;
   2240 }