int wolfsslSetup(int argc, char** argv, char action)
{
    char     outNameE[256];     /* default outFile for encrypt */
    char     outNameD[256];     /* default outfile for decrypt */
    char     inName[256];       /* name of the in File if not provided */

    char*    name = NULL;       /* string of algorithm, mode, keysize */
    char*    alg = NULL;        /* algorithm from name */
    char*    mode = NULL;       /* mode from name */
    char*    out = outNameE;    /* default output file name */
    char*    in = inName;       /* default in data */
    byte*    pwdKey = NULL;     /* password for generating pwdKey */
    byte*    key = NULL;        /* user set key NOT PWDBASED */
    byte*    iv = NULL;         /* iv for initial encryption */


    int      size       =   0;  /* keysize from name */
    int      ret        =   0;  /* return variable */
    int      block      =   0;  /* block size based on algorithm */
    int      pwdKeyChk  =   0;  /* if a pwdKey has been provided */
    int      ivCheck    =   0;  /* if the user sets the IV explicitly */
    int      keyCheck   =   0;  /* if ivCheck is 1 this should be set also */
    int      inCheck    =   0;  /* if input has been provided */
    int      outCheck   =   0;  /* if output has been provided */
    int      i          =   0;  /* loop counter */
    int      eCheck     =   0;  /* if user is encrypting data */
    int      dCheck     =   0;  /* if user is decrypting data */
    int      inputHex   =   0;  /* if user is encrypting hexidecimal stuff */
    int      keyType    =   0;  /* tells Decrypt which key it will be using
                                 * 1 = password based key, 2 = user set key
                                 */
    word32   ivSize     =   0;  /* IV if provided should be 2*block */
    word32   numBits    =   0;  /* number of bits in argument from the user */

    if (action == 'e')
        eCheck = 1;
    if (action == 'd')
        dCheck = 1;

    for (i = 2; i < argc; i++) {
        if (strcmp(argv[i], "-help") == 0) {
            if (eCheck == 1) {
                /*wolfsslEncryptHelp*/
                wolfsslEncryptHelp();
                return 0;
            } else {
                /*wolfsslDecryptHelp*/
                wolfsslDecryptHelp();
                return 0;
            }
        }
    }

    name = argv[2];
    /* gets blocksize, algorithm, mode, and key size from name argument */
    block = wolfsslGetAlgo(name, &alg, &mode, &size);

    if (block != FATAL_ERROR) {
        pwdKey = (byte*) malloc(size);
        iv = (byte*) malloc(block);
        key = (byte*) malloc(size);

        /* Start at the third flag entered */
        i = 3;
        do {
            if (argv[i] == NULL){
                break;
            }
            else if (strcmp(argv[i], "-o") == 0 && argv[i+1] != NULL) {
                /* output file */
                out = argv[i+1];
                outCheck = 1;
                i+=2;
                /* it is mandatory that this be set last */
                continue;
            }

            else if (strcmp(argv[i], "-i") == 0 && argv[i+1] != NULL) {
                 /* input file/text */
                in = argv[i+1];
                inCheck = 1;
                /* continue while out check not equal 1 */
                i+=2;
                continue;
            }

            else if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL) {
                /* password pwdKey */
                XMEMCPY(pwdKey, argv[i+1], size);
                pwdKeyChk = 1;
                keyType = 1;
                i+=2;
                continue;
            }
            else if (strcmp(argv[i], "-x") == 0) {
                /* using hexidecimal format */
                inputHex = 1;
                i++;
                continue;
            }
            else if (strcmp(argv[i], "-V") == 0 && argv[i+1] != NULL) {
                /* iv for encryption */
                if (pwdKeyChk == 1) {
                    printf("Invalid option, attempting to use IV with password"
                           " based key.");
                    wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                    return FATAL_ERROR;
                }
                 ivSize = block*2;
                if (strlen(argv[i+1]) != ivSize) {
                    printf("Invalid IV. Must match algorithm block size.\n");
                    printf("Invalid IV size was: %d.\n",
                                                       (int) strlen(argv[i+1]));
                    printf("size of IV expected was: %d.\n", ivSize);
                    wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                    return FATAL_ERROR;
                }
                else {
                    char ivString[strlen(argv[i+1])];
                    XSTRNCPY(ivString, argv[i+1], XSTRLEN(argv[i+1]));
                    ret = wolfsslHexToBin(ivString, &iv, &ivSize,
                                            NULL, NULL, NULL,
                                            NULL, NULL, NULL,
                                            NULL, NULL, NULL);
                    if (ret != 0) {
                        printf("failed during conversion of IV, ret = %d\n",
                                                                           ret);
                        wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                        return -1;
                    }
                    ivCheck = 1;
                    i+=2;
                    continue;
                }
            }
            else if (strcmp(argv[i], "-K") == 0 && argv[i+1] != NULL) {
                /* 2 characters = 1 byte. 1 byte = 8 bits
                 * number of characters / 2 = bytes
                 * bytes * 8 = bits
                 */
                numBits = (int) (strlen(argv[i+1]) / 2 ) * 8;
                /* Key for encryption */
                if ((int)numBits != size) {
                    printf("Length of key provided was: %d.\n", numBits);
                    printf("Length of key expected was: %d.\n", size);
                    printf("Invalid Key. Must match algorithm key size.\n");
                    wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                    return FATAL_ERROR;
                }
                else {
                    char keyString[strlen(argv[i+1])];
                    XSTRNCPY(keyString, argv[i+1], XSTRLEN(argv[i+1]));
                    ret = wolfsslHexToBin(keyString, &key, &numBits,
                                            NULL, NULL, NULL,
                                            NULL, NULL, NULL,
                                            NULL, NULL, NULL);
                     if (ret != 0) {
                        printf("failed during conversion of Key, ret = %d\n",
                                                                           ret);
                        wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                        return -1;
                    }
                    keyCheck = 1;
                    keyType = 2;
                    i+=2;
                    continue;
                }
            }
            else {
                i++; continue;
            }

        }while(i < 15);

        if (pwdKeyChk == 0 && keyCheck == 0) {
            if (dCheck == 1) {
                printf("\nDECRYPT ERROR:\n");
                printf("Please type \"wolfssl -d -help\" for decryption usage."
                                                                        "\n\n");
                return 0;
            }
            /* if no pwdKey is provided */
            else {
                printf("No -p flag set, please enter a password to use for"
                " encrypting.\n");
                printf("Write your password down so you don't forget it.\n");
                ret = wolfsslNoEcho((char*)pwdKey, size);
                pwdKeyChk = 1;
            }
        }

        if (inCheck == 0 && eCheck == 1) {
            ret = 0;
            while (ret == 0) {
                printf("-i flag was not set, please enter a string or\n"
                       "file name to be encrypted: ");
                ret = (int) scanf("%s", inName);
            } 
            in = inName;
            /* if no input is provided */
            printf("Ok,  We will encrypt:\"%s\" for you.\n", inName);
            inCheck = 1;
        }

        if (eCheck == 1 && dCheck == 1) {
            printf("You want to encrypt and decrypt simultaneously? That is"
                    "not possible...\n");
            wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
            return FATAL_ERROR;
        }

        if (inCheck == 0 && dCheck == 1) {
            printf("We are so sorry but you must specify what it is you are "
                    "trying to decrypt.\n");
            wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
            return FATAL_ERROR;
        }

        if (ivCheck == 1) {
            if (keyCheck == 0) {
                printf("IV was explicitly set, but no -K <key> was set. User\n"
                    " needs to provide a non-password based key when setting"
                        " the IV.\n");
                wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
                return FATAL_ERROR;
            }
        }

        if (pwdKeyChk == 1 && keyCheck == 1) {
            XMEMSET(pwdKey, 0, size);
        }

        /* encryption function call */
        if (eCheck == 1) {

            printf("\n");
            if (outCheck == 0) {
                ret = 0;
                while (ret == 0) {
                    printf("Please enter a name for the output file: ");
                    ret = (int) scanf("%s", outNameE);
                    out = (ret > 0) ? outNameE : '\0';
                }
            }
            ret = wolfsslEncrypt(alg, mode, pwdKey, key, size, in, out,
                    iv, block, ivCheck, inputHex);
        }
        /* decryption function call */
        else if (dCheck == 1) {
            if (outCheck == 0) {
                ret = 0;
                while (ret == 0) {
                    printf("Please enter a name for the output file: ");
                    ret = (int) scanf("%s", outNameD);
                    out = (ret > 0) ? outNameD : '\0';
                }
            }
            ret = wolfsslDecrypt(alg, mode, pwdKey, key, size, in, out,
                    iv, block, keyType);
        }
        else {
            wolfsslHelp();
        }
        /* clear and free data */
        XMEMSET(key, 0, size);
        XMEMSET(pwdKey, 0, size);
        XMEMSET(iv, 0, block);
        wolfsslFreeBins(pwdKey, iv, key, NULL, NULL);
    }
    else
        ret = FATAL_ERROR;
    return ret;
}
int wolfsslEncrypt(char* alg, char* mode, byte* pwdKey, byte* key, int size,
        char* in, char* out, byte* iv, int block, int ivCheck, int inputHex)
{
#ifndef NO_AES
    Aes aes;                        /* aes declaration */
#endif

#ifndef NO_DES3
    Des3 des3;                      /* 3des declaration */
#endif

#ifdef HAVE_CAMELLIA
    Camellia camellia;              /* camellia declaration */
#endif

    FILE*  tempInFile = NULL;       /* if user not provide a file */
    FILE*  inFile = NULL;           /* input file */
    FILE*  outFile = NULL;          /* output file */

    RNG     rng;                    /* random number generator declaration */

    byte*   input = NULL;           /* input buffer */
    byte*   output = NULL;          /* output buffer */
    byte    salt[SALT_SIZE] = {0};  /* salt variable */

    int     ret             = 0;    /* return variable */
    int     inputLength     = 0;    /* length of input */
    int     length          = 0;    /* total length */
    int     padCounter      = 0;    /* number of padded bytes */
    int     i               = 0;    /* loop variable */
    int     hexRet          = 0;    /* hex -> bin return*/

    word32  tempInputL      = 0;    /* temporary input Length */
    word32  tempMax         = MAX;  /* controls encryption amount */

    char    inputString[MAX];       /* the input string */
    char*   userInputBuffer = NULL; /* buffer when input is not a file */


    if (access (in, F_OK) == -1) {
        printf("file did not exist, encrypting string following \"-i\""
                "instead.\n");

        /* use user entered data to encrypt */
        inputLength = (int) strlen(in);
        userInputBuffer = (char*) malloc(inputLength);

        /* writes the entered text to the input buffer */
        XMEMCPY(userInputBuffer, in, inputLength);

        /* open the file to write */
        tempInFile = fopen(in, "wb");
        fwrite(userInputBuffer, 1, inputLength, tempInFile);
        fclose(tempInFile);

        /* free buffer */
        free(userInputBuffer);
    }

    /* open the inFile in read mode */
    inFile = fopen(in, "rb");

    /* find length */
    fseek(inFile, 0, SEEK_END);
    inputLength = (int) ftell(inFile);
    fseek(inFile, 0, SEEK_SET);

    length = inputLength;

    /* Start up the random number generator */
    ret = (int) wc_InitRng(&rng);
    if (ret != 0) {
        printf("Random Number Generator failed to start.\n");
        return ret;
    }

    /* pads the length until it matches a block,
     * and increases pad number
     */
    while (length % block != 0) {
        length++;
        padCounter++;
    }

    /* if the iv was not explicitly set,
     * generate an iv and use the pwdKey
     */
    if (ivCheck == 0) {
        /* IV not set, generate it */
        ret = wc_RNG_GenerateBlock(&rng, iv, block);

        if (ret != 0) {
            return ret;
        }

        /* stretches pwdKey to fit size based on wolfsslGetAlgo() */
        ret = wolfsslGenKey(&rng, pwdKey, size, salt, padCounter);

        if (ret != 0) {
            printf("failed to set pwdKey.\n");
            return ret;
        }
        /* move the generated pwdKey to "key" for encrypting */
        for (i = 0; i < size; i++) {
            key[i] = pwdKey[i];
        }
    }

    /* open the outFile in write mode */
    outFile = fopen(out, "wb");
    fwrite(salt, 1, SALT_SIZE, outFile);
    fwrite(iv, 1, block, outFile);
    fclose(outFile);

    /* malloc 1kB buffers */
    input = (byte*) malloc(MAX);
    output = (byte*) malloc(MAX);

    /* loop, encrypt 1kB at a time till length <= 0 */
    while (length > 0) {
        /* Read in 1kB to input[] */
        if (inputHex == 1)
            ret = (int) fread(inputString, 1, MAX, inFile);
        else
            ret = (int) fread(input, 1, MAX, inFile);

        if (ret != MAX) {
            /* check for end of file */
            if (feof(inFile)) {

                /* hex or ascii */
                if (inputHex == 1) {
                    hexRet = wolfsslHexToBin(inputString, &input,
                                                &tempInputL,
                                                NULL, NULL, NULL,
                                                NULL, NULL, NULL,
                                                NULL, NULL, NULL);
                     if (hexRet != 0) {
                        printf("failed during conversion of input,"
                            " ret = %d\n", hexRet);
                        return hexRet;
                    }
                }/* end hex or ascii */

                /* pad to end of block */
                for (i = ret ; i < (ret + padCounter); i++) {
                    input[i] = padCounter;
                }
                /* adjust tempMax for less than 1kB encryption */
                tempMax = ret + padCounter;
            }
            else { /* otherwise we got a file read error */
                wolfsslFreeBins(input, output, NULL, NULL, NULL);
                return FREAD_ERROR;
            }/* End feof check */
        }/* End fread check */

        /* sets key encrypts the message to ouput from input */
#ifndef NO_AES
        if (XSTRNCMP(alg, "aes", 3) == 0) {
            if (XSTRNCMP(mode, "cbc", 3) == 0) {
                ret = wc_AesSetKey(&aes, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION);
                if (ret != 0) {
                    printf("wc_AesSetKey failed.\n");
                    wolfsslFreeBins(input, output, NULL, NULL, NULL);
                    return ret;
                }
                ret = wc_AesCbcEncrypt(&aes, output, input, tempMax);
                if (ret != 0) {
                    printf("wc_AesCbcEncrypt failed.\n");
                    wolfsslFreeBins(input, output, NULL, NULL, NULL);
                    return ENCRYPT_ERROR;
                }
            }
#ifdef WOLFSSL_AES_COUNTER
            else if (XSTRNCMP(mode, "ctr", 3) == 0) {
                /* if mode is ctr */
                wc_AesSetKeyDirect(&aes, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION);
                wc_AesCtrEncrypt(&aes, output, input, tempMax);
            }
#endif
        }
#endif
#ifndef NO_DES3
        if (XSTRNCMP(alg, "3des", 4) == 0) {
            ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION);
            if (ret != 0) {
                printf("wc_Des3_SetKey failed.\n");
                wolfsslFreeBins(input, output, NULL, NULL, NULL);
                return ret;
            }
            ret = wc_Des3_CbcEncrypt(&des3, output, input, tempMax);
            if (ret != 0) {
                printf("wc_Des3_cbcEncrypt failed.\n");
                wolfsslFreeBins(input, output, NULL, NULL, NULL);
                return ENCRYPT_ERROR;
            }
        }
#endif
#ifdef HAVE_CAMELLIA
        if (XSTRNCMP(alg, "camellia", 8) == 0) {
            ret = wc_CamelliaSetKey(&camellia, key, block, iv);
            if (ret != 0) {
                printf("CamelliaSetKey failed.\n");
                wolfsslFreeBins(input, output, NULL, NULL, NULL);
                return ret;
            }
            if (XSTRNCMP(mode, "cbc", 3) == 0) {
                wc_CamelliaCbcEncrypt(&camellia, output, input, tempMax);
            }
            else {
                printf("Incompatible mode while using Camellia.\n");
                wolfsslFreeBins(input, output, NULL, NULL, NULL);
                return FATAL_ERROR;
            }
        }
#endif /* HAVE_CAMELLIA */

        /* this method added for visual confirmation of nist test vectors,
         * automated tests to come soon
         */

        /* something in the output buffer and using hex */
        if (output != NULL && inputHex == 1) {
            int tempi;

            printf("\nUser specified hex input this is a representation of "
                "what\nis being written to file in hex form.\n\n[ ");
            for (tempi = 0; tempi < block; tempi++ ) {
                printf("%02x", output[tempi]);
            }
            printf(" ]\n\n");
        } /* end visual confirmation */

        /* Open the outFile in append mode */
        outFile = fopen(out, "ab");
        ret = (int) fwrite(output, 1, tempMax, outFile);

        if (ferror(outFile)) {
            printf("failed to write to file.\n");
            if (input != NULL)
                XMEMSET(input, 0, tempMax);
            if (output != NULL)
                XMEMSET(output, 0, tempMax);
            wolfsslFreeBins(input, output, NULL, NULL, NULL);
            return FWRITE_ERROR;
        }
        if (ret > MAX) {
            printf("Wrote too much to file.\n");
            if (input != NULL)
                XMEMSET(input, 0, tempMax);
            if (output != NULL)
                XMEMSET(output, 0, tempMax);
            wolfsslFreeBins(input, output, NULL, NULL, NULL);
            return FWRITE_ERROR;
        }
        /* close the outFile */
        fclose(outFile);

        length -= tempMax;
        if (length < 0)
            printf("length went past zero.\n");
        if (input != NULL)
            XMEMSET(input, 0, tempMax);
        if (output != NULL)
            XMEMSET(output, 0, tempMax);
    }

    /* closes the opened files and frees the memory */
    fclose(inFile);
    XMEMSET(key, 0, size);
    XMEMSET(iv, 0 , block);
    XMEMSET(alg, 0, size);
    XMEMSET(mode, 0 , block);
    /* Use the wolfssl free for rng */
    wc_FreeRng(&rng);
    wolfsslFreeBins(input, output, NULL, NULL, NULL);
    return 0;
}